esp_alox/goTool/uart/parser.go
simon 0767ddac38 Big Gotool Refactoring
- Added Event Bus
- Reworked Package Parsing
- Rewokred Frame Parsing
2026-01-27 16:23:51 +01:00

129 lines
2.2 KiB
Go

package uart
import (
"fmt"
"time"
"alox.tool/api"
"alox.tool/eventbus"
)
const (
StartByte = 0xAA
EscapeByte = 0xBB
EndByte = 0xCC
)
type parserState int
const (
stateWaitingForStart parserState = iota
stateGetID
stateEscapedID
stateInPayload
stateEscapedPayload
)
type Parser struct {
bus eventbus.EventBus
state parserState
parsedData []byte
rawCapture []byte
checksum byte
}
func New(bus eventbus.EventBus) *Parser {
return &Parser{
bus: bus,
state: stateWaitingForStart,
parsedData: make([]byte, 0, 1024*4),
rawCapture: make([]byte, 0, 1024*4),
}
}
func (p *Parser) reset() {
p.state = stateWaitingForStart
p.parsedData = p.parsedData[:0]
p.rawCapture = p.rawCapture[:0]
p.checksum = 0
}
func (p *Parser) pushError(reason string) {
// Throw Error on the Bus befor resetting
p.bus.Publish(api.TopicUARTError, fmt.Errorf("%s: %02X", reason, p.rawCapture))
p.reset()
}
func (p *Parser) emitFrame() {
if len(p.parsedData) == 0 {
p.reset()
return
}
// Copy Data for Message Frame
dataCopy := make([]byte, len(p.parsedData)-1) // Exclude ID
copy(dataCopy, p.parsedData[1:])
f := api.Frame{
Time: uint64(time.Now().UnixNano()),
ID: p.parsedData[0],
Data: dataCopy,
}
p.bus.Publish(api.TopicUARTRx, f)
p.reset()
}
func (p *Parser) addByte(b byte) {
p.parsedData = append(p.parsedData, b)
p.checksum ^= b
}
func (p *Parser) ParseByte(b byte) {
p.rawCapture = append(p.rawCapture, b)
switch p.state {
case stateWaitingForStart:
if b == StartByte {
p.reset()
p.rawCapture = append(p.rawCapture, b) // Start Byte behalten
p.state = stateGetID
}
case stateGetID:
if b == EscapeByte {
p.state = stateEscapedID
} else {
p.addByte(b)
p.state = stateInPayload
}
case stateEscapedID:
p.addByte(b)
p.state = stateInPayload
case stateInPayload:
if b == EscapeByte {
p.state = stateEscapedPayload
return
}
if b == StartByte {
p.pushError("unexpected start byte")
return
}
if b == EndByte {
if p.checksum != 0 {
p.pushError("checksum mismatch")
return
}
p.emitFrame()
return
}
p.addByte(b)
case stateEscapedPayload:
p.addByte(b)
p.state = stateInPayload
}
}