queclink-parser 1.4.3 → 1.8.3

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.
@@ -0,0 +1,3206 @@
1
+ 'use strict'
2
+ const utils = require('./utils.js')
3
+
4
+ /*
5
+ Parses messages data from GV310LAU 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-GV310LAU',
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 index = 6 + 12 * number // position append mask
36
+ let satelliteInfo = false
37
+
38
+ // If get satellites is configured
39
+ if (utils.includeSatellites(parsedData[18])) {
40
+ index += 1
41
+ satelliteInfo = true
42
+ }
43
+
44
+ data = Object.assign(data, {
45
+ alarm: utils.getAlarm(command[1], null),
46
+ loc: {
47
+ type: 'Point',
48
+ coordinates: [parseFloat(parsedData[11]), parseFloat(parsedData[12])]
49
+ },
50
+ speed: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
51
+ gpsStatus: utils.checkGps(
52
+ parseFloat(parsedData[11]),
53
+ parseFloat(parsedData[12])
54
+ ),
55
+ hdop: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
56
+ status: {
57
+ // parsedData[26]
58
+ raw: parsedData[index + 7],
59
+ sos: false,
60
+ input: {
61
+ '1':
62
+ utils.nHexDigit(
63
+ utils.hex2bin(
64
+ utils.nHexDigit(parsedData[index + 7], 10).substring(6, 8)
65
+ ),
66
+ 4
67
+ )[3] === '1',
68
+ '2':
69
+ utils.nHexDigit(
70
+ utils.hex2bin(
71
+ utils.nHexDigit(parsedData[index + 7], 10).substring(6, 8)
72
+ ),
73
+ 4
74
+ )[2] === '1',
75
+ '3':
76
+ utils.nHexDigit(
77
+ utils.hex2bin(
78
+ utils.nHexDigit(parsedData[index + 7], 10).substring(6, 8)
79
+ ),
80
+ 4
81
+ )[1] === '1',
82
+ '4':
83
+ utils.nHexDigit(
84
+ utils.hex2bin(
85
+ utils.nHexDigit(parsedData[index + 7], 10).substring(6, 8)
86
+ ),
87
+ 4
88
+ )[0] === '1'
89
+ },
90
+ output: {
91
+ '1':
92
+ utils.nHexDigit(
93
+ utils.hex2bin(
94
+ utils.nHexDigit(parsedData[index + 7], 10).substring(8, 10)
95
+ ),
96
+ 3
97
+ )[2] === '1',
98
+ '2':
99
+ utils.nHexDigit(
100
+ utils.hex2bin(
101
+ utils.nHexDigit(parsedData[index + 7], 10).substring(8, 10)
102
+ ),
103
+ 3
104
+ )[1] === '1',
105
+ '3':
106
+ utils.nHexDigit(
107
+ utils.hex2bin(
108
+ utils.nHexDigit(parsedData[index + 7], 10).substring(8, 10)
109
+ ),
110
+ 3
111
+ )[0] === '1'
112
+ },
113
+ charge: parseFloat(parsedData[4]) > 5,
114
+ state:
115
+ utils.nHexDigit(parsedData[index + 7], 10).substring(4, 6) !== ''
116
+ ? utils.states[ // eslint-disable-line
117
+ utils.nHexDigit(parsedData[index + 7], 10).substring(4, 6)
118
+ ]
119
+ : null
120
+ },
121
+ azimuth: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
122
+ altitude: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
123
+ datetime:
124
+ parsedData[13] !== '' ? utils.parseDate(parsedData[13]) : null,
125
+ voltage: {
126
+ battery:
127
+ parsedData[index + 6] !== ''
128
+ ? parseFloat(parsedData[index + 6])
129
+ : null, // percentage
130
+ inputCharge:
131
+ parsedData[4] !== '' ? parseFloat(parsedData[4]) / 1000 : null,
132
+ ada:
133
+ parsedData[index + 4] !== ''
134
+ ? parseFloat(parsedData[index + 3]) / 1000
135
+ : null,
136
+ adb:
137
+ parsedData[index + 5] !== ''
138
+ ? parseFloat(parsedData[index + 4]) / 1000
139
+ : null,
140
+ adc:
141
+ parsedData[index + 6] !== ''
142
+ ? parseFloat(parsedData[index + 5]) / 1000
143
+ : null
144
+ },
145
+ mcc: parsedData[13] !== '' ? parseInt(parsedData[14], 10) : null,
146
+ mnc: parsedData[14] !== '' ? parseInt(parsedData[15], 10) : null,
147
+ lac: parsedData[15] !== '' ? parseInt(parsedData[16], 16) : null,
148
+ cid: parsedData[16] !== '' ? parseInt(parsedData[17], 16) : null,
149
+ satellites:
150
+ satelliteInfo && parsedData[index] !== ''
151
+ ? parseInt(parsedData[index], 10)
152
+ : null,
153
+ odometer:
154
+ parsedData[index + 1] !== ''
155
+ ? parseFloat(parsedData[index + 1])
156
+ : null,
157
+ hourmeter:
158
+ parsedData[index + 2] !== ''
159
+ ? utils.getHoursForHourmeter(parsedData[index + 2])
160
+ : null
161
+ })
162
+ } catch (err) {
163
+ return { type: 'UNKNOWN', raw: data.raw.toString() }
164
+ }
165
+ } else if (command[1] === 'GTERI') {
166
+ // GPS with AC100 and/or Bluetoth Devices Connected
167
+ let number = parsedData[7] !== '' ? parseInt(parsedData[7], 10) : 1
168
+ let index = 7 + 12 * number // position append mask
169
+ let satelliteInfo = false
170
+
171
+ // If get satellites is configured
172
+ if (utils.includeSatellites(parsedData[index])) {
173
+ index += 1
174
+ satelliteInfo = true
175
+ }
176
+
177
+ data = Object.assign(data, {
178
+ alarm: utils.getAlarm(command[1], null),
179
+ loc: {
180
+ type: 'Point',
181
+ coordinates: [parseFloat(parsedData[12]), parseFloat(parsedData[13])]
182
+ },
183
+ speed: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
184
+ gpsStatus: utils.checkGps(
185
+ parseFloat(parsedData[12]),
186
+ parseFloat(parsedData[13])
187
+ ),
188
+ hdop: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
189
+ status: {
190
+ // parsedData[index + 7]
191
+ raw: parsedData[index + 7],
192
+ sos: false,
193
+ input: {
194
+ '1':
195
+ utils.nHexDigit(
196
+ utils.hex2bin(
197
+ utils.nHexDigit(parsedData[index + 7], 10).substring(6, 8)
198
+ ),
199
+ 4
200
+ )[3] === '1',
201
+ '2':
202
+ utils.nHexDigit(
203
+ utils.hex2bin(
204
+ utils.nHexDigit(parsedData[index + 7], 10).substring(6, 8)
205
+ ),
206
+ 4
207
+ )[2] === '1',
208
+ '3':
209
+ utils.nHexDigit(
210
+ utils.hex2bin(
211
+ utils.nHexDigit(parsedData[index + 7], 10).substring(6, 8)
212
+ ),
213
+ 4
214
+ )[1] === '1',
215
+ '4':
216
+ utils.nHexDigit(
217
+ utils.hex2bin(
218
+ utils.nHexDigit(parsedData[index + 7], 10).substring(6, 8)
219
+ ),
220
+ 4
221
+ )[0] === '1'
222
+ },
223
+ output: {
224
+ '1':
225
+ utils.nHexDigit(
226
+ utils.hex2bin(
227
+ utils.nHexDigit(parsedData[index + 7], 10).substring(8, 10)
228
+ ),
229
+ 3
230
+ )[2] === '1',
231
+ '2':
232
+ utils.nHexDigit(
233
+ utils.hex2bin(
234
+ utils.nHexDigit(parsedData[index + 7], 10).substring(8, 10)
235
+ ),
236
+ 3
237
+ )[1] === '1',
238
+ '3':
239
+ utils.nHexDigit(
240
+ utils.hex2bin(
241
+ utils.nHexDigit(parsedData[index + 7], 10).substring(8, 10)
242
+ ),
243
+ 3
244
+ )[0] === '1'
245
+ },
246
+ charge: parseFloat(parsedData[5]) > 5,
247
+ state:
248
+ utils.nHexDigit(parsedData[index + 7], 10).substring(4, 6) !== ''
249
+ ? utils.states[ // eslint-disable-line
250
+ utils.nHexDigit(parsedData[index + 7], 10).substring(4, 6)
251
+ ]
252
+ : null
253
+ },
254
+ azimuth: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
255
+ altitude: parsedData[11] !== '' ? parseFloat(parsedData[11]) : null,
256
+ datetime: parsedData[14] !== '' ? utils.parseDate(parsedData[14]) : null,
257
+ voltage: {
258
+ battery:
259
+ parsedData[index + 6] !== ''
260
+ ? parseFloat(parsedData[index + 6])
261
+ : null, // percentage
262
+ inputCharge:
263
+ parsedData[5] !== '' ? parseFloat(parsedData[5]) / 1000 : null,
264
+ ada:
265
+ parsedData[index + 3] !== ''
266
+ ? parseFloat(parsedData[index + 3]) / 1000
267
+ : null,
268
+ adb:
269
+ parsedData[index + 4] !== ''
270
+ ? parseFloat(parsedData[index + 4]) / 1000
271
+ : null,
272
+ adc:
273
+ parsedData[index + 5] !== ''
274
+ ? parseFloat(parsedData[index + 5]) / 1000
275
+ : null
276
+ },
277
+ mcc: parsedData[15] !== '' ? parseInt(parsedData[15], 10) : null,
278
+ mnc: parsedData[16] !== '' ? parseInt(parsedData[16], 10) : null,
279
+ lac: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
280
+ cid: parsedData[18] !== '' ? parseInt(parsedData[18], 16) : null,
281
+ satellites:
282
+ satelliteInfo && parsedData[index] !== ''
283
+ ? parseFloat(parsedData[index])
284
+ : null,
285
+ odometer:
286
+ parsedData[index + 1] !== '' ? parseFloat(parsedData[index + 1]) : null,
287
+ hourmeter:
288
+ parsedData[index + 2] !== ''
289
+ ? utils.getHoursForHourmeter(parsedData[index + 2])
290
+ : null
291
+ })
292
+ // External Data
293
+ const digitFuelSensor =
294
+ utils.nHexDigit(utils.hex2bin(parsedData[4]), 11)[10] === '1'
295
+ const AC100 = utils.nHexDigit(utils.hex2bin(parsedData[4]), 11)[9] === '1'
296
+ const reserved =
297
+ utils.nHexDigit(utils.hex2bin(parsedData[4]), 11)[8] === '1'
298
+ const fuelLevelPercentage =
299
+ utils.nHexDigit(utils.hex2bin(parsedData[4]), 11)[7] === '1'
300
+ const fuelVolume =
301
+ utils.nHexDigit(utils.hex2bin(parsedData[4]), 11)[6] === '1'
302
+ const bluetoothAccessory =
303
+ utils.nHexDigit(utils.hex2bin(parsedData[4]), 11)[2] === '1'
304
+
305
+ const fuelSensorData = digitFuelSensor ? parsedData[index + 9] : null
306
+ const ac100DevicesConnected =
307
+ AC100 && digitFuelSensor
308
+ ? parseInt(parsedData[index + 10], 10)
309
+ : AC100 && !digitFuelSensor ? parseInt(parsedData[index + 9], 10) : 0
310
+
311
+ let externalData = {
312
+ eriMask: {
313
+ raw: parsedData[4],
314
+ digitFuelSensor: digitFuelSensor,
315
+ AC100: AC100,
316
+ reserved: reserved,
317
+ fuelLevelPercentage: fuelLevelPercentage,
318
+ fuelVolume: fuelVolume,
319
+ bluetoothAccessory: bluetoothAccessory
320
+ },
321
+ uartDeviceType:
322
+ parsedData[index + 8] !== ''
323
+ ? utils.uartDeviceTypes[parsedData[index + 8]]
324
+ : null
325
+ }
326
+
327
+ if (parsedData[index + 8] === '1') {
328
+ // Fuel Sensor
329
+ if (digitFuelSensor && !AC100) {
330
+ externalData = Object.assign(externalData, {
331
+ fuelSensorData: {
332
+ data: fuelSensorData,
333
+ sensorType: parsedData[index + 11],
334
+ percentage:
335
+ fuelLevelPercentage && parsedData[index + 12] !== ''
336
+ ? parseInt(parsedData[index + 12], 10)
337
+ : null,
338
+ volume:
339
+ fuelVolume && fuelLevelPercentage && parsedData[index + 12] !== ''
340
+ ? parseInt(parsedData[index + 13], 10)
341
+ : fuelVolume &&
342
+ !fuelLevelPercentage &&
343
+ parsedData[index + 12] !== ''
344
+ ? parseInt(parsedData[index + 12], 10)
345
+ : null
346
+ },
347
+ AC100Devices: null
348
+ })
349
+ } else if (!digitFuelSensor && AC100) {
350
+ let ac100Devices = []
351
+ let count = index + 11
352
+ for (var i = 0; i < ac100DevicesConnected; i++) {
353
+ ac100Devices.push({
354
+ deviceNumber: parsedData[count],
355
+ deviceType: parsedData[count + 1],
356
+ deviceData: parsedData[count + 2]
357
+ ? utils.getTempInCelciousDegrees(parsedData[count + 2])
358
+ : null
359
+ })
360
+ count += 3
361
+ }
362
+ externalData = Object.assign(externalData, {
363
+ fuelSensorData: null,
364
+ AC100Devices: ac100Devices
365
+ })
366
+ } else if (digitFuelSensor && AC100) {
367
+ let ac100Devices = []
368
+ let count =
369
+ fuelVolume && fuelLevelPercentage
370
+ ? 33
371
+ : fuelVolume && !fuelLevelPercentage ? index + 13 : index + 12
372
+ for (var j = 0; j < ac100DevicesConnected; j++) {
373
+ ac100Devices.push({
374
+ deviceNumber: parsedData[count],
375
+ deviceType: parsedData[count + 1],
376
+ deviceData: parsedData[count + 2]
377
+ ? utils.getTempInCelciousDegrees(parsedData[count + 2])
378
+ : null
379
+ })
380
+ count += 3
381
+ }
382
+ externalData = Object.assign(externalData, {
383
+ fuelSensorData: {
384
+ data: fuelSensorData,
385
+ sensorType: parsedData[index + 11],
386
+ percentage:
387
+ fuelLevelPercentage && parsedData[index + 12] !== ''
388
+ ? parseInt(parsedData[index + 12], 10)
389
+ : null,
390
+ volume:
391
+ fuelVolume && fuelLevelPercentage && parsedData[index + 13] !== ''
392
+ ? parseInt(parsedData[index + 13], 10)
393
+ : fuelVolume &&
394
+ !fuelLevelPercentage &&
395
+ parsedData[index + 12] !== ''
396
+ ? parseInt(parsedData[index + 12], 10)
397
+ : null
398
+ },
399
+ AC100Devices: ac100Devices
400
+ })
401
+ }
402
+ } else if (parsedData[index + 8] === '2') {
403
+ // AC100 1 Wire Bus
404
+ if (!digitFuelSensor && AC100) {
405
+ let ac100Devices = []
406
+ let count = index + 10
407
+ for (var k = 0; k < ac100DevicesConnected; k++) {
408
+ ac100Devices.push({
409
+ deviceNumber: parsedData[count],
410
+ deviceType: parsedData[count + 1],
411
+ deviceData: parsedData[count + 2]
412
+ ? utils.getTempInCelciousDegrees(parsedData[count + 2])
413
+ : null
414
+ })
415
+ count += 3
416
+ }
417
+ externalData = Object.assign(externalData, {
418
+ fuelSensorData: null,
419
+ AC100Devices: ac100Devices
420
+ })
421
+ } else if (digitFuelSensor && !AC100) {
422
+ externalData = Object.assign(externalData, {
423
+ fuelSensorData: {
424
+ data: fuelSensorData,
425
+ sensorType: null,
426
+ percentage: null,
427
+ volume: null
428
+ },
429
+ AC100Devices: null
430
+ })
431
+ } else if (digitFuelSensor && AC100) {
432
+ let ac100Devices = []
433
+ let count = index + 12
434
+ for (var l = 0; l < ac100DevicesConnected; l++) {
435
+ ac100Devices.push({
436
+ deviceNumber: parsedData[count],
437
+ deviceType: parsedData[count + 1],
438
+ deviceData: parsedData[count + 2]
439
+ ? utils.getTempInCelciousDegrees(parsedData[count + 2])
440
+ : null
441
+ })
442
+ count += 3
443
+ }
444
+ externalData = Object.assign(externalData, {
445
+ fuelSensorData: {
446
+ data: fuelSensorData,
447
+ sensorType: null,
448
+ percentage: null,
449
+ volume: null
450
+ },
451
+ AC100Devices: ac100Devices
452
+ })
453
+ }
454
+ }
455
+
456
+ // Bluetooth Accessories
457
+ if (bluetoothAccessory) {
458
+ let btDevices = []
459
+ let btIndex = digitFuelSensor ? index + 10 : index + 9
460
+ let cnt = btIndex + 1
461
+ let btNum = parsedData[btIndex] !== '' ? parseInt(parsedData[btIndex]) : 1
462
+ for (let c = 0; c < btNum; c++) {
463
+ let appendMask = utils.nHexDigit(utils.hex2bin(parsedData[cnt + 4]), 16)
464
+
465
+ let aNameIx = cnt + 4 + parseInt(appendMask[15])
466
+ let aMacIx = aNameIx + parseInt(appendMask[14])
467
+ let aStatIx = aMacIx + parseInt(appendMask[13])
468
+ let aBatIx = aStatIx + parseInt(appendMask[12])
469
+ let aTmpIx = aBatIx + parseInt(appendMask[11])
470
+ let aHumIx = aTmpIx + parseInt(appendMask[10])
471
+ let ioIx = aHumIx + parseInt(appendMask[8])
472
+ let modeIx =
473
+ appendMask[8] === '1' ? ioIx + 2 + parseInt(appendMask[7]) : ioIx
474
+ let aEvIx = appendMask[7] === '1' ? modeIx + 1 : modeIx
475
+ let pressIx = aEvIx + parseInt(appendMask[6])
476
+ let timeIx = pressIx + parseInt(appendMask[5])
477
+ let eTmpIx = timeIx + parseInt(appendMask[4])
478
+ let magIx = eTmpIx + parseInt(appendMask[3])
479
+ let aBatpIx =
480
+ appendMask[3] === '1' ? magIx + 2 + parseInt(appendMask[2]) : eTmpIx
481
+ let relIx = aBatpIx + parseInt(appendMask[1])
482
+
483
+ btDevices.push({
484
+ index: parsedData[cnt],
485
+ type: utils.bluetoothAccessories[parsedData[cnt + 1]],
486
+ model:
487
+ parsedData[cnt + 2] !== ''
488
+ ? utils.bluetoothModels[parsedData[cnt + 1]][parsedData[cnt + 2]]
489
+ : utils.bluetoothAccessories[parsedData[cnt + 1]],
490
+ appendMask: parsedData[cnt + 4],
491
+ name:
492
+ parsedData[aNameIx] !== '' && appendMask[15] === '1'
493
+ ? parsedData[aNameIx]
494
+ : null,
495
+ mac:
496
+ parsedData[aMacIx] !== '' && appendMask[14] === '1'
497
+ ? parsedData[aMacIx]
498
+ : null,
499
+ status:
500
+ parsedData[aStatIx] !== '' && appendMask[13] === '1'
501
+ ? parseInt(parsedData[aStatIx])
502
+ : null,
503
+ batteryLevel:
504
+ parsedData[aBatIx] !== '' && appendMask[12] === '1'
505
+ ? parseInt(parsedData[aBatIx])
506
+ : null,
507
+ batteryPercentage:
508
+ parsedData[aBatpIx] !== '' && appendMask[2] === '1'
509
+ ? parseFloat(parsedData[aBatpIx])
510
+ : null,
511
+ accessoryData: {
512
+ rawData: parsedData[cnt + 3] !== '' ? parsedData[cnt + 3] : null,
513
+ temperature:
514
+ parsedData[aTmpIx] !== '' && appendMask[11] === '1'
515
+ ? parseInt(parsedData[aTmpIx])
516
+ : null,
517
+ humidity:
518
+ parsedData[aHumIx] !== '' && appendMask[10] === '1'
519
+ ? parseInt(parsedData[aHumIx])
520
+ : null,
521
+ outputStatus:
522
+ parsedData[ioIx] !== '' && appendMask[8] === '1'
523
+ ? parsedData[ioIx]
524
+ : null,
525
+ inputStatus:
526
+ parsedData[ioIx + 1] !== '' && appendMask[8] === '1'
527
+ ? parsedData[ioIx + 1]
528
+ : null,
529
+ analogInputStatus:
530
+ parsedData[ioIx + 2] !== '' && appendMask[8] === '1'
531
+ ? parsedData[ioIx + 2]
532
+ : null,
533
+ mode:
534
+ parsedData[modeIx] !== '' && appendMask[7] === '1'
535
+ ? parseInt(parsedData[modeIx])
536
+ : null,
537
+ event:
538
+ parsedData[aEvIx] !== '' && appendMask[7] === '1'
539
+ ? parseInt(parsedData[aEvIx])
540
+ : null,
541
+ tirePresure:
542
+ parsedData[pressIx] !== '' && appendMask[6] === '1'
543
+ ? parseInt(parsedData[pressIx])
544
+ : null,
545
+ timestamp:
546
+ parsedData[timeIx] !== '' && appendMask[5] === '1'
547
+ ? utils.parseDate(parsedData[timeIx])
548
+ : null,
549
+ enhancedTemperature:
550
+ parsedData[eTmpIx] !== '' && appendMask[4] === '1'
551
+ ? parseFloat(parsedData[eTmpIx])
552
+ : null,
553
+ magDevice: {
554
+ id:
555
+ parsedData[magIx] !== '' && appendMask[3] === '1'
556
+ ? parsedData[magIx]
557
+ : null,
558
+ eventCounter:
559
+ parsedData[magIx + 1] !== '' && appendMask[3] === '1'
560
+ ? parseInt(parsedData[magIx + 1])
561
+ : null,
562
+ magnetState:
563
+ parsedData[magIx + 2] !== '' && appendMask[3] === '1'
564
+ ? parseInt(parsedData[magIx + 2])
565
+ : null
566
+ },
567
+ relay: {
568
+ configResult:
569
+ parsedData[relIx] !== '' && appendMask[1] === '1'
570
+ ? parseInt(parsedData[relIx])
571
+ : null,
572
+ state:
573
+ parsedData[relIx + 1] !== '' && appendMask[1] === '1'
574
+ ? parseInt(parsedData[relIx + 1])
575
+ : null
576
+ }
577
+ }
578
+ })
579
+ cnt = appendMask[1] === '1' ? relIx + 1 : relIx + 2
580
+ }
581
+ externalData = Object.assign(externalData, {
582
+ btDevices: btDevices
583
+ })
584
+ }
585
+
586
+ data = Object.assign(data, {
587
+ externalData: externalData
588
+ })
589
+ } else if (command[1] === 'GTHBD') {
590
+ // Heartbeat. It must response an ACK command
591
+ data = Object.assign(data, {
592
+ alarm: utils.getAlarm(command[1], null)
593
+ })
594
+ } else if (command[1] === 'GTINF') {
595
+ // General Info Report
596
+ data = Object.assign(data, {
597
+ alarm: utils.getAlarm(command[1], null),
598
+ state: utils.states[parsedData[4]],
599
+ gsmInfo: {
600
+ SIM_ICC: parsedData[5],
601
+ networkType: utils.networkTypes[parsedData[10]],
602
+ RSSI: parseInt(parsedData[6], 10),
603
+ RSSI_quality: utils.getSignalStrength(
604
+ utils.networkTypes[parsedData[10]],
605
+ parseInt(parsedData[6], 10)
606
+ ), // Signal Strength
607
+ RSSI_percentage: utils.getSignalPercentage(
608
+ utils.networkTypes[parsedData[10]],
609
+ parseInt(parsedData[6], 10)
610
+ ), // Signal Percetange
611
+ GSM_quality:
612
+ parsedData[7] !== ''
613
+ ? 100 * parseInt(parseFloat(parsedData[7]) / 7, 10)
614
+ : null // Percentage
615
+ },
616
+ backupBattery: {
617
+ using: parsedData[11] !== '' && parseFloat(parsedData[11]) < 4.5,
618
+ voltage: parsedData[11] !== '' ? parseFloat(parsedData[11]) : null,
619
+ charging: parsedData[12] === '1'
620
+ },
621
+ externalGPSAntenna: utils.externalGPSAntennaOptions[parsedData[15]],
622
+ status: {
623
+ raw: parsedData[18] + parsedData[19] + parsedData[20],
624
+ sos: false,
625
+ input: {
626
+ '4': utils.nHexDigit(utils.hex2bin(parsedData[21][1]), 4)[0] === '1',
627
+ '3': utils.nHexDigit(utils.hex2bin(parsedData[21][1]), 4)[1] === '1',
628
+ '2': utils.nHexDigit(utils.hex2bin(parsedData[21][1]), 4)[2] === '1',
629
+ '1': utils.nHexDigit(utils.hex2bin(parsedData[21][1]), 4)[3] === '1'
630
+ },
631
+ output: {
632
+ '4': utils.nHexDigit(utils.hex2bin(parsedData[22][1]), 4)[0] === '1',
633
+ '3': utils.nHexDigit(utils.hex2bin(parsedData[22][1]), 4)[1] === '1',
634
+ '2': utils.nHexDigit(utils.hex2bin(parsedData[22][1]), 4)[2] === '1',
635
+ '1': utils.nHexDigit(utils.hex2bin(parsedData[22][1]), 4)[3] === '1'
636
+ },
637
+ charge: parsedData[12] === '1'
638
+ },
639
+ voltage: {
640
+ battery:
641
+ parsedData[11] !== ''
642
+ ? parseInt(100 * (parseFloat(parsedData[11]) / 4.5), 10)
643
+ : null, // percentage
644
+ inputCharge:
645
+ parsedData[9] !== '' ? parseFloat(parsedData[9]) / 1000 : null,
646
+ ada: parsedData[18] !== '' ? parseFloat(parsedData[18]) / 1000 : null,
647
+ adb: parsedData[19] !== '' ? parseFloat(parsedData[19]) / 1000 : null,
648
+ adc: parsedData[20] !== '' ? parseFloat(parsedData[20]) / 1000 : null
649
+ },
650
+ lastFixUTCTime:
651
+ parsedData[16] !== '' ? utils.parseDate(parsedData[16]) : null,
652
+ timezoneOffset: parsedData[23]
653
+ })
654
+ } else if (
655
+ command[1] === 'GTTOW' ||
656
+ command[1] === 'GTDIS' ||
657
+ command[1] === 'GTIOB' ||
658
+ command[1] === 'GTSPD' ||
659
+ command[1] === 'GTSOS' ||
660
+ command[1] === 'GTRTL' ||
661
+ command[1] === 'GTDOG' ||
662
+ command[1] === 'GTIGL' ||
663
+ command[1] === 'GTVGL' ||
664
+ command[1] === 'GTHBM'
665
+ ) {
666
+ // Common Alarms
667
+ let number = parsedData[6] !== '' ? parseInt(parsedData[6], 10) : 1
668
+ let index = 6 + 12 * number // position append mask
669
+ let satelliteInfo = false
670
+
671
+ // If get satellites is configured
672
+ if (utils.includeSatellites(parsedData[18])) {
673
+ index += 1
674
+ satelliteInfo = true
675
+ }
676
+
677
+ data = Object.assign(data, {
678
+ alarm: utils.getAlarm(command[1], parsedData[5], 'gv310lau'),
679
+ loc: {
680
+ type: 'Point',
681
+ coordinates: [parseFloat(parsedData[11]), parseFloat(parsedData[12])]
682
+ },
683
+ speed: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
684
+ gpsStatus: utils.checkGps(
685
+ parseFloat(parsedData[11]),
686
+ parseFloat(parsedData[12])
687
+ ),
688
+ hdop: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
689
+ status: null,
690
+ azimuth: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
691
+ altitude: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
692
+ datetime: parsedData[13] !== '' ? utils.parseDate(parsedData[13]) : null,
693
+ voltage: {
694
+ battery: null,
695
+ inputCharge: null,
696
+ ada: null,
697
+ adb: null,
698
+ adc: null
699
+ },
700
+ mcc: parsedData[14] !== '' ? parseInt(parsedData[14], 10) : null,
701
+ mnc: parsedData[15] !== '' ? parseInt(parsedData[15], 10) : null,
702
+ lac: parsedData[16] !== '' ? parseInt(parsedData[16], 16) : null,
703
+ cid: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
704
+ satellites:
705
+ satelliteInfo && parsedData[index] !== ''
706
+ ? parseInt(parsedData[index])
707
+ : null,
708
+ odometer:
709
+ parsedData[index + 1] !== '' ? parseFloat(parsedData[index + 1]) : null,
710
+ overspeedStatus:
711
+ parseInt(parsedData[4], 10) === 1 || parseInt(parsedData[4], 10) === 3
712
+ ? parsedData[index + 2] === '1'
713
+ : null,
714
+ lastSpeedStateDuration:
715
+ parseInt(parsedData[4], 10) === 2
716
+ ? parsedData[index + 2]
717
+ : parseInt(parsedData[4], 10) === 3 ? parsedData[index + 3] : null,
718
+ hourmeter: null
719
+ })
720
+ } else if (command[1] === 'GTEPS' || command[1] === 'GTAIS') {
721
+ // External low battery and Low voltage for analog input
722
+ let number = parsedData[6] !== '' ? parseInt(parsedData[6], 10) : 1
723
+ let index = 6 + 12 * number // position append mask
724
+ let satelliteInfo = false
725
+
726
+ // If get satellites is configured
727
+ if (utils.includeSatellites(parsedData[18])) {
728
+ index += 1
729
+ satelliteInfo = true
730
+ }
731
+
732
+ data = Object.assign(data, {
733
+ alarm: utils.getAlarm(command[1], parsedData[5]),
734
+ loc: {
735
+ type: 'Point',
736
+ coordinates: [parseFloat(parsedData[11]), parseFloat(parsedData[12])]
737
+ },
738
+ speed: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
739
+ gpsStatus: utils.checkGps(
740
+ parseFloat(parsedData[11]),
741
+ parseFloat(parsedData[12])
742
+ ),
743
+ hdop: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
744
+ status: null,
745
+ azimuth: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
746
+ altitude: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
747
+ datetime: parsedData[13] !== '' ? utils.parseDate(parsedData[13]) : null,
748
+ voltage: {
749
+ battery: parsedData[4] !== '' ? parseFloat(parsedData[4]) / 1000 : null,
750
+ inputCharge: null,
751
+ ada: null,
752
+ adb: null,
753
+ adc: null
754
+ },
755
+ mcc: parsedData[14] !== '' ? parseInt(parsedData[14], 10) : null,
756
+ mnc: parsedData[15] !== '' ? parseInt(parsedData[15], 10) : null,
757
+ lac: parsedData[16] !== '' ? parseInt(parsedData[16], 16) : null,
758
+ cid: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
759
+ satellites:
760
+ satelliteInfo && parsedData[index] !== ''
761
+ ? parseInt(parsedData[index])
762
+ : null,
763
+ odometer:
764
+ parsedData[index + 1] !== '' ? parseFloat(parsedData[index + 1]) : null,
765
+ hourmeter: null
766
+ })
767
+ } else if (command[1] === 'GTTMP') {
768
+ // Temperature Alarm
769
+ let number = parsedData[7] !== '' ? parseInt(parsedData[7], 10) : 1
770
+ let index = 7 + 12 * number // position append mask
771
+ let satelliteInfo = false
772
+
773
+ // If get satellites is configured
774
+ if (utils.includeSatellites(parsedData[19])) {
775
+ index += 1
776
+ satelliteInfo = true
777
+ }
778
+
779
+ data = Object.assign(data, {
780
+ alarm: utils.getAlarm(command[1], parsedData[6], [
781
+ parsedData[index + 11],
782
+ parsedData[index + 13]
783
+ ]),
784
+ loc: {
785
+ type: 'Point',
786
+ coordinates: [parseFloat(parsedData[12]), parseFloat(parsedData[13])]
787
+ },
788
+ speed: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
789
+ gpsStatus: utils.checkGps(
790
+ parseFloat(parsedData[12]),
791
+ parseFloat(parsedData[13])
792
+ ),
793
+ hdop: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
794
+ status: {
795
+ // parsedData[24]
796
+ raw: `${parsedData[index + 6]}${parsedData[index + 7]}`,
797
+ sos: false,
798
+ input: {
799
+ '4':
800
+ utils.nHexDigit(utils.hex2bin(parsedData[index + 6][1]), 4)[0] ===
801
+ '1',
802
+ '3':
803
+ utils.nHexDigit(utils.hex2bin(parsedData[index + 6][1]), 4)[1] ===
804
+ '1',
805
+ '2':
806
+ utils.nHexDigit(utils.hex2bin(parsedData[index + 6][1]), 4)[2] ===
807
+ '1',
808
+ '1':
809
+ utils.nHexDigit(utils.hex2bin(parsedData[index + 6][1]), 4)[3] ===
810
+ '1'
811
+ },
812
+ output: {
813
+ '3':
814
+ utils.nHexDigit(utils.hex2bin(parsedData[index + 7][1]), 4)[1] ===
815
+ '1',
816
+ '2':
817
+ utils.nHexDigit(utils.hex2bin(parsedData[index + 7][1]), 4)[2] ===
818
+ '1',
819
+ '1':
820
+ utils.nHexDigit(utils.hex2bin(parsedData[index + 7][1]), 4)[3] ===
821
+ '1'
822
+ },
823
+ charge: parseFloat(parsedData[5]) > 5,
824
+ state: null
825
+ },
826
+ azimuth: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
827
+ altitude: parsedData[11] !== '' ? parseFloat(parsedData[11]) : null,
828
+ datetime: parsedData[14] !== '' ? utils.parseDate(parsedData[14]) : null,
829
+ voltage: {
830
+ battery: null, // percentage
831
+ inputCharge:
832
+ parsedData[5] !== '' ? parseFloat(parsedData[5]) / 1000 : null,
833
+ ada:
834
+ parsedData[index + 3] !== ''
835
+ ? parseFloat(parsedData[index + 3]) / 1000
836
+ : null,
837
+ adb:
838
+ parsedData[index + 4] !== ''
839
+ ? parseFloat(parsedData[index + 4]) / 1000
840
+ : null,
841
+ adc:
842
+ parsedData[index + 5] !== ''
843
+ ? parseFloat(parsedData[index + 5]) / 1000
844
+ : null
845
+ },
846
+ mcc: parsedData[15] !== '' ? parseInt(parsedData[15], 10) : null,
847
+ mnc: parsedData[16] !== '' ? parseInt(parsedData[16], 10) : null,
848
+ lac: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
849
+ cid: parsedData[18] !== '' ? parseInt(parsedData[18], 16) : null,
850
+ satellites:
851
+ satelliteInfo && parsedData[index] !== ''
852
+ ? parseInt(parsedData[index], 10)
853
+ : null,
854
+ odometer:
855
+ parsedData[index + 1] !== '' ? parseFloat(parsedData[index + 1]) : null,
856
+ hourmeter:
857
+ parsedData[index + 2] !== ''
858
+ ? utils.getHoursForHourmeter(parsedData[index + 2])
859
+ : null
860
+ })
861
+ } else if (
862
+ command[1] === 'GTPNA' ||
863
+ command[1] === 'GTPFA' ||
864
+ command[1] === 'GTPDP'
865
+ ) {
866
+ // Event report (It uses the last GPS data and MCC info)
867
+ data = Object.assign(data, {
868
+ alarm: utils.getAlarm(command[1], null),
869
+ loc: null,
870
+ speed: null,
871
+ gpsStatus: null,
872
+ hdop: null,
873
+ status: null,
874
+ azimuth: null,
875
+ altitude: null,
876
+ datetime: parsedData[4] !== '' ? utils.parseDate(parsedData[4]) : null,
877
+ voltage: {
878
+ battery: null,
879
+ inputCharge: null,
880
+ ada: null,
881
+ adb: null,
882
+ adc: null
883
+ },
884
+ mcc: null,
885
+ mnc: null,
886
+ lac: null,
887
+ cid: null,
888
+ odometer: null,
889
+ hourmeter: null
890
+ })
891
+ } else if (command[1] === 'GTPNR' || command[1] === 'GTPFR') {
892
+ // Power on/off reason
893
+ data = Object.assign(data, {
894
+ alarm: utils.getAlarm(command[1], parsedData[4]),
895
+ loc: null,
896
+ speed: null,
897
+ gpsStatus: null,
898
+ hdop: null,
899
+ status: null,
900
+ azimuth: null,
901
+ altitude: null,
902
+ datetime: parsedData[9] !== '' ? utils.parseDate(parsedData[9]) : null,
903
+ voltage: {
904
+ battery: null,
905
+ inputCharge: null,
906
+ ada: null,
907
+ adb: null,
908
+ adc: null
909
+ },
910
+ mcc: null,
911
+ mnc: null,
912
+ lac: null,
913
+ cid: null,
914
+ odometer: null,
915
+ hourmeter: null
916
+ })
917
+ } else if (
918
+ command[1] === 'GTMPN' ||
919
+ command[1] === 'GTMPF' ||
920
+ command[1] === 'GTBTC'
921
+ ) {
922
+ data = Object.assign(data, {
923
+ alarm: utils.getAlarm(command[1], null),
924
+ loc: {
925
+ type: 'Point',
926
+ coordinates: [parseFloat(parsedData[8]), parseFloat(parsedData[9])]
927
+ },
928
+ speed: parsedData[5] !== '' ? parseFloat(parsedData[5]) : null,
929
+ gpsStatus: utils.checkGps(
930
+ parseFloat(parsedData[8]),
931
+ parseFloat(parsedData[9])
932
+ ),
933
+ hdop: parsedData[4] !== '' ? parseFloat(parsedData[4]) : null,
934
+ status: null,
935
+ azimuth: parsedData[6] !== '' ? parseFloat(parsedData[6]) : null,
936
+ altitude: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
937
+ datetime: parsedData[10] !== '' ? utils.parseDate(parsedData[10]) : null,
938
+ voltage: {
939
+ battery: null,
940
+ inputCharge: null,
941
+ ada: null,
942
+ adb: null,
943
+ adc: null
944
+ },
945
+ mcc: parsedData[11] !== '' ? parseInt(parsedData[11], 10) : null,
946
+ mnc: parsedData[12] !== '' ? parseInt(parsedData[12], 10) : null,
947
+ lac: parsedData[13] !== '' ? parseInt(parsedData[13], 16) : null,
948
+ cid: parsedData[14] !== '' ? parseInt(parsedData[14], 16) : null,
949
+ odometer: null,
950
+ hourmeter: null
951
+ })
952
+ } else if (
953
+ command[1] === 'GTJDR' ||
954
+ command[1] === 'GTANT' ||
955
+ command[1] === 'GTRMD' ||
956
+ command[1] === 'GTCRA' ||
957
+ command[1] === 'GTBPL' ||
958
+ command[1] === 'GTSTT' ||
959
+ command[1] === 'GTAVC' ||
960
+ command[1] === 'GTWPB'
961
+ ) {
962
+ let index = 16 // position append mask
963
+ let satelliteInfo = false
964
+
965
+ // If get satellites is configured
966
+ if (utils.includeSatellites(parsedData[index])) {
967
+ index += 1
968
+ satelliteInfo = true
969
+ }
970
+
971
+ data = Object.assign(data, {
972
+ alarm: utils.getAlarm(command[1], parsedData[4]),
973
+ loc: {
974
+ type: 'Point',
975
+ coordinates: [parseFloat(parsedData[9]), parseFloat(parsedData[10])]
976
+ },
977
+ speed: parsedData[6] !== '' ? parseFloat(parsedData[6]) : null,
978
+ gpsStatus: utils.checkGps(
979
+ parseFloat(parsedData[9]),
980
+ parseFloat(parsedData[10])
981
+ ),
982
+ hdop: parsedData[5] !== '' ? parseFloat(parsedData[5]) : null,
983
+ status: null,
984
+ azimuth: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
985
+ altitude: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
986
+ datetime: parsedData[11] !== '' ? utils.parseDate(parsedData[11]) : null,
987
+ voltage: {
988
+ battery: null,
989
+ inputCharge: null,
990
+ ada: null,
991
+ adb: null,
992
+ adc: null
993
+ },
994
+ mcc: parsedData[12] !== '' ? parseInt(parsedData[12], 10) : null,
995
+ mnc: parsedData[13] !== '' ? parseInt(parsedData[13], 10) : null,
996
+ lac: parsedData[14] !== '' ? parseInt(parsedData[14], 16) : null,
997
+ cid: parsedData[15] !== '' ? parseInt(parsedData[15], 16) : null,
998
+ satellites:
999
+ satelliteInfo && parsedData[index] !== ''
1000
+ ? parseInt(parsedData[index], 10)
1001
+ : null,
1002
+ odometer: null,
1003
+ hourmeter: null
1004
+ })
1005
+ } else if (command[1] === 'GTCRG') {
1006
+ let number = parsedData[5] !== '' ? parseInt(parsedData[5]) : 1
1007
+ let start = 6
1008
+
1009
+ data = Object.assign(data, {
1010
+ alarm: utils.getAlarm(command[1], parsedData[4]),
1011
+ voltage: {
1012
+ battery: null,
1013
+ inputCharge: null,
1014
+ ada: null,
1015
+ adb: null,
1016
+ adc: null
1017
+ }
1018
+ })
1019
+
1020
+ let more = []
1021
+ for (let i = 1; i <= number; i++) {
1022
+ more.push({
1023
+ id: parsedData[start] !== '' ? parseInt(parsedData[start]) : null,
1024
+ loc: {
1025
+ type: 'Point',
1026
+ coordinates: [
1027
+ parseFloat(parsedData[start + 5]),
1028
+ parseFloat(parsedData[start + 6])
1029
+ ]
1030
+ },
1031
+ speed:
1032
+ parsedData[start + 2] !== ''
1033
+ ? parseFloat(parsedData[start + 2])
1034
+ : null,
1035
+ gpsStatus: utils.checkGps(
1036
+ parseFloat(parsedData[start + 5]),
1037
+ parseFloat(parsedData[start + 6])
1038
+ ),
1039
+ hdop:
1040
+ parsedData[start + 1] !== ''
1041
+ ? parseFloat(parsedData[start + 1])
1042
+ : null,
1043
+ azimuth:
1044
+ parsedData[start + 3] !== ''
1045
+ ? parseFloat(parsedData[start + 3])
1046
+ : null,
1047
+ altitude:
1048
+ parsedData[start + 4] !== ''
1049
+ ? parseFloat(parsedData[start + 4])
1050
+ : null,
1051
+ datetime:
1052
+ parsedData[start + 7] !== ''
1053
+ ? utils.parseDate(parsedData[start + 7])
1054
+ : null
1055
+ })
1056
+ start += 8
1057
+ }
1058
+
1059
+ data = Object.assign(data, {
1060
+ gnssData: more
1061
+ })
1062
+ } else if (command[1] === 'GTJDS') {
1063
+ let index = 17 // position append mask
1064
+ let satelliteInfo = false
1065
+
1066
+ // If get satellites is configured
1067
+ if (utils.includeSatellites(parsedData[17])) {
1068
+ index += 1
1069
+ satelliteInfo = true
1070
+ }
1071
+
1072
+ data = Object.assign(data, {
1073
+ alarm: utils.getAlarm(command[1], parsedData[4]),
1074
+ loc: {
1075
+ type: 'Point',
1076
+ coordinates: [parseFloat(parsedData[10]), parseFloat(parsedData[11])]
1077
+ },
1078
+ speed: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
1079
+ gpsStatus: utils.checkGps(
1080
+ parseFloat(parsedData[10]),
1081
+ parseFloat(parsedData[11])
1082
+ ),
1083
+ hdop: parsedData[6] !== '' ? parseFloat(parsedData[6]) : null,
1084
+ status: null,
1085
+ azimuth: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
1086
+ altitude: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
1087
+ datetime: parsedData[12] !== '' ? utils.parseDate(parsedData[12]) : null,
1088
+ voltage: {
1089
+ battery: null,
1090
+ inputCharge: null,
1091
+ ada: null,
1092
+ adb: null,
1093
+ adc: null
1094
+ },
1095
+ mcc: parsedData[13] !== '' ? parseInt(parsedData[13], 10) : null,
1096
+ mnc: parsedData[14] !== '' ? parseInt(parsedData[14], 10) : null,
1097
+ lac: parsedData[15] !== '' ? parseInt(parsedData[15], 16) : null,
1098
+ cid: parsedData[16] !== '' ? parseInt(parsedData[16], 16) : null,
1099
+ satellites:
1100
+ satelliteInfo && parsedData[index] !== ''
1101
+ ? parseInt(parsedData[index], 10)
1102
+ : null,
1103
+ odometer: null,
1104
+ hourmeter: null
1105
+ })
1106
+ } else if (command[1] === 'GTIGN' || command[1] === 'GTIGF') {
1107
+ let index = 16 // position append mask
1108
+ let satelliteInfo = false
1109
+
1110
+ // If get satellites is configured
1111
+ if (utils.includeSatellites(parsedData[index])) {
1112
+ index += 1
1113
+ satelliteInfo = true
1114
+ }
1115
+
1116
+ data = Object.assign(data, {
1117
+ alarm: utils.getAlarm(command[1], parsedData[4]),
1118
+ loc: {
1119
+ type: 'Point',
1120
+ coordinates: [parseFloat(parsedData[9]), parseFloat(parsedData[10])]
1121
+ },
1122
+ speed: parsedData[6] !== '' ? parseFloat(parsedData[6]) : null,
1123
+ gpsStatus: utils.checkGps(
1124
+ parseFloat(parsedData[9]),
1125
+ parseFloat(parsedData[10])
1126
+ ),
1127
+ hdop: parsedData[5] !== '' ? parseFloat(parsedData[5]) : null,
1128
+ status: null,
1129
+ azimuth: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
1130
+ altitude: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
1131
+ datetime: parsedData[11] !== '' ? utils.parseDate(parsedData[11]) : null,
1132
+ voltage: {
1133
+ battery: null,
1134
+ inputCharge: null,
1135
+ ada: null,
1136
+ adb: null,
1137
+ adc: null
1138
+ },
1139
+ mcc: parsedData[12] !== '' ? parseInt(parsedData[12], 10) : null,
1140
+ mnc: parsedData[13] !== '' ? parseInt(parsedData[13], 10) : null,
1141
+ lac: parsedData[14] !== '' ? parseInt(parsedData[14], 16) : null,
1142
+ cid: parsedData[15] !== '' ? parseInt(parsedData[15], 16) : null,
1143
+ satellites:
1144
+ satelliteInfo && parsedData[index] !== ''
1145
+ ? parseInt(parsedData[index], 10)
1146
+ : null,
1147
+ odometer:
1148
+ parsedData[index + 2] !== '' ? parseFloat(parsedData[index + 2]) : null,
1149
+ hourmeter:
1150
+ parsedData[index + 1] !== ''
1151
+ ? utils.getHoursForHourmeter(parsedData[index + 1])
1152
+ : null
1153
+ })
1154
+ } else if (command[1] === 'GTIDN' || command[1] === 'GTIDF') {
1155
+ let index = 17 // position append mask
1156
+ let satelliteInfo = false
1157
+
1158
+ // If get satellites is configured
1159
+ if (utils.includeSatellites(parsedData[index])) {
1160
+ index += 1
1161
+ satelliteInfo = true
1162
+ }
1163
+
1164
+ data = Object.assign(data, {
1165
+ alarm: utils.getAlarm(command[1], parsedData[5]),
1166
+ loc: {
1167
+ type: 'Point',
1168
+ coordinates: [parseFloat(parsedData[10]), parseFloat(parsedData[11])]
1169
+ },
1170
+ speed: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
1171
+ gpsStatus: utils.checkGps(
1172
+ parseFloat(parsedData[10]),
1173
+ parseFloat(parsedData[11])
1174
+ ),
1175
+ hdop: parsedData[6] !== '' ? parseFloat(parsedData[6]) : null,
1176
+ status: null,
1177
+ azimuth: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
1178
+ altitude: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
1179
+ datetime: parsedData[12] !== '' ? utils.parseDate(parsedData[12]) : null,
1180
+ voltage: {
1181
+ battery: null,
1182
+ inputCharge: null,
1183
+ ada: null,
1184
+ adb: null,
1185
+ adc: null
1186
+ },
1187
+ mcc: parsedData[13] !== '' ? parseInt(parsedData[13], 10) : null,
1188
+ mnc: parsedData[14] !== '' ? parseInt(parsedData[14], 10) : null,
1189
+ lac: parsedData[15] !== '' ? parseInt(parsedData[15], 16) : null,
1190
+ cid: parsedData[16] !== '' ? parseInt(parsedData[16], 16) : null,
1191
+ satellites:
1192
+ satelliteInfo && parsedData[index] !== ''
1193
+ ? parseInt(parsedData[index], 10)
1194
+ : null,
1195
+ odometer:
1196
+ parsedData[index + 1] !== '' ? parseFloat(parsedData[index + 1]) : null,
1197
+ hourmeter: null
1198
+ })
1199
+ } else if (
1200
+ command[1] === 'GTSTR' ||
1201
+ command[1] === 'GTSTP' ||
1202
+ command[1] === 'GTLSP'
1203
+ ) {
1204
+ let index = 17 // position append mask
1205
+ let satelliteInfo = false
1206
+
1207
+ // If get satellites is configured
1208
+ if (utils.includeSatellites(parsedData[index])) {
1209
+ index += 1
1210
+ satelliteInfo = true
1211
+ }
1212
+
1213
+ data = Object.assign(data, {
1214
+ alarm: utils.getAlarm(command[1], null),
1215
+ loc: {
1216
+ type: 'Point',
1217
+ coordinates: [parseFloat(parsedData[10]), parseFloat(parsedData[11])]
1218
+ },
1219
+ speed: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
1220
+ gpsStatus: utils.checkGps(
1221
+ parseFloat(parsedData[10]),
1222
+ parseFloat(parsedData[11])
1223
+ ),
1224
+ hdop: parsedData[6] !== '' ? parseFloat(parsedData[6]) : null,
1225
+ status: null,
1226
+ azimuth: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
1227
+ altitude: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
1228
+ datetime: parsedData[12] !== '' ? utils.parseDate(parsedData[12]) : null,
1229
+ voltage: {
1230
+ battery: null,
1231
+ inputCharge: null,
1232
+ ada: null,
1233
+ adb: null,
1234
+ adc: null
1235
+ },
1236
+ mcc: parsedData[13] !== '' ? parseInt(parsedData[13], 10) : null,
1237
+ mnc: parsedData[14] !== '' ? parseInt(parsedData[14], 10) : null,
1238
+ lac: parsedData[15] !== '' ? parseInt(parsedData[15], 16) : null,
1239
+ cid: parsedData[16] !== '' ? parseInt(parsedData[16], 16) : null,
1240
+ satellites:
1241
+ satelliteInfo && parsedData[index] !== ''
1242
+ ? parseInt(parsedData[index], 10)
1243
+ : null,
1244
+ odometer:
1245
+ parsedData[index + 1] !== '' ? parseFloat(parsedData[index + 1]) : null,
1246
+ hourmeter: null
1247
+ })
1248
+ } else if (command[1] === 'GTGSS') {
1249
+ // GPS Status
1250
+ let index = 19 // position append mask
1251
+ let satelliteInfo = false
1252
+
1253
+ // If get satellites is configured
1254
+ if (utils.includeSatellites(parsedData[index])) {
1255
+ index += 1
1256
+ satelliteInfo = true
1257
+ }
1258
+
1259
+ data = Object.assign(data, {
1260
+ alarm: utils.getAlarm(command[1], parsedData[4]),
1261
+ loc: {
1262
+ type: 'Point',
1263
+ coordinates: [parseFloat(parsedData[12]), parseFloat(parsedData[13])]
1264
+ },
1265
+ speed: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
1266
+ gpsStatus: utils.checkGps(
1267
+ parseFloat(parsedData[12]),
1268
+ parseFloat(parsedData[13])
1269
+ ),
1270
+ hdop: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
1271
+ status: null,
1272
+ azimuth: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
1273
+ altitude: parsedData[11] !== '' ? parseFloat(parsedData[11]) : null,
1274
+ datetime: parsedData[14] !== '' ? utils.parseDate(parsedData[14]) : null,
1275
+ voltage: {
1276
+ battery: null,
1277
+ inputCharge: null,
1278
+ ada: null,
1279
+ adb: null,
1280
+ adc: null
1281
+ },
1282
+ mcc: parsedData[15] !== '' ? parseInt(parsedData[15], 10) : null,
1283
+ mnc: parsedData[16] !== '' ? parseInt(parsedData[16], 10) : null,
1284
+ lac: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
1285
+ cid: parsedData[18] !== '' ? parseInt(parsedData[18], 16) : null,
1286
+ usedSatellites: parsedData[5] !== '' ? parseInt(parsedData[5], 16) : null,
1287
+ satellites:
1288
+ satelliteInfo && parsedData[index] !== ''
1289
+ ? parseInt(parsedData[index], 10)
1290
+ : null,
1291
+ odometer: null,
1292
+ hourmeter: null
1293
+ })
1294
+ } else if (command[1] === 'GTIDA') {
1295
+ // iButton
1296
+ let number = parsedData[7] !== '' ? parseInt(parsedData[7], 10) : 1
1297
+ let index = 7 + 12 * number // position append mask
1298
+ let satelliteInfo = false
1299
+
1300
+ // If get satellites is configured
1301
+ if (utils.includeSatellites(parsedData[index])) {
1302
+ index += 1
1303
+ satelliteInfo = true
1304
+ }
1305
+
1306
+ data = Object.assign(data, {
1307
+ alarm: utils.getAlarm(command[1], `${parsedData[5]},${parsedData[6]}`),
1308
+ loc: {
1309
+ type: 'Point',
1310
+ coordinates: [parseFloat(parsedData[12]), parseFloat(parsedData[13])]
1311
+ },
1312
+ speed: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
1313
+ gpsStatus: utils.checkGps(
1314
+ parseFloat(parsedData[12]),
1315
+ parseFloat(parsedData[13])
1316
+ ),
1317
+ hdop: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
1318
+ status: null,
1319
+ azimuth: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
1320
+ altitude: parsedData[11] !== '' ? parseFloat(parsedData[11]) : null,
1321
+ datetime: parsedData[14] !== '' ? utils.parseDate(parsedData[14]) : null,
1322
+ voltage: {
1323
+ battery: null,
1324
+ inputCharge: null,
1325
+ ada: null,
1326
+ adb: null,
1327
+ adc: null
1328
+ },
1329
+ mcc: parsedData[15] !== '' ? parseInt(parsedData[15], 10) : null,
1330
+ mnc: parsedData[16] !== '' ? parseInt(parsedData[16], 10) : null,
1331
+ lac: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
1332
+ cid: parsedData[18] !== '' ? parseInt(parsedData[18], 16) : null,
1333
+ satellites:
1334
+ satelliteInfo && parsedData[index] !== ''
1335
+ ? parseInt(parsedData[index], 10)
1336
+ : null,
1337
+ odometer:
1338
+ parsedData[index + 1] !== '' ? parseFloat(parsedData[index + 1]) : null,
1339
+ hourmeter: null
1340
+ })
1341
+ } else if (command[1] === 'GTCAN') {
1342
+ let index = 67 // position append mask
1343
+ let satelliteInfo = false
1344
+
1345
+ // If get satellites is configured
1346
+ if (utils.includeSatellites(parsedData[index])) {
1347
+ index += 1
1348
+ satelliteInfo = true
1349
+ }
1350
+
1351
+ let inicatorsBin =
1352
+ parsedData[24] !== ''
1353
+ ? utils.nHexDigit(utils.hex2bin(parsedData[24]), 16)
1354
+ : null
1355
+ let lights =
1356
+ parsedData[25] !== ''
1357
+ ? utils.nHexDigit(utils.hex2bin(parsedData[25]), 8)
1358
+ : null
1359
+ let doors =
1360
+ parsedData[26] !== ''
1361
+ ? utils.nHexDigit(utils.hex2bin(parsedData[26]), 8)
1362
+ : null
1363
+ let canExpansionMask =
1364
+ parsedData[29] !== ''
1365
+ ? utils
1366
+ .nHexDigit(utils.hex2bin(parsedData[29]), 32)
1367
+ .split('')
1368
+ .reverse()
1369
+ .join('')
1370
+ : null
1371
+ let expansionBin =
1372
+ parsedData[50] !== ''
1373
+ ? utils
1374
+ .nHexDigit(utils.hex2bin(parsedData[50]), 16)
1375
+ .split('')
1376
+ .reverse()
1377
+ .join('')
1378
+ : null
1379
+ let tachographBin =
1380
+ parsedData[23] !== ''
1381
+ ? utils
1382
+ .nHexDigit(utils.hex2bin(parsedData[23]), 8)
1383
+ .split('')
1384
+ .reverse()
1385
+ .join('')
1386
+ : null
1387
+
1388
+ data = Object.assign(data, {
1389
+ alarm: utils.getAlarm(command[1], parsedData[4]),
1390
+ loc: {
1391
+ type: 'Point',
1392
+ coordinates: [parseFloat(parsedData[60]), parseFloat(parsedData[61])]
1393
+ },
1394
+ speed: parsedData[57] !== '' ? parseFloat(parsedData[57]) : null,
1395
+ gpsStatus: utils.checkGps(
1396
+ parseFloat(parsedData[60]),
1397
+ parseFloat(parsedData[61])
1398
+ ),
1399
+ hdop: parsedData[56] !== '' ? parseFloat(parsedData[56]) : null,
1400
+ status: null,
1401
+ azimuth: parsedData[58] !== '' ? parseFloat(parsedData[58]) : null,
1402
+ altitude: parsedData[59] !== '' ? parseFloat(parsedData[59]) : null,
1403
+ datetime: parsedData[62] !== '' ? utils.parseDate(parsedData[62]) : null,
1404
+ voltage: {
1405
+ battery: null,
1406
+ inputCharge: null,
1407
+ ada: null,
1408
+ adb: null,
1409
+ adc: null
1410
+ },
1411
+ mcc: parsedData[63] !== '' ? parseInt(parsedData[63], 10) : null,
1412
+ mnc: parsedData[64] !== '' ? parseInt(parsedData[64], 10) : null,
1413
+ lac: parsedData[65] !== '' ? parseInt(parsedData[65], 16) : null,
1414
+ cid: parsedData[66] !== '' ? parseInt(parsedData[66], 16) : null,
1415
+ satellites:
1416
+ satelliteInfo && parsedData[index]
1417
+ ? parseInt(parsedData[index], 10)
1418
+ : null,
1419
+ odometer: null,
1420
+ hourmeter: null,
1421
+ can: {
1422
+ comunicationOk: parsedData[5] === '1',
1423
+ vin: parsedData[7] !== '' ? parsedData[7] : null,
1424
+ ignitionKey: parsedData[8] !== '' ? parseInt(parsedData[8], 10) : null,
1425
+ distance: parsedData[9] !== '' ? parsedData[9] : null,
1426
+ fuelUsed: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null, // float
1427
+ rpm: parsedData[11] !== '' ? parseInt(parsedData[11], 10) : null, // int
1428
+ speed: parsedData[12] !== '' ? parseFloat(parsedData[12]) : null,
1429
+ coolantTemp:
1430
+ parsedData[13] !== '' ? parseInt(parsedData[13], 10) : null,
1431
+ fuelConsumption: parsedData[14] !== '' ? parsedData[14] : null,
1432
+ fuelLevel: parsedData[15] !== '' ? parsedData[15] : null,
1433
+ range: parsedData[16] !== '' ? parsedData[16] : null,
1434
+ acceleratorPressure:
1435
+ parsedData[17] !== '' ? parseFloat(parsedData[17]) : null, // %
1436
+ engineHours: parsedData[18] !== '' ? parseFloat(parsedData[18]) : null,
1437
+ drivingTime: parsedData[19] !== '' ? parseFloat(parsedData[19]) : null,
1438
+ idleTime: parsedData[20] !== '' ? parseFloat(parsedData[20]) : null,
1439
+ idleFuelUsed: parsedData[21] !== '' ? parseFloat(parsedData[21]) : null,
1440
+ axleWight: parsedData[22] !== '' ? parsedData[22] : null,
1441
+ tachograph: {
1442
+ raw: parsedData[23] !== '' ? parsedData[23] : null,
1443
+ validDriverData: tachographBin ? tachographBin[7] === '1' : null,
1444
+ insertedDriverCard: tachographBin ? tachographBin[5] === '1' : null,
1445
+ driverWorkingState: tachographBin
1446
+ ? utils.dWorkingStates[parseInt(tachographBin.substring(3, 5), 2)]
1447
+ : null,
1448
+ drivingTimeState: tachographBin
1449
+ ? utils.dTimeStates[parseInt(tachographBin.substring(5, 8), 2)]
1450
+ : null
1451
+ },
1452
+ indicators: {
1453
+ raw: parsedData[24] !== '' ? parsedData[24] : null,
1454
+ lowFuel: inicatorsBin ? inicatorsBin[0] === '1' : null,
1455
+ driverSeatbelt: inicatorsBin ? inicatorsBin[1] === '1' : null,
1456
+ airConditioning: inicatorsBin ? inicatorsBin[2] === '1' : null,
1457
+ cruiseControl: inicatorsBin ? inicatorsBin[3] === '1' : null,
1458
+ brakePedal: inicatorsBin ? inicatorsBin[4] === '1' : null,
1459
+ clutchPedal: inicatorsBin ? inicatorsBin[5] === '1' : null,
1460
+ handbrake: inicatorsBin ? inicatorsBin[6] === '1' : null,
1461
+ centralLock: inicatorsBin ? inicatorsBin[7] === '1' : null,
1462
+ reverseGear: inicatorsBin ? inicatorsBin[8] === '1' : null,
1463
+ runningLights: inicatorsBin ? inicatorsBin[9] === '1' : null,
1464
+ lowBeams: inicatorsBin ? inicatorsBin[10] === '1' : null,
1465
+ highBeams: inicatorsBin ? inicatorsBin[11] === '1' : null,
1466
+ rearFogLights: inicatorsBin ? inicatorsBin[12] === '1' : null,
1467
+ frontFogLights: inicatorsBin ? inicatorsBin[13] === '1' : null,
1468
+ doors: inicatorsBin ? inicatorsBin[14] === '1' : null,
1469
+ trunk: inicatorsBin ? inicatorsBin[15] === '1' : null
1470
+ },
1471
+ lights: {
1472
+ raw: parsedData[25] !== '' ? parsedData[25] : null,
1473
+ running: lights ? lights[0] === '1' : null,
1474
+ lowBeams: lights ? lights[1] === '1' : null,
1475
+ frontFog: lights ? lights[2] === '1' : null,
1476
+ rearFog: lights ? lights[3] === '1' : null,
1477
+ hazard: lights ? lights[4] === '1' : null
1478
+ },
1479
+ doors: {
1480
+ raw: parsedData[26] !== '' ? parsedData[26] : null,
1481
+ driver: doors ? doors[0] === '1' : null,
1482
+ passenger: doors ? doors[1] === '1' : null,
1483
+ rearLeft: doors ? doors[2] === '1' : null,
1484
+ rearRight: doors ? doors[3] === '1' : null,
1485
+ trunk: doors ? doors[4] === '1' : null,
1486
+ hood: doors ? doors[5] === '1' : null
1487
+ },
1488
+ overSpeedTime: parsedData[27] !== '' ? parsedData[27] : null,
1489
+ overSpeedEngineTime: parsedData[28] !== '' ? parsedData[28] : null,
1490
+ canReportExpansionMask: {
1491
+ raw: parsedData[29] !== '' ? parsedData[29] : null,
1492
+ engineTorque: canExpansionMask ? canExpansionMask[23] === '1' : null,
1493
+ rapidAccelerations: canExpansionMask
1494
+ ? canExpansionMask[22] === '1'
1495
+ : null,
1496
+ rapidBrakings: canExpansionMask ? canExpansionMask[21] === '1' : null,
1497
+ expansionInformation: canExpansionMask
1498
+ ? canExpansionMask[20] === '1'
1499
+ : null,
1500
+ registrationNumber: canExpansionMask
1501
+ ? canExpansionMask[19] === '1'
1502
+ : null,
1503
+ tachographDriver2Name: canExpansionMask
1504
+ ? canExpansionMask[18] === '1'
1505
+ : null,
1506
+ tachographDriver1Name: canExpansionMask
1507
+ ? canExpansionMask[17] === '1'
1508
+ : null,
1509
+ tachographDriver2Card: canExpansionMask
1510
+ ? canExpansionMask[16] === '1'
1511
+ : null,
1512
+ tachographDriver1Card: canExpansionMask
1513
+ ? canExpansionMask[15] === '1'
1514
+ : null,
1515
+ totalBrakeApplications: canExpansionMask
1516
+ ? canExpansionMask[14] === '1'
1517
+ : null,
1518
+ totalAcceleratorKickDownTime: canExpansionMask
1519
+ ? canExpansionMask[13] === '1'
1520
+ : null,
1521
+ totalCruiseControlTime: canExpansionMask
1522
+ ? canExpansionMask[12] === '1'
1523
+ : null,
1524
+ totalEffectiveEngineSpeedTime: canExpansionMask
1525
+ ? canExpansionMask[11] === '1'
1526
+ : null,
1527
+ totalAcceleratorKickDown: canExpansionMask
1528
+ ? canExpansionMask[10] === '1'
1529
+ : null,
1530
+ pedalBrakingFactor: canExpansionMask
1531
+ ? canExpansionMask[9] === '1'
1532
+ : null,
1533
+ engineBrakingFactor: canExpansionMask
1534
+ ? canExpansionMask[8] === '1'
1535
+ : null,
1536
+ analogInputValue: canExpansionMask
1537
+ ? canExpansionMask[7] === '1'
1538
+ : null,
1539
+ tachographDrivingDirection: canExpansionMask
1540
+ ? canExpansionMask[6] === '1'
1541
+ : null,
1542
+ tachographVehicleMotionSignal: canExpansionMask
1543
+ ? canExpansionMask[5] === '1'
1544
+ : null,
1545
+ tachographOverspeedSignal: canExpansionMask
1546
+ ? canExpansionMask[4] === '1'
1547
+ : null,
1548
+ AxleWeight4: canExpansionMask ? canExpansionMask[3] === '1' : null,
1549
+ AxleWeight3: canExpansionMask ? canExpansionMask[2] === '1' : null,
1550
+ AxleWeight1: canExpansionMask ? canExpansionMask[1] === '1' : null,
1551
+ adBlueLevel: canExpansionMask ? canExpansionMask[0] === '1' : null
1552
+ },
1553
+ canExpanded: {
1554
+ adBlueLevel:
1555
+ parsedData[30] !== '' ? parseFloat(parsedData[30]) : null,
1556
+ axleWeight1: parsedData[31] !== '' ? parseInt(parsedData[31]) : null,
1557
+ axleWeight3: parsedData[32] !== '' ? parseInt(parsedData[32]) : null,
1558
+ axleWeight4: parsedData[33] !== '' ? parseInt(parsedData[33]) : null,
1559
+ tachographOverspeedSignal:
1560
+ parsedData[34] !== '' ? parseInt(parsedData[34]) : null,
1561
+ tachographVehicleMotionSignal:
1562
+ parsedData[35] !== '' ? parseInt(parsedData[35]) : null,
1563
+ tachographDrivingDirection:
1564
+ parsedData[36] !== '' ? parseInt(parsedData[36]) : null,
1565
+ analogInputValue:
1566
+ parsedData[37] !== '' ? parseInt(parsedData[37]) : null,
1567
+ engineBrakingFactor:
1568
+ parsedData[38] !== '' ? parseInt(parsedData[38]) : null,
1569
+ pedalBrakingFactor:
1570
+ parsedData[39] !== '' ? parseInt(parsedData[39]) : null,
1571
+ totalAcceleratorKickDown:
1572
+ parsedData[40] !== '' ? parseInt(parsedData[40]) : null,
1573
+ totalEffectiveEngineSpeedTime:
1574
+ parsedData[41] !== '' ? parseFloat(parsedData[41]) : null,
1575
+ totalCruiseControlTime:
1576
+ parsedData[42] !== '' ? parseFloat(parsedData[42]) : null,
1577
+ totalAcceleratorKickDownTime:
1578
+ parsedData[43] !== '' ? parseFloat(parsedData[43]) : null,
1579
+ totalBrakeApplications:
1580
+ parsedData[44] !== '' ? parseInt(parsedData[44]) : null,
1581
+ tachographDriver1Card:
1582
+ parsedData[45] !== '' ? parseInt(parsedData[45]) : null,
1583
+ tachographDriver2Card:
1584
+ parsedData[46] !== '' ? parseInt(parsedData[46]) : null,
1585
+ tachographDriver1Name: parsedData[47] !== '' ? parsedData[47] : null,
1586
+ tachographDriver2Name: parsedData[48] !== '' ? parsedData[48] : null,
1587
+ registrationNumber:
1588
+ parsedData[49] !== '' ? parseInt(parsedData[49]) : null,
1589
+ expansionInformation: {
1590
+ raw: parsedData[50] !== '' ? parsedData[50] : null,
1591
+ webasto: expansionBin ? expansionBin[0] === '1' : null,
1592
+ brakeFluidLowIndicator: expansionBin
1593
+ ? expansionBin[1] === '1'
1594
+ : null,
1595
+ coolantLevelLowIndicator: expansionBin
1596
+ ? expansionBin[2] === '1'
1597
+ : null,
1598
+ batteryIndicator: expansionBin ? expansionBin[3] === '1' : null,
1599
+ brakeSystemaFailureIndicator: expansionBin
1600
+ ? expansionBin[4] === '1'
1601
+ : null,
1602
+ oilPressureIndicator: expansionBin ? expansionBin[5] === '1' : null,
1603
+ engineHotIndicator: expansionBin ? expansionBin[6] === '1' : null,
1604
+ ABSFailureIndicator: expansionBin ? expansionBin[7] === '1' : null,
1605
+ checkEngineIndicator: expansionBin ? expansionBin[9] === '1' : null,
1606
+ aribagsIndicator: expansionBin ? expansionBin[10] === '1' : null,
1607
+ serviceCallIndicator: expansionBin
1608
+ ? expansionBin[11] === '1'
1609
+ : null,
1610
+ oilLevelLowIndicator: expansionBin ? expansionBin[12] === '1' : null
1611
+ },
1612
+ adblueLevel: parsedData[30] !== '' ? parsedData[30] : null
1613
+ }
1614
+ }
1615
+ })
1616
+ } else if (command[1] === 'GTDAT') {
1617
+ let dataIndex = 4
1618
+ // Short format
1619
+ if (parsedData.length === 7) {
1620
+ data = Object.assign(data, {
1621
+ loc: null,
1622
+ speed: null,
1623
+ gpsStatus: null,
1624
+ hdop: null,
1625
+ status: null,
1626
+ azimuth: null,
1627
+ altitude: null,
1628
+ datetime: null,
1629
+ voltage: {
1630
+ battery: null,
1631
+ inputCharge: null,
1632
+ ada: null,
1633
+ adb: null,
1634
+ adc: null
1635
+ },
1636
+ mcc: null,
1637
+ mnc: null,
1638
+ lac: null,
1639
+ cid: null,
1640
+ satellites: null,
1641
+ odometer: null,
1642
+ hourmeter: null
1643
+ })
1644
+ } else {
1645
+ dataIndex = 7
1646
+ let index = 19 // position append mask
1647
+ let satelliteInfo = false
1648
+
1649
+ // If get satellites is configured
1650
+ if (utils.includeSatellites(parsedData[index])) {
1651
+ index += 1
1652
+ satelliteInfo = true
1653
+ }
1654
+
1655
+ data = Object.assign(data, {
1656
+ loc: {
1657
+ type: 'Point',
1658
+ coordinates: [parseFloat(parsedData[12]), parseFloat(parsedData[13])]
1659
+ },
1660
+ speed: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
1661
+ gpsStatus: utils.checkGps(
1662
+ parseFloat(parsedData[12]),
1663
+ parseFloat(parsedData[13])
1664
+ ),
1665
+ hdop: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
1666
+ status: null,
1667
+ azimuth: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
1668
+ altitude: parsedData[11] !== '' ? parseFloat(parsedData[11]) : null,
1669
+ datetime:
1670
+ parsedData[14] !== '' ? utils.parseDate(parsedData[14]) : null,
1671
+ voltage: {
1672
+ battery: null,
1673
+ inputCharge: null,
1674
+ ada: null,
1675
+ adb: null,
1676
+ adc: null
1677
+ },
1678
+ mcc: parsedData[15] !== '' ? parseInt(parsedData[15], 10) : null,
1679
+ mnc: parsedData[16] !== '' ? parseInt(parsedData[16], 10) : null,
1680
+ lac: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
1681
+ cid: parsedData[18] !== '' ? parseInt(parsedData[18], 16) : null,
1682
+ satellites:
1683
+ satelliteInfo && parsedData[index] !== ''
1684
+ ? parseInt(parsedData[index], 10)
1685
+ : null,
1686
+ odometer: null,
1687
+ hourmeter: null
1688
+ })
1689
+ }
1690
+
1691
+ // Checks if its a temperature GTDAT -> DT
1692
+ if (/^>DT/.test(parsedData[7])) {
1693
+ const parsedSerialData =
1694
+ parsedData[7] !== '' ? parsedData[7].split('|') : ''
1695
+ let externalData = {
1696
+ eriMask: {
1697
+ raw: '00000000',
1698
+ digitFuelSensor: false,
1699
+ AC100: false,
1700
+ reserved: false,
1701
+ fuelLevelPercentage: false,
1702
+ fuelVolume: false
1703
+ },
1704
+ uartDeviceType: 'Camaleon',
1705
+ fuelSensorData: null
1706
+ }
1707
+ let AC100Devices = [
1708
+ {
1709
+ deviceNumber: `${parsedData[2]}|1`,
1710
+ deviceType: '1',
1711
+ deviceData:
1712
+ parsedSerialData[3] !== '' ? parseFloat(parsedSerialData[3]) : null
1713
+ }
1714
+ ]
1715
+ if (parsedSerialData[4] !== '') {
1716
+ AC100Devices.push({
1717
+ deviceNumber: `${parsedData[2]}|2`,
1718
+ deviceType: '1',
1719
+ deviceData:
1720
+ parsedSerialData[4] !== '' ? parseFloat(parsedSerialData[4]) : null
1721
+ })
1722
+ }
1723
+ externalData = Object.assign(externalData, {
1724
+ AC100Devices: AC100Devices
1725
+ })
1726
+ data = Object.assign(data, {
1727
+ alarm: utils.getAlarm('GTERI', null),
1728
+ externalData: externalData
1729
+ })
1730
+ } else if (/^>ET/.test(parsedData[7])) {
1731
+ // Temp Alarms
1732
+ // GTTMP
1733
+ const parsedSerialData =
1734
+ parsedData[7] !== '' ? parsedData[7].split('|') : ''
1735
+ const alarm = utils.getAlarm('GTTMP', `${parsedSerialData[2]}0`, [
1736
+ `${parsedData[2]}|${parsedSerialData[2]}`,
1737
+ parsedSerialData[4]
1738
+ ])
1739
+ data = Object.assign(data, {
1740
+ alarm: alarm
1741
+ })
1742
+ } else if (/^>ID/.test(parsedData[7])) {
1743
+ // Checks if its a iButton GTDAT -> DT
1744
+ const parsedSerialData =
1745
+ parsedData[7] !== '' ? parsedData[7].split('|') : ''
1746
+ const driverID = parsedSerialData[2] ? parsedSerialData[2] : ''
1747
+ const alarm = utils.getAlarm('GTIDA', `${driverID},1`)
1748
+ data = Object.assign(data, {
1749
+ alarm: alarm
1750
+ })
1751
+ } else {
1752
+ // Normal GTDAT
1753
+ data = Object.assign(data, {
1754
+ alarm: utils.getAlarm(command[1], parsedData[dataIndex])
1755
+ })
1756
+ }
1757
+ } else if (command[1] === 'GTDTT') {
1758
+ // short format
1759
+ if (parsedData.length === 11) {
1760
+ data = Object.assign(data, {
1761
+ alarm: utils.getAlarm(command[1], parsedData[8], parsedData[6]),
1762
+ loc: null,
1763
+ speed: null,
1764
+ gpsStatus: null,
1765
+ hdop: null,
1766
+ status: null,
1767
+ azimuth: null,
1768
+ altitude: null,
1769
+ datetime: null,
1770
+ voltage: {
1771
+ battery: null,
1772
+ inputCharge: null,
1773
+ ada: null,
1774
+ adb: null,
1775
+ adc: null
1776
+ },
1777
+ mcc: null,
1778
+ mnc: null,
1779
+ lac: null,
1780
+ cid: null,
1781
+ satellites: null,
1782
+ odometer: null,
1783
+ hourmeter: null
1784
+ })
1785
+ } else {
1786
+ // Long format
1787
+ let index = 20 // position append mask
1788
+ let satelliteInfo = false
1789
+
1790
+ // If get satellites is configured
1791
+ if (utils.includeSatellites(parsedData[index])) {
1792
+ index += 1
1793
+ satelliteInfo = true
1794
+ }
1795
+
1796
+ data = Object.assign(data, {
1797
+ alarm: utils.getAlarm(command[1], parsedData[8], parsedData[6]),
1798
+ loc: {
1799
+ type: 'Point',
1800
+ coordinates: [parseFloat(parsedData[13]), parseFloat(parsedData[14])]
1801
+ },
1802
+ speed: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
1803
+ gpsStatus: utils.checkGps(
1804
+ parseFloat(parsedData[13]),
1805
+ parseFloat(parsedData[14])
1806
+ ),
1807
+ hdop: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
1808
+ status: null,
1809
+ azimuth: parsedData[11] !== '' ? parseFloat(parsedData[11]) : null,
1810
+ altitude: parsedData[12] !== '' ? parseFloat(parsedData[12]) : null,
1811
+ datetime:
1812
+ parsedData[15] !== '' ? utils.parseDate(parsedData[15]) : null,
1813
+ voltage: {
1814
+ battery: null,
1815
+ inputCharge: null,
1816
+ ada: null,
1817
+ adb: null,
1818
+ adc: null
1819
+ },
1820
+ mcc: parsedData[16] !== '' ? parseInt(parsedData[16], 10) : null,
1821
+ mnc: parsedData[17] !== '' ? parseInt(parsedData[17], 10) : null,
1822
+ lac: parsedData[18] !== '' ? parseInt(parsedData[18], 16) : null,
1823
+ cid: parsedData[19] !== '' ? parseInt(parsedData[19], 16) : null,
1824
+ satellites:
1825
+ satelliteInfo && parsedData[index] !== ''
1826
+ ? parseInt(parsedData[index], 10)
1827
+ : null,
1828
+ odometer: null,
1829
+ hourmeter: null
1830
+ })
1831
+ }
1832
+ } else if (command[1] === 'GTDOS') {
1833
+ let index = 17 // position append mask
1834
+ let satelliteInfo = false
1835
+
1836
+ // If get satellites is configured
1837
+ if (utils.includeSatellites(parsedData[index])) {
1838
+ index += 1
1839
+ satelliteInfo = true
1840
+ }
1841
+
1842
+ data = Object.assign(data, {
1843
+ alarm: utils.getAlarm(command[1], `${parsedData[4]},${parsedData[5]}`),
1844
+ loc: {
1845
+ type: 'Point',
1846
+ coordinates: [parseFloat(parsedData[10]), parseFloat(parsedData[11])]
1847
+ },
1848
+ speed: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
1849
+ gpsStatus: utils.checkGps(
1850
+ parseFloat(parsedData[10]),
1851
+ parseFloat(parsedData[11])
1852
+ ),
1853
+ hdop: parsedData[6] !== '' ? parseFloat(parsedData[6]) : null,
1854
+ status: null,
1855
+ azimuth: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
1856
+ altitude: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
1857
+ datetime: parsedData[12] !== '' ? utils.parseDate(parsedData[12]) : null,
1858
+ voltage: {
1859
+ battery: null,
1860
+ inputCharge: null,
1861
+ ada: null,
1862
+ adb: null,
1863
+ adc: null
1864
+ },
1865
+ mcc: parsedData[13] !== '' ? parseInt(parsedData[13], 10) : null,
1866
+ mnc: parsedData[14] !== '' ? parseInt(parsedData[14], 10) : null,
1867
+ lac: parsedData[15] !== '' ? parseInt(parsedData[15], 16) : null,
1868
+ cid: parsedData[16] !== '' ? parseInt(parsedData[16], 16) : null,
1869
+ satellites:
1870
+ satelliteInfo && parsedData[index] !== ''
1871
+ ? parseInt(parsedData[index], 10)
1872
+ : null,
1873
+ odometer: null,
1874
+ hourmeter: null
1875
+ })
1876
+ } else if (command[1] === 'GTDOM') {
1877
+ // Waveform beeing monitored
1878
+ let index = 18 // position append mask
1879
+ let satelliteInfo = false
1880
+
1881
+ // If get satellites is configured
1882
+ if (utils.includeSatellites(parsedData[index])) {
1883
+ index += 1
1884
+ satelliteInfo = true
1885
+ }
1886
+
1887
+ data = Object.assign(data, {
1888
+ alarm: utils.getAlarm(command[1], [parsedData[4], parsedData[5]]),
1889
+ loc: {
1890
+ type: 'Point',
1891
+ coordinates: [parseFloat(parsedData[11]), parseFloat(parsedData[12])]
1892
+ },
1893
+ speed: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
1894
+ gpsStatus: utils.checkGps(
1895
+ parseFloat(parsedData[11]),
1896
+ parseFloat(parsedData[12])
1897
+ ),
1898
+ hdop: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
1899
+ status: null,
1900
+ azimuth: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
1901
+ altitude: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
1902
+ datetime: parsedData[13] !== '' ? utils.parseDate(parsedData[13]) : null,
1903
+ voltage: {
1904
+ battery: null,
1905
+ inputCharge: null,
1906
+ ada: null,
1907
+ adb: null,
1908
+ adc: null
1909
+ },
1910
+ mcc: parsedData[14] !== '' ? parseInt(parsedData[14], 10) : null,
1911
+ mnc: parsedData[15] !== '' ? parseInt(parsedData[15], 10) : null,
1912
+ lac: parsedData[16] !== '' ? parseInt(parsedData[16], 16) : null,
1913
+ cid: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
1914
+ satellites:
1915
+ satelliteInfo && parsedData[index] !== ''
1916
+ ? parseInt(parsedData[index], 10)
1917
+ : null,
1918
+ odometer: null,
1919
+ hourmeter: null
1920
+ })
1921
+ } else if (command[1] === 'GTCID') {
1922
+ data = Object.assign(data, {
1923
+ alarm: utils.getAlarm(command[1], parsedData[4], 'gv310lau'),
1924
+ loc: {
1925
+ type: 'Point',
1926
+ coordinates: [null, null]
1927
+ },
1928
+ speed: null,
1929
+ gpsStatus: null,
1930
+ hdop: null,
1931
+ status: null,
1932
+ azimuth: null,
1933
+ altitude: null,
1934
+ datetime: parsedData[5] !== '' ? utils.parseDate(parsedData[5]) : null,
1935
+ voltage: {
1936
+ battery: null,
1937
+ inputCharge: null,
1938
+ ada: null,
1939
+ adb: null,
1940
+ adc: null
1941
+ },
1942
+ mcc: null,
1943
+ mnc: null,
1944
+ lac: null,
1945
+ cid: null,
1946
+ satellites: null,
1947
+ odometer: null,
1948
+ hourmeter: null
1949
+ })
1950
+ } else if (command[1] === 'GTCSQ') {
1951
+ data = Object.assign(data, {
1952
+ alarm: utils.getAlarm(command[1], parsedData[5], 'gv310lau'),
1953
+ loc: {
1954
+ type: 'Point',
1955
+ coordinates: [null, null]
1956
+ },
1957
+ speed: null,
1958
+ gpsStatus: null,
1959
+ hdop: null,
1960
+ status: null,
1961
+ azimuth: null,
1962
+ altitude: null,
1963
+ datetime: parsedData[6] !== '' ? utils.parseDate(parsedData[6]) : null,
1964
+ voltage: {
1965
+ battery: null,
1966
+ inputCharge: null,
1967
+ ada: null,
1968
+ adb: null,
1969
+ adc: null
1970
+ },
1971
+ mcc: null,
1972
+ mnc: null,
1973
+ lac: null,
1974
+ cid: null,
1975
+ satellites: null,
1976
+ odometer: null,
1977
+ hourmeter: null
1978
+ })
1979
+ } else if (command[1] === 'GTVER') {
1980
+ data = Object.assign(data, {
1981
+ alarm: utils.getAlarm(
1982
+ command[1],
1983
+ [parsedData[5], parsedData[6]],
1984
+ 'gv310lau'
1985
+ ),
1986
+ loc: {
1987
+ type: 'Point',
1988
+ coordinates: [null, null]
1989
+ },
1990
+ speed: null,
1991
+ gpsStatus: null,
1992
+ hdop: null,
1993
+ status: null,
1994
+ azimuth: null,
1995
+ altitude: null,
1996
+ datetime: parsedData[7] !== '' ? utils.parseDate(parsedData[7]) : null,
1997
+ voltage: {
1998
+ battery: null,
1999
+ inputCharge: null,
2000
+ ada: null,
2001
+ adb: null,
2002
+ adc: null
2003
+ },
2004
+ mcc: null,
2005
+ mnc: null,
2006
+ lac: null,
2007
+ cid: null,
2008
+ satellites: null,
2009
+ odometer: null,
2010
+ hourmeter: null
2011
+ })
2012
+ } else if (command[1] === 'GTBCS' || command[1] === 'GTBDS') {
2013
+ // Bluetooth connection/desconnection
2014
+ let index = 16 // position append mask
2015
+ let satelliteInfo = false
2016
+
2017
+ // If get satellites is configured
2018
+ if (utils.includeSatellites(parsedData[index])) {
2019
+ index += 1
2020
+ satelliteInfo = true
2021
+ }
2022
+
2023
+ data = Object.assign(data, {
2024
+ alarm: utils.getAlarm(command[1], null, 'gv310lau'),
2025
+ loc: {
2026
+ type: 'Point',
2027
+ coordinates: [parseFloat(parsedData[11]), parseFloat(parsedData[12])]
2028
+ },
2029
+ speed: parsedData[6] !== '' ? parseFloat(parsedData[6]) : null,
2030
+ gpsStatus: utils.checkGps(
2031
+ parseFloat(parsedData[11]),
2032
+ parseFloat(parsedData[12])
2033
+ ),
2034
+ hdop: parsedData[5] !== '' ? parseFloat(parsedData[5]) : null,
2035
+ status: null,
2036
+ azimuth: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
2037
+ altitude: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
2038
+ datetime: parsedData[11] !== '' ? utils.parseDate(parsedData[11]) : null,
2039
+ voltage: {
2040
+ battery: null,
2041
+ inputCharge: null,
2042
+ ada: null,
2043
+ adb: null,
2044
+ adc: null
2045
+ },
2046
+ mcc: parsedData[12] !== '' ? parseInt(parsedData[12], 10) : null,
2047
+ mnc: parsedData[13] !== '' ? parseInt(parsedData[13], 10) : null,
2048
+ lac: parsedData[14] !== '' ? parseInt(parsedData[14], 16) : null,
2049
+ cid: parsedData[15] !== '' ? parseInt(parsedData[15], 16) : null,
2050
+ satellites:
2051
+ satelliteInfo && parsedData[index] !== ''
2052
+ ? parseInt(parsedData[index])
2053
+ : null,
2054
+ odometer: null,
2055
+ hourmeter: null,
2056
+ bluetooth: {
2057
+ raw: parsedData[index + 1],
2058
+ connected: parsedData[index + 6] !== '',
2059
+ bluetoothInfo: {
2060
+ name:
2061
+ parsedData[index + 2] !== '' &&
2062
+ utils.nHexDigit(utils.hex2bin(parsedData[index + 1]), 16)[15] ===
2063
+ '1'
2064
+ ? parsedData[index + 2]
2065
+ : null,
2066
+ mac:
2067
+ parsedData[index + 3] !== '' &&
2068
+ utils.nHexDigit(utils.hex2bin(parsedData[index + 1]), 16)[14] ===
2069
+ '1'
2070
+ ? parsedData[index + 3]
2071
+ : null
2072
+ },
2073
+ accessoryInfo: {
2074
+ accessory: null,
2075
+ model: null,
2076
+ name: null,
2077
+ role:
2078
+ parsedData[index + 4] !== '' &&
2079
+ utils.nHexDigit(utils.hex2bin(parsedData[index + 1]), 16)[7] === '1'
2080
+ ? utils.peerRoles[parsedData[index + 4]]
2081
+ : null,
2082
+ type:
2083
+ parsedData[index + 5] !== '' &&
2084
+ utils.nHexDigit(utils.hex2bin(parsedData[index + 1]), 16)[5] === '1'
2085
+ ? utils.peerAddressesTypes[parsedData[index + 5]]
2086
+ : null,
2087
+ mac:
2088
+ parsedData[index + 6] !== '' &&
2089
+ utils.nHexDigit(utils.hex2bin(parsedData[index + 1]), 16)[4] === '1'
2090
+ ? parsedData[index + 6]
2091
+ : null
2092
+ },
2093
+ accessoryData: {
2094
+ temperature: null,
2095
+ humidity: null,
2096
+ mode: null,
2097
+ event: null,
2098
+ tirePresure: null,
2099
+ timestamp: null,
2100
+ enhancedTemperature: null,
2101
+ magDevice: {
2102
+ id: null,
2103
+ eventCounter: null,
2104
+ magnetState: null
2105
+ },
2106
+ relay: {
2107
+ configResult: null,
2108
+ state: null
2109
+ }
2110
+ },
2111
+ disconnectionReason:
2112
+ parsedData[index + 7] !== '' && command[1] === 'GTBDS'
2113
+ ? utils.disconnectionReasons[parsedData[index + 7]]
2114
+ : null
2115
+ }
2116
+ })
2117
+ } else if (command[1] === 'GTBAA') {
2118
+ // Bluetooth alarms
2119
+ let satelliteInfo = false
2120
+ let appendIx = 8
2121
+ let appendMask = utils.nHexDigit(utils.hex2bin(parsedData[appendIx]), 16)
2122
+ let btAccessory = parsedData[5]
2123
+ let aNameIx = appendIx + parseInt(appendMask[15])
2124
+ let aMacIx = aNameIx + parseInt(appendMask[14])
2125
+ let aStatIx = aMacIx + parseInt(appendMask[13])
2126
+ let aBatIx = aStatIx + parseInt(appendMask[12])
2127
+ let aTmpIx = aBatIx + parseInt(appendMask[11])
2128
+ let aHumIx = aTmpIx + parseInt(appendMask[10])
2129
+ let ioIx = aHumIx + parseInt(appendMask[8])
2130
+ let modeIx =
2131
+ appendMask[8] === '1' ? ioIx + 2 + parseInt(appendMask[7]) : ioIx
2132
+ let aEvIx = appendMask[7] === '1' ? modeIx + 1 : modeIx
2133
+ let pressIx = aEvIx + parseInt(appendMask[6])
2134
+ let timeIx = pressIx + parseInt(appendMask[5])
2135
+ let eTmpIx = timeIx + parseInt(appendMask[4])
2136
+ let magIx = eTmpIx + parseInt(appendMask[3])
2137
+ let aBatpIx =
2138
+ appendMask[3] === '1' ? magIx + 2 + parseInt(appendMask[2]) : eTmpIx
2139
+ let relIx = aBatpIx + parseInt(appendMask[1])
2140
+
2141
+ let newIndex = appendMask[1] === '1' ? relIx + 2 : relIx + 1
2142
+ let satIndex = newIndex + 11
2143
+
2144
+ // If get satellites is configured
2145
+ if (utils.includeSatellites(parsedData[satIndex])) {
2146
+ satIndex += 1
2147
+ satelliteInfo = true
2148
+ }
2149
+
2150
+ data = Object.assign(data, {
2151
+ alarm: utils.getAlarm(command[1], parsedData[7], 'gv310lau'),
2152
+ loc: {
2153
+ type: 'Point',
2154
+ coordinates: [
2155
+ parseFloat(parsedData[newIndex + 4]),
2156
+ parseFloat(parsedData[newIndex + 5])
2157
+ ]
2158
+ },
2159
+ speed:
2160
+ parsedData[newIndex + 1] !== ''
2161
+ ? parseFloat(parsedData[newIndex + 1])
2162
+ : null,
2163
+ gpsStatus: utils.checkGps(
2164
+ parseFloat(parsedData[newIndex + 4]),
2165
+ parseFloat(parsedData[newIndex + 5])
2166
+ ),
2167
+ hdop:
2168
+ parsedData[newIndex] !== '' ? parseFloat(parsedData[newIndex]) : null,
2169
+ status: null,
2170
+ azimuth:
2171
+ parsedData[newIndex + 2] !== ''
2172
+ ? parseFloat(parsedData[newIndex + 2])
2173
+ : null,
2174
+ altitude:
2175
+ parsedData[newIndex + 3] !== ''
2176
+ ? parseFloat(parsedData[newIndex + 3])
2177
+ : null,
2178
+ datetime:
2179
+ parsedData[newIndex + 6] !== ''
2180
+ ? utils.parseDate(parsedData[newIndex + 6])
2181
+ : null,
2182
+ voltage: {
2183
+ battery: null,
2184
+ inputCharge: null,
2185
+ ada: null,
2186
+ adb: null,
2187
+ adc: null
2188
+ },
2189
+ mcc:
2190
+ parsedData[newIndex + 7] !== ''
2191
+ ? parseInt(parsedData[newIndex + 7], 10)
2192
+ : null,
2193
+ mnc:
2194
+ parsedData[newIndex + 8] !== ''
2195
+ ? parseInt(parsedData[newIndex + 8], 10)
2196
+ : null,
2197
+ lac:
2198
+ parsedData[newIndex + 9] !== ''
2199
+ ? parseInt(parsedData[newIndex + 9], 16)
2200
+ : null,
2201
+ cid:
2202
+ parsedData[newIndex + 10] !== ''
2203
+ ? parseInt(parsedData[newIndex + 10], 16)
2204
+ : null,
2205
+ satellites:
2206
+ satelliteInfo && parsedData[satIndex] !== ''
2207
+ ? parseInt(parsedData[satIndex])
2208
+ : null,
2209
+ odometer: null,
2210
+ hourmeter: null,
2211
+ bluetooth: {
2212
+ raw: null,
2213
+ connected: null,
2214
+ bluetoothInfo: {
2215
+ name: null,
2216
+ mac: null
2217
+ },
2218
+ accessoryInfo: {
2219
+ accesory:
2220
+ btAccessory !== '' ? utils.bluetoothAccessories[btAccessory] : null,
2221
+ model: parsedData[6] !== '' ? parseInt(parsedData[6]) : null,
2222
+ name:
2223
+ parsedData[aNameIx] !== '' && appendMask[15] === '1'
2224
+ ? parsedData[aNameIx]
2225
+ : null,
2226
+ role: null,
2227
+ type: null,
2228
+ mac:
2229
+ parsedData[aMacIx] !== '' && appendMask[14] === '1'
2230
+ ? parsedData[aMacIx]
2231
+ : null,
2232
+ status:
2233
+ parsedData[aStatIx] !== '' && appendMask[13] === '1'
2234
+ ? parseInt(parsedData[aStatIx])
2235
+ : null,
2236
+ batteryLevel:
2237
+ parsedData[aBatIx] !== '' && appendMask[12] === '1'
2238
+ ? parseInt(parsedData[aBatIx])
2239
+ : null,
2240
+ batteryPercentage:
2241
+ parsedData[aBatpIx] !== '' && appendMask[2] === '1'
2242
+ ? parseFloat(parsedData[aBatpIx])
2243
+ : null
2244
+ },
2245
+ accessoryData: {
2246
+ temperature:
2247
+ parsedData[aTmpIx] !== '' && appendMask[11] === '1'
2248
+ ? parseInt(parsedData[aTmpIx])
2249
+ : null,
2250
+ humidity:
2251
+ parsedData[aHumIx] !== '' && appendMask[10] === '1'
2252
+ ? parseInt(parsedData[aHumIx])
2253
+ : null,
2254
+ mode:
2255
+ parsedData[modeIx] !== '' && appendMask[7] === '1'
2256
+ ? parseInt(parsedData[modeIx])
2257
+ : null,
2258
+ event:
2259
+ parsedData[aEvIx] !== '' && appendMask[7] === '1'
2260
+ ? parseInt(parsedData[aEvIx])
2261
+ : null,
2262
+ tirePresure:
2263
+ parsedData[pressIx] !== '' && appendMask[6] === '1'
2264
+ ? parseInt(parsedData[pressIx])
2265
+ : null,
2266
+ timestamp:
2267
+ parsedData[timeIx] !== '' && appendMask[5] === '1'
2268
+ ? utils.parseDate(parsedData[timeIx])
2269
+ : null,
2270
+ enhancedTemperature:
2271
+ parsedData[eTmpIx] !== '' && appendMask[4] === '1'
2272
+ ? parseFloat(parsedData[eTmpIx])
2273
+ : null,
2274
+ magDevice: {
2275
+ id:
2276
+ parsedData[magIx] !== '' && appendMask[3] === '1'
2277
+ ? parsedData[magIx]
2278
+ : null,
2279
+ eventCounter:
2280
+ parsedData[magIx + 1] !== '' && appendMask[3] === '1'
2281
+ ? parseInt(parsedData[magIx + 1])
2282
+ : null,
2283
+ magnetState:
2284
+ parsedData[magIx + 2] !== '' && appendMask[3] === '1'
2285
+ ? parseInt(parsedData[magIx + 2])
2286
+ : null
2287
+ },
2288
+ relay: {
2289
+ configResult:
2290
+ parsedData[relIx] !== '' && appendMask[1] === '1'
2291
+ ? parseInt(parsedData[relIx])
2292
+ : null,
2293
+ state:
2294
+ parsedData[relIx + 1] !== '' && appendMask[1] === '1'
2295
+ ? parseInt(parsedData[relIx + 1])
2296
+ : null
2297
+ }
2298
+ }
2299
+ }
2300
+ })
2301
+ } else if (command[1] === 'GTBID') {
2302
+ // Bluetooth beacon detection
2303
+ let number = parsedData[4] !== '' ? parseInt(parsedData[4]) : 1
2304
+ let index = 4
2305
+ let appMk
2306
+ for (let i = 1; i <= number; i++) {
2307
+ appMk = utils.sumOnes(parsedData[index + 2])
2308
+ index += 2 + appMk
2309
+ }
2310
+ let satelliteInfo = false
2311
+ let satIndex = index + 12
2312
+
2313
+ // If get satellites is configured
2314
+ if (utils.includeSatellites(parsedData[satIndex])) {
2315
+ satIndex += 1
2316
+ satelliteInfo = true
2317
+ }
2318
+
2319
+ data = Object.assign(data, {
2320
+ alarm: utils.getAlarm(command[1], null, 'gv310lau'),
2321
+ loc: {
2322
+ type: 'Point',
2323
+ coordinates: [
2324
+ parseFloat(parsedData[index + 5]),
2325
+ parseFloat(parsedData[index + 6])
2326
+ ]
2327
+ },
2328
+ speed:
2329
+ parsedData[index + 2] !== '' ? parseFloat(parsedData[index + 2]) : null,
2330
+ gpsStatus: utils.checkGps(
2331
+ parseFloat(parsedData[index + 5]),
2332
+ parseFloat(parsedData[index + 6])
2333
+ ),
2334
+ hdop:
2335
+ parsedData[index + 1] !== '' ? parseFloat(parsedData[index + 1]) : null,
2336
+ status: null,
2337
+ azimuth:
2338
+ parsedData[index + 3] !== '' ? parseFloat(parsedData[index + 3]) : null,
2339
+ altitude:
2340
+ parsedData[index + 4] !== '' ? parseFloat(parsedData[index + 4]) : null,
2341
+ datetime:
2342
+ parsedData[index + 7] !== ''
2343
+ ? utils.parseDate(parsedData[index + 7])
2344
+ : null,
2345
+ voltage: {
2346
+ battery: null,
2347
+ inputCharge: null,
2348
+ ada: null,
2349
+ adb: null,
2350
+ adc: null
2351
+ },
2352
+ mcc:
2353
+ parsedData[index + 8] !== ''
2354
+ ? parseInt(parsedData[index + 8], 10)
2355
+ : null,
2356
+ mnc:
2357
+ parsedData[index + 9] !== ''
2358
+ ? parseInt(parsedData[index + 9], 10)
2359
+ : null,
2360
+ lac:
2361
+ parsedData[index + 10] !== ''
2362
+ ? parseInt(parsedData[index + 10], 16)
2363
+ : null,
2364
+ cid:
2365
+ parsedData[index + 11] !== ''
2366
+ ? parseInt(parsedData[index + 11], 16)
2367
+ : null,
2368
+ satellites:
2369
+ satelliteInfo && parsedData[satIndex] !== ''
2370
+ ? parseInt(parsedData[satIndex])
2371
+ : null,
2372
+ odometer: null,
2373
+ hourmeter: null
2374
+ })
2375
+
2376
+ let btDevices = []
2377
+ let btIndex = 5
2378
+ for (let i = 1; i <= number; i++) {
2379
+ let appendMask = utils.nHexDigit(
2380
+ utils.hex2bin(parsedData[btIndex + 1]),
2381
+ 8
2382
+ )
2383
+ let macIx = btIndex + 1 + parseInt(appendMask[6])
2384
+ let batIx = macIx + parseInt(appendMask[4])
2385
+ let sigIx = batIx + parseInt(appendMask[1])
2386
+ let typeIx = sigIx + parseInt(appendMask[0])
2387
+ btDevices.push({
2388
+ model:
2389
+ parsedData[btIndex] !== ''
2390
+ ? utils.beaconModels[parsedData[btIndex]]
2391
+ : null,
2392
+ appendMask:
2393
+ parsedData[btIndex + 1] !== '' ? parsedData[btIndex + 1] : null,
2394
+ mac:
2395
+ appendMask[6] === '1' && parsedData[macIx] !== ''
2396
+ ? parsedData[macIx]
2397
+ : null,
2398
+ battery:
2399
+ appendMask[4] === '1' && parsedData[batIx] !== ''
2400
+ ? parseInt(parsedData[batIx]) / 1000
2401
+ : null,
2402
+ signalStrength:
2403
+ appendMask[1] === '1' && parsedData[sigIx] !== ''
2404
+ ? parseInt(parsedData[sigIx])
2405
+ : null,
2406
+ type:
2407
+ appendMask[0] === '1' && parsedData[typeIx] !== ''
2408
+ ? utils.beaconTypes[parsedData[typeIx]]
2409
+ : null,
2410
+ data:
2411
+ appendMask[0] === '1' && parsedData[typeIx + 1] !== ''
2412
+ ? parsedData[typeIx + 1]
2413
+ : null
2414
+ })
2415
+ btIndex = typeIx + 1
2416
+ }
2417
+
2418
+ let bluetoothData = {
2419
+ connectedDevices: number,
2420
+ btDevices: btDevices
2421
+ }
2422
+
2423
+ data = Object.assign(data, {
2424
+ bluetoothData: bluetoothData
2425
+ })
2426
+ } else if (command[1] === 'GTVGN' || command[1] === 'GTVGF') {
2427
+ // Virtual ignition
2428
+ let index = 18 // possition append mask
2429
+ let satelliteInfo = false
2430
+
2431
+ // If get satellites is configured
2432
+ if (utils.includeSatellites(parsedData[index])) {
2433
+ index += 1
2434
+ satelliteInfo = true
2435
+ }
2436
+
2437
+ data = Object.assign(data, {
2438
+ alarm: utils.getAlarm(command[1], [parsedData[6], parsedData[5]]),
2439
+ loc: {
2440
+ type: 'Point',
2441
+ coordinates: [parseFloat(parsedData[11]), parseFloat(parsedData[12])]
2442
+ },
2443
+ speed: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
2444
+ gpsStatus: utils.checkGps(
2445
+ parseFloat(parsedData[11]),
2446
+ parseFloat(parsedData[12])
2447
+ ),
2448
+ hdop: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
2449
+ status: null,
2450
+ azimuth: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
2451
+ altitude: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
2452
+ datetime: parsedData[13] !== '' ? utils.parseDate(parsedData[13]) : null,
2453
+ voltage: {
2454
+ battery: null,
2455
+ inputCharge: null,
2456
+ ada: null,
2457
+ adb: null,
2458
+ adc: null
2459
+ },
2460
+ mcc: parsedData[14] !== '' ? parseInt(parsedData[14], 10) : null,
2461
+ mnc: parsedData[15] !== '' ? parseInt(parsedData[15], 10) : null,
2462
+ lac: parsedData[16] !== '' ? parseInt(parsedData[16], 16) : null,
2463
+ cid: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
2464
+ satellites:
2465
+ satelliteInfo && parsedData[index] !== ''
2466
+ ? parseInt(parsedData[index])
2467
+ : null,
2468
+ odometer:
2469
+ parsedData[index + 2] !== '' ? parseFloat(parsedData[index + 2]) : null,
2470
+ hourmeter: parsedData[index + 1] !== '' ? parsedData[index + 1] : null
2471
+ })
2472
+ } else if (command[1] === 'GTGSM') {
2473
+ data = Object.assign(data, {
2474
+ alarm: utils.getAlarm(command[1], null),
2475
+ fixType: parsedData[3] !== '' ? parsedData[3] : null
2476
+ })
2477
+ let antData = []
2478
+ var index = 4
2479
+ for (let i = 0; i < 6; i++) {
2480
+ antData.push({
2481
+ mcc: parsedData[index] !== '' ? parseInt(parsedData[index], 10) : null,
2482
+ mnc:
2483
+ parsedData[index + 1] !== ''
2484
+ ? parseInt(parsedData[index + 1], 10)
2485
+ : null,
2486
+ lac:
2487
+ parsedData[index + 2] !== '' ||
2488
+ parsedData[index + 2].toUpperCase() === 'FFFF'
2489
+ ? parseInt(parsedData[index + 2], 16)
2490
+ : null,
2491
+ cid:
2492
+ parsedData[index + 3] !== '' ||
2493
+ parsedData[index + 3].toUpperCase() === 'FFFF'
2494
+ ? parseInt(parsedData[index + 3], 16)
2495
+ : null,
2496
+ rxLevel:
2497
+ parsedData[index + 4] !== ''
2498
+ ? utils.getSignalStrength(
2499
+ 'GSM',
2500
+ parseInt(parsedData[index + 4], 10)
2501
+ )
2502
+ : null,
2503
+ rxSignalPercentage:
2504
+ parsedData[index + 4] !== ''
2505
+ ? utils.getSignalPercentage(
2506
+ 'GSM',
2507
+ parseInt(parsedData[index + 4], 10)
2508
+ )
2509
+ : null
2510
+ })
2511
+ index += 6
2512
+ }
2513
+ data = Object.assign(data, {
2514
+ neighborCells: antData,
2515
+ mcc: parsedData[index] !== '' ? parseInt(parsedData[index], 10) : null,
2516
+ mnc:
2517
+ parsedData[index + 1] !== ''
2518
+ ? parseInt(parsedData[index + 1], 10)
2519
+ : null,
2520
+ lac:
2521
+ parsedData[index + 2] !== '' ||
2522
+ parsedData[index + 2].toUpperCase() === 'FFFF'
2523
+ ? parseInt(parsedData[index + 2], 16)
2524
+ : null,
2525
+ cid:
2526
+ parsedData[index + 3] !== '' ||
2527
+ parsedData[index + 3].toUpperCase() === 'FFFF'
2528
+ ? parseInt(parsedData[index + 3], 16)
2529
+ : null,
2530
+ rxLevel:
2531
+ parsedData[index + 4] !== ''
2532
+ ? utils.getSignalStrength('GSM', parseInt(parsedData[index + 4], 10))
2533
+ : null,
2534
+ rxSignalPercentage:
2535
+ parsedData[index + 4] !== ''
2536
+ ? utils.getSignalPercentage(
2537
+ 'GSM',
2538
+ parseInt(parsedData[index + 4], 10)
2539
+ )
2540
+ : null
2541
+ })
2542
+ } else if (command[1] === 'GTCLT') {
2543
+ // CANBUS Alarm
2544
+ let index = 71 // position append mask
2545
+ let satelliteInfo = false
2546
+
2547
+ // If get satellites is configured
2548
+ if (utils.includeSatellites(parsedData[index])) {
2549
+ index += 1
2550
+ satelliteInfo = true
2551
+ }
2552
+
2553
+ let alarmMask1 =
2554
+ parsedData[5] !== ''
2555
+ ? utils
2556
+ .nHexDigit(utils.hex2bin(parsedData[5]), 32)
2557
+ .split('')
2558
+ .reverse()
2559
+ .join('')
2560
+ : null
2561
+ let alarmMask2 =
2562
+ parsedData[6] !== ''
2563
+ ? utils
2564
+ .nHexDigit(utils.hex2bin(parsedData[6]), 32)
2565
+ .split('')
2566
+ .reverse()
2567
+ .join('')
2568
+ : null
2569
+ let alarmMask3 =
2570
+ parsedData[7] !== ''
2571
+ ? utils
2572
+ .nHexDigit(utils.hex2bin(parsedData[7]), 32)
2573
+ .split('')
2574
+ .reverse()
2575
+ .join('')
2576
+ : null
2577
+ let inicatorsBin =
2578
+ parsedData[28] !== ''
2579
+ ? utils.nHexDigit(utils.hex2bin(parsedData[28]), 16)
2580
+ : null
2581
+ let lights =
2582
+ parsedData[29] !== ''
2583
+ ? utils.nHexDigit(utils.hex2bin(parsedData[29]), 8)
2584
+ : null
2585
+ let doors =
2586
+ parsedData[30] !== ''
2587
+ ? utils.nHexDigit(utils.hex2bin(parsedData[30]), 8)
2588
+ : null
2589
+ let canExpansionMask =
2590
+ parsedData[33] !== ''
2591
+ ? utils
2592
+ .nHexDigit(utils.hex2bin(parsedData[33]), 32)
2593
+ .split('')
2594
+ .reverse()
2595
+ .join('')
2596
+ : null
2597
+ let expansionBin =
2598
+ parsedData[54] !== ''
2599
+ ? utils
2600
+ .nHexDigit(utils.hex2bin(parsedData[54]), 16)
2601
+ .split('')
2602
+ .reverse()
2603
+ .join('')
2604
+ : null
2605
+ let tachographBin =
2606
+ parsedData[27] !== ''
2607
+ ? utils
2608
+ .nHexDigit(utils.hex2bin(parsedData[27]), 8)
2609
+ .split('')
2610
+ .reverse()
2611
+ .join('')
2612
+ : null
2613
+ data = Object.assign(data, {
2614
+ alarm: utils.getAlarm(command[1], parsedData[6], [
2615
+ parsedData[index + 11],
2616
+ parsedData[index + 13]
2617
+ ]),
2618
+ loc: {
2619
+ type: 'Point',
2620
+ coordinates: [parseFloat(parsedData[64]), parseFloat(parsedData[65])]
2621
+ },
2622
+ speed: parsedData[61] !== '' ? parseFloat(parsedData[61]) : null,
2623
+ gpsStatus: utils.checkGps(
2624
+ parseFloat(parsedData[64]),
2625
+ parseFloat(parsedData[65])
2626
+ ),
2627
+ hdop: parsedData[60] !== '' ? parseFloat(parsedData[60]) : null,
2628
+ canBusDataMask: parsedData[10] !== '' ? parsedData[10] : null,
2629
+ azimuth: parsedData[62] !== '' ? parseFloat(parsedData[62]) : null,
2630
+ altitude: parsedData[63] !== '' ? parseFloat(parsedData[63]) : null,
2631
+ datetime: parsedData[66] !== '' ? utils.parseDate(parsedData[66]) : null,
2632
+ mcc: parsedData[67] !== '' ? parseInt(parsedData[67], 10) : null,
2633
+ mnc: parsedData[68] !== '' ? parseInt(parsedData[68], 10) : null,
2634
+ lac: parsedData[69] !== '' ? parseInt(parsedData[69], 16) : null,
2635
+ cid: parsedData[70] !== '' ? parseInt(parsedData[70], 16) : null,
2636
+ satellites:
2637
+ satelliteInfo && parsedData[index] !== ''
2638
+ ? parseInt(parsedData[index], 10)
2639
+ : null,
2640
+ odometer: null,
2641
+ hourmeter: null,
2642
+ configuredAlarms: {
2643
+ alarm1: {
2644
+ raw: parsedData[5] !== '' ? parsedData[5] : null,
2645
+ oilLevelLowIndicator: alarmMask1 ? alarmMask1[28] === '1' : null,
2646
+ serviceCallIndicator: alarmMask1 ? alarmMask1[27] === '1' : null,
2647
+ aribagsIndicator: alarmMask1 ? alarmMask1[26] === '1' : null,
2648
+ checkEngineIndicator: alarmMask1 ? alarmMask1[25] === '1' : null,
2649
+ ABSFailureIndicator: alarmMask1 ? alarmMask1[23] === '1' : null,
2650
+ engineHotIndicator: alarmMask1 ? alarmMask1[22] === '1' : null,
2651
+ oilPressureIndicator: alarmMask1 ? alarmMask1[21] === '1' : null,
2652
+ brakeSystemaFailureIndicator: alarmMask1
2653
+ ? alarmMask1[20] === '1'
2654
+ : null,
2655
+ batteryIndicator: alarmMask1 ? alarmMask1[19] === '1' : null,
2656
+ coolantLevelLowIndicator: alarmMask1 ? alarmMask1[18] === '1' : null,
2657
+ brakeFluidLowIndicator: alarmMask1 ? alarmMask1[17] === '1' : null,
2658
+ webcastIndicator: alarmMask1 ? alarmMask1[16] === '1' : null,
2659
+ trunkIndicator: alarmMask1 ? alarmMask1[15] === '1' : null,
2660
+ doorsIndicator: alarmMask1 ? alarmMask1[14] === '1' : null,
2661
+ frontFogLightsIndicator: alarmMask1 ? alarmMask1[13] === '1' : null,
2662
+ rearFogLightsIndicator: alarmMask1 ? alarmMask1[12] === '1' : null,
2663
+ highBeamsIndicator: alarmMask1 ? alarmMask1[11] === '1' : null,
2664
+ lowBeamsIndicator: alarmMask1 ? alarmMask1[10] === '1' : null,
2665
+ runningLightsIndicator: alarmMask1 ? alarmMask1[9] === '1' : null,
2666
+ reverseGearIndicator: alarmMask1 ? alarmMask1[8] === '1' : null,
2667
+ centralLockIndicator: alarmMask1 ? alarmMask1[7] === '1' : null,
2668
+ handbrakeIndicator: alarmMask1 ? alarmMask1[6] === '1' : null,
2669
+ clutchPedalIndicator: alarmMask1 ? alarmMask1[5] === '1' : null,
2670
+ brakePedalIndicator: alarmMask1 ? alarmMask1[4] === '1' : null,
2671
+ cruiseControlIndicator: alarmMask1 ? alarmMask1[3] === '1' : null,
2672
+ airConditioningIndicator: alarmMask1 ? alarmMask1[2] === '1' : null,
2673
+ driverSeatbeltIndicator: alarmMask1 ? alarmMask1[1] === '1' : null,
2674
+ fuelLowIndicator: alarmMask1 ? alarmMask1[0] === '1' : null
2675
+ },
2676
+ alarm2: {
2677
+ raw: parsedData[6] !== '' ? parsedData[6] : null,
2678
+ hood: alarmMask2 ? alarmMask2[21] === '1' : null,
2679
+ trunk: alarmMask2 ? alarmMask2[20] === '1' : null,
2680
+ rearRightDoor: alarmMask2 ? alarmMask2[19] === '1' : null,
2681
+ rearLeftDoor: alarmMask2 ? alarmMask2[18] === '1' : null,
2682
+ passengeDoor: alarmMask2 ? alarmMask2[17] === '1' : null,
2683
+ driverDoor: alarmMask2 ? alarmMask2[16] === '1' : null,
2684
+ hazadrLights: alarmMask2 ? alarmMask2[5] === '1' : null,
2685
+ readFogLights: alarmMask2 ? alarmMask2[4] === '1' : null,
2686
+ fronFogLights: alarmMask2 ? alarmMask2[3] === '1' : null,
2687
+ highBeam: alarmMask2 ? alarmMask2[2] === '1' : null,
2688
+ lowBeam: alarmMask2 ? alarmMask2[1] === '1' : null,
2689
+ runningLights: alarmMask2 ? alarmMask2[0] === '1' : null
2690
+ },
2691
+ alarm3: {
2692
+ raw: parsedData[7] !== '' ? parsedData[7] : null,
2693
+ overHighRPM: alarmMask3 ? alarmMask3[3] === '1' : null,
2694
+ underHighRPM: alarmMask3 ? alarmMask3[2] === '1' : null,
2695
+ overLowRPM: alarmMask3 ? alarmMask3[1] === '1' : null,
2696
+ underLowRPM: alarmMask3 ? alarmMask3[0] === '1' : null
2697
+ }
2698
+ },
2699
+ can: {
2700
+ vin: parsedData[11] !== '' ? parseInt(parsedData[11]) : null,
2701
+ ignitionKey:
2702
+ parsedData[12] !== '' ? parseInt(parsedData[12], 10) : null,
2703
+ distance: parsedData[13] !== '' ? parsedData[13] : null,
2704
+ fuelUsed: parsedData[14] !== '' ? parseFloat(parsedData[14]) : null, // float
2705
+ rpm: parsedData[15] !== '' ? parseInt(parsedData[15], 10) : null, // int
2706
+ speed: parsedData[16] !== '' ? parseFloat(parsedData[16]) : null,
2707
+ coolantTemp:
2708
+ parsedData[17] !== '' ? parseInt(parsedData[17], 10) : null,
2709
+ fuelConsumption: parsedData[18] !== '' ? parsedData[18] : null,
2710
+ fuelLevel: parsedData[19] !== '' ? parsedData[19] : null,
2711
+ range: parsedData[20] !== '' ? parsedData[20] : null,
2712
+ acceleratorPressure:
2713
+ parsedData[21] !== '' ? parseFloat(parsedData[21]) : null, // %
2714
+ engineHours: parsedData[22] !== '' ? parseFloat(parsedData[22]) : null,
2715
+ drivingTime: parsedData[23] !== '' ? parseFloat(parsedData[23]) : null,
2716
+ idleTime: parsedData[24] !== '' ? parseFloat(parsedData[24]) : null,
2717
+ idleFuelUsed: parsedData[25] !== '' ? parseFloat(parsedData[25]) : null,
2718
+ axleWight2: parsedData[26] !== '' ? parseInt(parsedData[26]) : null,
2719
+ tachograph: {
2720
+ raw: parsedData[27] !== '' ? parsedData[27] : null,
2721
+ validDriverData: tachographBin ? tachographBin[7] === '1' : null,
2722
+ insertedDriverCard: tachographBin ? tachographBin[5] === '1' : null,
2723
+ driverWorkingState: tachographBin
2724
+ ? utils.dWorkingStates[parseInt(tachographBin.substring(3, 5), 2)]
2725
+ : null,
2726
+ drivingTimeState: tachographBin
2727
+ ? utils.dTimeStates[parseInt(tachographBin.substring(5, 8), 2)]
2728
+ : null
2729
+ },
2730
+ indicators: {
2731
+ raw: parsedData[28] !== '' ? parsedData[28] : null,
2732
+ lowFuel: inicatorsBin ? inicatorsBin[0] === '1' : null,
2733
+ driverSeatbelt: inicatorsBin ? inicatorsBin[1] === '1' : null,
2734
+ airConditioning: inicatorsBin ? inicatorsBin[2] === '1' : null,
2735
+ cruiseControl: inicatorsBin ? inicatorsBin[3] === '1' : null,
2736
+ brakePedal: inicatorsBin ? inicatorsBin[4] === '1' : null,
2737
+ clutchPedal: inicatorsBin ? inicatorsBin[5] === '1' : null,
2738
+ handbrake: inicatorsBin ? inicatorsBin[6] === '1' : null,
2739
+ centralLock: inicatorsBin ? inicatorsBin[7] === '1' : null,
2740
+ reverseGear: inicatorsBin ? inicatorsBin[8] === '1' : null,
2741
+ runningLights: inicatorsBin ? inicatorsBin[9] === '1' : null,
2742
+ lowBeams: inicatorsBin ? inicatorsBin[10] === '1' : null,
2743
+ highBeams: inicatorsBin ? inicatorsBin[11] === '1' : null,
2744
+ rearFogLights: inicatorsBin ? inicatorsBin[12] === '1' : null,
2745
+ frontFogLights: inicatorsBin ? inicatorsBin[13] === '1' : null,
2746
+ doors: inicatorsBin ? inicatorsBin[14] === '1' : null,
2747
+ trunk: inicatorsBin ? inicatorsBin[15] === '1' : null
2748
+ },
2749
+ lights: {
2750
+ raw: parsedData[29] !== '' ? parsedData[29] : null,
2751
+ running: lights ? lights[0] === '1' : null,
2752
+ lowBeams: lights ? lights[1] === '1' : null,
2753
+ frontFog: lights ? lights[2] === '1' : null,
2754
+ rearFog: lights ? lights[3] === '1' : null,
2755
+ hazard: lights ? lights[4] === '1' : null
2756
+ },
2757
+ doors: {
2758
+ raw: parsedData[30] !== '' ? parsedData[30] : null,
2759
+ driver: doors ? doors[0] === '1' : null,
2760
+ passenger: doors ? doors[1] === '1' : null,
2761
+ rearLeft: doors ? doors[2] === '1' : null,
2762
+ rearRight: doors ? doors[3] === '1' : null,
2763
+ trunk: doors ? doors[4] === '1' : null,
2764
+ hood: doors ? doors[5] === '1' : null
2765
+ },
2766
+ overSpeedTime: parsedData[31] !== '' ? parsedData[31] : null,
2767
+ overSpeedEngineTime: parsedData[32] !== '' ? parsedData[32] : null,
2768
+ canReportExpansionMask: {
2769
+ raw: parsedData[33] !== '' ? parsedData[33] : null,
2770
+ engineTorque: canExpansionMask ? canExpansionMask[23] === '1' : null,
2771
+ rapidAccelerations: canExpansionMask
2772
+ ? canExpansionMask[22] === '1'
2773
+ : null,
2774
+ rapidBrakings: canExpansionMask ? canExpansionMask[21] === '1' : null,
2775
+ expansionInformation: canExpansionMask
2776
+ ? canExpansionMask[20] === '1'
2777
+ : null,
2778
+ registrationNumber: canExpansionMask
2779
+ ? canExpansionMask[19] === '1'
2780
+ : null,
2781
+ tachographDriver2Name: canExpansionMask
2782
+ ? canExpansionMask[18] === '1'
2783
+ : null,
2784
+ tachographDriver1Name: canExpansionMask
2785
+ ? canExpansionMask[17] === '1'
2786
+ : null,
2787
+ tachographDriver2Card: canExpansionMask
2788
+ ? canExpansionMask[16] === '1'
2789
+ : null,
2790
+ tachographDriver1Card: canExpansionMask
2791
+ ? canExpansionMask[15] === '1'
2792
+ : null,
2793
+ totalBrakeApplications: canExpansionMask
2794
+ ? canExpansionMask[14] === '1'
2795
+ : null,
2796
+ totalAcceleratorKickDownTime: canExpansionMask
2797
+ ? canExpansionMask[13] === '1'
2798
+ : null,
2799
+ totalCruiseControlTime: canExpansionMask
2800
+ ? canExpansionMask[12] === '1'
2801
+ : null,
2802
+ totalEffectiveEngineSpeedTime: canExpansionMask
2803
+ ? canExpansionMask[11] === '1'
2804
+ : null,
2805
+ totalAcceleratorKickDown: canExpansionMask
2806
+ ? canExpansionMask[10] === '1'
2807
+ : null,
2808
+ pedalBrakingFactor: canExpansionMask
2809
+ ? canExpansionMask[9] === '1'
2810
+ : null,
2811
+ engineBrakingFactor: canExpansionMask
2812
+ ? canExpansionMask[8] === '1'
2813
+ : null,
2814
+ analogInputValue: canExpansionMask
2815
+ ? canExpansionMask[7] === '1'
2816
+ : null,
2817
+ tachographDrivingDirection: canExpansionMask
2818
+ ? canExpansionMask[6] === '1'
2819
+ : null,
2820
+ tachographVehicleMotionSignal: canExpansionMask
2821
+ ? canExpansionMask[5] === '1'
2822
+ : null,
2823
+ tachographOverspeedSignal: canExpansionMask
2824
+ ? canExpansionMask[4] === '1'
2825
+ : null,
2826
+ AxleWeight4: canExpansionMask ? canExpansionMask[3] === '1' : null,
2827
+ AxleWeight3: canExpansionMask ? canExpansionMask[2] === '1' : null,
2828
+ AxleWeight1: canExpansionMask ? canExpansionMask[1] === '1' : null,
2829
+ adBlueLevel: canExpansionMask ? canExpansionMask[0] === '1' : null
2830
+ },
2831
+ canExpanded: {
2832
+ adBlueLevel:
2833
+ parsedData[34] !== '' ? parseFloat(parsedData[34]) : null,
2834
+ axleWeight1: parsedData[35] !== '' ? parseInt(parsedData[35]) : null,
2835
+ axleWeight3: parsedData[36] !== '' ? parseInt(parsedData[36]) : null,
2836
+ axleWeight4: parsedData[37] !== '' ? parseInt(parsedData[37]) : null,
2837
+ tachographOverspeedSignal:
2838
+ parsedData[38] !== '' ? parseInt(parsedData[38]) : null,
2839
+ tachographVehicleMotionSignal:
2840
+ parsedData[39] !== '' ? parseInt(parsedData[39]) : null,
2841
+ tachographDrivingDirection:
2842
+ parsedData[40] !== '' ? parseInt(parsedData[40]) : null,
2843
+ analogInputValue:
2844
+ parsedData[41] !== '' ? parseInt(parsedData[41]) : null,
2845
+ engineBrakingFactor:
2846
+ parsedData[42] !== '' ? parseInt(parsedData[42]) : null,
2847
+ pedalBrakingFactor:
2848
+ parsedData[43] !== '' ? parseInt(parsedData[43]) : null,
2849
+ totalAcceleratorKickDown:
2850
+ parsedData[44] !== '' ? parseInt(parsedData[44]) : null,
2851
+ totalEffectiveEngineSpeedTime:
2852
+ parsedData[45] !== '' ? parseFloat(parsedData[45]) : null,
2853
+ totalCruiseControlTime:
2854
+ parsedData[46] !== '' ? parseFloat(parsedData[46]) : null,
2855
+ totalAcceleratorKickDownTime:
2856
+ parsedData[47] !== '' ? parseFloat(parsedData[47]) : null,
2857
+ totalBrakeApplications:
2858
+ parsedData[48] !== '' ? parseInt(parsedData[48]) : null,
2859
+ tachographDriver1Card:
2860
+ parsedData[49] !== '' ? parseInt(parsedData[49]) : null,
2861
+ tachographDriver2Card:
2862
+ parsedData[50] !== '' ? parseInt(parsedData[50]) : null,
2863
+ tachographDriver1Name: parsedData[51] !== '' ? parsedData[51] : null,
2864
+ tachographDriver2Name: parsedData[52] !== '' ? parsedData[52] : null,
2865
+ registrationNumber:
2866
+ parsedData[53] !== '' ? parseInt(parsedData[53]) : null,
2867
+ expansionInformation: {
2868
+ raw: parsedData[54] !== '' ? parsedData[54] : null,
2869
+ webasto: expansionBin ? expansionBin[0] === '1' : null,
2870
+ brakeFluidLowIndicator: expansionBin
2871
+ ? expansionBin[1] === '1'
2872
+ : null,
2873
+ coolantLevelLowIndicator: expansionBin
2874
+ ? expansionBin[2] === '1'
2875
+ : null,
2876
+ batteryIndicator: expansionBin ? expansionBin[3] === '1' : null,
2877
+ brakeSystemaFailureIndicator: expansionBin
2878
+ ? expansionBin[4] === '1'
2879
+ : null,
2880
+ oilPressureIndicator: expansionBin ? expansionBin[5] === '1' : null,
2881
+ engineHotIndicator: expansionBin ? expansionBin[6] === '1' : null,
2882
+ ABSFailureIndicator: expansionBin ? expansionBin[7] === '1' : null,
2883
+ checkEngineIndicator: expansionBin ? expansionBin[9] === '1' : null,
2884
+ aribagsIndicator: expansionBin ? expansionBin[10] === '1' : null,
2885
+ serviceCallIndicator: expansionBin
2886
+ ? expansionBin[11] === '1'
2887
+ : null,
2888
+ oilLevelLowIndicator: expansionBin ? expansionBin[12] === '1' : null
2889
+ },
2890
+ rapidBrakings:
2891
+ parsedData[55] !== '' ? parseInt(parsedData[55]) : null,
2892
+ rapidAccelerations:
2893
+ parsedData[56] !== '' ? parseInt(parsedData[56]) : null,
2894
+ engineTorque:
2895
+ parsedData[57] !== '' ? parseFloat(parsedData[57]) : null
2896
+ }
2897
+ }
2898
+ })
2899
+ } else if (command[1] === 'GTSVR') {
2900
+ // Primary Stolen Vehicle Recovery
2901
+ // Primary: GV310LAU - Ghost: GV58LAU
2902
+ let index = 19 // possition append mask
2903
+ let satelliteInfo = false
2904
+
2905
+ // If get satellites is configured
2906
+ if (utils.includeSatellites(parsedData[index])) {
2907
+ index += 1
2908
+ satelliteInfo = true
2909
+ }
2910
+
2911
+ data = Object.assign(data, {
2912
+ alarm: utils.getAlarm(command[1], parsedData[4]),
2913
+ loc: {
2914
+ type: 'Point',
2915
+ coordinates: [parseFloat(parsedData[12]), parseFloat(parsedData[13])]
2916
+ },
2917
+ speed: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
2918
+ gpsStatus: utils.checkGps(
2919
+ parseFloat(parsedData[12]),
2920
+ parseFloat(parsedData[13])
2921
+ ),
2922
+ hdop: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
2923
+ status: null,
2924
+ azimuth: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
2925
+ altitude: parsedData[11] !== '' ? parseFloat(parsedData[11]) : null,
2926
+ datetime: parsedData[14] !== '' ? utils.parseDate(parsedData[14]) : null,
2927
+ voltage: {
2928
+ battery: null,
2929
+ inputCharge: null,
2930
+ ada: null,
2931
+ adb: null,
2932
+ adc: null
2933
+ },
2934
+ mcc: parsedData[15] !== '' ? parseInt(parsedData[15], 10) : null,
2935
+ mnc: parsedData[16] !== '' ? parseInt(parsedData[16], 10) : null,
2936
+ lac: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
2937
+ cid: parsedData[18] !== '' ? parseInt(parsedData[18], 16) : null,
2938
+ satellites:
2939
+ satelliteInfo && parsedData[index] !== ''
2940
+ ? parseInt(parsedData[index])
2941
+ : null,
2942
+ odometer:
2943
+ parsedData[index + 2] !== '' ? parseFloat(parsedData[index + 2]) : null,
2944
+ hourmeter: parsedData[index + 1] !== '' ? parsedData[index + 1] : null,
2945
+ bluetooth: {
2946
+ mac: parsedData[5] !== '' ? parsedData[5] : null,
2947
+ svrInfo: parsedData[6] !== '' ? parsedData[6] : null
2948
+ }
2949
+ })
2950
+ } else if (command[1] === 'GTLBA') {
2951
+ // Low Battery for FR433 devices
2952
+ let index = 17 // possition append mask
2953
+ let satelliteInfo = false
2954
+
2955
+ // If get satellites is configured
2956
+ if (utils.includeSatellites(parsedData[index])) {
2957
+ index += 1
2958
+ satelliteInfo = true
2959
+ }
2960
+
2961
+ data = Object.assign(data, {
2962
+ alarm: utils.getAlarm(command[1], [parsedData[4], parsedData[5]]),
2963
+ loc: {
2964
+ type: 'Point',
2965
+ coordinates: [parseFloat(parsedData[10]), parseFloat(parsedData[11])]
2966
+ },
2967
+ speed: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
2968
+ gpsStatus: utils.checkGps(
2969
+ parseFloat(parsedData[10]),
2970
+ parseFloat(parsedData[11])
2971
+ ),
2972
+ hdop: parsedData[6] !== '' ? parseFloat(parsedData[6]) : null,
2973
+ status: null,
2974
+ azimuth: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
2975
+ altitude: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
2976
+ datetime: parsedData[12] !== '' ? utils.parseDate(parsedData[12]) : null,
2977
+ voltage: {
2978
+ battery: null,
2979
+ inputCharge: null,
2980
+ ada: null,
2981
+ adb: null,
2982
+ adc: null
2983
+ },
2984
+ mcc: parsedData[13] !== '' ? parseInt(parsedData[13], 10) : null,
2985
+ mnc: parsedData[14] !== '' ? parseInt(parsedData[14], 10) : null,
2986
+ lac: parsedData[15] !== '' ? parseInt(parsedData[15], 16) : null,
2987
+ cid: parsedData[16] !== '' ? parseInt(parsedData[16], 16) : null,
2988
+ satellites:
2989
+ satelliteInfo && parsedData[index] !== ''
2990
+ ? parseInt(parsedData[index])
2991
+ : null,
2992
+ odometer: null,
2993
+ hourmeter: null
2994
+ })
2995
+ } else if (command[1] === 'GTASC') {
2996
+ // Calibrarion data for XYZ-axis acceleration sensor
2997
+ let index = 24 // possition append mask
2998
+ let satelliteInfo = false
2999
+
3000
+ // If get satellites is configured
3001
+ if (utils.includeSatellites(parsedData[index])) {
3002
+ index += 1
3003
+ satelliteInfo = true
3004
+ }
3005
+
3006
+ data = Object.assign(data, {
3007
+ alarm: utils.getAlarm(command[1], null),
3008
+ loc: {
3009
+ type: 'Point',
3010
+ coordinates: [parseFloat(parsedData[17]), parseFloat(parsedData[18])]
3011
+ },
3012
+ speed: parsedData[14] !== '' ? parseFloat(parsedData[14]) : null,
3013
+ gpsStatus: utils.checkGps(
3014
+ parseFloat(parsedData[17]),
3015
+ parseFloat(parsedData[18])
3016
+ ),
3017
+ hdop: parsedData[13] !== '' ? parseFloat(parsedData[13]) : null,
3018
+ status: null,
3019
+ azimuth: parsedData[15] !== '' ? parseFloat(parsedData[15]) : null,
3020
+ altitude: parsedData[16] !== '' ? parseFloat(parsedData[16]) : null,
3021
+ datetime: parsedData[19] !== '' ? utils.parseDate(parsedData[19]) : null,
3022
+ voltage: {
3023
+ battery: null,
3024
+ inputCharge: null,
3025
+ ada: null,
3026
+ adb: null,
3027
+ adc: null
3028
+ },
3029
+ mcc: parsedData[20] !== '' ? parseInt(parsedData[20], 10) : null,
3030
+ mnc: parsedData[21] !== '' ? parseInt(parsedData[21], 10) : null,
3031
+ lac: parsedData[22] !== '' ? parseInt(parsedData[22], 16) : null,
3032
+ cid: parsedData[23] !== '' ? parseInt(parsedData[23], 16) : null,
3033
+ satellites:
3034
+ satelliteInfo && parsedData[index] !== ''
3035
+ ? parseInt(parsedData[index])
3036
+ : null,
3037
+ calibration: {
3038
+ xForward: parsedData[4] !== '' ? parseFloat(parsedData[4]) : null,
3039
+ yForward: parsedData[5] !== '' ? parseFloat(parsedData[5]) : null,
3040
+ zForward: parsedData[6] !== '' ? parseFloat(parsedData[6]) : null,
3041
+ xSide: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
3042
+ ySide: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
3043
+ zSide: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
3044
+ xVertical: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
3045
+ yVertical: parsedData[11] !== '' ? parseFloat(parsedData[11]) : null,
3046
+ zVertical: parsedData[12] !== '' ? parseFloat(parsedData[12]) : null
3047
+ },
3048
+ odometer: null,
3049
+ hourmeter: null
3050
+ })
3051
+ } else if (command[1] === 'GTHBE') {
3052
+ // Harsh Behavior Information
3053
+ // Only works when GTHBM is in mode 5
3054
+ let index = 18 // possition append mask
3055
+ let satelliteInfo = false
3056
+
3057
+ // If get satellites is configured
3058
+ if (utils.includeSatellites(parsedData[index])) {
3059
+ index += 1
3060
+ satelliteInfo = true
3061
+ }
3062
+
3063
+ let maxAcc = parsedData[index + 1] !== '' ? parsedData[index + 1] : null
3064
+ let avgAcc = parsedData[index + 2] !== '' ? parsedData[index + 2] : null
3065
+ let duration =
3066
+ parsedData[index + 3] !== '' ? parseFloat(parsedData[index + 3]) : null
3067
+
3068
+ data = Object.assign(data, {
3069
+ alarm: utils.getAlarm(
3070
+ command[1],
3071
+ [parsedData[5], parsedData[6]],
3072
+ [maxAcc, duration]
3073
+ ),
3074
+ loc: {
3075
+ type: 'Point',
3076
+ coordinates: [parseFloat(parsedData[11]), parseFloat(parsedData[12])]
3077
+ },
3078
+ speed: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
3079
+ gpsStatus: utils.checkGps(
3080
+ parseFloat(parsedData[11]),
3081
+ parseFloat(parsedData[12])
3082
+ ),
3083
+ hdop: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
3084
+ status: null,
3085
+ azimuth: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
3086
+ altitude: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
3087
+ datetime: parsedData[13] !== '' ? utils.parseDate(parsedData[13]) : null,
3088
+ voltage: {
3089
+ battery: null,
3090
+ inputCharge: null,
3091
+ ada: null,
3092
+ adb: null,
3093
+ adc: null
3094
+ },
3095
+ mcc: parsedData[14] !== '' ? parseInt(parsedData[14], 10) : null,
3096
+ mnc: parsedData[15] !== '' ? parseInt(parsedData[15], 10) : null,
3097
+ lac: parsedData[16] !== '' ? parseInt(parsedData[16], 16) : null,
3098
+ cid: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
3099
+ satellites:
3100
+ satelliteInfo && parsedData[index] !== ''
3101
+ ? parseInt(parsedData[index])
3102
+ : null,
3103
+ maxAcceleration: {
3104
+ // Acceleration in m/s2
3105
+ raw: maxAcc,
3106
+ x: maxAcc
3107
+ ? utils.getAccelerationMagnitude(maxAcc.substring(0, 4), 4)
3108
+ : null,
3109
+ y: maxAcc
3110
+ ? utils.getAccelerationMagnitude(maxAcc.substring(4, 8), 4)
3111
+ : null,
3112
+ z: maxAcc
3113
+ ? utils.getAccelerationMagnitude(maxAcc.substring(8, 12), 4)
3114
+ : null
3115
+ },
3116
+ avgAcceleration: {
3117
+ // Acceleration in m/s2
3118
+ raw: avgAcc,
3119
+ x: avgAcc
3120
+ ? utils.getAccelerationMagnitude(avgAcc.substring(0, 4), 4)
3121
+ : null,
3122
+ y: avgAcc
3123
+ ? utils.getAccelerationMagnitude(avgAcc.substring(4, 8), 4)
3124
+ : null,
3125
+ z: avgAcc
3126
+ ? utils.getAccelerationMagnitude(avgAcc.substring(8, 12), 4)
3127
+ : null
3128
+ },
3129
+ duration: duration,
3130
+ odometer:
3131
+ parsedData[index + 4] !== '' ? parseFloat(parsedData[index + 4]) : null,
3132
+ hourmeter: null
3133
+ })
3134
+ } else if (command[1] === 'GTAUR') {
3135
+ // Result of AU100 Configuration
3136
+ // Not verified yet (possible error in documentation)
3137
+ let index = 21 // possition append mask
3138
+ let satelliteInfo = false
3139
+
3140
+ // If get satellites is configured
3141
+ if (utils.includeSatellites(parsedData[index])) {
3142
+ index += 1
3143
+ satelliteInfo = true
3144
+ }
3145
+
3146
+ data = Object.assign(data, {
3147
+ alarm: utils.getAlarm(command[1], [
3148
+ parsedData[4],
3149
+ parsedData[5],
3150
+ parsedData[6]
3151
+ ]),
3152
+ loc: {
3153
+ type: 'Point',
3154
+ coordinates: [parseFloat(parsedData[14]), parseFloat(parsedData[15])]
3155
+ },
3156
+ speed: parsedData[11] !== '' ? parseFloat(parsedData[11]) : null,
3157
+ gpsStatus: utils.checkGps(
3158
+ parseFloat(parsedData[14]),
3159
+ parseFloat(parsedData[15])
3160
+ ),
3161
+ hdop: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
3162
+ status: null,
3163
+ azimuth: parsedData[12] !== '' ? parseFloat(parsedData[12]) : null,
3164
+ altitude: parsedData[13] !== '' ? parseFloat(parsedData[13]) : null,
3165
+ datetime: parsedData[16] !== '' ? utils.parseDate(parsedData[16]) : null,
3166
+ voltage: {
3167
+ battery: null,
3168
+ inputCharge: null,
3169
+ ada: null,
3170
+ adb: null,
3171
+ adc: null
3172
+ },
3173
+ mcc: parsedData[17] !== '' ? parseInt(parsedData[17], 10) : null,
3174
+ mnc: parsedData[18] !== '' ? parseInt(parsedData[18], 10) : null,
3175
+ lac: parsedData[19] !== '' ? parseInt(parsedData[19], 16) : null,
3176
+ cid: parsedData[20] !== '' ? parseInt(parsedData[20], 16) : null,
3177
+ satellites:
3178
+ satelliteInfo && parsedData[index] !== ''
3179
+ ? parseInt(parsedData[index])
3180
+ : null,
3181
+ odometer: null,
3182
+ hourmeter: null
3183
+ })
3184
+ } else {
3185
+ // GTBAR report is not parsed because it only supports one device
3186
+ data = Object.assign(data, {
3187
+ alarm: utils.getAlarm(command[1], raw.toString())
3188
+ })
3189
+ }
3190
+ // Check gps data
3191
+ if (data.loc !== null && typeof data.loc !== 'undefined') {
3192
+ if (
3193
+ data.loc.coordinates[0] === 0 ||
3194
+ isNaN(data.loc.coordinates[0]) ||
3195
+ data.loc.coordinates[1] === 0 ||
3196
+ isNaN(data.loc.coordinates[1])
3197
+ ) {
3198
+ data.loc = null
3199
+ }
3200
+ }
3201
+ return data
3202
+ }
3203
+
3204
+ module.exports = {
3205
+ parse: parse
3206
+ }