queclink-parser 1.9.6 → 1.9.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/gv57cg.js ADDED
@@ -0,0 +1,2464 @@
1
+ 'use strict'
2
+ const utils = require('./utils.js')
3
+
4
+ /*
5
+ Parses messages data from GV58LAU devices
6
+ */
7
+ const parse = raw => {
8
+ raw = raw.substr(0, raw.length - 1)
9
+
10
+ const parsedData = raw.split(',')
11
+ const command = parsedData[0].split(':')
12
+
13
+ let history = false
14
+ if (utils.patterns.buffer.test(command[0])) {
15
+ history = true
16
+ }
17
+
18
+ let data = {
19
+ raw: `${raw.toString()}$`,
20
+ manufacturer: 'queclink',
21
+ device: 'Queclink-GV57CG',
22
+ type: 'data',
23
+ imei: parsedData[2],
24
+ protocolVersion: utils.getProtocolVersion(parsedData[1]),
25
+ // temperature: null,
26
+ history: history,
27
+ sentTime: utils.parseDate(parsedData[parsedData.length - 2]),
28
+ serialId: parseInt(parsedData[parsedData.length - 1], 16)
29
+ }
30
+
31
+ // Gps
32
+ if (command[1] === 'GTFRI') {
33
+ try {
34
+ let number = parsedData[6] !== '' ? parseInt(parsedData[6], 10) : 1
35
+ let satelliteInfo = utils.includeSatellites(parsedData[18])
36
+ let gnssInfo = utils.includeGnssTrigger(parsedData[18])
37
+ let index = 6 + (12 + satelliteInfo + gnssInfo) * number + 1
38
+
39
+ data = Object.assign(data, {
40
+ alarm: utils.getAlarm(command[1], null),
41
+ loc: {
42
+ type: 'Point',
43
+ coordinates: [parseFloat(parsedData[11]), parseFloat(parsedData[12])]
44
+ },
45
+ speed: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
46
+ gpsStatus: utils.checkGps(
47
+ parseFloat(parsedData[11]),
48
+ parseFloat(parsedData[12])
49
+ ),
50
+ hdop: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
51
+ status: {
52
+ raw: parsedData[index + 6],
53
+ sos: false,
54
+ input: {
55
+ '2':
56
+ utils.nHexDigit(
57
+ utils.hex2bin(parsedData[index + 6].substring(2, 4)),
58
+ 8
59
+ )[7] === '1',
60
+ '1':
61
+ utils.nHexDigit(
62
+ utils.hex2bin(parsedData[index + 6].substring(2, 4)),
63
+ 8
64
+ )[6] === '1'
65
+ },
66
+ output: {
67
+ '3':
68
+ utils.nHexDigit(
69
+ utils.hex2bin(parsedData[index + 6].substring(4, 6)),
70
+ 8
71
+ )[5] === '1',
72
+ '2':
73
+ utils.nHexDigit(
74
+ utils.hex2bin(parsedData[index + 6].substring(4, 6)),
75
+ 8
76
+ )[6] === '1',
77
+ '1':
78
+ utils.nHexDigit(
79
+ utils.hex2bin(parsedData[index + 6].substring(4, 6)),
80
+ 8
81
+ )[7] === '1'
82
+ },
83
+ charge: parseFloat(parsedData[4]) > 5,
84
+ state: utils.states[parsedData[index + 6].substring(0, 2)]
85
+ },
86
+ azimuth: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
87
+ altitude: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
88
+ datetime:
89
+ parsedData[13] !== '' ? utils.parseDate(parsedData[13]) : null,
90
+ voltage: {
91
+ battery: parsedData[index + 5] !== ''
92
+ ? parseFloat(parsedData[index + 5])
93
+ : null,
94
+ inputCharge:
95
+ parsedData[4] !== '' ? parseFloat(parsedData[4]) / 1000 : null
96
+ },
97
+ mcc: parsedData[14] !== '' ? utils.latamMcc[parseInt(parsedData[14], 10)] : null,
98
+ mnc: parsedData[15] !== '' ? utils.getMNC(parsedData[14], parsedData[15]) : null,
99
+ lac: parsedData[16] !== '' ? parseInt(parsedData[16], 16) : null,
100
+ cid: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
101
+ satellites:
102
+ satelliteInfo && parsedData[index - (satelliteInfo + gnssInfo)] !== ''
103
+ ? parseInt(parsedData[index - (satelliteInfo + gnssInfo)], 10)
104
+ : null,
105
+ gnssTrigger:
106
+ gnssInfo && parsedData[index - gnssInfo] !== ''
107
+ ? utils.gnssTriggerTypes[parsedData[index - gnssInfo]]
108
+ : null,
109
+ odometer:
110
+ parsedData[index] !== '' ? parseFloat(parsedData[index]) : null,
111
+ hourmeter:
112
+ parsedData[index + 1] !== ''
113
+ ? utils.getHoursForHourmeter(parsedData[index + 1])
114
+ : null
115
+ })
116
+
117
+ // More than 1 GNSS report in data
118
+ if (number > 1) {
119
+ let moreData = []
120
+ for (let i = 1; i < number; i++) {
121
+ let gnssIx = 7 + (12 + gnssInfo + satelliteInfo) * i
122
+
123
+ moreData.push({
124
+ index: i,
125
+ loc: {
126
+ type: 'Point',
127
+ coordinates: [
128
+ parseFloat(parsedData[gnssIx + 4]),
129
+ parseFloat(parsedData[gnssIx + 5])
130
+ ]
131
+ },
132
+ speed:
133
+ parsedData[gnssIx + 1] !== ''
134
+ ? parseFloat(parsedData[gnssIx + 1])
135
+ : null,
136
+ gpsStatus: utils.checkGps(
137
+ parseFloat(parsedData[gnssIx + 4]),
138
+ parseFloat(parsedData[gnssIx + 5])
139
+ ),
140
+ hdop:
141
+ parsedData[gnssIx] !== '' ? parseFloat(parsedData[gnssIx]) : null,
142
+ azimuth:
143
+ parsedData[gnssIx + 2] !== ''
144
+ ? parseFloat(parsedData[gnssIx + 2])
145
+ : null,
146
+ altitude:
147
+ parsedData[gnssIx + 3] !== ''
148
+ ? parseFloat(parsedData[gnssIx + 3])
149
+ : null,
150
+ datetime:
151
+ parsedData[gnssIx + 6] !== ''
152
+ ? utils.parseDate(parsedData[gnssIx + 6])
153
+ : null,
154
+ mcc:
155
+ parsedData[gnssIx + 7] !== ''
156
+ ? parseInt(parsedData[gnssIx + 7], 10)
157
+ : null,
158
+ mnc:
159
+ parsedData[gnssIx + 8] !== ''
160
+ ? parseInt(parsedData[gnssIx + 8], 10)
161
+ : null,
162
+ lac:
163
+ parsedData[gnssIx + 9] !== ''
164
+ ? parseInt(parsedData[gnssIx + 9], 16)
165
+ : null,
166
+ cid:
167
+ parsedData[gnssIx + 10] !== ''
168
+ ? parseInt(parsedData[gnssIx + 10], 16)
169
+ : null,
170
+ satellites:
171
+ satelliteInfo && parsedData[gnssIx + satelliteInfo + 11] !== ''
172
+ ? parseInt(parsedData[gnssIx + satelliteInfo + 11], 10)
173
+ : null,
174
+ gnssTrigger:
175
+ gnssInfo &&
176
+ parsedData[gnssIx + satelliteInfo + gnssInfo + 11] !== ''
177
+ ? utils.gnssTriggerTypes[
178
+ parsedData[gnssIx + satelliteInfo + gnssInfo + 11]
179
+ ]
180
+ : null
181
+ })
182
+ }
183
+
184
+ data = Object.assign(data, { moreData: moreData })
185
+ }
186
+ } catch (err) {
187
+ return { type: 'UNKNOWN', raw: data.raw.toString() }
188
+ }
189
+ } else if (command[1] === 'GTERI') {
190
+ // GPS with AC100 and/or Bluetoth Devices Connected
191
+ let number = parsedData[7] !== '' ? parseInt(parsedData[7], 10) : 1
192
+ let satelliteInfo = utils.includeSatellites(parsedData[19])
193
+ let gnssInfo = utils.includeGnssTrigger(parsedData[19])
194
+ let index = 7 + (12 + satelliteInfo + gnssInfo) * number + 1
195
+
196
+ data = Object.assign(data, {
197
+ alarm: utils.getAlarm(command[1], null),
198
+ loc: {
199
+ type: 'Point',
200
+ coordinates: [parseFloat(parsedData[12]), parseFloat(parsedData[13])]
201
+ },
202
+ speed: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
203
+ gpsStatus: utils.checkGps(
204
+ parseFloat(parsedData[12]),
205
+ parseFloat(parsedData[13])
206
+ ),
207
+ hdop: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
208
+ status: {
209
+ raw: parsedData[index + 6],
210
+ sos: false,
211
+ input: {
212
+ '2':
213
+ utils.nHexDigit(
214
+ utils.hex2bin(parsedData[index + 6].substring(2, 4)),
215
+ 8
216
+ )[7] === '1',
217
+ '1':
218
+ utils.nHexDigit(
219
+ utils.hex2bin(parsedData[index + 6].substring(2, 4)),
220
+ 8
221
+ )[6] === '1'
222
+ },
223
+ output: {
224
+ '3':
225
+ utils.nHexDigit(
226
+ utils.hex2bin(parsedData[index + 6].substring(4, 6)),
227
+ 8
228
+ )[5] === '1',
229
+ '2':
230
+ utils.nHexDigit(
231
+ utils.hex2bin(parsedData[index + 6].substring(4, 6)),
232
+ 8
233
+ )[6] === '1',
234
+ '1':
235
+ utils.nHexDigit(
236
+ utils.hex2bin(parsedData[index + 6].substring(4, 6)),
237
+ 8
238
+ )[7] === '1'
239
+ },
240
+ charge: parseFloat(parsedData[5]) > 5,
241
+ state: utils.states[parsedData[index + 6].substring(0, 2)]
242
+ },
243
+ azimuth: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
244
+ altitude: parsedData[11] !== '' ? parseFloat(parsedData[11]) : null,
245
+ datetime: parsedData[14] !== '' ? utils.parseDate(parsedData[14]) : null,
246
+ voltage: {
247
+ battery:
248
+ parsedData[index + 5] !== ''
249
+ ? parseFloat(parsedData[index + 5])
250
+ : null, // percentage
251
+ inputCharge:
252
+ parsedData[5] !== '' ? parseFloat(parsedData[5]) / 1000 : null
253
+ },
254
+ mcc: parsedData[15] !== '' ? utils.latamMcc[parseInt(parsedData[15], 10)] : null,
255
+ mnc: parsedData[16] !== '' ? utils.getMNC(parsedData[15], parsedData[16]) : null,
256
+ lac: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
257
+ cid: parsedData[18] !== '' ? parseInt(parsedData[18], 16) : null,
258
+ satellites:
259
+ satelliteInfo && parsedData[index - (satelliteInfo + gnssInfo)] !== ''
260
+ ? parseInt(parsedData[index - (satelliteInfo + gnssInfo)], 10)
261
+ : null,
262
+ gnssTrigger:
263
+ gnssInfo && parsedData[index - gnssInfo] !== ''
264
+ ? utils.gnssTriggerTypes[parsedData[index - gnssInfo]]
265
+ : null,
266
+ odometer: parsedData[index] !== '' ? parseFloat(parsedData[index]) : null,
267
+ hourmeter:
268
+ parsedData[index + 1] !== ''
269
+ ? utils.getHoursForHourmeter(parsedData[index + 1])
270
+ : null
271
+ })
272
+ // External Data
273
+ const canData = utils.nHexDigit(utils.hex2bin(parsedData[4]), 32)[8] === '1'
274
+ const bandData = utils.nHexDigit(utils.hex2bin(parsedData[4]), 32)[16] === '1'
275
+
276
+ let externalData = {
277
+ eriMask: {
278
+ raw: parsedData[4],
279
+ canData: canData,
280
+ bandData: bandData
281
+ }
282
+ }
283
+
284
+ // TO-DO: agregar datos de bandData
285
+
286
+ // Bluetooth Accessories
287
+ // if (bluetoothAccessory) {
288
+ // let btDevices = []
289
+ // let btIndex
290
+
291
+ // if (canData) {
292
+ // btIndex = index + 57
293
+ // } else {
294
+ // btIndex = index + 8
295
+ // }
296
+
297
+ // let cnt = btIndex + 1
298
+ // let btNum = parsedData[btIndex] !== '' ? parseInt(parsedData[btIndex]) : 1
299
+
300
+ // for (let c = 0; c < btNum; c++) {
301
+ // let appendMask = utils.nHexDigit(utils.hex2bin(parsedData[cnt + 4]), 16)
302
+
303
+ // let aNameIx = cnt + 4 + parseInt(appendMask[15])
304
+ // let aMacIx = aNameIx + parseInt(appendMask[14])
305
+ // let aStatIx = aMacIx + parseInt(appendMask[13])
306
+ // let aBatIx = aStatIx + parseInt(appendMask[12])
307
+ // let aTmpIx = aBatIx + parseInt(appendMask[11])
308
+ // let aHumIx = aTmpIx + parseInt(appendMask[10])
309
+ // let ioIx = aHumIx + parseInt(appendMask[8])
310
+ // let modeIx =
311
+ // appendMask[8] === '1' ? ioIx + 2 + parseInt(appendMask[7]) : ioIx
312
+ // let aEvIx = appendMask[7] === '1' ? modeIx + 1 : modeIx
313
+ // let pressIx = aEvIx + parseInt(appendMask[6])
314
+ // let timeIx = pressIx + parseInt(appendMask[5])
315
+ // let eTmpIx = timeIx + parseInt(appendMask[4])
316
+ // let magIx = eTmpIx + parseInt(appendMask[3])
317
+ // let aBatpIx =
318
+ // appendMask[3] === '1' ? magIx + 2 + parseInt(appendMask[2]) : eTmpIx
319
+ // let relIx = aBatpIx + parseInt(appendMask[1])
320
+
321
+ // btDevices.push({
322
+ // index: parsedData[cnt],
323
+ // type: utils.bluetoothAccessories[parsedData[cnt + 1]],
324
+ // model:
325
+ // parsedData[cnt + 2] !== ''
326
+ // ? utils.bluetoothModels[parsedData[cnt + 1]][parsedData[cnt + 2]]
327
+ // : utils.bluetoothAccessories[parsedData[cnt + 1]],
328
+ // appendMask: parsedData[cnt + 4],
329
+ // rawData:
330
+ // parsedData[cnt + 3] !== ''
331
+ // ? {
332
+ // raw: parsedData[cnt + 3],
333
+ // fuelLevel:
334
+ // `${parsedData[cnt + 1]}${parsedData[cnt + 2]}` === '10'
335
+ // ? parsedData[cnt + 3]
336
+ // : null,
337
+ // temperature:
338
+ // `${parsedData[cnt + 1]}${parsedData[cnt + 2]}` === '20'
339
+ // ? utils.getBtTempHumData(
340
+ // parsedData[cnt + 3].substring(4, 8)
341
+ // )
342
+ // : `${parsedData[cnt + 1]}${parsedData[cnt + 2]}` === '21'
343
+ // ? parsedData[cnt + 3] // Conversion not specified in documentation
344
+ // : `${parsedData[cnt + 1]}${parsedData[cnt + 2]}` ===
345
+ // '62'
346
+ // ? utils.getBtTempHumData(
347
+ // parsedData[cnt + 3].substring(0, 4)
348
+ // )
349
+ // : ['64', '65'].includes(
350
+ // `${parsedData[cnt + 1]}${parsedData[cnt + 2]}`
351
+ // )
352
+ // ? parseInt(
353
+ // parsedData[cnt + 3].substring(4, 8),
354
+ // 16
355
+ // ) / 100
356
+ // : null,
357
+ // humidity:
358
+ // `${parsedData[cnt + 1]}${parsedData[cnt + 2]}` === '20'
359
+ // ? utils.getBtTempHumData(
360
+ // parsedData[cnt + 3].substring(4, 8)
361
+ // )
362
+ // : `${parsedData[cnt + 1]}${parsedData[cnt + 2]}` === '62'
363
+ // ? utils.getBtTempHumData(
364
+ // parsedData[cnt + 3].substring(4, 8)
365
+ // )
366
+ // : ['64', '65'].includes(
367
+ // `${parsedData[cnt + 1]}${parsedData[cnt + 2]}`
368
+ // )
369
+ // ? parseInt(parsedData[cnt + 3].substring(0, 4), 16) /
370
+ // 100
371
+ // : null
372
+ // }
373
+ // : null,
374
+ // name:
375
+ // parsedData[aNameIx] !== '' && appendMask[15] === '1'
376
+ // ? parsedData[aNameIx]
377
+ // : null,
378
+ // mac:
379
+ // parsedData[aMacIx] !== '' && appendMask[14] === '1'
380
+ // ? parsedData[aMacIx]
381
+ // : null,
382
+ // status:
383
+ // parsedData[aStatIx] !== '' && appendMask[13] === '1'
384
+ // ? parseInt(parsedData[aStatIx])
385
+ // : null,
386
+ // batteryLevel:
387
+ // parsedData[aBatIx] !== '' && appendMask[12] === '1'
388
+ // ? parseInt(parsedData[aBatIx])
389
+ // : null,
390
+ // batteryPercentage:
391
+ // parsedData[aBatpIx] !== '' && appendMask[2] === '1'
392
+ // ? parseFloat(parsedData[aBatpIx])
393
+ // : null,
394
+ // accessoryData: {
395
+ // rawData: parsedData[cnt + 3] !== '' ? parsedData[cnt + 3] : null,
396
+ // temperature:
397
+ // parsedData[aTmpIx] !== '' && appendMask[11] === '1'
398
+ // ? parseInt(parsedData[aTmpIx])
399
+ // : null,
400
+ // humidity:
401
+ // parsedData[aHumIx] !== '' && appendMask[10] === '1'
402
+ // ? parseInt(parsedData[aHumIx])
403
+ // : null,
404
+ // outputStatus:
405
+ // parsedData[ioIx] !== '' && appendMask[8] === '1'
406
+ // ? parsedData[ioIx]
407
+ // : null,
408
+ // inputStatus:
409
+ // parsedData[ioIx + 1] !== '' && appendMask[8] === '1'
410
+ // ? parsedData[ioIx + 1]
411
+ // : null,
412
+ // analogInputStatus:
413
+ // parsedData[ioIx + 2] !== '' && appendMask[8] === '1'
414
+ // ? parsedData[ioIx + 2]
415
+ // : null,
416
+ // mode:
417
+ // parsedData[modeIx] !== '' && appendMask[7] === '1'
418
+ // ? parseInt(parsedData[modeIx])
419
+ // : null,
420
+ // event:
421
+ // parsedData[aEvIx] !== '' && appendMask[7] === '1'
422
+ // ? parseInt(parsedData[aEvIx])
423
+ // : null,
424
+ // tirePresure:
425
+ // parsedData[pressIx] !== '' && appendMask[6] === '1'
426
+ // ? parseInt(parsedData[pressIx])
427
+ // : null,
428
+ // timestamp:
429
+ // parsedData[timeIx] !== '' && appendMask[5] === '1'
430
+ // ? utils.parseDate(parsedData[timeIx])
431
+ // : null,
432
+ // enhancedTemperature:
433
+ // parsedData[eTmpIx] !== '' && appendMask[4] === '1'
434
+ // ? parseFloat(parsedData[eTmpIx])
435
+ // : null,
436
+ // magDevice: {
437
+ // id:
438
+ // parsedData[magIx] !== '' && appendMask[3] === '1'
439
+ // ? parsedData[magIx]
440
+ // : null,
441
+ // eventCounter:
442
+ // parsedData[magIx + 1] !== '' && appendMask[3] === '1'
443
+ // ? parseInt(parsedData[magIx + 1])
444
+ // : null,
445
+ // magnetState:
446
+ // parsedData[magIx + 2] !== '' && appendMask[3] === '1'
447
+ // ? parseInt(parsedData[magIx + 2])
448
+ // : null
449
+ // },
450
+ // relay: {
451
+ // state:
452
+ // parsedData[relIx] !== '' && appendMask[1] === '1'
453
+ // ? parseInt(parsedData[relIx])
454
+ // : null
455
+ // }
456
+ // }
457
+ // })
458
+ // cnt = appendMask[1] === '1' ? relIx + 1 : relIx + 2
459
+ // cnt = parsedData[cnt + 3] !== '' ? cnt - 1 : cnt
460
+ // }
461
+ // externalData = Object.assign(externalData, {
462
+ // btDevices: btDevices
463
+ // })
464
+ // }
465
+
466
+ data = Object.assign(data, {
467
+ externalData: externalData
468
+ })
469
+
470
+ // More than 1 GNSS report in data
471
+ if (number > 1) {
472
+ let moreData = []
473
+ for (let i = 1; i < number; i++) {
474
+ let gnssIx = 8 + (12 + gnssInfo + satelliteInfo) * i
475
+ moreData.push({
476
+ index: i,
477
+ loc: {
478
+ type: 'Point',
479
+ coordinates: [
480
+ parseFloat(parsedData[gnssIx + 4]),
481
+ parseFloat(parsedData[gnssIx + 5])
482
+ ]
483
+ },
484
+ speed:
485
+ parsedData[gnssIx + 1] !== ''
486
+ ? parseFloat(parsedData[gnssIx + 1])
487
+ : null,
488
+ gpsStatus: utils.checkGps(
489
+ parseFloat(parsedData[gnssIx + 4]),
490
+ parseFloat(parsedData[gnssIx + 5])
491
+ ),
492
+ hdop:
493
+ parsedData[gnssIx] !== '' ? parseFloat(parsedData[gnssIx]) : null,
494
+ azimuth:
495
+ parsedData[gnssIx + 2] !== ''
496
+ ? parseFloat(parsedData[gnssIx + 2])
497
+ : null,
498
+ altitude:
499
+ parsedData[gnssIx + 3] !== ''
500
+ ? parseFloat(parsedData[gnssIx + 3])
501
+ : null,
502
+ datetime:
503
+ parsedData[gnssIx + 6] !== ''
504
+ ? utils.parseDate(parsedData[gnssIx + 6])
505
+ : null,
506
+ mcc:
507
+ parsedData[gnssIx + 7] !== ''
508
+ ? parseInt(parsedData[gnssIx + 7], 10)
509
+ : null,
510
+ mnc:
511
+ parsedData[gnssIx + 8] !== ''
512
+ ? parseInt(parsedData[gnssIx + 8], 10)
513
+ : null,
514
+ lac:
515
+ parsedData[gnssIx + 9] !== ''
516
+ ? parseInt(parsedData[gnssIx + 9], 16)
517
+ : null,
518
+ cid:
519
+ parsedData[gnssIx + 10] !== ''
520
+ ? parseInt(parsedData[gnssIx + 10], 16)
521
+ : null,
522
+ satellites:
523
+ satelliteInfo && parsedData[gnssIx + satelliteInfo + 11] !== ''
524
+ ? parseInt(parsedData[gnssIx + satelliteInfo + 11], 10)
525
+ : null,
526
+ gnssTrigger:
527
+ gnssInfo &&
528
+ parsedData[gnssIx + satelliteInfo + gnssInfo + 11] !== ''
529
+ ? utils.gnssTriggerTypes[
530
+ parsedData[gnssIx + satelliteInfo + gnssInfo + 11]
531
+ ]
532
+ : null
533
+ })
534
+ }
535
+
536
+ data = Object.assign(data, { moreData: moreData })
537
+ }
538
+ } else if (command[1] === 'GTHBD') {
539
+ // Heartbeat. It must response an ACK command
540
+ data = Object.assign(data, {
541
+ alarm: utils.getAlarm(command[1], null)
542
+ })
543
+ } else if (command[1] === 'GTINF') {
544
+ // General Info Report
545
+ data = Object.assign(data, {
546
+ alarm: utils.getAlarm(command[1], null),
547
+ state: utils.states[parsedData[4]],
548
+ gsmInfo: {
549
+ SIM_ICC: parsedData[5] !== '' ? parsedData[5] : null,
550
+ networkType:
551
+ parsedData[10] !== '' ? utils.networkTypes[parsedData[10]] : null,
552
+ RSSI: parsedData[6] !== '' ? parseInt(parsedData[6], 10) : null,
553
+ RSSI_quality:
554
+ parsedData[10] !== ''
555
+ ? utils.getSignalStrength(
556
+ utils.networkTypes[parsedData[10]],
557
+ parseInt(parsedData[6], 10)
558
+ )
559
+ : null, // Signal Strength
560
+ RSSI_percentage:
561
+ parsedData[10] !== ''
562
+ ? utils.getSignalPercentage(
563
+ utils.networkTypes[parsedData[10]],
564
+ parseInt(parsedData[6], 10)
565
+ )
566
+ : null, // Signal Percetange
567
+ GSM_quality:
568
+ parsedData[7] !== ''
569
+ ? 100 * parseInt(parseFloat(parsedData[7]) / 7, 10)
570
+ : null // Percentage
571
+ },
572
+ backupBattery: {
573
+ using: parsedData[11] !== '' && parseFloat(parsedData[11]) < 4.5,
574
+ voltage: parsedData[11] !== '' ? parseFloat(parsedData[11]) : null,
575
+ charging: parsedData[12] === '1'
576
+ },
577
+ externalGPSAntenna: null,
578
+ status: {
579
+ raw: `${parsedData[21]}${parsedData[22]}`,
580
+ sos: false,
581
+ input: {
582
+ '2': utils.nHexDigit(utils.hex2bin(parsedData[21]), 8)[7] === '1',
583
+ '1': utils.nHexDigit(utils.hex2bin(parsedData[21]), 8)[6] === '1'
584
+ },
585
+ output: {
586
+ '3': utils.nHexDigit(utils.hex2bin(parsedData[22]), 8)[5] === '1',
587
+ '2': utils.nHexDigit(utils.hex2bin(parsedData[22]), 8)[6] === '1',
588
+ '1': utils.nHexDigit(utils.hex2bin(parsedData[22]), 8)[7] === '1'
589
+ },
590
+ charge: parsedData[12] === '1'
591
+ },
592
+ voltage: {
593
+ battery:
594
+ parsedData[11] !== ''
595
+ ? parseInt(100 * (parseFloat(parsedData[11]) / 4.5), 10)
596
+ : null, // percentage
597
+ inputCharge:
598
+ parsedData[9] !== '' ? parseFloat(parsedData[9]) / 1000 : null
599
+ },
600
+ lastFixUTCTime:
601
+ parsedData[16] !== '' ? utils.parseDate(parsedData[16]) : null,
602
+ timezoneOffset: parsedData[23]
603
+ })
604
+ } else if (
605
+ command[1] === 'GTTOW' ||
606
+ command[1] === 'GTDIS' ||
607
+ command[1] === 'GTIOB' ||
608
+ command[1] === 'GTSPD' ||
609
+ command[1] === 'GTSOS' ||
610
+ command[1] === 'GTRTL' ||
611
+ command[1] === 'GTDOG' ||
612
+ command[1] === 'GTIGL' ||
613
+ command[1] === 'GTVGL' ||
614
+ command[1] === 'GTHBM'
615
+ ) {
616
+ // Common Alarms
617
+ let number = parsedData[6] !== '' ? parseInt(parsedData[6], 10) : 1
618
+ let index = 6 + 12 * number // position append mask
619
+ let satelliteInfo = false
620
+
621
+ // If get satellites is configured
622
+ if (utils.includeSatellites(parsedData[index])) {
623
+ index += 1
624
+ satelliteInfo = true
625
+ }
626
+
627
+ data = Object.assign(data, {
628
+ alarm: utils.getAlarm(command[1], parsedData[5], 'gv58lau'),
629
+ loc: {
630
+ type: 'Point',
631
+ coordinates: [parseFloat(parsedData[11]), parseFloat(parsedData[12])]
632
+ },
633
+ speed: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
634
+ gpsStatus: utils.checkGps(
635
+ parseFloat(parsedData[11]),
636
+ parseFloat(parsedData[12])
637
+ ),
638
+ hdop: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
639
+ azimuth: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
640
+ altitude: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
641
+ datetime: parsedData[13] !== '' ? utils.parseDate(parsedData[13]) : null,
642
+ // voltage: {
643
+ // battery: null,
644
+ // inputCharge: null
645
+ // },
646
+ mcc: parsedData[14] !== '' ? utils.latamMcc[parseInt(parsedData[14], 10)] : null,
647
+ mnc: parsedData[15] !== '' ? utils.getMNC(parsedData[14], parsedData[15]) : null,
648
+ lac: parsedData[16] !== '' ? parseInt(parsedData[16], 16) : null,
649
+ cid: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
650
+ satellites:
651
+ satelliteInfo && parsedData[index] !== ''
652
+ ? parseInt(parsedData[index])
653
+ : null,
654
+ // status: includeStatus
655
+ // ? {
656
+ // raw: parsedData[index + 1],
657
+ // sos: false,
658
+ // input: {
659
+ // '2':
660
+ // utils.nHexDigit(
661
+ // utils.hex2bin(parsedData[index + 1].substring(2, 4)),
662
+ // 8
663
+ // )[7] === '1',
664
+ // '1':
665
+ // utils.nHexDigit(
666
+ // utils.hex2bin(parsedData[index + 1].substring(2, 4)),
667
+ // 8
668
+ // )[6] === '1'
669
+ // },
670
+ // output: {
671
+ // '3':
672
+ // utils.nHexDigit(
673
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
674
+ // 8
675
+ // )[5] === '1',
676
+ // '2':
677
+ // utils.nHexDigit(
678
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
679
+ // 8
680
+ // )[6] === '1',
681
+ // '1':
682
+ // utils.nHexDigit(
683
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
684
+ // 8
685
+ // )[7] === '1'
686
+ // },
687
+ // charge: null,
688
+ // state: utils.states[parsedData[index + 1].substring(0, 2)]
689
+ // }
690
+ // : null,
691
+ odometer: parsedData[index + 1] !== ''
692
+ ? parseFloat(parsedData[index + 1])
693
+ : null,
694
+ // hourmeter: null
695
+ })
696
+ } else if (command[1] === 'GTEPS' || command[1] === 'GTAIS') {
697
+ // External low battery and Low voltage for analog input
698
+ let number = parsedData[6] !== '' ? parseInt(parsedData[6], 10) : 1
699
+ let index = 6 + 12 * number // position append mask
700
+ let satelliteInfo = false
701
+
702
+ // If get satellites is configured
703
+ if (utils.includeSatellites(parsedData[18])) {
704
+ index += 1
705
+ satelliteInfo = true
706
+ }
707
+
708
+ data = Object.assign(data, {
709
+ alarm: utils.getAlarm(command[1], parsedData[5]),
710
+ loc: {
711
+ type: 'Point',
712
+ coordinates: [parseFloat(parsedData[11]), parseFloat(parsedData[12])]
713
+ },
714
+ speed: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
715
+ gpsStatus: utils.checkGps(
716
+ parseFloat(parsedData[11]),
717
+ parseFloat(parsedData[12])
718
+ ),
719
+ hdop: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
720
+ // status: null,
721
+ azimuth: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
722
+ altitude: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
723
+ datetime: parsedData[13] !== '' ? utils.parseDate(parsedData[13]) : null,
724
+ voltage: {
725
+ battery: parsedData[4] !== '' ? parseFloat(parsedData[4]) / 1000 : null,
726
+ inputCharge: null
727
+ },
728
+ mcc: parsedData[14] !== '' ? utils.latamMcc[parseInt(parsedData[14], 10)] : null,
729
+ mnc: parsedData[15] !== '' ? utils.getMNC(parsedData[14], parsedData[15]) : null,
730
+ lac: parsedData[16] !== '' ? parseInt(parsedData[16], 16) : null,
731
+ cid: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
732
+ satellites:
733
+ satelliteInfo && parsedData[index] !== ''
734
+ ? parseInt(parsedData[index])
735
+ : null,
736
+ odometer:
737
+ parsedData[index + 1] !== '' ? parseFloat(parsedData[index + 1]) : null,
738
+ // hourmeter: null
739
+ })
740
+ } else if (
741
+ command[1] === 'GTPNA' ||
742
+ command[1] === 'GTPFA' ||
743
+ command[1] === 'GTPDP'
744
+ ) {
745
+ // Event report (It uses the last GPS data and MCC info)
746
+ data = Object.assign(data, {
747
+ alarm: utils.getAlarm(command[1], null),
748
+ // loc: null,
749
+ // speed: null,
750
+ // gpsStatus: null,
751
+ // hdop: null,
752
+ // status: null,
753
+ // azimuth: null,
754
+ // altitude: null,
755
+ datetime: parsedData[4] !== '' ? utils.parseDate(parsedData[4]) : null,
756
+ // voltage: {
757
+ // battery: null,
758
+ // inputCharge: null
759
+ // },
760
+ // mcc: null,
761
+ // mnc: null,
762
+ // lac: null,
763
+ // cid: null,
764
+ // odometer: null,
765
+ // hourmeter: null
766
+ })
767
+ } else if (command[1] === 'GTPNR' || command[1] === 'GTPFR') {
768
+ // Power on/off reason
769
+ data = Object.assign(data, {
770
+ alarm: utils.getAlarm(command[1], parsedData[4]),
771
+ datetime: parsedData[9] !== '' ? utils.parseDate(parsedData[9]) : null
772
+ })
773
+ } else if (
774
+ command[1] === 'GTMPN' ||
775
+ command[1] === 'GTMPF' ||
776
+ command[1] === 'GTBTC' ||
777
+ command[1] === 'GTDRM'
778
+ ) {
779
+ var index = 15
780
+ let satelliteInfo = false
781
+ // let includeStatus =
782
+ // parsedData[index] !== '' ? parseInt(parsedData[index]) > 3 : null
783
+
784
+ // If get satellites is configured
785
+ if (utils.includeSatellites(parsedData[index])) {
786
+ index += 1
787
+ satelliteInfo = true
788
+ }
789
+
790
+ data = Object.assign(data, {
791
+ alarm: utils.getAlarm(command[1], null),
792
+ loc: {
793
+ type: 'Point',
794
+ coordinates: [parseFloat(parsedData[8]), parseFloat(parsedData[9])]
795
+ },
796
+ speed: parsedData[5] !== '' ? parseFloat(parsedData[5]) : null,
797
+ gpsStatus: utils.checkGps(
798
+ parseFloat(parsedData[8]),
799
+ parseFloat(parsedData[9])
800
+ ),
801
+ hdop: parsedData[4] !== '' ? parseFloat(parsedData[4]) : null,
802
+ azimuth: parsedData[6] !== '' ? parseFloat(parsedData[6]) : null,
803
+ altitude: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
804
+ datetime: parsedData[10] !== '' ? utils.parseDate(parsedData[10]) : null,
805
+ // voltage: {
806
+ // battery: null,
807
+ // inputCharge: null
808
+ // },
809
+ mcc: parsedData[11] !== '' ? utils.latamMcc[parseInt(parsedData[11], 10)] : null,
810
+ mnc: parsedData[12] !== '' ? utils.getMNC(parsedData[11], parsedData[12]) : null,
811
+ lac: parsedData[13] !== '' ? parseInt(parsedData[13], 16) : null,
812
+ cid: parsedData[14] !== '' ? parseInt(parsedData[14], 16) : null,
813
+ satellites:
814
+ satelliteInfo && parsedData[index] !== ''
815
+ ? parseInt(parsedData[index])
816
+ : null,
817
+ // status: includeStatus
818
+ // ? {
819
+ // raw: parsedData[index + 1],
820
+ // sos: false,
821
+ // input: {
822
+ // '2':
823
+ // utils.nHexDigit(
824
+ // utils.hex2bin(parsedData[index + 1].substring(2, 4)),
825
+ // 8
826
+ // )[7] === '1',
827
+ // '1':
828
+ // utils.nHexDigit(
829
+ // utils.hex2bin(parsedData[index + 1].substring(2, 4)),
830
+ // 8
831
+ // )[6] === '1'
832
+ // },
833
+ // output: {
834
+ // '3':
835
+ // utils.nHexDigit(
836
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
837
+ // 8
838
+ // )[5] === '1',
839
+ // '2':
840
+ // utils.nHexDigit(
841
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
842
+ // 8
843
+ // )[6] === '1',
844
+ // '1':
845
+ // utils.nHexDigit(
846
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
847
+ // 8
848
+ // )[7] === '1'
849
+ // },
850
+ // charge: null,
851
+ // state: utils.states[parsedData[index + 1].substring(0, 2)]
852
+ // }
853
+ // : null,
854
+ // odometer: null,
855
+ // hourmeter: null
856
+ })
857
+ } else if (
858
+ command[1] === 'GTJDR' ||
859
+ command[1] === 'GTANT' ||
860
+ command[1] === 'GTRMD' ||
861
+ command[1] === 'GTCRA' ||
862
+ command[1] === 'GTBPL' ||
863
+ command[1] === 'GTSTT'
864
+ ) {
865
+ let index = 16 // position append mask
866
+ let satelliteInfo = false
867
+ // let includeStatus =
868
+ // parsedData[index] !== '' ? parseInt(parsedData[index]) > 3 : null
869
+
870
+ // If get satellites is configured
871
+ if (utils.includeSatellites(parsedData[index])) {
872
+ index += 1
873
+ satelliteInfo = true
874
+ }
875
+
876
+ data = Object.assign(data, {
877
+ alarm: utils.getAlarm(command[1], parsedData[4]),
878
+ loc: {
879
+ type: 'Point',
880
+ coordinates: [parseFloat(parsedData[9]), parseFloat(parsedData[10])]
881
+ },
882
+ speed: parsedData[6] !== '' ? parseFloat(parsedData[6]) : null,
883
+ gpsStatus: utils.checkGps(
884
+ parseFloat(parsedData[9]),
885
+ parseFloat(parsedData[10])
886
+ ),
887
+ hdop: parsedData[5] !== '' ? parseFloat(parsedData[5]) : null,
888
+ azimuth: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
889
+ altitude: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
890
+ datetime: parsedData[11] !== '' ? utils.parseDate(parsedData[11]) : null,
891
+ // voltage: {
892
+ // battery: null,
893
+ // inputCharge: null
894
+ // },
895
+ mcc: parsedData[12] !== '' ? utils.latamMcc[parseInt(parsedData[12], 10)] : null,
896
+ mnc: parsedData[13] !== '' ? utils.getMNC(parsedData[12], parsedData[13]) : null,
897
+ lac: parsedData[14] !== '' ? parseInt(parsedData[14], 16) : null,
898
+ cid: parsedData[15] !== '' ? parseInt(parsedData[15], 16) : null,
899
+ satellites:
900
+ satelliteInfo && parsedData[index] !== ''
901
+ ? parseInt(parsedData[index])
902
+ : null,
903
+ // status: includeStatus
904
+ // ? {
905
+ // raw: parsedData[index + 1],
906
+ // sos: false,
907
+ // input: {
908
+ // '2':
909
+ // utils.nHexDigit(
910
+ // utils.hex2bin(parsedData[index + 1].substring(2, 4)),
911
+ // 8
912
+ // )[7] === '1',
913
+ // '1':
914
+ // utils.nHexDigit(
915
+ // utils.hex2bin(parsedData[index + 1].substring(2, 4)),
916
+ // 8
917
+ // )[6] === '1'
918
+ // },
919
+ // output: {
920
+ // '3':
921
+ // utils.nHexDigit(
922
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
923
+ // 8
924
+ // )[5] === '1',
925
+ // '2':
926
+ // utils.nHexDigit(
927
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
928
+ // 8
929
+ // )[6] === '1',
930
+ // '1':
931
+ // utils.nHexDigit(
932
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
933
+ // 8
934
+ // )[7] === '1'
935
+ // },
936
+ // charge: null,
937
+ // state: utils.states[parsedData[index + 1].substring(0, 2)]
938
+ // }
939
+ // : null,
940
+ // odometer: null,
941
+ // hourmeter: null
942
+ })
943
+ } else if (command[1] === 'GTJDS') {
944
+ let index = 17 // position append mask
945
+ let satelliteInfo = false
946
+ // let includeStatus =
947
+ // parsedData[index] !== '' ? parseInt(parsedData[index]) > 3 : null
948
+
949
+ // If get satellites is configured
950
+ if (utils.includeSatellites(parsedData[17])) {
951
+ index += 1
952
+ satelliteInfo = true
953
+ }
954
+
955
+ data = Object.assign(data, {
956
+ alarm: utils.getAlarm(command[1], parsedData[4], parsedData[5]),
957
+ loc: {
958
+ type: 'Point',
959
+ coordinates: [parseFloat(parsedData[10]), parseFloat(parsedData[11])]
960
+ },
961
+ speed: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
962
+ gpsStatus: utils.checkGps(
963
+ parseFloat(parsedData[10]),
964
+ parseFloat(parsedData[11])
965
+ ),
966
+ hdop: parsedData[6] !== '' ? parseFloat(parsedData[6]) : null,
967
+ azimuth: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
968
+ altitude: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
969
+ datetime: parsedData[12] !== '' ? utils.parseDate(parsedData[12]) : null,
970
+ // voltage: {
971
+ // battery: null,
972
+ // inputCharge: null
973
+ // },
974
+ mcc: parsedData[13] !== '' ? utils.latamMcc[parseInt(parsedData[13], 10)] : null,
975
+ mnc: parsedData[14] !== '' ? utils.getMNC(parsedData[13], parsedData[14]) : null,
976
+ lac: parsedData[15] !== '' ? parseInt(parsedData[15], 16) : null,
977
+ cid: parsedData[16] !== '' ? parseInt(parsedData[16], 16) : null,
978
+ satellites:
979
+ satelliteInfo && parsedData[index] !== ''
980
+ ? parseInt(parsedData[index], 10)
981
+ : null,
982
+ // status: includeStatus
983
+ // ? {
984
+ // raw: parsedData[index + 1],
985
+ // sos: false,
986
+ // input: {
987
+ // '2':
988
+ // utils.nHexDigit(
989
+ // utils.hex2bin(parsedData[index + 1].substring(2, 4)),
990
+ // 8
991
+ // )[7] === '1',
992
+ // '1':
993
+ // utils.nHexDigit(
994
+ // utils.hex2bin(parsedData[index + 1].substring(2, 4)),
995
+ // 8
996
+ // )[6] === '1'
997
+ // },
998
+ // output: {
999
+ // '3':
1000
+ // utils.nHexDigit(
1001
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
1002
+ // 8
1003
+ // )[5] === '1',
1004
+ // '2':
1005
+ // utils.nHexDigit(
1006
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
1007
+ // 8
1008
+ // )[6] === '1',
1009
+ // '1':
1010
+ // utils.nHexDigit(
1011
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
1012
+ // 8
1013
+ // )[7] === '1'
1014
+ // },
1015
+ // charge: null,
1016
+ // state: utils.states[parsedData[index + 1].substring(0, 2)]
1017
+ // }
1018
+ // : null,
1019
+ // odometer: null,
1020
+ // hourmeter: null
1021
+ })
1022
+ } else if (command[1] === 'GTIGN' || command[1] === 'GTIGF') {
1023
+ let index = 16 // position append mask
1024
+ let satelliteInfo = false
1025
+ let includeStatus =
1026
+ parsedData[index] !== '' ? parseInt(parsedData[index]) > 3 : null
1027
+
1028
+ // If get satellites is configured
1029
+ if (utils.includeSatellites(parsedData[index])) {
1030
+ index += 1
1031
+ satelliteInfo = true
1032
+ }
1033
+
1034
+ data = Object.assign(data, {
1035
+ alarm: utils.getAlarm(command[1], parsedData[4]),
1036
+ loc: {
1037
+ type: 'Point',
1038
+ coordinates: [parseFloat(parsedData[9]), parseFloat(parsedData[10])]
1039
+ },
1040
+ speed: parsedData[6] !== '' ? parseFloat(parsedData[6]) : null,
1041
+ gpsStatus: utils.checkGps(
1042
+ parseFloat(parsedData[9]),
1043
+ parseFloat(parsedData[10])
1044
+ ),
1045
+ hdop: parsedData[5] !== '' ? parseFloat(parsedData[5]) : null,
1046
+ azimuth: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
1047
+ altitude: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
1048
+ datetime: parsedData[11] !== '' ? utils.parseDate(parsedData[11]) : null,
1049
+ voltage: {
1050
+ battery: null,
1051
+ inputCharge: null
1052
+ },
1053
+ mcc: parsedData[12] !== '' ? utils.latamMcc[parseInt(parsedData[12], 10)] : null,
1054
+ mnc: parsedData[13] !== '' ? utils.getMNC(parsedData[12], parsedData[13]) : null,
1055
+ lac: parsedData[14] !== '' ? parseInt(parsedData[14], 16) : null,
1056
+ cid: parsedData[15] !== '' ? parseInt(parsedData[15], 16) : null,
1057
+ satellites:
1058
+ satelliteInfo && parsedData[index] !== ''
1059
+ ? parseInt(parsedData[index], 10)
1060
+ : null,
1061
+ status: includeStatus
1062
+ ? {
1063
+ raw: parsedData[index + 1],
1064
+ sos: false,
1065
+ input: {
1066
+ '2':
1067
+ utils.nHexDigit(
1068
+ utils.hex2bin(parsedData[index + 1].substring(2, 4)),
1069
+ 8
1070
+ )[7] === '1',
1071
+ '1':
1072
+ utils.nHexDigit(
1073
+ utils.hex2bin(parsedData[index + 1].substring(2, 4)),
1074
+ 8
1075
+ )[6] === '1'
1076
+ },
1077
+ output: {
1078
+ '3':
1079
+ utils.nHexDigit(
1080
+ utils.hex2bin(parsedData[index + 1].substring(4, 6)),
1081
+ 8
1082
+ )[5] === '1',
1083
+ '2':
1084
+ utils.nHexDigit(
1085
+ utils.hex2bin(parsedData[index + 1].substring(4, 6)),
1086
+ 8
1087
+ )[6] === '1',
1088
+ '1':
1089
+ utils.nHexDigit(
1090
+ utils.hex2bin(parsedData[index + 1].substring(4, 6)),
1091
+ 8
1092
+ )[7] === '1'
1093
+ },
1094
+ charge: null,
1095
+ state: utils.states[parsedData[index + 1].substring(0, 2)]
1096
+ }
1097
+ : null,
1098
+ odometer: includeStatus
1099
+ ? parsedData[index + 3] !== ''
1100
+ ? parseFloat(parsedData[index + 3])
1101
+ : null
1102
+ : parsedData[index + 2] !== ''
1103
+ ? parseFloat(parsedData[index + 2])
1104
+ : null,
1105
+ hourmeter: includeStatus
1106
+ ? parsedData[index + 2] !== ''
1107
+ ? utils.getHoursForHourmeter(parsedData[index + 2])
1108
+ : null
1109
+ : parsedData[index + 1] !== ''
1110
+ ? utils.getHoursForHourmeter(parsedData[index + 1])
1111
+ : null
1112
+ })
1113
+ } else if (command[1] === 'GTIDN' || command[1] === 'GTIDF') {
1114
+ let index = 17 // position append mask
1115
+ let satelliteInfo = false
1116
+ // let includeStatus =
1117
+ // parsedData[index] !== '' ? parseInt(parsedData[index]) > 3 : null
1118
+
1119
+ // If get satellites is configured
1120
+ if (utils.includeSatellites(parsedData[index])) {
1121
+ index += 1
1122
+ satelliteInfo = true
1123
+ }
1124
+
1125
+ data = Object.assign(data, {
1126
+ alarm: utils.getAlarm(command[1], parsedData[5]),
1127
+ loc: {
1128
+ type: 'Point',
1129
+ coordinates: [parseFloat(parsedData[10]), parseFloat(parsedData[11])]
1130
+ },
1131
+ speed: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
1132
+ gpsStatus: utils.checkGps(
1133
+ parseFloat(parsedData[10]),
1134
+ parseFloat(parsedData[11])
1135
+ ),
1136
+ hdop: parsedData[6] !== '' ? parseFloat(parsedData[6]) : null,
1137
+ azimuth: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
1138
+ altitude: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
1139
+ datetime: parsedData[12] !== '' ? utils.parseDate(parsedData[12]) : null,
1140
+ // voltage: {
1141
+ // battery: null,
1142
+ // inputCharge: null
1143
+ // },
1144
+ mcc: parsedData[13] !== '' ? utils.latamMcc[parseInt(parsedData[13], 10)] : null,
1145
+ mnc: parsedData[14] !== '' ? utils.getMNC(parsedData[13], parsedData[14]) : null,
1146
+ lac: parsedData[15] !== '' ? parseInt(parsedData[15], 16) : null,
1147
+ cid: parsedData[16] !== '' ? parseInt(parsedData[16], 16) : null,
1148
+ satellites:
1149
+ satelliteInfo && parsedData[index] !== ''
1150
+ ? parseInt(parsedData[index], 10)
1151
+ : null,
1152
+ // status: includeStatus
1153
+ // ? {
1154
+ // raw: parsedData[index + 1],
1155
+ // sos: false,
1156
+ // input: {
1157
+ // '2':
1158
+ // utils.nHexDigit(
1159
+ // utils.hex2bin(parsedData[index + 1].substring(2, 4)),
1160
+ // 8
1161
+ // )[7] === '1',
1162
+ // '1':
1163
+ // utils.nHexDigit(
1164
+ // utils.hex2bin(parsedData[index + 1].substring(2, 4)),
1165
+ // 8
1166
+ // )[6] === '1'
1167
+ // },
1168
+ // output: {
1169
+ // '3':
1170
+ // utils.nHexDigit(
1171
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
1172
+ // 8
1173
+ // )[5] === '1',
1174
+ // '2':
1175
+ // utils.nHexDigit(
1176
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
1177
+ // 8
1178
+ // )[6] === '1',
1179
+ // '1':
1180
+ // utils.nHexDigit(
1181
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
1182
+ // 8
1183
+ // )[7] === '1'
1184
+ // },
1185
+ // charge: null,
1186
+ // state: utils.states[parsedData[index + 1].substring(0, 2)]
1187
+ // }
1188
+ // : null,
1189
+ odometer: parsedData[index + 1] !== ''
1190
+ ? parseFloat(parsedData[index + 1])
1191
+ : null,
1192
+ // hourmeter: null
1193
+ })
1194
+ } else if (
1195
+ command[1] === 'GTSTR' ||
1196
+ command[1] === 'GTSTP' ||
1197
+ command[1] === 'GTLSP'
1198
+ ) {
1199
+ let index = 17 // position append mask
1200
+ let satelliteInfo = false
1201
+ // let includeStatus =
1202
+ // parsedData[index] !== '' ? parseInt(parsedData[index]) > 3 : null
1203
+
1204
+ // If get satellites is configured
1205
+ if (utils.includeSatellites(parsedData[index])) {
1206
+ index += 1
1207
+ satelliteInfo = true
1208
+ }
1209
+
1210
+ data = Object.assign(data, {
1211
+ alarm: utils.getAlarm(command[1], null),
1212
+ loc: {
1213
+ type: 'Point',
1214
+ coordinates: [parseFloat(parsedData[10]), parseFloat(parsedData[11])]
1215
+ },
1216
+ speed: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
1217
+ gpsStatus: utils.checkGps(
1218
+ parseFloat(parsedData[10]),
1219
+ parseFloat(parsedData[11])
1220
+ ),
1221
+ hdop: parsedData[6] !== '' ? parseFloat(parsedData[6]) : null,
1222
+ azimuth: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
1223
+ altitude: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
1224
+ datetime: parsedData[12] !== '' ? utils.parseDate(parsedData[12]) : null,
1225
+ // voltage: {
1226
+ // battery: null,
1227
+ // inputCharge: null
1228
+ // },
1229
+ mcc: parsedData[13] !== '' ? utils.latamMcc[parseInt(parsedData[13], 10)] : null,
1230
+ mnc: parsedData[14] !== '' ? utils.getMNC(parsedData[13], parsedData[14]) : null,
1231
+ lac: parsedData[15] !== '' ? parseInt(parsedData[15], 16) : null,
1232
+ cid: parsedData[16] !== '' ? parseInt(parsedData[16], 16) : null,
1233
+ satellites:
1234
+ satelliteInfo && parsedData[index] !== ''
1235
+ ? parseInt(parsedData[index], 10)
1236
+ : null,
1237
+ // status: includeStatus
1238
+ // ? {
1239
+ // raw: parsedData[index + 1],
1240
+ // sos: false,
1241
+ // input: {
1242
+ // '2':
1243
+ // utils.nHexDigit(
1244
+ // utils.hex2bin(parsedData[index + 1].substring(2, 4)),
1245
+ // 8
1246
+ // )[7] === '1',
1247
+ // '1':
1248
+ // utils.nHexDigit(
1249
+ // utils.hex2bin(parsedData[index + 1].substring(2, 4)),
1250
+ // 8
1251
+ // )[6] === '1'
1252
+ // },
1253
+ // output: {
1254
+ // '3':
1255
+ // utils.nHexDigit(
1256
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
1257
+ // 8
1258
+ // )[5] === '1',
1259
+ // '2':
1260
+ // utils.nHexDigit(
1261
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
1262
+ // 8
1263
+ // )[6] === '1',
1264
+ // '1':
1265
+ // utils.nHexDigit(
1266
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
1267
+ // 8
1268
+ // )[7] === '1'
1269
+ // },
1270
+ // charge: null,
1271
+ // state: utils.states[parsedData[index + 1].substring(0, 2)]
1272
+ // }
1273
+ // : null,
1274
+ odometer: parsedData[index + 1] !== ''
1275
+ ? parseFloat(parsedData[index + 1])
1276
+ : null,
1277
+ // hourmeter: null
1278
+ })
1279
+ } else if (command[1] === 'GTGSS') {
1280
+ // GPS Status
1281
+ let index = 19 // position append mask
1282
+ let satelliteInfo = false
1283
+ // let includeStatus =
1284
+ // parsedData[index] !== '' ? parseInt(parsedData[index]) > 3 : null
1285
+
1286
+ // If get satellites is configured
1287
+ if (utils.includeSatellites(parsedData[index])) {
1288
+ index += 1
1289
+ satelliteInfo = true
1290
+ }
1291
+
1292
+ data = Object.assign(data, {
1293
+ alarm: utils.getAlarm(command[1], parsedData[4]),
1294
+ loc: {
1295
+ type: 'Point',
1296
+ coordinates: [parseFloat(parsedData[12]), parseFloat(parsedData[13])]
1297
+ },
1298
+ speed: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
1299
+ gpsStatus: utils.checkGps(
1300
+ parseFloat(parsedData[12]),
1301
+ parseFloat(parsedData[13])
1302
+ ),
1303
+ hdop: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
1304
+ azimuth: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
1305
+ altitude: parsedData[11] !== '' ? parseFloat(parsedData[11]) : null,
1306
+ datetime: parsedData[14] !== '' ? utils.parseDate(parsedData[14]) : null,
1307
+ // voltage: {
1308
+ // battery: null,
1309
+ // inputCharge: null
1310
+ // },
1311
+ mcc: parsedData[15] !== '' ? utils.latamMcc[parseInt(parsedData[15], 10)] : null,
1312
+ mnc: parsedData[16] !== '' ? utils.getMNC(parsedData[15], parsedData[16]) : null,
1313
+ lac: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
1314
+ cid: parsedData[18] !== '' ? parseInt(parsedData[18], 16) : null,
1315
+ usedSatellites: parsedData[5] !== '' ? parseInt(parsedData[5], 16) : null,
1316
+ satellites:
1317
+ satelliteInfo && parsedData[index] !== ''
1318
+ ? parseInt(parsedData[index], 10)
1319
+ : null,
1320
+ // status: includeStatus
1321
+ // ? {
1322
+ // raw: parsedData[index + 1],
1323
+ // sos: false,
1324
+ // input: {
1325
+ // '2':
1326
+ // utils.nHexDigit(
1327
+ // utils.hex2bin(parsedData[index + 1].substring(2, 4)),
1328
+ // 8
1329
+ // )[7] === '1',
1330
+ // '1':
1331
+ // utils.nHexDigit(
1332
+ // utils.hex2bin(parsedData[index + 1].substring(2, 4)),
1333
+ // 8
1334
+ // )[6] === '1'
1335
+ // },
1336
+ // output: {
1337
+ // '3':
1338
+ // utils.nHexDigit(
1339
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
1340
+ // 8
1341
+ // )[5] === '1',
1342
+ // '2':
1343
+ // utils.nHexDigit(
1344
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
1345
+ // 8
1346
+ // )[6] === '1',
1347
+ // '1':
1348
+ // utils.nHexDigit(
1349
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
1350
+ // 8
1351
+ // )[7] === '1'
1352
+ // },
1353
+ // charge: null,
1354
+ // state: utils.states[parsedData[index + 1].substring(0, 2)]
1355
+ // }
1356
+ // : null,
1357
+ // odometer: null,
1358
+ // hourmeter: null
1359
+ })
1360
+ // } else if (command[1] === 'GTIDA') {
1361
+ // // bluetooth identification
1362
+ // let number = parsedData[7] !== '' ? parseInt(parsedData[7], 10) : 1
1363
+ // let index = 7 + 12 * number // position append mask
1364
+ // let satelliteInfo = false
1365
+
1366
+ // // If get satellites is configured
1367
+ // if (utils.includeSatellites(parsedData[index])) {
1368
+ // index += 1
1369
+ // satelliteInfo = true
1370
+ // }
1371
+
1372
+ // data = Object.assign(data, {
1373
+ // alarm: utils.getAlarm(command[1], `${parsedData[5]},${parsedData[6]}`),
1374
+ // loc: {
1375
+ // type: 'Point',
1376
+ // coordinates: [parseFloat(parsedData[12]), parseFloat(parsedData[13])]
1377
+ // },
1378
+ // speed: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
1379
+ // gpsStatus: utils.checkGps(
1380
+ // parseFloat(parsedData[12]),
1381
+ // parseFloat(parsedData[13])
1382
+ // ),
1383
+ // hdop: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
1384
+ // status: null,
1385
+ // azimuth: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
1386
+ // altitude: parsedData[11] !== '' ? parseFloat(parsedData[11]) : null,
1387
+ // datetime: parsedData[14] !== '' ? utils.parseDate(parsedData[14]) : null,
1388
+ // voltage: {
1389
+ // battery: null,
1390
+ // inputCharge: null
1391
+ // },
1392
+ // mcc: parsedData[15] !== '' ? utils.latamMcc[parseInt(parsedData[15], 10)] : null,
1393
+ // mnc: parsedData[16] !== '' ? utils.getMNC(parsedData[15], parsedData[16]) : null,
1394
+ // lac: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
1395
+ // cid: parsedData[18] !== '' ? parseInt(parsedData[18], 16) : null,
1396
+ // satellites:
1397
+ // satelliteInfo && parsedData[index] !== ''
1398
+ // ? parseInt(parsedData[index], 10)
1399
+ // : null,
1400
+ // odometer:
1401
+ // parsedData[index + 1] !== '' ? parseFloat(parsedData[index + 1]) : null,
1402
+ // hourmeter: null
1403
+ // })
1404
+ } else if (command[1] === 'GTDAT') {
1405
+ let dataIndex = 4
1406
+ // Short format
1407
+ if (parsedData.length === 7) {
1408
+ data = Object.assign(data, {
1409
+ datetime: parsedData[5] !== '' ? utils.parseDate(parsedData[5]) : null
1410
+ })
1411
+ } else {
1412
+ dataIndex = 7
1413
+ let index = 19 // position append mask
1414
+ let satelliteInfo = false
1415
+
1416
+ // If get satellites is configured
1417
+ if (utils.includeSatellites(parsedData[index])) {
1418
+ index += 1
1419
+ satelliteInfo = true
1420
+ }
1421
+
1422
+ data = Object.assign(data, {
1423
+ loc: {
1424
+ type: 'Point',
1425
+ coordinates: [parseFloat(parsedData[12]), parseFloat(parsedData[13])]
1426
+ },
1427
+ speed: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
1428
+ gpsStatus: utils.checkGps(
1429
+ parseFloat(parsedData[12]),
1430
+ parseFloat(parsedData[13])
1431
+ ),
1432
+ hdop: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
1433
+ status: null,
1434
+ azimuth: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
1435
+ altitude: parsedData[11] !== '' ? parseFloat(parsedData[11]) : null,
1436
+ datetime:
1437
+ parsedData[14] !== '' ? utils.parseDate(parsedData[14]) : null,
1438
+ voltage: {
1439
+ battery: null,
1440
+ inputCharge: null,
1441
+ ada: null,
1442
+ adb: null,
1443
+ adc: null
1444
+ },
1445
+ mcc: parsedData[15] !== '' ? utils.latamMcc[parseInt(parsedData[15], 10)] : null,
1446
+ mnc: parsedData[16] !== '' ? utils.getMNC(parsedData[15], parsedData[16]) : null,
1447
+ lac: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
1448
+ cid: parsedData[18] !== '' ? parseInt(parsedData[18], 16) : null,
1449
+ satellites:
1450
+ satelliteInfo && parsedData[index] !== ''
1451
+ ? parseInt(parsedData[index], 10)
1452
+ : null,
1453
+ odometer: null,
1454
+ hourmeter: null
1455
+ })
1456
+ }
1457
+
1458
+ data = Object.assign(data, {
1459
+ alarm: utils.getAlarm(command[1], parsedData[dataIndex])
1460
+ })
1461
+ } else if (command[1] === 'GTDOS') {
1462
+ let index = 17 // position append mask
1463
+ let satelliteInfo = false
1464
+ // let includeStatus =
1465
+ // parsedData[index] !== '' ? parseInt(parsedData[index]) > 3 : null
1466
+
1467
+ // If get satellites is configured
1468
+ if (utils.includeSatellites(parsedData[index])) {
1469
+ index += 1
1470
+ satelliteInfo = true
1471
+ }
1472
+
1473
+ data = Object.assign(data, {
1474
+ alarm: utils.getAlarm(command[1], `${parsedData[4]},${parsedData[5]}`),
1475
+ loc: {
1476
+ type: 'Point',
1477
+ coordinates: [parseFloat(parsedData[10]), parseFloat(parsedData[11])]
1478
+ },
1479
+ speed: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
1480
+ gpsStatus: utils.checkGps(
1481
+ parseFloat(parsedData[10]),
1482
+ parseFloat(parsedData[11])
1483
+ ),
1484
+ hdop: parsedData[6] !== '' ? parseFloat(parsedData[6]) : null,
1485
+ azimuth: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
1486
+ altitude: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
1487
+ datetime: parsedData[12] !== '' ? utils.parseDate(parsedData[12]) : null,
1488
+ // voltage: {
1489
+ // battery: null,
1490
+ // inputCharge: null
1491
+ // },
1492
+ mcc: parsedData[13] !== '' ? utils.latamMcc[parseInt(parsedData[13], 10)] : null,
1493
+ mnc: parsedData[14] !== '' ? utils.getMNC(parsedData[13], parsedData[14]) : null,
1494
+ lac: parsedData[15] !== '' ? parseInt(parsedData[15], 16) : null,
1495
+ cid: parsedData[16] !== '' ? parseInt(parsedData[16], 16) : null,
1496
+ satellites:
1497
+ satelliteInfo && parsedData[index] !== ''
1498
+ ? parseInt(parsedData[index], 10)
1499
+ : null,
1500
+ // status: includeStatus
1501
+ // ? {
1502
+ // raw: parsedData[index + 1],
1503
+ // sos: false,
1504
+ // input: {
1505
+ // '2':
1506
+ // utils.nHexDigit(
1507
+ // utils.hex2bin(parsedData[index + 1].substring(2, 4)),
1508
+ // 8
1509
+ // )[7] === '1',
1510
+ // '1':
1511
+ // utils.nHexDigit(
1512
+ // utils.hex2bin(parsedData[index + 1].substring(2, 4)),
1513
+ // 8
1514
+ // )[6] === '1'
1515
+ // },
1516
+ // output: {
1517
+ // '3':
1518
+ // utils.nHexDigit(
1519
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
1520
+ // 8
1521
+ // )[5] === '1',
1522
+ // '2':
1523
+ // utils.nHexDigit(
1524
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
1525
+ // 8
1526
+ // )[6] === '1',
1527
+ // '1':
1528
+ // utils.nHexDigit(
1529
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
1530
+ // 8
1531
+ // )[7] === '1'
1532
+ // },
1533
+ // charge: null,
1534
+ // state: utils.states[parsedData[index + 1].substring(0, 2)]
1535
+ // }
1536
+ // : null,
1537
+ // odometer: null,
1538
+ // hourmeter: null
1539
+ })
1540
+ } else if (command[1] === 'GTDOM') {
1541
+ // Waveform beeing monitored
1542
+ let index = 18 // position append mask
1543
+ let satelliteInfo = false
1544
+ // let includeStatus =
1545
+ // parsedData[index] !== '' ? parseInt(parsedData[index]) > 3 : null
1546
+
1547
+ // If get satellites is configured
1548
+ if (utils.includeSatellites(parsedData[index])) {
1549
+ index += 1
1550
+ satelliteInfo = true
1551
+ }
1552
+
1553
+ data = Object.assign(data, {
1554
+ alarm: utils.getAlarm(command[1], [parsedData[4], parsedData[5]]),
1555
+ loc: {
1556
+ type: 'Point',
1557
+ coordinates: [parseFloat(parsedData[11]), parseFloat(parsedData[12])]
1558
+ },
1559
+ speed: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
1560
+ gpsStatus: utils.checkGps(
1561
+ parseFloat(parsedData[11]),
1562
+ parseFloat(parsedData[12])
1563
+ ),
1564
+ hdop: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
1565
+ azimuth: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
1566
+ altitude: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
1567
+ datetime: parsedData[13] !== '' ? utils.parseDate(parsedData[13]) : null,
1568
+ // voltage: {
1569
+ // battery: null,
1570
+ // inputCharge: null
1571
+ // },
1572
+ mcc: parsedData[14] !== '' ? utils.latamMcc[parseInt(parsedData[14], 10)] : null,
1573
+ mnc: parsedData[15] !== '' ? utils.getMNC(parsedData[14], parsedData[15]) : null,
1574
+ lac: parsedData[16] !== '' ? parseInt(parsedData[16], 16) : null,
1575
+ cid: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
1576
+ satellites:
1577
+ satelliteInfo && parsedData[index] !== ''
1578
+ ? parseInt(parsedData[index], 10)
1579
+ : null,
1580
+ // status: includeStatus
1581
+ // ? {
1582
+ // raw: parsedData[index + 1],
1583
+ // sos: false,
1584
+ // input: {
1585
+ // '2':
1586
+ // utils.nHexDigit(
1587
+ // utils.hex2bin(parsedData[index + 1].substring(2, 4)),
1588
+ // 8
1589
+ // )[7] === '1',
1590
+ // '1':
1591
+ // utils.nHexDigit(
1592
+ // utils.hex2bin(parsedData[index + 1].substring(2, 4)),
1593
+ // 8
1594
+ // )[6] === '1'
1595
+ // },
1596
+ // output: {
1597
+ // '3':
1598
+ // utils.nHexDigit(
1599
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
1600
+ // 8
1601
+ // )[5] === '1',
1602
+ // '2':
1603
+ // utils.nHexDigit(
1604
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
1605
+ // 8
1606
+ // )[6] === '1',
1607
+ // '1':
1608
+ // utils.nHexDigit(
1609
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
1610
+ // 8
1611
+ // )[7] === '1'
1612
+ // },
1613
+ // charge: null,
1614
+ // state: utils.states[parsedData[index + 1].substring(0, 2)]
1615
+ // }
1616
+ // : null,
1617
+ // odometer: null,
1618
+ // hourmeter: null
1619
+ })
1620
+ } else if (command[1] === 'GTVER') {
1621
+ data = Object.assign(data, {
1622
+ alarm: utils.getAlarm(
1623
+ command[1],
1624
+ [parsedData[5], parsedData[6]],
1625
+ 'gv58lau'
1626
+ )
1627
+ })
1628
+ } else if (command[1] === 'GTVGN' || command[1] === 'GTVGF') {
1629
+ // Virtual ignition
1630
+ let index = 18 // possition append mask
1631
+ let satelliteInfo = false
1632
+ let includeStatus =
1633
+ parsedData[index] !== '' ? parseInt(parsedData[index]) > 3 : null
1634
+
1635
+ // If get satellites is configured
1636
+ if (utils.includeSatellites(parsedData[index])) {
1637
+ index += 1
1638
+ satelliteInfo = true
1639
+ }
1640
+
1641
+ data = Object.assign(data, {
1642
+ alarm: utils.getAlarm(command[1], [parsedData[6], parsedData[5]]),
1643
+ loc: {
1644
+ type: 'Point',
1645
+ coordinates: [parseFloat(parsedData[11]), parseFloat(parsedData[12])]
1646
+ },
1647
+ speed: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
1648
+ gpsStatus: utils.checkGps(
1649
+ parseFloat(parsedData[11]),
1650
+ parseFloat(parsedData[12])
1651
+ ),
1652
+ hdop: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
1653
+ azimuth: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
1654
+ altitude: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
1655
+ datetime: parsedData[13] !== '' ? utils.parseDate(parsedData[13]) : null,
1656
+ voltage: {
1657
+ battery: null,
1658
+ inputCharge: null
1659
+ },
1660
+ mcc: parsedData[14] !== '' ? utils.latamMcc[parseInt(parsedData[14], 10)] : null,
1661
+ mnc: parsedData[15] !== '' ? utils.getMNC(parsedData[14], parsedData[15]) : null,
1662
+ lac: parsedData[16] !== '' ? parseInt(parsedData[16], 16) : null,
1663
+ cid: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
1664
+ satellites:
1665
+ satelliteInfo && parsedData[index] !== ''
1666
+ ? parseInt(parsedData[index])
1667
+ : null,
1668
+ status: includeStatus
1669
+ ? {
1670
+ raw: parsedData[index + 1],
1671
+ sos: false,
1672
+ input: {
1673
+ '2':
1674
+ utils.nHexDigit(
1675
+ utils.hex2bin(parsedData[index + 1].substring(2, 4)),
1676
+ 8
1677
+ )[7] === '1',
1678
+ '1':
1679
+ utils.nHexDigit(
1680
+ utils.hex2bin(parsedData[index + 1].substring(2, 4)),
1681
+ 8
1682
+ )[6] === '1'
1683
+ },
1684
+ output: {
1685
+ '3':
1686
+ utils.nHexDigit(
1687
+ utils.hex2bin(parsedData[index + 1].substring(4, 6)),
1688
+ 8
1689
+ )[5] === '1',
1690
+ '2':
1691
+ utils.nHexDigit(
1692
+ utils.hex2bin(parsedData[index + 1].substring(4, 6)),
1693
+ 8
1694
+ )[6] === '1',
1695
+ '1':
1696
+ utils.nHexDigit(
1697
+ utils.hex2bin(parsedData[index + 1].substring(4, 6)),
1698
+ 8
1699
+ )[7] === '1'
1700
+ },
1701
+ charge: null,
1702
+ state: utils.states[parsedData[index + 1].substring(0, 2)]
1703
+ }
1704
+ : null,
1705
+ odometer: includeStatus
1706
+ ? parsedData[index + 3] !== ''
1707
+ ? parseFloat(parsedData[index + 3])
1708
+ : null
1709
+ : parsedData[index + 2] !== ''
1710
+ ? parseFloat(parsedData[index + 2])
1711
+ : null,
1712
+ hourmeter: includeStatus
1713
+ ? parsedData[index + 2] !== ''
1714
+ ? utils.getHoursForHourmeter(parsedData[index + 2])
1715
+ : null
1716
+ : parsedData[index + 1] !== ''
1717
+ ? utils.getHoursForHourmeter(parsedData[index + 1])
1718
+ : null
1719
+ })
1720
+ } else if (command[1] === 'GTGSM') {
1721
+ data = Object.assign(data, {
1722
+ alarm: utils.getAlarm(command[1], null),
1723
+ fixType: parsedData[3] !== '' ? parsedData[3] : null
1724
+ })
1725
+ let antData = []
1726
+ let index = 4
1727
+ for (let i = 0; i < 6; i++) {
1728
+ antData.push({
1729
+ mcc: parsedData[index] !== '' ? parseInt(parsedData[index], 10) : null,
1730
+ mnc:
1731
+ parsedData[index + 1] !== ''
1732
+ ? parseInt(parsedData[index + 1], 10)
1733
+ : null,
1734
+ lac:
1735
+ parsedData[index + 2] !== '' ||
1736
+ parsedData[index + 2].toUpperCase() === 'FFFF'
1737
+ ? parseInt(parsedData[index + 2], 16)
1738
+ : null,
1739
+ cid:
1740
+ parsedData[index + 3] !== '' ||
1741
+ parsedData[index + 3].toUpperCase() === 'FFFF'
1742
+ ? parseInt(parsedData[index + 3], 16)
1743
+ : null,
1744
+ rxLevel:
1745
+ parsedData[index + 4] !== ''
1746
+ ? utils.getSignalStrength(
1747
+ 'GSM',
1748
+ parseInt(parsedData[index + 4], 10)
1749
+ )
1750
+ : null,
1751
+ rxSignalPercentage:
1752
+ parsedData[index + 4] !== ''
1753
+ ? utils.getSignalPercentage(
1754
+ 'GSM',
1755
+ parseInt(parsedData[index + 4], 10)
1756
+ )
1757
+ : null
1758
+ })
1759
+ index += 6
1760
+ }
1761
+ data = Object.assign(data, {
1762
+ neighborCells: antData,
1763
+ mcc: parsedData[index] !== '' ? parseInt(parsedData[index], 10) : null,
1764
+ mnc:
1765
+ parsedData[index + 1] !== ''
1766
+ ? parseInt(parsedData[index + 1], 10)
1767
+ : null,
1768
+ lac:
1769
+ parsedData[index + 2] !== '' ||
1770
+ parsedData[index + 2].toUpperCase() === 'FFFF'
1771
+ ? parseInt(parsedData[index + 2], 16)
1772
+ : null,
1773
+ cid:
1774
+ parsedData[index + 3] !== '' ||
1775
+ parsedData[index + 3].toUpperCase() === 'FFFF'
1776
+ ? parseInt(parsedData[index + 3], 16)
1777
+ : null,
1778
+ rxLevel:
1779
+ parsedData[index + 4] !== ''
1780
+ ? utils.getSignalStrength('GSM', parseInt(parsedData[index + 4], 10))
1781
+ : null,
1782
+ rxSignalPercentage:
1783
+ parsedData[index + 4] !== ''
1784
+ ? utils.getSignalPercentage(
1785
+ 'GSM',
1786
+ parseInt(parsedData[index + 4], 10)
1787
+ )
1788
+ : null
1789
+ })
1790
+ } else if (command[1] === 'GTCLT') {
1791
+ // CANBUS Alarm
1792
+ let index = 71 // position append mask
1793
+ let satelliteInfo = false
1794
+
1795
+ let includeStatus =
1796
+ parsedData[index] !== '' ? parseInt(parsedData[index]) > 3 : null
1797
+
1798
+ // If get satellites is configured
1799
+ if (utils.includeSatellites(parsedData[index])) {
1800
+ index += 1
1801
+ satelliteInfo = true
1802
+ }
1803
+
1804
+ let alarmMask1 =
1805
+ parsedData[5] !== ''
1806
+ ? utils
1807
+ .nHexDigit(utils.hex2bin(parsedData[5]), 32)
1808
+ .split('')
1809
+ .reverse()
1810
+ .join('')
1811
+ : null
1812
+ let alarmMask2 =
1813
+ parsedData[6] !== ''
1814
+ ? utils
1815
+ .nHexDigit(utils.hex2bin(parsedData[6]), 32)
1816
+ .split('')
1817
+ .reverse()
1818
+ .join('')
1819
+ : null
1820
+ let alarmMask3 =
1821
+ parsedData[7] !== ''
1822
+ ? utils
1823
+ .nHexDigit(utils.hex2bin(parsedData[7]), 32)
1824
+ .split('')
1825
+ .reverse()
1826
+ .join('')
1827
+ : null
1828
+ let inicatorsBin =
1829
+ parsedData[28] !== ''
1830
+ ? utils.nHexDigit(utils.hex2bin(parsedData[28]), 16)
1831
+ : null
1832
+ let lights =
1833
+ parsedData[29] !== ''
1834
+ ? utils.nHexDigit(utils.hex2bin(parsedData[29]), 8)
1835
+ : null
1836
+ let doors =
1837
+ parsedData[30] !== ''
1838
+ ? utils.nHexDigit(utils.hex2bin(parsedData[30]), 8)
1839
+ : null
1840
+ let canExpansionMask =
1841
+ parsedData[33] !== ''
1842
+ ? utils
1843
+ .nHexDigit(utils.hex2bin(parsedData[33]), 32)
1844
+ .split('')
1845
+ .reverse()
1846
+ .join('')
1847
+ : null
1848
+ let expansionBin =
1849
+ parsedData[54] !== ''
1850
+ ? utils
1851
+ .nHexDigit(utils.hex2bin(parsedData[54]), 16)
1852
+ .split('')
1853
+ .reverse()
1854
+ .join('')
1855
+ : null
1856
+ let tachographBin =
1857
+ parsedData[27] !== ''
1858
+ ? utils
1859
+ .nHexDigit(utils.hex2bin(parsedData[27]), 8)
1860
+ .split('')
1861
+ .reverse()
1862
+ .join('')
1863
+ : null
1864
+ data = Object.assign(data, {
1865
+ alarm: utils.getAlarm(command[1], parsedData[6]),
1866
+ loc: {
1867
+ type: 'Point',
1868
+ coordinates: [parseFloat(parsedData[64]), parseFloat(parsedData[65])]
1869
+ },
1870
+ speed: parsedData[61] !== '' ? parseFloat(parsedData[61]) : null,
1871
+ gpsStatus: utils.checkGps(
1872
+ parseFloat(parsedData[64]),
1873
+ parseFloat(parsedData[65])
1874
+ ),
1875
+ hdop: parsedData[60] !== '' ? parseFloat(parsedData[60]) : null,
1876
+ canBusDataMask: parsedData[10] !== '' ? parsedData[10] : null,
1877
+ azimuth: parsedData[62] !== '' ? parseFloat(parsedData[62]) : null,
1878
+ altitude: parsedData[63] !== '' ? parseFloat(parsedData[63]) : null,
1879
+ datetime: parsedData[66] !== '' ? utils.parseDate(parsedData[66]) : null,
1880
+ mcc: parsedData[67] !== '' ? utils.latamMcc[parseInt(parsedData[67], 10)] : null,
1881
+ mnc: parsedData[68] !== '' ? utils.getMNC(parsedData[67], parsedData[68]) : null,
1882
+ lac: parsedData[69] !== '' ? parseInt(parsedData[69], 16) : null,
1883
+ cid: parsedData[70] !== '' ? parseInt(parsedData[70], 16) : null,
1884
+ satellites:
1885
+ satelliteInfo && parsedData[index] !== ''
1886
+ ? parseInt(parsedData[index], 10)
1887
+ : null,
1888
+ status: includeStatus
1889
+ ? {
1890
+ raw: parsedData[index + 1],
1891
+ sos: false,
1892
+ input: {
1893
+ '2':
1894
+ utils.nHexDigit(
1895
+ utils.hex2bin(parsedData[index + 1].substring(2, 4)),
1896
+ 8
1897
+ )[7] === '1',
1898
+ '1':
1899
+ utils.nHexDigit(
1900
+ utils.hex2bin(parsedData[index + 1].substring(2, 4)),
1901
+ 8
1902
+ )[6] === '1'
1903
+ },
1904
+ output: {
1905
+ '3':
1906
+ utils.nHexDigit(
1907
+ utils.hex2bin(parsedData[index + 1].substring(4, 6)),
1908
+ 8
1909
+ )[5] === '1',
1910
+ '2':
1911
+ utils.nHexDigit(
1912
+ utils.hex2bin(parsedData[index + 1].substring(4, 6)),
1913
+ 8
1914
+ )[6] === '1',
1915
+ '1':
1916
+ utils.nHexDigit(
1917
+ utils.hex2bin(parsedData[index + 1].substring(4, 6)),
1918
+ 8
1919
+ )[7] === '1'
1920
+ },
1921
+ charge: null,
1922
+ state: utils.states[parsedData[index + 1].substring(0, 2)]
1923
+ }
1924
+ : null,
1925
+ odometer: null,
1926
+ hourmeter: null,
1927
+ configuredAlarms: {
1928
+ alarm1: {
1929
+ raw: parsedData[5] !== '' ? parsedData[5] : null,
1930
+ oilLevelLowIndicator: alarmMask1 ? alarmMask1[28] === '1' : null,
1931
+ serviceCallIndicator: alarmMask1 ? alarmMask1[27] === '1' : null,
1932
+ aribagsIndicator: alarmMask1 ? alarmMask1[26] === '1' : null,
1933
+ checkEngineIndicator: alarmMask1 ? alarmMask1[25] === '1' : null,
1934
+ ABSFailureIndicator: alarmMask1 ? alarmMask1[23] === '1' : null,
1935
+ engineHotIndicator: alarmMask1 ? alarmMask1[22] === '1' : null,
1936
+ oilPressureIndicator: alarmMask1 ? alarmMask1[21] === '1' : null,
1937
+ brakeSystemaFailureIndicator: alarmMask1
1938
+ ? alarmMask1[20] === '1'
1939
+ : null,
1940
+ batteryIndicator: alarmMask1 ? alarmMask1[19] === '1' : null,
1941
+ coolantLevelLowIndicator: alarmMask1 ? alarmMask1[18] === '1' : null,
1942
+ brakeFluidLowIndicator: alarmMask1 ? alarmMask1[17] === '1' : null,
1943
+ webcastIndicator: alarmMask1 ? alarmMask1[16] === '1' : null,
1944
+ trunkIndicator: alarmMask1 ? alarmMask1[15] === '1' : null,
1945
+ doorsIndicator: alarmMask1 ? alarmMask1[14] === '1' : null,
1946
+ frontFogLightsIndicator: alarmMask1 ? alarmMask1[13] === '1' : null,
1947
+ rearFogLightsIndicator: alarmMask1 ? alarmMask1[12] === '1' : null,
1948
+ highBeamsIndicator: alarmMask1 ? alarmMask1[11] === '1' : null,
1949
+ lowBeamsIndicator: alarmMask1 ? alarmMask1[10] === '1' : null,
1950
+ runningLightsIndicator: alarmMask1 ? alarmMask1[9] === '1' : null,
1951
+ reverseGearIndicator: alarmMask1 ? alarmMask1[8] === '1' : null,
1952
+ centralLockIndicator: alarmMask1 ? alarmMask1[7] === '1' : null,
1953
+ handbrakeIndicator: alarmMask1 ? alarmMask1[6] === '1' : null,
1954
+ clutchPedalIndicator: alarmMask1 ? alarmMask1[5] === '1' : null,
1955
+ brakePedalIndicator: alarmMask1 ? alarmMask1[4] === '1' : null,
1956
+ cruiseControlIndicator: alarmMask1 ? alarmMask1[3] === '1' : null,
1957
+ airConditioningIndicator: alarmMask1 ? alarmMask1[2] === '1' : null,
1958
+ driverSeatbeltIndicator: alarmMask1 ? alarmMask1[1] === '1' : null,
1959
+ fuelLowIndicator: alarmMask1 ? alarmMask1[0] === '1' : null
1960
+ },
1961
+ alarm2: {
1962
+ raw: parsedData[6] !== '' ? parsedData[6] : null,
1963
+ hood: alarmMask2 ? alarmMask2[21] === '1' : null,
1964
+ trunk: alarmMask2 ? alarmMask2[20] === '1' : null,
1965
+ rearRightDoor: alarmMask2 ? alarmMask2[19] === '1' : null,
1966
+ rearLeftDoor: alarmMask2 ? alarmMask2[18] === '1' : null,
1967
+ passengeDoor: alarmMask2 ? alarmMask2[17] === '1' : null,
1968
+ driverDoor: alarmMask2 ? alarmMask2[16] === '1' : null,
1969
+ hazadrLights: alarmMask2 ? alarmMask2[5] === '1' : null,
1970
+ readFogLights: alarmMask2 ? alarmMask2[4] === '1' : null,
1971
+ fronFogLights: alarmMask2 ? alarmMask2[3] === '1' : null,
1972
+ highBeam: alarmMask2 ? alarmMask2[2] === '1' : null,
1973
+ lowBeam: alarmMask2 ? alarmMask2[1] === '1' : null,
1974
+ runningLights: alarmMask2 ? alarmMask2[0] === '1' : null
1975
+ },
1976
+ alarm3: {
1977
+ raw: parsedData[7] !== '' ? parsedData[7] : null,
1978
+ overHighRPM: alarmMask3 ? alarmMask3[3] === '1' : null,
1979
+ underHighRPM: alarmMask3 ? alarmMask3[2] === '1' : null,
1980
+ overLowRPM: alarmMask3 ? alarmMask3[1] === '1' : null,
1981
+ underLowRPM: alarmMask3 ? alarmMask3[0] === '1' : null
1982
+ }
1983
+ },
1984
+ can: {
1985
+ vin: parsedData[11] !== '' ? parseInt(parsedData[11]) : null,
1986
+ ignitionKey:
1987
+ parsedData[12] !== '' ? parseInt(parsedData[12], 10) : null,
1988
+ distance: parsedData[13] !== '' ? parsedData[13] : null,
1989
+ fuelUsed: parsedData[14] !== '' ? parseFloat(parsedData[14]) : null, // float
1990
+ rpm: parsedData[15] !== '' ? parseInt(parsedData[15], 10) : null, // int
1991
+ speed: parsedData[16] !== '' ? parseFloat(parsedData[16]) : null,
1992
+ coolantTemp:
1993
+ parsedData[17] !== '' ? parseInt(parsedData[17], 10) : null,
1994
+ fuelConsumption: parsedData[18] !== '' ? parsedData[18] : null,
1995
+ fuelLevel: parsedData[19] !== '' ? parsedData[19] : null,
1996
+ range: parsedData[20] !== '' ? parsedData[20] : null,
1997
+ acceleratorPressure:
1998
+ parsedData[21] !== '' ? parseFloat(parsedData[21]) : null, // %
1999
+ engineHours: parsedData[22] !== '' ? parseFloat(parsedData[22]) : null,
2000
+ drivingTime: parsedData[23] !== '' ? parseFloat(parsedData[23]) : null,
2001
+ idleTime: parsedData[24] !== '' ? parseFloat(parsedData[24]) : null,
2002
+ idleFuelUsed: parsedData[25] !== '' ? parseFloat(parsedData[25]) : null,
2003
+ axleWight2: parsedData[26] !== '' ? parseInt(parsedData[26]) : null,
2004
+ tachograph: {
2005
+ raw: parsedData[27] !== '' ? parsedData[27] : null,
2006
+ validDriverData: tachographBin ? tachographBin[7] === '1' : null,
2007
+ insertedDriverCard: tachographBin ? tachographBin[5] === '1' : null,
2008
+ driverWorkingState: tachographBin
2009
+ ? utils.dWorkingStates[parseInt(tachographBin.substring(3, 5), 2)]
2010
+ : null,
2011
+ drivingTimeState: tachographBin
2012
+ ? utils.dTimeStates[parseInt(tachographBin.substring(5, 8), 2)]
2013
+ : null
2014
+ },
2015
+ indicators: {
2016
+ raw: parsedData[28] !== '' ? parsedData[28] : null,
2017
+ lowFuel: inicatorsBin ? inicatorsBin[0] === '1' : null,
2018
+ driverSeatbelt: inicatorsBin ? inicatorsBin[1] === '1' : null,
2019
+ airConditioning: inicatorsBin ? inicatorsBin[2] === '1' : null,
2020
+ cruiseControl: inicatorsBin ? inicatorsBin[3] === '1' : null,
2021
+ brakePedal: inicatorsBin ? inicatorsBin[4] === '1' : null,
2022
+ clutchPedal: inicatorsBin ? inicatorsBin[5] === '1' : null,
2023
+ handbrake: inicatorsBin ? inicatorsBin[6] === '1' : null,
2024
+ centralLock: inicatorsBin ? inicatorsBin[7] === '1' : null,
2025
+ reverseGear: inicatorsBin ? inicatorsBin[8] === '1' : null,
2026
+ runningLights: inicatorsBin ? inicatorsBin[9] === '1' : null,
2027
+ lowBeams: inicatorsBin ? inicatorsBin[10] === '1' : null,
2028
+ highBeams: inicatorsBin ? inicatorsBin[11] === '1' : null,
2029
+ rearFogLights: inicatorsBin ? inicatorsBin[12] === '1' : null,
2030
+ frontFogLights: inicatorsBin ? inicatorsBin[13] === '1' : null,
2031
+ doors: inicatorsBin ? inicatorsBin[14] === '1' : null,
2032
+ trunk: inicatorsBin ? inicatorsBin[15] === '1' : null
2033
+ },
2034
+ lights: {
2035
+ raw: parsedData[29] !== '' ? parsedData[29] : null,
2036
+ running: lights ? lights[0] === '1' : null,
2037
+ lowBeams: lights ? lights[1] === '1' : null,
2038
+ frontFog: lights ? lights[2] === '1' : null,
2039
+ rearFog: lights ? lights[3] === '1' : null,
2040
+ hazard: lights ? lights[4] === '1' : null
2041
+ },
2042
+ doors: {
2043
+ raw: parsedData[30] !== '' ? parsedData[30] : null,
2044
+ driver: doors ? doors[0] === '1' : null,
2045
+ passenger: doors ? doors[1] === '1' : null,
2046
+ rearLeft: doors ? doors[2] === '1' : null,
2047
+ rearRight: doors ? doors[3] === '1' : null,
2048
+ trunk: doors ? doors[4] === '1' : null,
2049
+ hood: doors ? doors[5] === '1' : null
2050
+ },
2051
+ overSpeedTime: parsedData[31] !== '' ? parsedData[31] : null,
2052
+ overSpeedEngineTime: parsedData[32] !== '' ? parsedData[32] : null,
2053
+ canReportExpansionMask: {
2054
+ raw: parsedData[33] !== '' ? parsedData[33] : null,
2055
+ engineTorque: canExpansionMask ? canExpansionMask[23] === '1' : null,
2056
+ rapidAccelerations: canExpansionMask
2057
+ ? canExpansionMask[22] === '1'
2058
+ : null,
2059
+ rapidBrakings: canExpansionMask ? canExpansionMask[21] === '1' : null,
2060
+ expansionInformation: canExpansionMask
2061
+ ? canExpansionMask[20] === '1'
2062
+ : null,
2063
+ registrationNumber: canExpansionMask
2064
+ ? canExpansionMask[19] === '1'
2065
+ : null,
2066
+ tachographDriver2Name: canExpansionMask
2067
+ ? canExpansionMask[18] === '1'
2068
+ : null,
2069
+ tachographDriver1Name: canExpansionMask
2070
+ ? canExpansionMask[17] === '1'
2071
+ : null,
2072
+ tachographDriver2Card: canExpansionMask
2073
+ ? canExpansionMask[16] === '1'
2074
+ : null,
2075
+ tachographDriver1Card: canExpansionMask
2076
+ ? canExpansionMask[15] === '1'
2077
+ : null,
2078
+ totalBrakeApplications: canExpansionMask
2079
+ ? canExpansionMask[14] === '1'
2080
+ : null,
2081
+ totalAcceleratorKickDownTime: canExpansionMask
2082
+ ? canExpansionMask[13] === '1'
2083
+ : null,
2084
+ totalCruiseControlTime: canExpansionMask
2085
+ ? canExpansionMask[12] === '1'
2086
+ : null,
2087
+ totalEffectiveEngineSpeedTime: canExpansionMask
2088
+ ? canExpansionMask[11] === '1'
2089
+ : null,
2090
+ totalAcceleratorKickDown: canExpansionMask
2091
+ ? canExpansionMask[10] === '1'
2092
+ : null,
2093
+ pedalBrakingFactor: canExpansionMask
2094
+ ? canExpansionMask[9] === '1'
2095
+ : null,
2096
+ engineBrakingFactor: canExpansionMask
2097
+ ? canExpansionMask[8] === '1'
2098
+ : null,
2099
+ analogInputValue: canExpansionMask
2100
+ ? canExpansionMask[7] === '1'
2101
+ : null,
2102
+ tachographDrivingDirection: canExpansionMask
2103
+ ? canExpansionMask[6] === '1'
2104
+ : null,
2105
+ tachographVehicleMotionSignal: canExpansionMask
2106
+ ? canExpansionMask[5] === '1'
2107
+ : null,
2108
+ tachographOverspeedSignal: canExpansionMask
2109
+ ? canExpansionMask[4] === '1'
2110
+ : null,
2111
+ AxleWeight4: canExpansionMask ? canExpansionMask[3] === '1' : null,
2112
+ AxleWeight3: canExpansionMask ? canExpansionMask[2] === '1' : null,
2113
+ AxleWeight1: canExpansionMask ? canExpansionMask[1] === '1' : null,
2114
+ adBlueLevel: canExpansionMask ? canExpansionMask[0] === '1' : null
2115
+ },
2116
+ canExpanded: {
2117
+ adBlueLevel:
2118
+ parsedData[34] !== '' ? parseFloat(parsedData[34]) : null,
2119
+ axleWeight1: parsedData[35] !== '' ? parseInt(parsedData[35]) : null,
2120
+ axleWeight3: parsedData[36] !== '' ? parseInt(parsedData[36]) : null,
2121
+ axleWeight4: parsedData[37] !== '' ? parseInt(parsedData[37]) : null,
2122
+ tachographOverspeedSignal:
2123
+ parsedData[38] !== '' ? parseInt(parsedData[38]) : null,
2124
+ tachographVehicleMotionSignal:
2125
+ parsedData[39] !== '' ? parseInt(parsedData[39]) : null,
2126
+ tachographDrivingDirection:
2127
+ parsedData[40] !== '' ? parseInt(parsedData[40]) : null,
2128
+ analogInputValue:
2129
+ parsedData[41] !== '' ? parseInt(parsedData[41]) : null,
2130
+ engineBrakingFactor:
2131
+ parsedData[42] !== '' ? parseInt(parsedData[42]) : null,
2132
+ pedalBrakingFactor:
2133
+ parsedData[43] !== '' ? parseInt(parsedData[43]) : null,
2134
+ totalAcceleratorKickDown:
2135
+ parsedData[44] !== '' ? parseInt(parsedData[44]) : null,
2136
+ totalEffectiveEngineSpeedTime:
2137
+ parsedData[45] !== '' ? parseFloat(parsedData[45]) : null,
2138
+ totalCruiseControlTime:
2139
+ parsedData[46] !== '' ? parseFloat(parsedData[46]) : null,
2140
+ totalAcceleratorKickDownTime:
2141
+ parsedData[47] !== '' ? parseFloat(parsedData[47]) : null,
2142
+ totalBrakeApplications:
2143
+ parsedData[48] !== '' ? parseInt(parsedData[48]) : null,
2144
+ tachographDriver1Card:
2145
+ parsedData[49] !== '' ? parseInt(parsedData[49]) : null,
2146
+ tachographDriver2Card:
2147
+ parsedData[50] !== '' ? parseInt(parsedData[50]) : null,
2148
+ tachographDriver1Name: parsedData[51] !== '' ? parsedData[51] : null,
2149
+ tachographDriver2Name: parsedData[52] !== '' ? parsedData[52] : null,
2150
+ registrationNumber:
2151
+ parsedData[53] !== '' ? parseInt(parsedData[53]) : null,
2152
+ expansionInformation: {
2153
+ raw: parsedData[54] !== '' ? parsedData[54] : null,
2154
+ webasto: expansionBin ? expansionBin[0] === '1' : null,
2155
+ brakeFluidLowIndicator: expansionBin
2156
+ ? expansionBin[1] === '1'
2157
+ : null,
2158
+ coolantLevelLowIndicator: expansionBin
2159
+ ? expansionBin[2] === '1'
2160
+ : null,
2161
+ batteryIndicator: expansionBin ? expansionBin[3] === '1' : null,
2162
+ brakeSystemaFailureIndicator: expansionBin
2163
+ ? expansionBin[4] === '1'
2164
+ : null,
2165
+ oilPressureIndicator: expansionBin ? expansionBin[5] === '1' : null,
2166
+ engineHotIndicator: expansionBin ? expansionBin[6] === '1' : null,
2167
+ ABSFailureIndicator: expansionBin ? expansionBin[7] === '1' : null,
2168
+ checkEngineIndicator: expansionBin ? expansionBin[9] === '1' : null,
2169
+ aribagsIndicator: expansionBin ? expansionBin[10] === '1' : null,
2170
+ serviceCallIndicator: expansionBin
2171
+ ? expansionBin[11] === '1'
2172
+ : null,
2173
+ oilLevelLowIndicator: expansionBin ? expansionBin[12] === '1' : null
2174
+ },
2175
+ rapidBrakings:
2176
+ parsedData[55] !== '' ? parseInt(parsedData[55]) : null,
2177
+ rapidAccelerations:
2178
+ parsedData[56] !== '' ? parseInt(parsedData[56]) : null,
2179
+ engineTorque:
2180
+ parsedData[57] !== '' ? parseFloat(parsedData[57]) : null
2181
+ }
2182
+ }
2183
+ })
2184
+ } else if (command[1] === 'GTSVR') {
2185
+ // Primary Stolen Vehicle Recovery
2186
+ // Primary: GV310LAU - Ghost: GV58LAU
2187
+ let index = 19 // possition append mask
2188
+ let satelliteInfo = false
2189
+
2190
+ // If get satellites is configured
2191
+ if (utils.includeSatellites(parsedData[index])) {
2192
+ index += 1
2193
+ satelliteInfo = true
2194
+ }
2195
+
2196
+ data = Object.assign(data, {
2197
+ alarm: utils.getAlarm(command[1], parsedData[4]),
2198
+ loc: {
2199
+ type: 'Point',
2200
+ coordinates: [parseFloat(parsedData[12]), parseFloat(parsedData[13])]
2201
+ },
2202
+ speed: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
2203
+ gpsStatus: utils.checkGps(
2204
+ parseFloat(parsedData[12]),
2205
+ parseFloat(parsedData[13])
2206
+ ),
2207
+ hdop: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
2208
+ status: null,
2209
+ azimuth: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
2210
+ altitude: parsedData[11] !== '' ? parseFloat(parsedData[11]) : null,
2211
+ datetime: parsedData[14] !== '' ? utils.parseDate(parsedData[14]) : null,
2212
+ voltage: {
2213
+ battery: null,
2214
+ inputCharge: null
2215
+ },
2216
+ mcc: parsedData[15] !== '' ? utils.latamMcc[parseInt(parsedData[15], 10)] : null,
2217
+ mnc: parsedData[16] !== '' ? utils.getMNC(parsedData[15], parsedData[16]) : null,
2218
+ lac: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
2219
+ cid: parsedData[18] !== '' ? parseInt(parsedData[18], 16) : null,
2220
+ satellites:
2221
+ satelliteInfo && parsedData[index] !== ''
2222
+ ? parseInt(parsedData[index])
2223
+ : null,
2224
+ odometer:
2225
+ parsedData[index + 2] !== '' ? parseFloat(parsedData[index + 2]) : null,
2226
+ hourmeter: parsedData[index + 1] !== '' ? parsedData[index + 1] : null,
2227
+ bluetooth: {
2228
+ mac: parsedData[5] !== '' ? parsedData[5] : null,
2229
+ svrInfo: parsedData[6] !== '' ? parsedData[6] : null
2230
+ }
2231
+ })
2232
+ } else if (command[1] === 'GTASC') {
2233
+ // Calibrarion data for XYZ-axis acceleration sensor
2234
+ let index = 24 // possition append mask
2235
+ let satelliteInfo = false
2236
+
2237
+ // let includeStatus =
2238
+ // parsedData[index] !== '' ? parseInt(parsedData[index]) > 3 : null
2239
+
2240
+ // If get satellites is configured
2241
+ if (utils.includeSatellites(parsedData[index])) {
2242
+ index += 1
2243
+ satelliteInfo = true
2244
+ }
2245
+
2246
+ data = Object.assign(data, {
2247
+ alarm: utils.getAlarm(command[1], null),
2248
+ loc: {
2249
+ type: 'Point',
2250
+ coordinates: [parseFloat(parsedData[17]), parseFloat(parsedData[18])]
2251
+ },
2252
+ speed: parsedData[14] !== '' ? parseFloat(parsedData[14]) : null,
2253
+ gpsStatus: utils.checkGps(
2254
+ parseFloat(parsedData[17]),
2255
+ parseFloat(parsedData[18])
2256
+ ),
2257
+ hdop: parsedData[13] !== '' ? parseFloat(parsedData[13]) : null,
2258
+ azimuth: parsedData[15] !== '' ? parseFloat(parsedData[15]) : null,
2259
+ altitude: parsedData[16] !== '' ? parseFloat(parsedData[16]) : null,
2260
+ datetime: parsedData[19] !== '' ? utils.parseDate(parsedData[19]) : null,
2261
+ // voltage: {
2262
+ // battery: null,
2263
+ // inputCharge: null
2264
+ // },
2265
+ mcc: parsedData[20] !== '' ? utils.latamMcc[parseInt(parsedData[20], 10)] : null,
2266
+ mnc: parsedData[21] !== '' ? utils.getMNC(parsedData[20], parsedData[21]) : null,
2267
+ lac: parsedData[22] !== '' ? parseInt(parsedData[22], 16) : null,
2268
+ cid: parsedData[23] !== '' ? parseInt(parsedData[23], 16) : null,
2269
+ satellites:
2270
+ satelliteInfo && parsedData[index] !== ''
2271
+ ? parseInt(parsedData[index])
2272
+ : null,
2273
+ // status: includeStatus
2274
+ // ? {
2275
+ // raw: parsedData[index + 1],
2276
+ // sos: false,
2277
+ // input: {
2278
+ // '2':
2279
+ // utils.nHexDigit(
2280
+ // utils.hex2bin(parsedData[index + 1].substring(2, 4)),
2281
+ // 8
2282
+ // )[7] === '1',
2283
+ // '1':
2284
+ // utils.nHexDigit(
2285
+ // utils.hex2bin(parsedData[index + 1].substring(2, 4)),
2286
+ // 8
2287
+ // )[6] === '1'
2288
+ // },
2289
+ // output: {
2290
+ // '3':
2291
+ // utils.nHexDigit(
2292
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
2293
+ // 8
2294
+ // )[5] === '1',
2295
+ // '2':
2296
+ // utils.nHexDigit(
2297
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
2298
+ // 8
2299
+ // )[6] === '1',
2300
+ // '1':
2301
+ // utils.nHexDigit(
2302
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
2303
+ // 8
2304
+ // )[7] === '1'
2305
+ // },
2306
+ // charge: null,
2307
+ // state: utils.states[parsedData[index + 1].substring(0, 2)]
2308
+ // }
2309
+ // : null,
2310
+ calibration: {
2311
+ xForward: parsedData[4] !== '' ? parseFloat(parsedData[4]) : null,
2312
+ yForward: parsedData[5] !== '' ? parseFloat(parsedData[5]) : null,
2313
+ zForward: parsedData[6] !== '' ? parseFloat(parsedData[6]) : null,
2314
+ xSide: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
2315
+ ySide: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
2316
+ zSide: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
2317
+ xVertical: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
2318
+ yVertical: parsedData[11] !== '' ? parseFloat(parsedData[11]) : null,
2319
+ zVertical: parsedData[12] !== '' ? parseFloat(parsedData[12]) : null
2320
+ },
2321
+ // odometer: null,
2322
+ // hourmeter: null
2323
+ })
2324
+ } else if (command[1] === 'GTHBE') {
2325
+ // Harsh Behavior Information
2326
+ // Only works when GTHBM is in mode 5
2327
+ let index = 18 // possition append mask
2328
+ let satelliteInfo = false
2329
+ // let includeStatus =
2330
+ // parsedData[index] !== '' ? parseInt(parsedData[index]) > 3 : null
2331
+
2332
+ // If get satellites is configured
2333
+ if (utils.includeSatellites(parsedData[index])) {
2334
+ index += 1
2335
+ satelliteInfo = true
2336
+ }
2337
+
2338
+ let maxAcc = parsedData[index + 1] !== '' ? parsedData[index + 1] : null
2339
+ let avgAcc = parsedData[index + 2] !== '' ? parsedData[index + 2] : null
2340
+ let duration = parsedData[index + 3] !== '' ? parseFloat(parsedData[index + 3]) : null
2341
+
2342
+ data = Object.assign(data, {
2343
+ alarm: utils.getAlarm(
2344
+ command[1],
2345
+ [parsedData[5], parsedData[6]],
2346
+ [maxAcc, duration]
2347
+ ),
2348
+ loc: {
2349
+ type: 'Point',
2350
+ coordinates: [parseFloat(parsedData[11]), parseFloat(parsedData[12])]
2351
+ },
2352
+ speed: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
2353
+ gpsStatus: utils.checkGps(
2354
+ parseFloat(parsedData[11]),
2355
+ parseFloat(parsedData[12])
2356
+ ),
2357
+ hdop: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
2358
+ azimuth: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
2359
+ altitude: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
2360
+ datetime: parsedData[13] !== '' ? utils.parseDate(parsedData[13]) : null,
2361
+ // voltage: {
2362
+ // battery: null,
2363
+ // inputCharge: null
2364
+ // },
2365
+ mcc: parsedData[14] !== '' ? utils.latamMcc[parseInt(parsedData[14], 10)] : null,
2366
+ mnc: parsedData[15] !== '' ? utils.getMNC(parsedData[14], parsedData[15]) : null,
2367
+ lac: parsedData[16] !== '' ? parseInt(parsedData[16], 16) : null,
2368
+ cid: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
2369
+ satellites:
2370
+ satelliteInfo && parsedData[index] !== ''
2371
+ ? parseInt(parsedData[index])
2372
+ : null,
2373
+ // status: includeStatus
2374
+ // ? {
2375
+ // raw: parsedData[index + 1],
2376
+ // sos: false,
2377
+ // input: {
2378
+ // '2':
2379
+ // utils.nHexDigit(
2380
+ // utils.hex2bin(parsedData[index + 1].substring(2, 4)),
2381
+ // 8
2382
+ // )[7] === '1',
2383
+ // '1':
2384
+ // utils.nHexDigit(
2385
+ // utils.hex2bin(parsedData[index + 1].substring(2, 4)),
2386
+ // 8
2387
+ // )[6] === '1'
2388
+ // },
2389
+ // output: {
2390
+ // '3':
2391
+ // utils.nHexDigit(
2392
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
2393
+ // 8
2394
+ // )[5] === '1',
2395
+ // '2':
2396
+ // utils.nHexDigit(
2397
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
2398
+ // 8
2399
+ // )[6] === '1',
2400
+ // '1':
2401
+ // utils.nHexDigit(
2402
+ // utils.hex2bin(parsedData[index + 1].substring(4, 6)),
2403
+ // 8
2404
+ // )[7] === '1'
2405
+ // },
2406
+ // charge: null,
2407
+ // state: utils.states[parsedData[index + 1].substring(0, 2)]
2408
+ // }
2409
+ // : null,
2410
+ maxAcceleration: {
2411
+ // Acceleration in m/s2
2412
+ raw: maxAcc,
2413
+ x: maxAcc
2414
+ ? utils.getAccelerationMagnitude(maxAcc.substring(0, 4), 4)
2415
+ : null,
2416
+ y: maxAcc
2417
+ ? utils.getAccelerationMagnitude(maxAcc.substring(4, 8), 4)
2418
+ : null,
2419
+ z: maxAcc
2420
+ ? utils.getAccelerationMagnitude(maxAcc.substring(8, 12), 4)
2421
+ : null
2422
+ },
2423
+ avgAcceleration: {
2424
+ // Acceleration in m/s2
2425
+ raw: avgAcc,
2426
+ x: avgAcc
2427
+ ? utils.getAccelerationMagnitude(avgAcc.substring(0, 4), 4)
2428
+ : null,
2429
+ y: avgAcc
2430
+ ? utils.getAccelerationMagnitude(avgAcc.substring(4, 8), 4)
2431
+ : null,
2432
+ z: avgAcc
2433
+ ? utils.getAccelerationMagnitude(avgAcc.substring(8, 12), 4)
2434
+ : null
2435
+ },
2436
+ duration: duration,
2437
+ odometer: parsedData[index + 4] !== ''
2438
+ ? parseFloat(parsedData[index + 4])
2439
+ : null,
2440
+ // hourmeter: null
2441
+ })
2442
+ } else {
2443
+ // GTBAR report is not parsed because it only supports one device
2444
+ data = Object.assign(data, {
2445
+ alarm: utils.getAlarm(command[1], raw.toString())
2446
+ })
2447
+ }
2448
+ // Check gps data
2449
+ if (data.loc !== null && typeof data.loc !== 'undefined') {
2450
+ if (
2451
+ data.loc.coordinates[0] === 0 ||
2452
+ isNaN(data.loc.coordinates[0]) ||
2453
+ data.loc.coordinates[1] === 0 ||
2454
+ isNaN(data.loc.coordinates[1])
2455
+ ) {
2456
+ data.loc = null
2457
+ }
2458
+ }
2459
+ return data
2460
+ }
2461
+
2462
+ module.exports = {
2463
+ parse: parse
2464
+ }