forked from filipkroca/teltonikaparser
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathioelementsparser.go
243 lines (201 loc) · 6.92 KB
/
ioelementsparser.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
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
// Copyright 2019 Filip Kroča. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"fmt"
"github.com/filipkroca/b2n"
)
// DecodeElements take pointer to a byte slice with raw data, start Byte position and Codec ID, and returns slice of Element
func DecodeElements(bs *[]byte, start int, codecID byte) ([]Element, int, error) {
var totalElements int
codecLenDel := 1
if codecID == 0x8e {
// if Codec 8 extended is used, Event id has size 2 bytes
// Codec ID 0x08 0x8E
// AVL Data IO element length 1 Byte 2 Bytes
// AVL Data IO element total IO count length 1 Byte 2 Bytes
// AVL Data IO element IO count length 1 Byte 2 Bytes
// AVL Data IO element AVL ID length 1 Byte 2 Bytes
codecLenDel = 2
}
// parse number of elements and prepare array
if codecID == 0x8e {
x, err := b2n.ParseBs2Uint16(bs, start)
if err != nil {
return []Element{}, 0, fmt.Errorf("DecodeElements error %v", err)
}
totalElements = int(x)
} else if codecID == 0x08 {
x, err := b2n.ParseBs2Uint8(bs, start)
if err != nil {
return []Element{}, 0, fmt.Errorf("DecodeElements error %v", err)
}
totalElements = int(x)
}
totalElementsChecksum := 0
// make a slice
ElementsBS := make([]Element, 0, totalElements)
// start parsing data
nextByte := start + codecLenDel
// parse 1Byte ios
x, err := b2n.ParseBs2Uint8(bs, nextByte)
if err != nil {
return []Element{}, 0, fmt.Errorf("DecodeElements error %v", err)
}
noOfElements := int(x)
if codecID == 0x8e {
z, err := b2n.ParseBs2Uint16(bs, nextByte)
if err != nil {
return []Element{}, 0, fmt.Errorf("DecodeElements error %v", err)
}
noOfElements = int(z)
}
nextByte = nextByte + codecLenDel
for ioB := 0; ioB < noOfElements; ioB++ {
cutted, err := cutIO(bs, nextByte, codecLenDel, 1)
if err != nil {
return []Element{}, 0, fmt.Errorf("DecodeElements 1B error %v", err)
}
// append element to the returned slice
ElementsBS = append(ElementsBS, cutted)
nextByte += codecLenDel + 1
totalElementsChecksum++
}
// parse 2Byte ios
noOfElementsX, err := b2n.ParseBs2Uint8(bs, nextByte)
if err != nil {
return []Element{}, 0, fmt.Errorf("DecodeElements noOfElements 2B error %v", err)
}
noOfElements = int(noOfElementsX)
if codecID == 0x8e {
noOfElementsX, err := b2n.ParseBs2Uint16(bs, nextByte)
if err != nil {
return []Element{}, 0, fmt.Errorf("DecodeElements noOfElements 2B Extended Codec error %v", err)
}
noOfElements = int(noOfElementsX)
}
nextByte = nextByte + codecLenDel
for ioB := 0; ioB < noOfElements; ioB++ {
cutted, err := cutIO(bs, nextByte, codecLenDel, 2)
if err != nil {
return []Element{}, 0, fmt.Errorf("DecodeElements 2B error %v", err)
}
// append element to the returned slice
ElementsBS = append(ElementsBS, cutted)
nextByte += codecLenDel + 2
totalElementsChecksum++
}
// parse 4Byte ios
noOfElementsX, err = b2n.ParseBs2Uint8(bs, nextByte)
if err != nil {
return []Element{}, 0, fmt.Errorf("DecodeElements noOfElements 4B error %v", err)
}
noOfElements = int(noOfElementsX)
if codecID == 0x8e {
noOfElementsX, err := b2n.ParseBs2Uint16(bs, nextByte)
if err != nil {
return []Element{}, 0, fmt.Errorf("DecodeElements noOfElements 4B Extended Codec error %v", err)
}
noOfElements = int(noOfElementsX)
}
nextByte = nextByte + codecLenDel
for ioB := 0; ioB < noOfElements; ioB++ {
cutted, err := cutIO(bs, nextByte, codecLenDel, 4)
if err != nil {
return []Element{}, 0, fmt.Errorf("DecodeElements 4B error %v", err)
}
// append element to the returned slice
ElementsBS = append(ElementsBS, cutted)
nextByte += codecLenDel + 4
totalElementsChecksum++
}
// parse 8Byte ios
noOfElementsX, err = b2n.ParseBs2Uint8(bs, nextByte)
if err != nil {
return []Element{}, 0, fmt.Errorf("DecodeElements noOfElements 8B error %v", err)
}
noOfElements = int(noOfElementsX)
if codecID == 0x8e {
noOfElementsX, err := b2n.ParseBs2Uint16(bs, nextByte)
if err != nil {
return []Element{}, 0, fmt.Errorf("DecodeElements noOfElements 8B Extended Codec error %v", err)
}
noOfElements = int(noOfElementsX)
}
nextByte = nextByte + codecLenDel
for ioB := 0; ioB < noOfElements; ioB++ {
cutted, err := cutIO(bs, nextByte, codecLenDel, 8)
if err != nil {
return []Element{}, 0, fmt.Errorf("DecodeElements 8B error %v", err)
}
// append element to the returned slice
ElementsBS = append(ElementsBS, cutted)
nextByte += codecLenDel + 8
totalElementsChecksum++
}
if codecID == 0x8e {
// parse variableByte ios, only Codec 8 extended
noOfElementsX, err := b2n.ParseBs2Uint16(bs, nextByte)
if err != nil {
return []Element{}, 0, fmt.Errorf("DecodeElements noOfElements variableB Extended Codec error %v", err)
}
noOfElements = int(noOfElementsX)
nextByte = nextByte + codecLenDel
for ioB := 0; ioB < noOfElements; ioB++ {
cutted, err := cutIOxLen(bs, nextByte)
if err != nil {
return []Element{}, 0, fmt.Errorf("DecodeElements 2B error %v", err)
}
// append element to the returned slice
ElementsBS = append(ElementsBS, cutted)
nextByte += 4 + int(cutted.Length)
totalElementsChecksum++
}
}
if totalElementsChecksum != totalElements {
// log.Fatalf("Error when counting parsed IO Elements, want %v, got %v", totalElements, totalElementsChecksum)
return []Element{}, 0, fmt.Errorf("Error when counting parsed IO Elements, want %v, got %v", totalElements, totalElementsChecksum)
}
return ElementsBS, nextByte, nil
}
// cutIO cuts a static length elements
func cutIO(bs *[]byte, start int, idLen int, length int) (Element, error) {
curIO := Element{}
// determine length of this sized elements (num. of 1Bytes elements, num. of 2Bytes elements ...)
curIO.Length = uint16(length)
var err error
var curIOX uint8
// parse element ID according to the length of ID [1, 2] Byte
if idLen == 1 {
curIOX, err = b2n.ParseBs2Uint8(bs, start)
curIO.IOID = uint16(curIOX)
} else if idLen == 2 {
curIO.IOID, err = b2n.ParseBs2Uint16(bs, start)
}
if err != nil {
return Element{}, fmt.Errorf("cutIO error ParseBs2Uint8 or ParseBs2Uint16, %v", err)
}
if (start + idLen + length) > len(*bs) {
return Element{}, fmt.Errorf("cutIO error, want minimum length of bs %v, got %v, packet %x", start+idLen+length, len(*bs), *bs)
}
curIO.Value = (*bs)[start+idLen : start+idLen+length]
return curIO, nil
}
// cutIOxLen cuts a variable length elements
func cutIOxLen(bs *[]byte, start int) (Element, error) {
curIO := Element{}
var err error
// parse element ID according to the length of ID [1, 2] Byte
curIO.IOID, err = b2n.ParseBs2Uint16(bs, start)
if err != nil {
return Element{}, fmt.Errorf("cutIOxLen error, %v", err)
}
// determine length of this variable element
curIO.Length, err = b2n.ParseBs2Uint16(bs, start+2)
if err != nil {
return Element{}, fmt.Errorf("cutIOxLen error, %v", err)
}
curIO.Value = (*bs)[start+4 : start+4+int(curIO.Length)]
return curIO, nil
}