/
communication.go
127 lines (105 loc) · 2.39 KB
/
communication.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package goenocean
import (
"bytes"
"encoding/binary"
"io"
"time"
"github.com/sirupsen/logrus"
serial "github.com/tarm/goserial"
)
type Encoder interface {
Encode() []byte
}
func Serial(dev string, send chan Encoder, recv chan Packet) error {
c := &serial.Config{Name: dev, Baud: 57600}
s, err := serial.OpenPort(c)
if err != nil {
return err
}
response := make(chan Packet, 100)
go readPackets(s, func(data []byte) {
reciever(data, recv, response)
})
go sender(s, send, response)
return nil
}
func sender(data io.Writer, send chan Encoder, response chan Packet) {
for p := range send {
gotResponse := make(chan struct{})
go waitForResponse(gotResponse, response)
_, err := data.Write(p.Encode())
//Dont send next until we have a response from the last one
<-gotResponse
if err != nil {
logrus.Error(err)
}
}
}
func waitForResponse(weGotResponse chan struct{}, response chan Packet) {
select {
case p := <-response:
logrus.Debugf("We got response after send: % x\n", p.Encode())
if !bytes.Equal(p.Data(), []byte{0}) {
logrus.Errorf("We got RESPONSE error after send: % x\n", p.Encode())
}
weGotResponse <- struct{}{}
return
case <-time.After(time.Second * 2):
logrus.Error("We got TIMOUT after send")
weGotResponse <- struct{}{}
return
}
}
func reciever(data []byte, recv chan Packet, resp chan Packet) {
p, err := Decode(data)
logrus.Debugf("%#v\n", p)
logrus.Debugf("%#v\n", p.Header())
logrus.Debugf("Data: %#v\n", p.Data())
if err != nil {
logrus.Error("Decode failed :", err)
return
}
if p.PacketType() == PacketTypeResponse {
select { // Nonblocking send just in case
case resp <- p:
default:
}
}
recv <- p
}
func readPackets(rd io.Reader, f func([]byte)) {
buf := make([]byte, 1)
var rawPacket []byte
state := 0
var length int
for {
readLen, err := rd.Read(buf)
if err != nil {
if err == io.EOF {
return
}
logrus.Error("ERROR reading:", err)
continue
}
logrus.Debugf("% x ", buf)
if readLen > 0 && buf[0] == 0x55 && state == 0 {
rawPacket = []byte{}
state = 1
}
rawPacket = append(rawPacket, buf...)
switch state {
case 1: //header
if len(rawPacket) > 5 {
length = int(binary.BigEndian.Uint16(rawPacket[1:3]))
state = 2
}
case 2: // the rest!
if len(rawPacket) > 5+length+int(rawPacket[3]) {
state = 3
}
case 3: //data crc
state = 0
f(rawPacket)
}
}
}