Files
esdi/peripheral/communication/walkieTalkie.go
T

210 lines
3.9 KiB
Go

package communication
import (
"bytes"
"encoding/binary"
"fmt"
"io"
helper "esdi/helpers"
"esdi/peripheral/communication/constvar"
"esdi/peripheral/communication/packets"
"esdi/peripheral/types"
"github.com/tarm/serial"
)
type WalkieTalkie struct {
Serial *serial.Port
Cfg *serial.Config
}
func (wt *WalkieTalkie) ReadFramedData(size int, packet any) error {
buf := make([]byte, size)
for {
b := make([]byte, 1)
_, err := wt.Serial.Read(b)
if err != nil {
// fmt.Fprintf(os.Stderr, "dev read: %s\n", err.Error())
return err
}
if b[0] == constvar.StartOfText {
buf[0] = b[0]
break
}
}
_, err := io.ReadFull(wt.Serial, buf[1:])
if err != nil {
return err
}
reader := bytes.NewReader(buf)
err = binary.Read(reader, binary.LittleEndian, packet)
if err != nil {
return err
}
return nil
}
func (wt *WalkieTalkie) TurnOn() error {
var err error
wt.Serial, err = serial.OpenPort(wt.Cfg)
if err != nil {
return err
}
return nil
}
func (wt *WalkieTalkie) TurnOff() error {
return wt.Serial.Close()
}
func (wt *WalkieTalkie) RequestIdentification() (int, error) {
return wt.Serial.Write([]byte{uint8(CmdRequestID)})
}
func (wt *WalkieTalkie) AknowledgeIdentification() (int, error) {
return wt.Serial.Write([]byte{uint8(CmdAckID)})
}
type header struct {
StartByte uint8
CMD types.Command
EndByte uint8
}
type CMDDataPacket struct {
StartMarker uint8
CMD types.Command
Len uint16
Payload []byte
CRC uint8
EndMarker uint8
}
func (cmdp *CMDDataPacket) Serialize() []byte {
buf := make([]byte, 0, 1+1+2+len(cmdp.Payload)+1+1)
buf = append(buf, cmdp.StartMarker)
buf = append(buf, byte(cmdp.CMD))
buf = append(buf, byte(cmdp.Len), byte(cmdp.Len>>8))
buf = append(buf, cmdp.Payload...)
buf = append(buf, cmdp.CRC)
buf = append(buf, cmdp.EndMarker)
return buf
}
func (wt *WalkieTalkie) sendPacket(cmd types.Command, data any) error {
// Prepare the payload
payload, err := helper.StructToBytes(data)
if err != nil {
return err
}
packet := CMDDataPacket{
StartMarker: constvar.StartOfText,
CMD: cmd,
Len: uint16(len(payload)),
Payload: payload,
CRC: CRC8(payload),
EndMarker: constvar.EndOfText,
}
// Send the payload
serializedPacket := packet.Serialize()
// fmt.Fprintf(os.Stderr, "%+v", serializedPacket)
_, err = wt.Serial.Write(serializedPacket)
if err != nil {
return err
}
return nil
}
func (wt *WalkieTalkie) readPacket(resp packets.Packet) error {
size := binary.Size(resp)
if size < 0 {
return fmt.Errorf("invalid packet size")
}
err := wt.ReadFramedData(size, resp)
if err != nil {
return err
}
if !resp.Validate() {
return fmt.Errorf("badly formatted response")
}
return nil
}
// func (wt *WalkieTalkie) sendHeader(h *header) error {
// err := wt.sendPacket(h)
// if err != nil {
// return err
// }
//
// // var ack packets.AckPacket
// // err = wt.readPacket(&ack)
// // if err != nil {
// // return err
// // }
//
// return nil
// }
// func (wt *WalkieTalkie) sendBody(payload any, resp packets.Packet) error {
// err := wt.sendPacket(payload)
// if err != nil {
// return err
// }
//
// // err = wt.readPacket(resp)
// // if err != nil {
// // return err
// // }
//
// return nil
// }
func (wt *WalkieTalkie) SendCommand(cmd types.Command, payload any,
responseBody packets.Packet) error {
// Prepare the header
// header := header{
// StartByte: constvar.StartOfText,
// CMD: cmd,
// EndByte: constvar.EndOfText,
// }
// Send the header
// err := wt.sendHeader(&header)
// if err != nil {
// return err
// }
// Send the body
err := wt.sendPacket(cmd, payload)
if err != nil {
return err
}
// if the responseBody != nil, then we also read and populate it???
if responseBody != nil {
err = wt.readPacket(responseBody)
if err != nil {
return err
}
}
return nil
}