Support variable sized reads from the serial port

This commit is contained in:
Nonoo 2020-10-25 12:56:28 +01:00
parent a45f07cd61
commit a222cbd92d

View file

@ -1,6 +1,9 @@
package main
import (
"bytes"
"time"
"github.com/nonoo/kappanhang/log"
)
@ -13,6 +16,12 @@ type serialStream struct {
sendSeq uint16
readFromSerialPort struct {
buf bytes.Buffer
frameStarted bool
frameTimeout *time.Timer
}
deinitNeededChan chan bool
deinitFinishedChan chan bool
}
@ -58,21 +67,73 @@ func (s *serialStream) sendOpenClose(close bool) error {
func (s *serialStream) handleRead(r []byte) {
if len(r) >= 22 {
if r[16] == 0xc1 && r[0]-0x15 == r[17] {
log.Print("rcv ", r[21:])
s.serialPort.write <- r[21:]
}
}
}
func (s *serialStream) gotDataFromSerialPort(r []byte) {
for len(r) > 0 {
for len(r) > 0 && !s.readFromSerialPort.frameStarted {
if s.readFromSerialPort.buf.Len() > 1 {
s.readFromSerialPort.buf.Reset()
}
if s.readFromSerialPort.buf.Len() == 0 {
// Cut until we find the frame start byte.
for r[0] != 0xfe {
r = r[1:]
if len(r) == 0 {
return
}
}
// Found the first start byte.
s.readFromSerialPort.buf.WriteByte(r[0])
r = r[1:]
}
if s.readFromSerialPort.buf.Len() == 1 {
if r[0] != 0xfe {
s.readFromSerialPort.buf.Reset()
r = r[1:]
} else {
// Found the second start byte.
s.readFromSerialPort.buf.WriteByte(r[0])
r = r[1:]
s.readFromSerialPort.frameTimeout.Reset(100 * time.Millisecond)
s.readFromSerialPort.frameStarted = true
}
}
}
for _, b := range r {
s.readFromSerialPort.buf.WriteByte(b)
if b == 0xfc || b == 0xfd || s.readFromSerialPort.buf.Len() == maxSerialFrameLength {
log.Print("snd ", s.readFromSerialPort.buf.Bytes())
if err := s.send(s.readFromSerialPort.buf.Bytes()); err != nil {
reportError(err)
}
if !s.readFromSerialPort.frameTimeout.Stop() {
<-s.readFromSerialPort.frameTimeout.C
}
s.readFromSerialPort.buf.Reset()
s.readFromSerialPort.frameStarted = false
break
}
}
}
}
func (s *serialStream) loop() {
for {
select {
case r := <-s.common.readChan:
s.handleRead(r)
case r := <-s.serialPort.read:
if err := s.send(r); err != nil {
reportError(err)
}
s.gotDataFromSerialPort(r)
case <-s.readFromSerialPort.frameTimeout.C:
s.readFromSerialPort.buf.Reset()
s.readFromSerialPort.frameStarted = false
case <-s.deinitNeededChan:
s.deinitFinishedChan <- true
return
@ -109,6 +170,10 @@ func (s *serialStream) start(devName string) error {
s.deinitNeededChan = make(chan bool)
s.deinitFinishedChan = make(chan bool)
s.readFromSerialPort.frameTimeout = time.NewTimer(0)
<-s.readFromSerialPort.frameTimeout.C
go s.loop()
return nil
}