139 lines
2.5 KiB
Go
139 lines
2.5 KiB
Go
package uart
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
"time"
|
|
|
|
"alox.tool/api"
|
|
"alox.tool/eventbus"
|
|
"go.bug.st/serial"
|
|
)
|
|
|
|
type Com struct {
|
|
bus eventbus.EventBus
|
|
port serial.Port
|
|
cancel context.CancelFunc
|
|
}
|
|
|
|
func NewCom(bus eventbus.EventBus) (*Com, error) {
|
|
return &Com{
|
|
bus: bus,
|
|
port: nil,
|
|
cancel: nil,
|
|
}, nil
|
|
}
|
|
|
|
func (c *Com) Connect(portName string, baudrate int) error {
|
|
if c.port != nil {
|
|
return fmt.Errorf("Port already connected")
|
|
}
|
|
mode := &serial.Mode{BaudRate: baudrate}
|
|
port, err := serial.Open(portName, mode)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
drv := New(c.bus)
|
|
|
|
go func() {
|
|
buff := make([]byte, 1024)
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
return
|
|
default:
|
|
n, err := port.Read(buff)
|
|
if err != nil {
|
|
log.Print("[Warning]: Read Error:", err)
|
|
return // Loop beenden bei Hardware-Fehler
|
|
}
|
|
if n > 0 {
|
|
for _, b := range buff[:n] {
|
|
//log.Printf("[RAW][RX] % X", b)
|
|
drv.ParseByte(b)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}()
|
|
|
|
c.port = port
|
|
c.cancel = cancel
|
|
return nil
|
|
}
|
|
|
|
func (c *Com) Close() {
|
|
c.cancel()
|
|
c.port.Close()
|
|
}
|
|
|
|
func packFrame(id byte, payload []byte) []byte {
|
|
out := make([]byte, 0, len(payload)+5) // Guessing extra Puffer size
|
|
checksum := id
|
|
|
|
out = append(out, StartByte)
|
|
|
|
// Helper für Escaping
|
|
writeEscaped := func(b byte) {
|
|
if b == StartByte || b == EscapeByte || b == EndByte {
|
|
out = append(out, EscapeByte)
|
|
}
|
|
out = append(out, b)
|
|
}
|
|
|
|
writeEscaped(id)
|
|
for _, b := range payload {
|
|
writeEscaped(b)
|
|
checksum ^= b
|
|
}
|
|
|
|
writeEscaped(checksum)
|
|
out = append(out, EndByte)
|
|
return out
|
|
}
|
|
|
|
func (c *Com) Send(id byte, payload []byte) error {
|
|
raw := packFrame(id, payload)
|
|
log.Printf("[RAW]: %v", raw)
|
|
|
|
//log.Printf("RAW: % X", raw)
|
|
_, err := c.port.Write(raw)
|
|
|
|
c.bus.Publish(api.TopicUARTTx, api.Frame{
|
|
Time: uint64(time.Now().UnixNano()),
|
|
ID: id,
|
|
Data: payload,
|
|
})
|
|
|
|
return err
|
|
}
|
|
|
|
func (c *Com) EventbusHandler(ctx context.Context) error {
|
|
UActions := c.bus.Subscribe(api.TopicUartAction)
|
|
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
return nil
|
|
case msgT := <-UActions:
|
|
switch msg := msgT.(type) {
|
|
case api.ActionUartConnect:
|
|
err := c.Connect(msg.Adapter, msg.Baudrate)
|
|
c.bus.Publish(api.TopicUartAction, api.ActionUartConnected{
|
|
Adapter: msg.Adapter,
|
|
Baudrate: msg.Baudrate,
|
|
Error: err,
|
|
})
|
|
case api.ActionUartDisconnect:
|
|
c.Close()
|
|
c.bus.Publish(api.TopicUartAction, api.ActionUartDisconnected{})
|
|
case api.ActionUartSendMessage:
|
|
c.Send(msg.MsgId, msg.Data)
|
|
}
|
|
}
|
|
}
|
|
}
|