diff --git a/cmd/repl.go b/cmd/repl.go index b6e5a2b..0382e90 100644 --- a/cmd/repl.go +++ b/cmd/repl.go @@ -62,29 +62,38 @@ func replCmdAction(cmd *cobra.Command, args []string) { return nil }, } - // selectDeviceREPLCmd := repl.Command{ - // Name: "select", - // Usage: "Selects a given device - pass its ID", - // Action: func(r *repl.REPL, args []string) error { - // // We should add this to the REPL instead - // if len(args) < 1 { - // return fmt.Errorf("requires at least on argument") - // } - // - // // First and only argument should be the ID of the device we want to use - // targetID, err := strconv.ParseInt(args[0], 10, 0) - // if err != nil { - // return err - // } - // - // return nil - // }, - // } + + runDeviceAPIREPLCmd := repl.Command{ + Name: "v-run", + Usage: "runs a funcion of a device - pass its ID and function name", + Action: func(r *repl.REPL, args []string) error { + // We should add this to the REPL instead + if len(args) < 3 { + return fmt.Errorf("requires at least on argument") + } + + // First and only argument should be the ID of the device we want to use + targetID, err := strconv.ParseInt(args[0], 10, 0) + if err != nil { + return err + } + + fnName := args[1] + fnArgs := args[2:] + + err = perClerk.RunDeviceFunction(uint8(targetID), fnName, fnArgs) + if err != nil { + return err + } + + return nil + }, + } r.RegisterCMD(discoverDevicesREPLCmd) r.RegisterCMD(listDevicesREPLCmd) - // r.RegisterCMD(selectDeviceREPLCmd) r.RegisterCMD(listDeviceAPIREPLCmd) + r.RegisterCMD(runDeviceAPIREPLCmd) r.Start() r.Close() diff --git a/helpers/helper.go b/helpers/helper.go index f943198..cc18d41 100644 --- a/helpers/helper.go +++ b/helpers/helper.go @@ -1,8 +1,23 @@ // Package helper package helper +import ( + "bytes" + "encoding/binary" +) + func B32(s string) [32]byte { var b [32]byte copy(b[:], s) return b } + +func StructToBytes(s any) ([]byte, error) { + var buf bytes.Buffer + err := binary.Write(&buf, binary.LittleEndian, s) + if err != nil { + return []byte{}, err + } + + return buf.Bytes(), nil +} diff --git a/peripheral/communication/walkieTalkie.go b/peripheral/communication/walkieTalkie.go index aa6656b..7cc4136 100644 --- a/peripheral/communication/walkieTalkie.go +++ b/peripheral/communication/walkieTalkie.go @@ -65,13 +65,6 @@ func (wt *WalkieTalkie) TurnOff() error { return wt.Serial.Close() } -// func (wt *WalkieTalkie) SendCommand(cmd Command, payload []byte) (int, error) { -// switch cmd { -// case CmdRequestID: -// return wt.RequestIdentification(d * serial.Port) -// } -// } - func (wt *WalkieTalkie) RequestIdentification() (int, error) { return wt.Serial.Write([]byte{uint8(CmdRequestID)}) } @@ -87,6 +80,7 @@ type header struct { } func (wt *WalkieTalkie) sendPacket(data any) error { + fmt.Println("Sending a packet...") // Prepare the payload var buf bytes.Buffer err := binary.Write(&buf, binary.LittleEndian, data) diff --git a/peripheral/device.go b/peripheral/device.go index f6aae18..1b57bf9 100644 --- a/peripheral/device.go +++ b/peripheral/device.go @@ -65,28 +65,16 @@ func (p *PeripheralDevice) Probe() error { return err } - // Papers, please! - _, err = p.WT.RequestIdentification() - if err != nil { - return err - } - - // Verify the papers - var pkt pack.IdentificationPacket - err = pkt.Read(p.WT) - if err != nil { - // Throw the man in the gulag! - return err - } - - // Acknowledge successful identification - _, err = p.WT.AknowledgeIdentification() + // Send the identification command + cmd := comm.CmdRequestID + var response pack.IdentificationPacket + err = p.WT.SendCommand(cmd, []byte{}, &response) if err != nil { return err } // copy the data - p.Merge(&pkt) + p.Merge(&response) p.ToConnectedIdling() return nil diff --git a/peripheral/devices/cdash_display.go b/peripheral/devices/cdash_display.go index 8f6d3b7..60ca314 100644 --- a/peripheral/devices/cdash_display.go +++ b/peripheral/devices/cdash_display.go @@ -1,9 +1,15 @@ package devices -import helper "esdi/helpers" +import ( + "fmt" + "strconv" + + helper "esdi/helpers" + "esdi/peripheral/types" +) const ( - newWindowCMDID = iota + newWindowCMDID types.CommandID = iota destroyWindowCMDID ) @@ -26,10 +32,62 @@ var CDashDisplay = Device{ }, } -func createWindow(data []byte) { +func createWindow(dCMD *DeviceCMD, args []string) (types.CommandID, []byte, error) { // Parse the command + // x0, y0, width, height, title # add other decorations later on + // fmt.Printf("%s command called: %+v\n", dCMD.GetName(), args) + + type UIWindow struct { + X0 uint16 + Y0 uint16 + Width uint16 + Height uint16 + Title [32]byte + } + + if len(args) != 5 { + return 0, []byte{}, fmt.Errorf("wrong parameters, got %d, want %d. "+ + "Command asks for: x0 y0 width height title", len(args), 5) + } + + x0, err := strconv.ParseInt(args[0], 10, 0) + if err != nil { + return 0, []byte{}, err + } + y0, err := strconv.ParseInt(args[1], 10, 0) + if err != nil { + return 0, []byte{}, err + } + width, err := strconv.ParseInt(args[2], 10, 0) + if err != nil { + return 0, []byte{}, err + } + height, err := strconv.ParseInt(args[3], 10, 0) + if err != nil { + return 0, []byte{}, err + } + + data := UIWindow{ + X0: uint16(x0), + Y0: uint16(y0), + Width: uint16(width), + Height: uint16(height), + Title: helper.B32(args[4]), + } + + // fmt.Printf("Data: %+v\n", data) + + bytes, err := helper.StructToBytes(data) + if err != nil { + return 0, []byte{}, err + } + + return dCMD.GetIdentifier(), bytes, nil } -func destroyWindow(data []byte) { +func destroyWindow(dCMD *DeviceCMD, args []string) (types.CommandID, []byte, error) { // Parse the command + fmt.Printf("%s command called: %+v\n", dCMD.GetName(), args) + + return dCMD.GetIdentifier(), []byte{}, nil } diff --git a/peripheral/devices/devices.go b/peripheral/devices/devices.go index 38b3aba..1f53040 100644 --- a/peripheral/devices/devices.go +++ b/peripheral/devices/devices.go @@ -23,6 +23,14 @@ type Device struct { API map[string]DeviceCMD } +func (dev *Device) HasFunction(f string) *DeviceCMD { + if cmd, ok := dev.API[f]; ok { + return &cmd + } + + return nil +} + type DeviceCMDHeader struct { Payload [64]byte } @@ -34,7 +42,7 @@ type DeviceCMDPayload struct { // DeviceCMDFn defines the basic type for the functions the devices can have // The function will receive a []byte that should be the arguments the user // types in the REPL - or however this will be used -type DeviceCMDFn func(data []byte) +type DeviceCMDFn func(dCMD *DeviceCMD, args []string) (types.CommandID, []byte, error) type DeviceCMD struct { Identifier types.CommandID @@ -44,3 +52,15 @@ type DeviceCMD struct { Data DeviceCMDPayload Fn DeviceCMDFn } + +func (dCMD *DeviceCMD) GetIdentifier() types.CommandID { + return dCMD.Identifier +} + +func (dCMD *DeviceCMD) GetName() string { + return dCMD.Name +} + +func (dCMD *DeviceCMD) GetDesc() string { + return dCMD.Desc +} diff --git a/peripheral/peripheral.go b/peripheral/peripheral.go index bf6cace..d0215dc 100644 --- a/peripheral/peripheral.go +++ b/peripheral/peripheral.go @@ -3,6 +3,7 @@ package peripheral import ( "esdi/peripheral/devices" + "esdi/peripheral/types" "fmt" "path/filepath" ) @@ -86,18 +87,59 @@ func (clerk *PeripheralDeviceClerk) ListDevices() error { return nil } -func (clerk *PeripheralDeviceClerk) ListDeviceAPI(ID uint8) error { +func (clerk *PeripheralDeviceClerk) getDevice(ID uint8) *devices.Device { if _, ok := clerk.Devices[ID]; !ok { + return nil + } + + return clerk.Devices[ID].DeviceAPI +} + +func (clerk *PeripheralDeviceClerk) ListDeviceAPI(ID uint8) error { + dev := clerk.getDevice(ID) + if dev == nil { return fmt.Errorf("device with ID %d not found", ID) } - for _, f := range clerk.Devices[ID].DeviceAPI.API { + for _, f := range dev.API { fmt.Printf("%s\t%s\n", f.Name, f.Desc) } return nil } +func (clerk *PeripheralDeviceClerk) sendDeviceFn(c types.CommandID, payload []byte) error { + fmt.Println("Send command:", c) + fmt.Println("With payload:", payload) + + return nil +} + +func (clerk *PeripheralDeviceClerk) RunDeviceFunction(ID uint8, f string, args []string) error { + dev := clerk.getDevice(ID) + if dev == nil { + return fmt.Errorf("device with ID %d not found", ID) + } + + cmd := dev.HasFunction(f) + if cmd == nil { + return fmt.Errorf("requested function %s doesnt exist", f) + } + + // Execute the function + command, payload, err := cmd.Fn(cmd, args) + if err != nil { + return err + } + + err = clerk.sendDeviceFn(command, payload) + if err != nil { + return err + } + + return nil +} + // func (c *PeripheralDeviceClerk) clerkBackgroundJob() { // for { // c.mu.RLock()