queclink-parser 1.3.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/gv300.js ADDED
@@ -0,0 +1,934 @@
1
+ 'use strict'
2
+ const utils = require('./utils.js')
3
+
4
+ /*
5
+ Parses messages data from GV300 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-GV300',
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
+ // Gps
31
+ if (command[1] === 'GTFRI') {
32
+ try {
33
+ data = Object.assign(data, {
34
+ alarm: utils.getAlarm(command[1], null),
35
+ loc: {
36
+ type: 'Point',
37
+ coordinates: [parseFloat(parsedData[11]), parseFloat(parsedData[12])]
38
+ },
39
+ speed: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
40
+ gpsStatus: utils.checkGps(
41
+ parseFloat(parsedData[11]),
42
+ parseFloat(parsedData[12])
43
+ ),
44
+ hdop: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
45
+ status: {
46
+ // parsedData[24]
47
+ raw: parsedData[24],
48
+ sos: false,
49
+ input: {
50
+ '1':
51
+ utils.nHexDigit(
52
+ utils.hex2bin(
53
+ utils.nHexDigit(parsedData[24], 10).substring(6, 8)
54
+ ),
55
+ 4
56
+ )[3] === '1',
57
+ '2':
58
+ utils.nHexDigit(
59
+ utils.hex2bin(
60
+ utils.nHexDigit(parsedData[24], 10).substring(6, 8)
61
+ ),
62
+ 4
63
+ )[2] === '1',
64
+ '3':
65
+ utils.nHexDigit(
66
+ utils.hex2bin(
67
+ utils.nHexDigit(parsedData[24], 10).substring(6, 8)
68
+ ),
69
+ 4
70
+ )[1] === '1',
71
+ '4':
72
+ utils.nHexDigit(
73
+ utils.hex2bin(
74
+ utils.nHexDigit(parsedData[24], 10).substring(6, 8)
75
+ ),
76
+ 4
77
+ )[0] === '1'
78
+ },
79
+ output: {
80
+ '1':
81
+ utils.nHexDigit(
82
+ utils.hex2bin(
83
+ utils.nHexDigit(parsedData[24], 10).substring(8, 10)
84
+ ),
85
+ 3
86
+ )[2] === '1',
87
+ '2':
88
+ utils.nHexDigit(
89
+ utils.hex2bin(
90
+ utils.nHexDigit(parsedData[24], 10).substring(8, 10)
91
+ ),
92
+ 3
93
+ )[1] === '1',
94
+ '3':
95
+ utils.nHexDigit(
96
+ utils.hex2bin(
97
+ utils.nHexDigit(parsedData[24], 10).substring(8, 10)
98
+ ),
99
+ 3
100
+ )[0] === '1'
101
+ },
102
+ charge: parseFloat(parsedData[4]) > 5,
103
+ state:
104
+ utils.nHexDigit(parsedData[24], 10).substring(4, 6) !== ''
105
+ ? utils.states[ // eslint-disable-line
106
+ utils.nHexDigit(parsedData[24], 10).substring(4, 6)
107
+ ]
108
+ : null
109
+ },
110
+ azimuth: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
111
+ altitude: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
112
+ datetime:
113
+ parsedData[13] !== '' ? utils.parseDate(parsedData[13]) : null,
114
+ voltage: {
115
+ battery: parsedData[23] !== '' ? parseFloat(parsedData[23]) : null, // percentage
116
+ inputCharge:
117
+ parsedData[4] !== '' ? parseFloat(parsedData[4]) / 1000 : null,
118
+ ada: parsedData[21] !== '' ? parseFloat(parsedData[21]) / 1000 : null,
119
+ adb: parsedData[22] !== '' ? parseFloat(parsedData[22]) / 1000 : null
120
+ },
121
+ mcc: parsedData[14] !== '' ? parseInt(parsedData[14], 10) : null,
122
+ mnc: parsedData[15] !== '' ? parseInt(parsedData[15], 10) : null,
123
+ lac: parsedData[16] !== '' ? parseInt(parsedData[16], 16) : null,
124
+ cid: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
125
+ odometer: parsedData[19] !== '' ? parseFloat(parsedData[19]) : null,
126
+ hourmeter:
127
+ parsedData[20] !== ''
128
+ ? utils.getHoursForHourmeter(parsedData[20])
129
+ : null
130
+ })
131
+ } catch (err) {
132
+ return { type: 'UNKNOWN', raw: data.raw.toString() }
133
+ }
134
+ } else if (command[1] === 'GTERI') {
135
+ // GPS with AC100 Devices Connected
136
+ data = Object.assign(data, {
137
+ alarm: utils.getAlarm(command[1], null),
138
+ loc: {
139
+ type: 'Point',
140
+ coordinates: [parseFloat(parsedData[12]), parseFloat(parsedData[13])]
141
+ },
142
+ speed: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
143
+ gpsStatus: utils.checkGps(
144
+ parseFloat(parsedData[12]),
145
+ parseFloat(parsedData[13])
146
+ ),
147
+ hdop: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
148
+ status: {
149
+ // parsedData[24]
150
+ raw: parsedData[25],
151
+ sos: false,
152
+ input: {
153
+ '1':
154
+ utils.nHexDigit(
155
+ utils.hex2bin(
156
+ utils.nHexDigit(parsedData[25], 10).substring(6, 8)
157
+ ),
158
+ 4
159
+ )[3] === '1',
160
+ '2':
161
+ utils.nHexDigit(
162
+ utils.hex2bin(
163
+ utils.nHexDigit(parsedData[25], 10).substring(6, 8)
164
+ ),
165
+ 4
166
+ )[2] === '1',
167
+ '3':
168
+ utils.nHexDigit(
169
+ utils.hex2bin(
170
+ utils.nHexDigit(parsedData[25], 10).substring(6, 8)
171
+ ),
172
+ 4
173
+ )[1] === '1',
174
+ '4':
175
+ utils.nHexDigit(
176
+ utils.hex2bin(
177
+ utils.nHexDigit(parsedData[25], 10).substring(6, 8)
178
+ ),
179
+ 4
180
+ )[0] === '1'
181
+ },
182
+ output: {
183
+ '1':
184
+ utils.nHexDigit(
185
+ utils.hex2bin(
186
+ utils.nHexDigit(parsedData[25], 10).substring(8, 10)
187
+ ),
188
+ 3
189
+ )[2] === '1',
190
+ '2':
191
+ utils.nHexDigit(
192
+ utils.hex2bin(
193
+ utils.nHexDigit(parsedData[25], 10).substring(8, 10)
194
+ ),
195
+ 3
196
+ )[1] === '1',
197
+ '3':
198
+ utils.nHexDigit(
199
+ utils.hex2bin(
200
+ utils.nHexDigit(parsedData[25], 10).substring(8, 10)
201
+ ),
202
+ 3
203
+ )[0] === '1'
204
+ },
205
+ charge: parseFloat(parsedData[5]) > 5,
206
+ state:
207
+ utils.nHexDigit(parsedData[25], 10).substring(4, 6) !== ''
208
+ ? utils.states[utils.nHexDigit(parsedData[25], 10).substring(4, 6)]
209
+ : null
210
+ },
211
+ azimuth: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
212
+ altitude: parsedData[11] !== '' ? parseFloat(parsedData[11]) : null,
213
+ datetime: parsedData[14] !== '' ? utils.parseDate(parsedData[14]) : null,
214
+ voltage: {
215
+ battery: parsedData[24] !== '' ? parseFloat(parsedData[24]) : null, // percentage
216
+ inputCharge:
217
+ parsedData[5] !== '' ? parseFloat(parsedData[5]) / 1000 : null,
218
+ ada: parsedData[22] !== '' ? parseFloat(parsedData[22]) / 1000 : null,
219
+ adb: parsedData[23] !== '' ? parseFloat(parsedData[23]) / 1000 : null
220
+ },
221
+ mcc: parsedData[15] !== '' ? parseInt(parsedData[15], 10) : null,
222
+ mnc: parsedData[16] !== '' ? parseInt(parsedData[16], 10) : null,
223
+ lac: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
224
+ cid: parsedData[18] !== '' ? parseInt(parsedData[18], 16) : null,
225
+ odometer: parsedData[20] !== '' ? parseFloat(parsedData[20]) : null,
226
+ hourmeter:
227
+ parsedData[21] !== ''
228
+ ? utils.getHoursForHourmeter(parsedData[21])
229
+ : null
230
+ })
231
+
232
+ // External Data
233
+ const digitFuelSensor =
234
+ utils.nHexDigit(utils.hex2bin(parsedData[4]), 5)[4] === '1'
235
+ const AC100 = utils.nHexDigit(utils.hex2bin(parsedData[4]), 5)[3] === '1'
236
+ const reserved = utils.nHexDigit(utils.hex2bin(parsedData[4]), 5)[2] === '1'
237
+ const fuelLevelPercentage =
238
+ utils.nHexDigit(utils.hex2bin(parsedData[4]), 5)[1] === '1'
239
+ const fuelVolume =
240
+ utils.nHexDigit(utils.hex2bin(parsedData[4]), 5)[0] === '1'
241
+ const fuelSensorData = digitFuelSensor ? parsedData[28] : null
242
+ const ac100DevicesConnected =
243
+ AC100 && digitFuelSensor
244
+ ? parseInt(parsedData[29], 10)
245
+ : AC100 && !digitFuelSensor ? parseInt(parsedData[28], 10) : 0
246
+
247
+ let externalData = {
248
+ eriMask: {
249
+ raw: parsedData[4],
250
+ digitFuelSensor: digitFuelSensor,
251
+ AC100: AC100,
252
+ reserved: reserved,
253
+ fuelLevelPercentage: fuelLevelPercentage,
254
+ fuelVolume: fuelVolume
255
+ },
256
+ uartDeviceType: utils.uartDeviceTypes[parsedData[26]]
257
+ }
258
+
259
+ // Fuel Sensor
260
+ if (parsedData[26] === '1') {
261
+ if (digitFuelSensor && !AC100) {
262
+ externalData = Object.assign(externalData, {
263
+ fuelSensorData: {
264
+ data: fuelSensorData,
265
+ sensorType: parsedData[29],
266
+ percentage:
267
+ fuelLevelPercentage && parsedData[30] !== ''
268
+ ? parseInt(parsedData[30], 10)
269
+ : null,
270
+ volume:
271
+ fuelVolume && fuelLevelPercentage && parsedData[31] !== ''
272
+ ? parseInt(parsedData[31], 10)
273
+ : fuelVolume && !fuelLevelPercentage && parsedData[30] !== ''
274
+ ? parseInt(parsedData[30], 10)
275
+ : null
276
+ },
277
+ AC100Devices: null
278
+ })
279
+ } else if (!digitFuelSensor && AC100) {
280
+ let ac100Devices = []
281
+ let count = 29
282
+ for (var i = 0; i < ac100DevicesConnected; i++) {
283
+ ac100Devices.push({
284
+ deviceNumber: parsedData[count],
285
+ deviceType: parsedData[count + 1],
286
+ deviceData: parsedData[count + 2]
287
+ ? utils.getTempInCelciousDegrees(parsedData[count + 2])
288
+ : null
289
+ })
290
+ count += 3
291
+ }
292
+ externalData = Object.assign(externalData, {
293
+ fuelSensorData: null,
294
+ AC100Devices: ac100Devices
295
+ })
296
+ } else if (digitFuelSensor && AC100) {
297
+ let ac100Devices = []
298
+ let count =
299
+ fuelVolume && fuelLevelPercentage
300
+ ? 33
301
+ : fuelVolume && !fuelLevelPercentage ? 32 : 31
302
+ for (var j = 0; j < ac100DevicesConnected; j++) {
303
+ ac100Devices.push({
304
+ deviceNumber: parsedData[count],
305
+ deviceType: parsedData[count + 1],
306
+ deviceData: parsedData[count + 2]
307
+ ? utils.getTempInCelciousDegrees(parsedData[count + 2])
308
+ : null
309
+ })
310
+ count += 3
311
+ }
312
+ externalData = Object.assign(externalData, {
313
+ fuelSensorData: {
314
+ data: fuelSensorData,
315
+ sensorType: parsedData[30],
316
+ percentage:
317
+ fuelLevelPercentage && parsedData[31] !== ''
318
+ ? parseInt(parsedData[31], 10)
319
+ : null,
320
+ volume:
321
+ fuelVolume && fuelLevelPercentage && parsedData[32] !== ''
322
+ ? parseInt(parsedData[32], 10)
323
+ : fuelVolume && !fuelLevelPercentage && parsedData[31] !== ''
324
+ ? parseInt(parsedData[31], 10)
325
+ : null
326
+ },
327
+ AC100Devices: ac100Devices
328
+ })
329
+ }
330
+ } else if (parsedData[26] === '2') {
331
+ // AC100 1 Wire Bus
332
+ if (!digitFuelSensor && AC100) {
333
+ let ac100Devices = []
334
+ let count = 29
335
+ for (var k = 0; k < ac100DevicesConnected; k++) {
336
+ ac100Devices.push({
337
+ deviceNumber: parsedData[count],
338
+ deviceType: parsedData[count + 1],
339
+ deviceData: parsedData[count + 2]
340
+ ? utils.getTempInCelciousDegrees(parsedData[count + 2])
341
+ : null
342
+ })
343
+ count += 3
344
+ }
345
+ externalData = Object.assign(externalData, {
346
+ fuelSensorData: null,
347
+ AC100Devices: ac100Devices
348
+ })
349
+ } else if (digitFuelSensor && !AC100) {
350
+ externalData = Object.assign(externalData, {
351
+ fuelSensorData: {
352
+ data: fuelSensorData,
353
+ sensorType: null,
354
+ percentage: null,
355
+ volume: null
356
+ },
357
+ AC100Devices: null
358
+ })
359
+ } else if (digitFuelSensor && AC100) {
360
+ let ac100Devices = []
361
+ let count = 29
362
+ for (var l = 0; l < ac100DevicesConnected; l++) {
363
+ ac100Devices.push({
364
+ deviceNumber: parsedData[count],
365
+ deviceType: parsedData[count + 1],
366
+ deviceData: parsedData[count + 2]
367
+ ? utils.getTempInCelciousDegrees(parsedData[count + 2])
368
+ : null
369
+ })
370
+ count += 3
371
+ }
372
+ externalData = Object.assign(externalData, {
373
+ fuelSensorData: {
374
+ data: fuelSensorData,
375
+ sensorType: null,
376
+ percentage: null,
377
+ volume: null
378
+ },
379
+ AC100Devices: ac100Devices
380
+ })
381
+ }
382
+ }
383
+ data = Object.assign(data, {
384
+ externalData: externalData
385
+ })
386
+ } else if (command[1] === 'GTHBD') {
387
+ // Heartbeat. It must response an ACK command
388
+ data = Object.assign(data, {
389
+ alarm: utils.getAlarm(command[1], null)
390
+ })
391
+ } else if (command[1] === 'GTINF') {
392
+ // General Info Report
393
+ data = Object.assign(data, {
394
+ alarm: utils.getAlarm(command[1], null),
395
+ state: utils.states[parsedData[4]],
396
+ gsmInfo: {
397
+ SIM_ICC: parsedData[5],
398
+ RSSI_dBm: parsedData[6],
399
+ RSSI_quality:
400
+ parsedData[7] !== ''
401
+ ? 100 * parseInt(parseFloat(parsedData[7]) / 7, 10)
402
+ : null // Percentage
403
+ },
404
+ backupBattery: {
405
+ using: parsedData[10] === '1',
406
+ voltage: parsedData[11] !== '' ? parseFloat(parsedData[11]) : null,
407
+ charging: parsedData[12] === '1'
408
+ },
409
+ externalGPSAntenna: parsedData[15] === '0',
410
+ status: {
411
+ // parsedData[24]
412
+ raw: parsedData[18] + parsedData[19],
413
+ sos: false,
414
+ input: {
415
+ '4': utils.nHexDigit(utils.hex2bin(parsedData[20][1]), 4)[0] === '1',
416
+ '3': utils.nHexDigit(utils.hex2bin(parsedData[20][1]), 4)[1] === '1',
417
+ '2': utils.nHexDigit(utils.hex2bin(parsedData[20][1]), 4)[2] === '1',
418
+ '1': utils.nHexDigit(utils.hex2bin(parsedData[20][1]), 4)[3] === '1'
419
+ },
420
+ output: {
421
+ '4': utils.nHexDigit(utils.hex2bin(parsedData[19][1]), 4)[0] === '1',
422
+ '3': utils.nHexDigit(utils.hex2bin(parsedData[19][1]), 4)[1] === '1',
423
+ '2': utils.nHexDigit(utils.hex2bin(parsedData[19][1]), 4)[2] === '1',
424
+ '1': utils.nHexDigit(utils.hex2bin(parsedData[19][1]), 4)[3] === '1'
425
+ },
426
+ charge: parsedData[8] === '1'
427
+ },
428
+ voltage: {
429
+ battery:
430
+ parsedData[11] !== ''
431
+ ? parseInt(100 * (parseFloat(parsedData[11]) / 5), 10)
432
+ : null, // percentage
433
+ inputCharge:
434
+ parsedData[17] !== '' ? parseFloat(parsedData[17]) / 1000 : null,
435
+ ada: parsedData[18] !== '' ? parseFloat(parsedData[18]) / 1000 : null,
436
+ adb: parsedData[19] !== '' ? parseFloat(parsedData[19]) / 1000 : null
437
+ },
438
+ lastFixUTCTime:
439
+ parsedData[16] !== '' ? utils.parseDate(parsedData[16]) : null,
440
+ timezoneOffset: parsedData[20]
441
+ })
442
+ } else if (
443
+ command[1] === 'GTTOW' ||
444
+ command[1] === 'GTDIS' ||
445
+ command[1] === 'GTIOB' ||
446
+ command[1] === 'GTSPD' ||
447
+ command[1] === 'GTSOS' ||
448
+ command[1] === 'GTRTL' ||
449
+ command[1] === 'GTDOG' ||
450
+ command[1] === 'GTIGL' ||
451
+ command[1] === 'GTHBM'
452
+ ) {
453
+ // Common Alarms
454
+ data = Object.assign(data, {
455
+ alarm: utils.getAlarm(command[1], parsedData[5]),
456
+ loc: {
457
+ type: 'Point',
458
+ coordinates: [parseFloat(parsedData[11]), parseFloat(parsedData[12])]
459
+ },
460
+ speed: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
461
+ gpsStatus: utils.checkGps(
462
+ parseFloat(parsedData[11]),
463
+ parseFloat(parsedData[12])
464
+ ),
465
+ hdop: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
466
+ status: null,
467
+ azimuth: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
468
+ altitude: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
469
+ datetime: parsedData[13] !== '' ? utils.parseDate(parsedData[13]) : null,
470
+ voltage: {
471
+ battery: null,
472
+ inputCharge: null,
473
+ ada: null,
474
+ adb: null
475
+ },
476
+ mcc: parsedData[14] !== '' ? parseInt(parsedData[14], 10) : null,
477
+ mnc: parsedData[15] !== '' ? parseInt(parsedData[15], 10) : null,
478
+ lac: parsedData[16] !== '' ? parseInt(parsedData[16], 16) : null,
479
+ cid: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
480
+ odometer: parsedData[19] !== '' ? parseFloat(parsedData[19]) : null,
481
+ hourmeter: null
482
+ })
483
+ } else if (command[1] === 'GTTMP') {
484
+ // Temperature Alarm
485
+ let number = parsedData[7] !== '' ? parseInt(parsedData[7], 10) : 1
486
+ let index = 8 + 12 * number // odometer
487
+ data = Object.assign(data, {
488
+ alarm: utils.getAlarm(command[1], parsedData[6], [
489
+ parsedData[index + 9],
490
+ parsedData[index + 11]
491
+ ]),
492
+ loc: {
493
+ type: 'Point',
494
+ coordinates: [parseFloat(parsedData[12]), parseFloat(parsedData[13])]
495
+ },
496
+ speed: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
497
+ gpsStatus: utils.checkGps(
498
+ parseFloat(parsedData[12]),
499
+ parseFloat(parsedData[13])
500
+ ),
501
+ hdop: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
502
+ status: {
503
+ // parsedData[24]
504
+ raw: `${parsedData[index + 4]}${parsedData[index + 5]}`,
505
+ sos: false,
506
+ input: {
507
+ '4':
508
+ utils.nHexDigit(utils.hex2bin(parsedData[index + 4][1]), 4)[0] ===
509
+ '1',
510
+ '3':
511
+ utils.nHexDigit(utils.hex2bin(parsedData[index + 4][1]), 4)[1] ===
512
+ '1',
513
+ '2':
514
+ utils.nHexDigit(utils.hex2bin(parsedData[index + 4][1]), 4)[2] ===
515
+ '1',
516
+ '1':
517
+ utils.nHexDigit(utils.hex2bin(parsedData[index + 4][1]), 4)[3] ===
518
+ '1'
519
+ },
520
+ output: {
521
+ '3':
522
+ utils.nHexDigit(utils.hex2bin(parsedData[index + 5][1]), 4)[1] ===
523
+ '1',
524
+ '2':
525
+ utils.nHexDigit(utils.hex2bin(parsedData[index + 5][1]), 4)[2] ===
526
+ '1',
527
+ '1':
528
+ utils.nHexDigit(utils.hex2bin(parsedData[index + 5][1]), 4)[3] ===
529
+ '1'
530
+ },
531
+ charge: parseFloat(parsedData[5]) > 5,
532
+ state: null
533
+ },
534
+ azimuth: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
535
+ altitude: parsedData[11] !== '' ? parseFloat(parsedData[11]) : null,
536
+ datetime: parsedData[14] !== '' ? utils.parseDate(parsedData[14]) : null,
537
+ voltage: {
538
+ battery: null, // percentage
539
+ inputCharge:
540
+ parsedData[5] !== '' ? parseFloat(parsedData[5]) / 1000 : null,
541
+ ada:
542
+ parsedData[index + 2] !== ''
543
+ ? parseFloat(parsedData[index + 2]) / 1000
544
+ : null,
545
+ adb:
546
+ parsedData[index + 3] !== ''
547
+ ? parseFloat(parsedData[index + 3]) / 1000
548
+ : null
549
+ },
550
+ mcc: parsedData[15] !== '' ? parseInt(parsedData[15], 10) : null,
551
+ mnc: parsedData[16] !== '' ? parseInt(parsedData[16], 10) : null,
552
+ lac: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
553
+ cid: parsedData[18] !== '' ? parseInt(parsedData[18], 16) : null,
554
+ odometer: parsedData[index] !== '' ? parseFloat(parsedData[index]) : null,
555
+ hourmeter:
556
+ parsedData[index + 1] !== ''
557
+ ? utils.getHoursForHourmeter(parsedData[index + 1])
558
+ : null
559
+ })
560
+ } else if (command[1] === 'GTEPS' || command[1] === 'GTAIS') {
561
+ // External low battery and Low voltage for analog input
562
+ data = Object.assign(data, {
563
+ alarm: utils.getAlarm(command[1], parsedData[5]),
564
+ loc: {
565
+ type: 'Point',
566
+ coordinates: [parseFloat(parsedData[11]), parseFloat(parsedData[12])]
567
+ },
568
+ speed: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
569
+ gpsStatus: utils.checkGps(
570
+ parseFloat(parsedData[11]),
571
+ parseFloat(parsedData[12])
572
+ ),
573
+ hdop: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
574
+ status: null,
575
+ azimuth: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
576
+ altitude: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
577
+ datetime: parsedData[13] !== '' ? utils.parseDate(parsedData[13]) : null,
578
+ voltage: {
579
+ battery: parsedData[23] !== '' ? parseFloat(parsedData[23]) : null, // percentage
580
+ inputCharge:
581
+ parsedData[4] !== '' ? parseFloat(parsedData[4]) / 1000 : null,
582
+ ada: parsedData[21] !== '' ? parseFloat(parsedData[21]) : null,
583
+ adb: parsedData[22] !== '' ? parseFloat(parsedData[22]) : null
584
+ },
585
+ mcc: parsedData[14] !== '' ? parseInt(parsedData[14], 10) : null,
586
+ mnc: parsedData[15] !== '' ? parseInt(parsedData[15], 10) : null,
587
+ lac: parsedData[16] !== '' ? parseInt(parsedData[16], 16) : null,
588
+ cid: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
589
+ odometer: parsedData[19] !== '' ? parseFloat(parsedData[19]) : null,
590
+ hourmeter:
591
+ parsedData[20] !== ''
592
+ ? utils.getHoursForHourmeter(parsedData[20])
593
+ : null
594
+ })
595
+ } else if (
596
+ command[1] === 'GTPNA' ||
597
+ command[1] === 'GTPFA' ||
598
+ command[1] === 'GTPDP'
599
+ ) {
600
+ // Event report (It uses the last GPS data and MCC info)
601
+ data = Object.assign(data, {
602
+ alarm: utils.getAlarm(command[1], null),
603
+ loc: null,
604
+ speed: null,
605
+ gpsStatus: null,
606
+ hdop: null,
607
+ status: null,
608
+ azimuth: null,
609
+ altitude: null,
610
+ datetime: parsedData[4] !== '' ? utils.parseDate(parsedData[4]) : null,
611
+ voltage: {
612
+ battery: null,
613
+ inputCharge: null,
614
+ ada: null,
615
+ adb: null
616
+ },
617
+ mcc: null,
618
+ mnc: null,
619
+ lac: null,
620
+ cid: null,
621
+ odometer: null,
622
+ hourmeter: null
623
+ })
624
+ } else if (
625
+ command[1] === 'GTMPN' ||
626
+ command[1] === 'GTMPF' ||
627
+ command[1] === 'GTCRA' ||
628
+ command[1] === 'GTJDR'
629
+ ) {
630
+ data = Object.assign(data, {
631
+ alarm: utils.getAlarm(command[1], null),
632
+ loc: {
633
+ type: 'Point',
634
+ coordinates: [parseFloat(parsedData[8]), parseFloat(parsedData[9])]
635
+ },
636
+ speed: parsedData[5] !== '' ? parseFloat(parsedData[5]) : null,
637
+ gpsStatus: utils.checkGps(
638
+ parseFloat(parsedData[8]),
639
+ parseFloat(parsedData[9])
640
+ ),
641
+ hdop: parsedData[4] !== '' ? parseFloat(parsedData[4]) : null,
642
+ status: null,
643
+ azimuth: parsedData[6] !== '' ? parseFloat(parsedData[6]) : null,
644
+ altitude: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
645
+ datetime: parsedData[10] !== '' ? utils.parseDate(parsedData[10]) : null,
646
+ voltage: {
647
+ battery: null,
648
+ inputCharge: null,
649
+ ada: null,
650
+ adb: null
651
+ },
652
+ mcc: parsedData[11] !== '' ? parseInt(parsedData[11], 10) : null,
653
+ mnc: parsedData[12] !== '' ? parseInt(parsedData[12], 10) : null,
654
+ lac: parsedData[13] !== '' ? parseInt(parsedData[13], 16) : null,
655
+ cid: parsedData[14] !== '' ? parseInt(parsedData[14], 16) : null,
656
+ odometer: null,
657
+ hourmeter: null
658
+ })
659
+ } else if (
660
+ command[1] === 'GTJDS' ||
661
+ command[1] === 'GTANT' ||
662
+ command[1] === 'GTRMD'
663
+ ) {
664
+ data = Object.assign(data, {
665
+ alarm: utils.getAlarm(command[1], parsedData[4]),
666
+ loc: {
667
+ type: 'Point',
668
+ coordinates: [parseFloat(parsedData[9]), parseFloat(parsedData[10])]
669
+ },
670
+ speed: parsedData[6] !== '' ? parseFloat(parsedData[6]) : null,
671
+ gpsStatus: utils.checkGps(
672
+ parseFloat(parsedData[9]),
673
+ parseFloat(parsedData[10])
674
+ ),
675
+ hdop: parsedData[5] !== '' ? parseFloat(parsedData[5]) : null,
676
+ status: null,
677
+ azimuth: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
678
+ altitude: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
679
+ datetime: parsedData[11] !== '' ? utils.parseDate(parsedData[11]) : null,
680
+ voltage: {
681
+ battery: null,
682
+ inputCharge: null,
683
+ ada: null,
684
+ adb: null
685
+ },
686
+ mcc: parsedData[12] !== '' ? parseInt(parsedData[12], 10) : null,
687
+ mnc: parsedData[13] !== '' ? parseInt(parsedData[13], 10) : null,
688
+ lac: parsedData[14] !== '' ? parseInt(parsedData[14], 16) : null,
689
+ cid: parsedData[15] !== '' ? parseInt(parsedData[15], 16) : null,
690
+ odometer: null,
691
+ hourmeter: null
692
+ })
693
+ } else if (command[1] === 'GTBPL') {
694
+ data = Object.assign(data, {
695
+ alarm: utils.getAlarm(command[1], null),
696
+ loc: {
697
+ type: 'Point',
698
+ coordinates: [parseFloat(parsedData[9]), parseFloat(parsedData[10])]
699
+ },
700
+ speed: parsedData[6] !== '' ? parseFloat(parsedData[6]) : null,
701
+ gpsStatus: utils.checkGps(
702
+ parseFloat(parsedData[9]),
703
+ parseFloat(parsedData[10])
704
+ ),
705
+ hdop: parsedData[5] !== '' ? parseFloat(parsedData[5]) : null,
706
+ status: null,
707
+ azimuth: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
708
+ altitude: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
709
+ datetime: parsedData[11] !== '' ? utils.parseDate(parsedData[11]) : null,
710
+ voltage: {
711
+ battery: parsedData[4] !== '' ? parseFloat(parsedData[4]) : null,
712
+ inputCharge: null,
713
+ ada: null,
714
+ adb: null
715
+ },
716
+ mcc: parsedData[12] !== '' ? parseInt(parsedData[12], 10) : null,
717
+ mnc: parsedData[13] !== '' ? parseInt(parsedData[13], 10) : null,
718
+ lac: parsedData[14] !== '' ? parseInt(parsedData[14], 16) : null,
719
+ cid: parsedData[15] !== '' ? parseInt(parsedData[15], 16) : null,
720
+ odometer: null,
721
+ hourmeter: null
722
+ })
723
+ } else if (command[1] === 'GTIGN' || command[1] === 'GTIGF') {
724
+ data = Object.assign(data, {
725
+ alarm: utils.getAlarm(command[1], parsedData[4]),
726
+ loc: {
727
+ type: 'Point',
728
+ coordinates: [parseFloat(parsedData[9]), parseFloat(parsedData[10])]
729
+ },
730
+ speed: parsedData[6] !== '' ? parseFloat(parsedData[6]) : null,
731
+ gpsStatus: utils.checkGps(
732
+ parseFloat(parsedData[9]),
733
+ parseFloat(parsedData[10])
734
+ ),
735
+ hdop: parsedData[5] !== '' ? parseFloat(parsedData[5]) : null,
736
+ status: null,
737
+ azimuth: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
738
+ altitude: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
739
+ datetime: parsedData[11] !== '' ? utils.parseDate(parsedData[11]) : null,
740
+ voltage: {
741
+ battery: null,
742
+ inputCharge: null,
743
+ ada: null,
744
+ adb: null
745
+ },
746
+ mcc: parsedData[12] !== '' ? parseInt(parsedData[12], 10) : null,
747
+ mnc: parsedData[13] !== '' ? parseInt(parsedData[13], 10) : null,
748
+ lac: parsedData[14] !== '' ? parseInt(parsedData[14], 16) : null,
749
+ cid: parsedData[15] !== '' ? parseInt(parsedData[15], 16) : null,
750
+ odometer: parsedData[18] !== '' ? parseFloat(parsedData[18]) : null,
751
+ hourmeter:
752
+ parsedData[17] !== ''
753
+ ? utils.getHoursForHourmeter(parsedData[17])
754
+ : null
755
+ })
756
+ } else if (command[1] === 'GTIDN' || command[1] === 'GTIDF') {
757
+ data = Object.assign(data, {
758
+ alarm: utils.getAlarm(command[1], parsedData[5]),
759
+ loc: {
760
+ type: 'Point',
761
+ coordinates: [parseFloat(parsedData[10]), parseFloat(parsedData[11])]
762
+ },
763
+ speed: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
764
+ gpsStatus: utils.checkGps(
765
+ parseFloat(parsedData[10]),
766
+ parseFloat(parsedData[11])
767
+ ),
768
+ hdop: parsedData[6] !== '' ? parseFloat(parsedData[6]) : null,
769
+ status: null,
770
+ azimuth: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
771
+ altitude: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
772
+ datetime: parsedData[12] !== '' ? utils.parseDate(parsedData[12]) : null,
773
+ voltage: {
774
+ battery: null,
775
+ inputCharge: null,
776
+ ada: null,
777
+ adb: null
778
+ },
779
+ mcc: parsedData[13] !== '' ? parseInt(parsedData[13], 10) : null,
780
+ mnc: parsedData[14] !== '' ? parseInt(parsedData[14], 10) : null,
781
+ lac: parsedData[15] !== '' ? parseInt(parsedData[15], 16) : null,
782
+ cid: parsedData[16] !== '' ? parseInt(parsedData[16], 16) : null,
783
+ odometer: parsedData[18] !== '' ? parseFloat(parsedData[18]) : null,
784
+ hourmeter: null
785
+ })
786
+ } else if (
787
+ command[1] === 'GTSTR' ||
788
+ command[1] === 'GTSTP' ||
789
+ command[1] === 'GTLSP'
790
+ ) {
791
+ data = Object.assign(data, {
792
+ alarm: utils.getAlarm(command[1], null),
793
+ loc: {
794
+ type: 'Point',
795
+ coordinates: [parseFloat(parsedData[10]), parseFloat(parsedData[11])]
796
+ },
797
+ speed: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
798
+ gpsStatus: utils.checkGps(
799
+ parseFloat(parsedData[10]),
800
+ parseFloat(parsedData[11])
801
+ ),
802
+ hdop: parsedData[6] !== '' ? parseFloat(parsedData[6]) : null,
803
+ status: null,
804
+ azimuth: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
805
+ altitude: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
806
+ datetime: parsedData[12] !== '' ? utils.parseDate(parsedData[12]) : null,
807
+ voltage: {
808
+ battery: null,
809
+ inputCharge: null,
810
+ ada: null,
811
+ adb: null
812
+ },
813
+ mcc: parsedData[13] !== '' ? parseInt(parsedData[13], 10) : null,
814
+ mnc: parsedData[14] !== '' ? parseInt(parsedData[14], 10) : null,
815
+ lac: parsedData[15] !== '' ? parseInt(parsedData[15], 16) : null,
816
+ cid: parsedData[16] !== '' ? parseInt(parsedData[16], 16) : null,
817
+ odometer: parsedData[18] !== '' ? parseFloat(parsedData[18]) : null,
818
+ hourmeter: null
819
+ })
820
+ } else if (command[1] === 'GTSTT') {
821
+ // Motion State Changed
822
+ data = Object.assign(data, {
823
+ alarm: utils.getAlarm(command[1], null),
824
+ loc: {
825
+ type: 'Point',
826
+ coordinates: [parseFloat(parsedData[9]), parseFloat(parsedData[10])]
827
+ },
828
+ speed: parsedData[6] !== '' ? parseFloat(parsedData[6]) : null,
829
+ gpsStatus: utils.checkGps(
830
+ parseFloat(parsedData[9]),
831
+ parseFloat(parsedData[10])
832
+ ),
833
+ hdop: parsedData[5] !== '' ? parseFloat(parsedData[5]) : null,
834
+ status: null,
835
+ azimuth: parsedData[7] !== '' ? parseFloat(parsedData[7]) : null,
836
+ altitude: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
837
+ datetime: parsedData[11] !== '' ? utils.parseDate(parsedData[11]) : null,
838
+ voltage: {
839
+ battery: null,
840
+ inputCharge: null,
841
+ ada: null,
842
+ adb: null
843
+ },
844
+ mcc: parsedData[12] !== '' ? parseInt(parsedData[12], 10) : null,
845
+ mnc: parsedData[13] !== '' ? parseInt(parsedData[13], 10) : null,
846
+ lac: parsedData[14] !== '' ? parseInt(parsedData[14], 16) : null,
847
+ cid: parsedData[15] !== '' ? parseInt(parsedData[15], 16) : null,
848
+ odometer: null,
849
+ hourmeter: null
850
+ })
851
+ } else if (command[1] === 'GTGSS') {
852
+ // GPS Status
853
+ data = Object.assign(data, {
854
+ alarm: utils.getAlarm(command[1], parsedData[4]),
855
+ loc: {
856
+ type: 'Point',
857
+ coordinates: [parseFloat(parsedData[12]), parseFloat(parsedData[13])]
858
+ },
859
+ speed: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
860
+ gpsStatus: utils.checkGps(
861
+ parseFloat(parsedData[12]),
862
+ parseFloat(parsedData[13])
863
+ ),
864
+ hdop: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
865
+ status: null,
866
+ azimuth: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
867
+ altitude: parsedData[11] !== '' ? parseFloat(parsedData[11]) : null,
868
+ datetime: parsedData[14] !== '' ? utils.parseDate(parsedData[14]) : null,
869
+ voltage: {
870
+ battery: null,
871
+ inputCharge: null,
872
+ ada: null,
873
+ adb: null
874
+ },
875
+ mcc: parsedData[15] !== '' ? parseInt(parsedData[15], 10) : null,
876
+ mnc: parsedData[16] !== '' ? parseInt(parsedData[16], 10) : null,
877
+ lac: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
878
+ cid: parsedData[18] !== '' ? parseInt(parsedData[18], 16) : null,
879
+ odometer: null,
880
+ hourmeter: null
881
+ })
882
+ } else if (command[1] === 'GTIDA') {
883
+ // iButton
884
+ data = Object.assign(data, {
885
+ alarm: utils.getAlarm(command[1], `${parsedData[5]},${parsedData[6]}`),
886
+ loc: {
887
+ type: 'Point',
888
+ coordinates: [parseFloat(parsedData[12]), parseFloat(parsedData[13])]
889
+ },
890
+ speed: parsedData[9] !== '' ? parseFloat(parsedData[9]) : null,
891
+ gpsStatus: utils.checkGps(
892
+ parseFloat(parsedData[12]),
893
+ parseFloat(parsedData[13])
894
+ ),
895
+ hdop: parsedData[8] !== '' ? parseFloat(parsedData[8]) : null,
896
+ status: null,
897
+ azimuth: parsedData[10] !== '' ? parseFloat(parsedData[10]) : null,
898
+ altitude: parsedData[11] !== '' ? parseFloat(parsedData[11]) : null,
899
+ datetime: parsedData[14] !== '' ? utils.parseDate(parsedData[14]) : null,
900
+ voltage: {
901
+ battery: null,
902
+ inputCharge: null,
903
+ ada: null,
904
+ adb: null
905
+ },
906
+ mcc: parsedData[15] !== '' ? parseInt(parsedData[15], 10) : null,
907
+ mnc: parsedData[16] !== '' ? parseInt(parsedData[16], 10) : null,
908
+ lac: parsedData[17] !== '' ? parseInt(parsedData[17], 16) : null,
909
+ cid: parsedData[18] !== '' ? parseInt(parsedData[18], 16) : null,
910
+ odometer: parsedData[20] !== '' ? parseFloat(parsedData[20]) : null,
911
+ hourmeter: null
912
+ })
913
+ } else {
914
+ data = Object.assign(data, {
915
+ alarm: utils.getAlarm(command[1], null)
916
+ })
917
+ }
918
+ // Check gps data
919
+ if (data.loc !== null && typeof data.loc !== 'undefined') {
920
+ if (
921
+ data.loc.coordinates[0] === 0 ||
922
+ isNaN(data.loc.coordinates[0]) ||
923
+ data.loc.coordinates[1] === 0 ||
924
+ isNaN(data.loc.coordinates[1])
925
+ ) {
926
+ data.loc = null
927
+ }
928
+ }
929
+ return data
930
+ }
931
+
932
+ module.exports = {
933
+ parse: parse
934
+ }