Compare commits

..

7 Commits

Author SHA1 Message Date
c86d0e1d8b refactored Redstone bin 2023-05-31 19:19:17 +02:00
8c041766c9 refactored Net bin 2023-05-31 19:12:44 +02:00
779933be32 refactored GPS bin 2023-05-31 18:57:10 +02:00
06b3e37138 refactored Disk bin to use CLIBaseApp 2023-05-31 18:40:14 +02:00
2a7f02c5e3 fixed null synaopsis 2023-05-31 18:39:36 +02:00
e11a9383ee added callback dispose in ps handle 2023-05-31 15:17:19 +02:00
182a2bce7d fixed termial newline handle 2023-05-29 22:10:25 +02:00
7 changed files with 261 additions and 315 deletions

View File

@@ -1,124 +1,130 @@
package bin;
import kernel.ps.ProcessHandle;
import kernel.ps.Process;
import lib.CLIAppBase;
import kernel.peripherals.Peripherals.Peripheral;
using tink.CoreApi;
using Lambda;
class Disk implements Process {
private var handle:ProcessHandle;
class Disk extends CLIAppBase {
public function new() {
registerSyncSubcommand("ls", (args)->{
Peripheral.instance.getDrives().foreach(drive -> {
var addr = drive.getAddr();
var label = drive.getDiskLabel();
var id = drive.getDiskID();
public function new() {}
public function run(handle:ProcessHandle):Void {
this.handle = handle;
var subcommand = handle.args[0];
var driveAddr:Null<String> = handle.args[1];
switch (subcommand) {
case "ls":
Peripheral.instance.getDrives().foreach(drive -> {
var addr = drive.getAddr();
var label = drive.getDiskLabel();
var id = drive.getDiskID();
if (drive.isDiskPresent()){
if (drive.hasAudio()){
handle.writeLine('${addr} => ${label} [AUDIO]');
}else{
handle.writeLine('${addr} => ${label} (${id})');
}
}else {
handle.writeLine('${addr} => [NO DISK]');
if (drive.isDiskPresent()){
if (drive.hasAudio()){
handle.writeLine('${addr} => ${label} [AUDIO]');
}else{
handle.writeLine('${addr} => ${label} (${id})');
}
return true;
});
case "play":
var drive = Peripheral.instance.getDrive(driveAddr);
if (drive == null){
handle.writeLine("Drive not found: " + driveAddr);
}else {
handle.writeLine('${addr} => [NO DISK]');
}
if (!drive.isDiskPresent()){
handle.writeLine("No disk in drive: " + driveAddr);
return true;
});
});
registerSyncSubcommand("play", (args)->{
if (args.length < 1){
handle.writeLine("Missing drive address");
return false;
}
return audioDiskPlayPause(args[0], true);
},"<drive>");
registerSyncSubcommand("stop", (args) -> {
if (args.length < 1){
handle.writeLine("Missing drive address");
return false;
}
return audioDiskPlayPause(args[0], false);
});
registerSyncSubcommand("eject", (args)->{
if (args.length < 1){
handle.writeLine("Missing drive address");
return false;
}
var driveAddr = args[0];
var drive = Peripheral.instance.getDrive(driveAddr);
if (drive == null){
handle.writeLine("Drive not found: " + driveAddr);
return false;
}
if (!drive.isDiskPresent()){
handle.writeLine("No disk in drive: " + driveAddr);
return false;
}
drive.ejectDisk();
return true;
},"<drive>");
registerSyncSubcommand("lable",(args) -> {
if (args.length < 1){
handle.writeLine("Missing drive address");
return false;
}
var driveAddr = args[0];
var drive = Peripheral.instance.getDrive(driveAddr);
var label:String = args[1];
if (drive == null){
handle.writeLine("Drive not found: " + driveAddr);
}
if (!drive.isDiskPresent()){
handle.writeLine("No disk in drive: " + driveAddr);
}
if (label == null || label == ""){
handle.writeLine(drive.getDiskLabel());
}else{
var err = drive.setDiskLabel(label);
if (err != null){
handle.writeLine("Failed to set lable");
return false;
}
}
if (!drive.hasAudio()){
handle.writeLine("Disk in drive " + driveAddr + " does not have audio");
}
return true;
},"<drive> [label]");
}
drive.playAudio();
case "stop":
var drive = Peripheral.instance.getDrive(driveAddr);
private function audioDiskPlayPause(driveAddr: String, play: Bool): Bool {
var drive = Peripheral.instance.getDrive(driveAddr);
if (drive == null){
handle.writeLine("Drive not found: " + driveAddr);
}
if (!drive.isDiskPresent()){
handle.writeLine("No disk in drive: " + driveAddr);
}
if (!drive.hasAudio()){
handle.writeLine("Disk in drive: " + driveAddr + " does not have audio");
}
drive.stopAudio();
case "eject":
var drive = Peripheral.instance.getDrive(driveAddr);
if (drive == null){
handle.writeLine("Drive not found: " + driveAddr);
}
if (!drive.isDiskPresent()){
handle.writeLine("No disk in drive: " + driveAddr);
}
drive.ejectDisk();
case "lable":
var drive = Peripheral.instance.getDrive(driveAddr);
var label:String = handle.args[2];
if (drive == null){
handle.writeLine("Drive not found: " + driveAddr);
}
if (!drive.isDiskPresent()){
handle.writeLine("No disk in drive: " + driveAddr);
}
if (label == null || label == ""){
handle.writeLine(drive.getDiskLabel());
}else{
var err = drive.setDiskLabel(label);
if (err != null){
handle.writeLine("Failed to set lable");
}
}
case "help":
case null:
printHelp();
default:
handle.writeLine("Unknown subcommand: " + subcommand);
printHelp();
if (drive == null){
handle.writeLine("Drive not found: " + driveAddr);
return false;
}
return handle.close(true);
}
if (!drive.isDiskPresent()){
handle.writeLine("No disk in drive: " + driveAddr);
return false;
}
private function printHelp() {
handle.writeLine("Usage: disk <subcommand> [args]");
handle.writeLine("Subcommands:");
handle.writeLine(" ls");
handle.writeLine(" play <drive>");
handle.writeLine(" stop <drive>");
handle.writeLine(" eject <drive>");
handle.writeLine(" label <drive> [label]");
if (!drive.hasAudio()){
handle.writeLine("Disk in drive: " + driveAddr + " does not have audio");
return false;
}
if (play){
drive.playAudio();
}else{
drive.stopAudio();
}
return true;
}
}

View File

@@ -1,97 +1,70 @@
package bin;
import kernel.ps.ProcessHandle;
import kernel.ps.Process;
import lib.CLIAppBase;
import kernel.gps.INS;
import lib.Pos3;
import lib.Vec.Vec3;
using tink.CoreApi;
class GPS implements Process {
private var handle:ProcessHandle;
class GPS extends CLIAppBase {
public function new() {
registerSyncSubcommand("set", (args)->{
var x: Float = Std.parseFloat(args[0]);
var y: Float = Std.parseFloat(args[1]);
var z: Float = Std.parseFloat(args[2]);
public function new() {}
var pos: Pos3 = new Vec3<Float>(x, y, z);
public function run(handle: ProcessHandle):Void {
this.handle = handle;
kernel.gps.GPS.instance.setManualPosition(pos);
var subcommand = handle.args[0];
var subcommand_args = handle.args.slice(1);
switch (subcommand) {
case "set":
handle.close(setManuelPos(subcommand_args));
case "status":
handle.close(getGPSStatus());
case "locate":
kernel.gps.GPS.instance.locate().handle((pos)->{
if (pos != null) {
handle.writeLine('Position x:${pos.x} y:${pos.y} z:${pos.z}');
handle.close(true);
} else {
handle.writeLine("Position not available");
handle.close(false);
}
});
case "ins":
INS.instance.align().handle(()->{
handle.writeLine("INS aligned");
handle.close(true);
});
default:
handle.writeLine("Unknown subcommand: " + subcommand);
printHelp();
handle.close(false);
}
}
private function printHelp(){
handle.writeLine("GPS commands:");
handle.writeLine("set <x> <y> <z> - set manual position");
handle.writeLine("status - get current position and accuracy");
handle.writeLine("locate - get current position");
handle.writeLine("ins - align INS");
}
private function setManuelPos(args: Array<String>): Bool {
var x: Float = Std.parseFloat(args[0]);
var y: Float = Std.parseFloat(args[1]);
var z: Float = Std.parseFloat(args[2]);
var pos: Pos3 = new Vec3<Float>(x, y, z);
kernel.gps.GPS.instance.setManualPosition(pos);
return true;
}
private function getGPSStatus(): Bool {
var pos = kernel.gps.GPS.instance.getPosition();
if (pos != null) {
handle.writeLine('Position x:${pos.x} y:${pos.y} z:${pos.z}');
} else {
handle.writeLine("Position not available");
return true;
}
},"<x> <y> <z>");
var acc = kernel.gps.GPS.instance.getAccuracy();
if (acc == 1){
handle.writeLine("Accuracy: Low");
} else if (acc == 2){
handle.writeLine("Accuracy: Medium");
} else if (acc == 3){
handle.writeLine("Accuracy: High");
}
registerSyncSubcommand("status",(args)->{
var pos = kernel.gps.GPS.instance.getPosition();
if (pos != null) {
handle.writeLine('Position x:${pos.x} y:${pos.y} z:${pos.z}');
} else {
handle.writeLine("Position not available");
return true;
}
var ins = INS.instance.getHeading();
if (ins != null) {
handle.writeLine('INS heading: ${ins.x} y:${ins.y} z:${ins.z}');
} else {
handle.writeLine("INS heading not available");
}
var acc = kernel.gps.GPS.instance.getAccuracy();
if (acc == 1){
handle.writeLine("Accuracy: Low");
} else if (acc == 2){
handle.writeLine("Accuracy: Medium");
} else if (acc == 3){
handle.writeLine("Accuracy: High");
}
return true;
var ins = INS.instance.getHeading();
if (ins != null) {
handle.writeLine('INS heading: ${ins.x} y:${ins.y} z:${ins.z}');
} else {
handle.writeLine("INS heading not available");
}
return true;
});
registerAsyncSubcommand("locate",(args)->{
return kernel.gps.GPS.instance.locate().map((pos)->{
if (pos != null) {
handle.writeLine('Position x:${pos.x} y:${pos.y} z:${pos.z}');
} else {
handle.writeLine("Position not available");
}
return true;
});
});
registerAsyncSubcommand("ins",(args)->{
return INS.instance.align().map((_)->{
handle.writeLine("INS aligned");
return true;
});
});
}
}

View File

@@ -1,102 +1,65 @@
package bin;
import kernel.ps.ProcessHandle;
import kernel.ps.Process;
import lib.CLIAppBase;
import kernel.peripherals.Peripherals.Peripheral;
import kernel.net.Routing;
import haxe.ds.ReadOnlyArray;
using tink.CoreApi;
class Net implements Process {
private var handle:ProcessHandle;
class Net extends CLIAppBase {
public function new() {
registerSyncSubcommand("route", (args)->{
var routes = Routing.instance.getRouteTable();
public function new() {}
public function run(handle:ProcessHandle):Void {
this.handle = handle;
var subcommand = handle.args[0];
var subcommand_args = handle.args.slice(1);
switch (subcommand) {
case "route":
route(subcommand_args);
return handle.close();
case "iface":
iface(subcommand_args);
return handle.close();
case "help":
printHelp();
return handle.close();
case "ping":
ping(subcommand_args);
// Closes itself
case "proto":
protos();
return handle.close();
default:
handle.write("Unknown subcommand: " + subcommand);
printHelp();
return handle.close(false);
}
}
private function printHelp() {
handle.write("net route");
handle.write("net iface");
handle.write("net help");
handle.write("net proto");
}
private function route(args:ReadOnlyArray<String>):Void {
var routes = Routing.instance.getRouteTable();
for(k => v in routes) {
handle.write('${k} => ${v.interf.name()}(${v.cost})');
}
}
private function iface(args:ReadOnlyArray<String>):Bool {
var modems = Peripheral.instance.getModems();
for (modem in modems) {
handle.write(modem.name());
}
return true;
}
function ping(args:ReadOnlyArray<String>): Void {
if (args.length != 1) {
handle.write("Usage: net ping id");
return handle.close(false);
}
var toID:Null<Int> = Std.parseInt(args[0]);
if (toID == null) {
handle.write("Invalid ID");
return handle.close(false);
}
kernel.net.Net.instance.ping(toID).handle(result -> {
switch (result){
case Success(_):
handle.write("Ping succeeded");
return handle.close();
case Failure(failure):
handle.write("Ping failed: " + failure);
return handle.close(false);
for(k => v in routes) {
handle.writeLine('${k} => ${v.interf.name()}(${v.cost})');
}
return true;
});
}
function protos():Void {
var protos = kernel.net.Net.instance.getActiveProtocols();
registerSyncSubcommand("iface", (args)->{
var modems = Peripheral.instance.getModems();
for (proto in protos) {
handle.write(proto);
}
for (modem in modems) {
handle.writeLine(modem.name());
}
return true;
});
registerSyncSubcommand("proto",(args)->{
var protos = kernel.net.Net.instance.getActiveProtocols();
for (proto in protos) {
handle.writeLine(proto);
}
return true;
});
registerAsyncSubcommand("ping",(args)->{
if (args.length < 1) {
return Future.sync(false);
}
var toID:Null<Int> = Std.parseInt(args[0]);
if (toID == null) {
handle.write("Invalid ID");
return Future.sync(false);
}
return kernel.net.Net.instance.ping(toID).map(result -> {
switch (result){
case Success(_):
handle.write("Ping succeeded");
case Failure(failure):
handle.write("Ping failed: " + failure);
}
return true;
});
},"<id>");
}
}

View File

@@ -1,44 +1,26 @@
package bin;
import kernel.ps.ProcessHandle;
import kernel.ps.Process;
import lib.CLIAppBase;
import kernel.peripherals.Peripherals.Peripheral;
import kernel.peripherals.Side;
using tink.CoreApi;
class Redstone implements Process {
public function new() {}
class Redstone extends CLIAppBase{
public function new() {
registerSyncSubcommand("on", (args)-> {
Peripheral.instance.getRedstone(args[0]).setOutput(true);
return true;
});
public function run(handle: ProcessHandle):Void {
var subcommand = handle.args[0];
registerSyncSubcommand("off", (args)-> {
Peripheral.instance.getRedstone(args[0]).setOutput(false);
return true;
});
if (subcommand == null) {
handle.write("Usage: redstone <on|off|get> <side>");
return handle.close(false);
}
var side:Null<Side> = handle.args[1];
if (side == null) {
handle.write("Invalid side");
return handle.close(false);
}
switch (subcommand) {
case "on":
Peripheral.instance.getRedstone(side).setOutput(true);
case "off":
Peripheral.instance.getRedstone(side).setOutput(false);
case "get":
var value = Peripheral.instance.getRedstone(side).getAnalogInput();
handle.write("Analog input: " + value);
case "help":
handle.write("Usage: redstone <on|off|get> <side>");
default:
handle.write("Invalid subcommand");
return handle.close(false);
}
return handle.close();
registerSyncSubcommand("get", (args)-> {
var value = Peripheral.instance.getRedstone(args[0]).getAnalogInput();
handle.write("Analog input: " + value);
return true;
});
}
}

View File

@@ -117,11 +117,24 @@ class Terminal implements Process {
ProcessManager.run(ps,{
args: commandArgs,
onWrite: (s:String) -> {
if (s == "") {
return;
}
if (!hadInput) {
// Add a new line, so that the input is not on the same line as the command
this.backlog.push("");
hadInput = true;
}
this.backlog[this.backlog.length - 1] += s;
for (line in s.split("\n")) {
if (line == ""){
this.backlog.push("");
} else {
this.backlog[this.backlog.length - 1] += s;
}
}
this.requestRender();
},
onExit: (success:Bool) -> {

View File

@@ -20,6 +20,7 @@ class ProcessHandle {
private final closeFuture: Future<Bool>;
private var closeFutureResolev: Bool -> Void;
private final windowContexts: Array<WindowContext> = [];
private final cbLinks:Array<CallbackLink> = [];
@:allow(kernel.ps.ProcessManager)
private function new(config: HandleConfig,pid: PID) {
@@ -34,8 +35,6 @@ class ProcessHandle {
if (this.config.onExit != null) {
this.closeFuture.handle(this.config.onExit);
}
this.closeFuture.eager();
}
public function onExit(): Future<Bool> {
@@ -75,7 +74,17 @@ class ProcessHandle {
}
private function dispose() {
// TODO
for (link in this.cbLinks) {
link.cancel();
}
}
public function getPid(): PID {
return this.pid;
}
public function addCallbackLink(link: CallbackLink) {
this.cbLinks.push(link);
}
function get_args():ReadOnlyArray<String> {

View File

@@ -40,12 +40,12 @@ abstract class CLIAppBase implements Process {
private function registerSyncSubcommand(command: String, callback: (Array<String>) -> Bool, synopsis: String = null) {
_subcommandsSync.set(command, callback);
_subcommandsSynopsis.push(command + " " + synopsis);
_subcommandsSynopsis.push(command + " " + (synopsis ?? ""));
}
private function registerAsyncSubcommand(command: String, callback: (Array<String>) -> Future<Bool>, synopsis: String = null) {
_subcommandsAsync.set(command, callback);
_subcommandsSynopsis.push(command + " " + synopsis);
_subcommandsSynopsis.push(command + " " + (synopsis ?? ""));
}
private function printHelp() {