-
Notifications
You must be signed in to change notification settings - Fork 1
/
helpers.go
196 lines (185 loc) · 4.49 KB
/
helpers.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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
package hexabus
import (
"bytes"
"encoding/binary"
)
// add Hexabus packet header
func addHeader(packet []byte) {
packet[0], packet[1], packet[2], packet[3] = HEADER0, HEADER1, HEADER2, HEADER3
}
// check if a received packet contains a valid Hexabus header
func checkHeader(packet []byte) error {
if packet[0] == HEADER0 && packet[1] == HEADER1 && packet[2] == HEADER2 && packet[3] == HEADER3 {
return nil
}
return Error(0xb0)
}
// set datatype and encode payload in bytes
func encData(packet []byte, data interface{}) ([]byte, error) {
switch data := data.(type) {
case bool:
packet[10] = DTYPE_BOOL
if data == true {
packet = append(packet, TRUE)
} else {
packet = append(packet, FALSE)
}
case uint8:
packet[10] = DTYPE_UINT8
packet = append(packet, data)
case uint32:
buf := new(bytes.Buffer)
err := binary.Write(buf, binary.BigEndian, data)
if err != nil {
return nil, err
}
packet[10] = DTYPE_UINT32
packet = append(packet, buf.Bytes()...)
// DateTime: holds DTYPE_DATETIME data ; needs testing
case DateTime:
buf := new(bytes.Buffer)
err := binary.Write(buf, binary.BigEndian, data)
if err != nil {
return nil, err
}
packet[10] = DTYPE_DATETIME
packet = append(packet, buf.Bytes()...)
case float32:
buf := new(bytes.Buffer)
err := binary.Write(buf, binary.BigEndian, data)
if err != nil {
return nil, err
}
packet[10] = DTYPE_FLOAT
packet = append(packet, buf.Bytes()...)
case string:
// TODO: check if you can send smaller string length then 128 bytes
// might be the same case as in 16BYTES and 66BYTES
if len(data) > STRING_PACKET_MAX_BUFFER_LENGTH {
return nil, Error(0xa0)
} else {
// TODO: check if 0 termination in string is right that way
packet[10] = DTYPE_128STRING
packet = append(packet, data...)
packet = append(packet, byte(0))
for len(packet[11:]) < 128 {
packet = append(packet, byte(0))
}
}
// TIMESTAMP: intended for type syscall.Sysinfo_t.Uptime not working
case Timestamp:
buf := new(bytes.Buffer)
err := binary.Write(buf, binary.BigEndian, data)
if err != nil {
return nil, err
}
packet[10] = DTYPE_TIMESTAMP
packet = append(packet, buf.Bytes()...)
case []byte:
// there are only 16, 66 bytes long byte packets, they where both added to
// serve a uniq purpos, bytes with variable length is planned in the next protokoll version or so
if len(data) == 16 {
packet[10] = DTYPE_16BYTES
packet = append(packet, data...)
} else if len(data) == 65 {
packet[10] = DTYPE_66BYTES
packet = append(packet, data...)
} else {
return nil, Error(0xa2)
}
default:
packet[10] = DTYPE_UNDEFINED
return nil, Error(0xa3)
}
return packet, nil
}
// decode received Data payload
func decData(data []byte, dtype byte) (interface{}, error) {
var ret_data interface{}
switch dtype {
case DTYPE_BOOL:
if data[0] == 0x01 {
ret_data = true
} else if data[0] == 0x00 {
ret_data = false
} else {
return nil, Error(0xa4)
}
case DTYPE_UINT8:
ret_data = uint8(data[0])
case DTYPE_UINT32:
var v uint32
buf := bytes.NewBuffer(data)
err := binary.Read(buf, binary.BigEndian, &v)
if err != nil {
return nil, err
}
ret_data = v
case DTYPE_DATETIME:
var v DateTime
buf := bytes.NewBuffer(data)
err := binary.Read(buf, binary.BigEndian, &v)
if err != nil {
return nil, err
}
ret_data = v
case DTYPE_FLOAT:
var v float32
buf := bytes.NewBuffer(data)
err := binary.Read(buf, binary.BigEndian, &v)
if err != nil {
return nil, err
}
ret_data = v
case DTYPE_128STRING:
if len(data) != 128 {
return nil, Error(0xa0)
}
end := bytes.IndexByte(data, 0x00)
if end != -1 {
ret_data = string(data[0:end])
} else {
return nil, Error(0xa1)
}
case DTYPE_TIMESTAMP:
var v Timestamp
buf := bytes.NewBuffer(data)
err := binary.Read(buf, binary.BigEndian, &v)
if err != nil {
return nil, err
}
ret_data = v
case DTYPE_16BYTES:
if len(data) != 16 {
return nil, Error(0xa2)
}
ret_data = data
case DTYPE_66BYTES:
if len(data) != 65 {
return nil, Error(0xa2)
}
ret_data = data
default:
return nil, Error(0xa3)
}
return ret_data, nil
}
func PacketType(packet []byte) (ptype byte, err error) {
switch packet[4] {
case PTYPE_ERROR:
ptype = PTYPE_ERROR
case PTYPE_INFO:
ptype = PTYPE_INFO
case PTYPE_QUERY:
ptype = PTYPE_QUERY
case PTYPE_WRITE:
ptype = PTYPE_WRITE
case PTYPE_EPINFO:
ptype = PTYPE_EPINFO
case PTYPE_EPQUERY:
ptype = PTYPE_EPQUERY
default:
return 0xff, Error(0xb1)
}
return ptype, nil
}