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 }