1package main
2
3import (
4 "bytes"
5 "errors"
6
7 "github.com/Lobaro/slip"
8 "go.bug.st/serial"
9)
10
11type Packet struct {
12 FrameType byte
13 Data []byte
14}
15
16type SerialEndpoint struct {
17 port serial.Port
18
19 RX <-chan Packet
20 TX chan<- []byte
21}
22
23func NewSerialEP(path string) (*SerialEndpoint, error) {
24 mode := &serial.Mode{
25 BaudRate: baudRate,
26 DataBits: 8,
27 Parity: serial.NoParity,
28 StopBits: serial.OneStopBit,
29 }
30
31 port, err := serial.Open(path, mode)
32 if err != nil {
33 return nil, err
34 }
35
36 rx := make(chan Packet)
37 tx := make(chan []byte)
38
39 ep := &SerialEndpoint{
40 port: port,
41 RX: rx,
42 TX: tx,
43 }
44
45 go ep.rcvLoop(rx)
46 go ep.sndLoop(tx)
47
48 return ep, nil
49}
50
51func (s *SerialEndpoint) sndLoop(ch <-chan []byte) {
52 writer := slip.NewSlipMuxWriter(NewSlowWriter(s.port))
53
54 for {
55 data := <-ch
56
57 err := writer.WritePacket(slip.FRAME_COAP, data)
58 if err != nil {
59 logger.Println("handleCoap:", err)
60 continue
61 }
62 }
63}
64
65func (s *SerialEndpoint) rcvLoop(ch chan<- Packet) {
66 reader := slip.NewSlipMuxReader(s.port)
67
68 for {
69 packet, frame, err := reader.ReadPacket()
70
71 var perr *serial.PortError
72 if errors.As(err, &perr) && perr.Code() == serial.PortClosed {
73 logger.Fatal("[SerialEndpoint]", err)
74 } else if err != nil {
75 logger.Println("[SerialEndpoint]", err)
76 continue
77 }
78
79 packet = bytes.TrimPrefix(packet, []byte{0})
80 ch <- Packet{frame, packet}
81 }
82}
83
84func (s *SerialEndpoint) Close() {
85 // close(s.Chan)
86 // TODO: Close TTYIO
87}