2026-01-27 17:36:41 +01:00

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("[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)
}
}
}
}
}()
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
}