// Package devices will define the available devices we can communicate with package devices import "esdi/peripheral/types" // IDs for our devices. They need to be correctly mapped on the devices // themselves so we can discover them const ( CDashDisplayDevID = 0x01 CDashDisplayDevName = "CDashDisplay" ESBtnBoxDevID = 0x02 ) // DeviceMap maps the implemented devices // When adding a new device we append it here too var DeviceMap = map[int]Device{ CDashDisplayDevID: CDashDisplay, ESBtnBoxDevID: ESBtnBox, } type Device struct { ID uint8 Name [32]byte API map[string]DeviceCMD State any } func (dev *Device) HasFunction(f string) *DeviceCMD { if cmd, ok := dev.API[f]; ok { return &cmd } return nil } type DeviceCMDHeader struct { Payload [64]byte } type DeviceCMDPayload struct { Payload [64]byte } // 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(dCMD *DeviceCMD, args []string) (types.Command, []byte, error) // ArgCheckFn is a function to check the arguments passed. Returns nil or the error // in the passed arguments type ArgCheckFn func(args []string) error type DeviceCMD struct { Identifier types.Command Name string Desc string ArgCheck ArgCheckFn Fn DeviceCMDFn } func (dCMD *DeviceCMD) Run(args []string) (types.Command, []byte, error) { // Validate the arguments in the device function err := dCMD.ArgCheck(args) if err != nil { return 0, []byte{}, err } // Run the function return dCMD.Fn(dCMD, args) } func (dCMD *DeviceCMD) GetIdentifier() types.Command { return dCMD.Identifier } func (dCMD *DeviceCMD) GetName() string { return dCMD.Name } func (dCMD *DeviceCMD) GetDesc() string { return dCMD.Desc } type DeviceInstance[T any] struct { Def *Device ID uint8 State T }