102 lines
1.7 KiB
Go
102 lines
1.7 KiB
Go
package uart
|
|
|
|
import (
|
|
"context"
|
|
"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 Connect(bus eventbus.EventBus, portName string, baudrate int) (*Com, error) {
|
|
mode := &serial.Mode{BaudRate: baudrate}
|
|
port, err := serial.Open(portName, mode)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
drv := New(bus)
|
|
|
|
go func() {
|
|
buff := make([]byte, 1024)
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
return
|
|
default:
|
|
n, err := port.Read(buff)
|
|
if err != nil {
|
|
log.Print("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)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}()
|
|
|
|
return &Com{
|
|
bus: bus,
|
|
port: port,
|
|
cancel: cancel,
|
|
}, 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: % 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
|
|
}
|