-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclient.go
113 lines (84 loc) · 1.91 KB
/
client.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
package hive
import (
"bufio"
"errors"
"sync"
"time"
"github.com/gosexy/to"
"github.com/tarm/serial"
"github.com/xiam/resp"
)
var (
ErrNilReply = errors.New(`Received a nil response.`)
ErrMaxReadAttemptsExceeded = errors.New(`Exceeded maximum read attempts.`)
)
var (
defaultTimeout = time.Second * 5
defaultConnectWait = time.Second * 3
maxReadAttempts = 50
maxReadAttemptsWait = 5
)
func toBytesArray(values ...interface{}) [][]byte {
cvalues := make([][]byte, len(values))
for i := 0; i < len(values); i++ {
cvalues[i] = to.Bytes(values[i])
}
return cvalues
}
type Client struct {
cfg *serial.Config
port *serial.Port
mu sync.Mutex
encoder *resp.Encoder
decoder *resp.Decoder
reader *bufio.Reader
writer *bufio.Writer
}
func NewClient(port string, speed int) (*Client, error) {
var err error
c := new(Client)
c.cfg = &serial.Config{
Name: port,
Baud: speed,
ReadTimeout: defaultTimeout,
}
if c.port, err = serial.OpenPort(c.cfg); err != nil {
return nil, err
}
c.reader = bufio.NewReader(c.port)
c.writer = bufio.NewWriter(c.port)
c.encoder = resp.NewEncoder(c.writer)
c.decoder = resp.NewDecoder(c.reader)
time.Sleep(defaultConnectWait)
return c, nil
}
func (c *Client) Command(dest interface{}, arguments ...interface{}) error {
var err error
c.mu.Lock()
defer c.mu.Unlock()
command := toBytesArray(arguments...)
if err = c.encoder.Encode(command); err != nil {
return err
}
if err = c.writer.Flush(); err != nil {
return err
}
for i := 0; ; i++ {
err = c.decoder.Decode(dest)
if err == resp.ErrInvalidInput {
time.Sleep(time.Millisecond * time.Duration(i*maxReadAttemptsWait))
} else {
break
}
if i > maxReadAttempts {
return ErrMaxReadAttemptsExceeded
}
}
if dest == nil && err == resp.ErrExpectingDestination {
return nil
}
if err == resp.ErrMessageIsNil {
return ErrNilReply
}
return err
}