queclink-parser 1.5.0 → 1.8.5

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/utils.js CHANGED
@@ -9,8 +9,8 @@ const langs = { es: langEs, en: langEn }
9
9
  */
10
10
  const patterns = {
11
11
  message: /^\+RESP.+\$$/,
12
- ack: /^\+ACK.+\$$/,
13
12
  buffer: /^\+BUFF/,
13
+ ack: /^\+ACK.+\$$/,
14
14
  heartbeat: /^\+ACK:GTHBD.+\$$/
15
15
  }
16
16
 
@@ -42,7 +42,8 @@ const devices = {
42
42
  '3F': 'GMT100', // New version
43
43
  F8: 'GV800W',
44
44
  '41': 'GV75W',
45
- FC: 'GV600W'
45
+ FC: 'GV600W',
46
+ '6E': 'GV310LAU'
46
47
  }
47
48
 
48
49
  /*
@@ -78,12 +79,161 @@ const OBDIIProtocols = {
78
79
  }
79
80
 
80
81
  /*
81
- Uart Devices
82
+ Possible Uart Devices
82
83
  */
83
84
  const uartDeviceTypes = {
84
85
  '0': 'No device',
85
86
  '1': 'Digit Fuel Sensor',
86
- '2': 'AC100 1 Wire Bus'
87
+ '2': 'AC100 1 Wire Bus',
88
+ '5': 'CANBUS device',
89
+ '6': 'AU100 device',
90
+ '7': 'RF433 accessory'
91
+ }
92
+
93
+ /*
94
+ Possible Data Types for DTT
95
+ */
96
+ const dataTypes = {
97
+ '0': 'Binary',
98
+ '1': 'Hexadecimal'
99
+ }
100
+ /*
101
+ Possible Network Types
102
+ */
103
+ const networkTypes = {
104
+ '0': '2G',
105
+ '1': '3G',
106
+ '2': '4G',
107
+ '99': 'Unknow'
108
+ }
109
+
110
+ /*
111
+ Possible GPS Antena Status
112
+ */
113
+ const externalGPSAntennaOptions = {
114
+ '0': 'Working',
115
+ '1': 'Detected in open circuit state',
116
+ '3': 'Unknow state',
117
+ '': 'Unknow'
118
+ }
119
+
120
+ /*
121
+ Possible Peer roles in Bluetooth
122
+ */
123
+ const peerRoles = {
124
+ '0': 'Master',
125
+ '1': 'Slave'
126
+ }
127
+
128
+ /*
129
+ Possible Peer addesses type for Bluetooth
130
+ */
131
+ const peerAddressesTypes = {
132
+ '0': 'Public',
133
+ '1': 'Random'
134
+ }
135
+
136
+ /*
137
+ Possible Reasons for bluetooth disconnection
138
+ */
139
+ const disconnectionReasons = {
140
+ '0': 'Normal',
141
+ '4': 'Device pairing fails'
142
+ }
143
+
144
+ /*
145
+ Possible Accesories Types of Bluetooth
146
+ */
147
+ const bluetoothAccessories = {
148
+ '0': 'No bluetooth Accessory',
149
+ '1': 'Escort sensor',
150
+ '2': 'Beacon temperature sensor',
151
+ '3': 'Bluetooth beacon accessory',
152
+ '6': 'Beacon Multi-Functional Sensor',
153
+ '11': 'Magnet Sensor',
154
+ '12': 'BLE TPMS sensor',
155
+ '13': 'Relay Sensor'
156
+ }
157
+
158
+ /*
159
+ Possible Accesories Models for Bluetooth Accessories
160
+ */
161
+ const bluetoothModels = {
162
+ '1': {
163
+ '0': 'TD_BLE fuel sensor',
164
+ '3': 'Angle sensor'
165
+ },
166
+ '2': {
167
+ '0': 'WTS300 (Temperature sensor)',
168
+ '1': 'Temperature ELA'
169
+ },
170
+ '6': {
171
+ '2': 'WTH300 (Temperature and Humidity Sensor)',
172
+ '3': 'RHT ELA (Temperature and Humidity Sensor)',
173
+ '4': 'WMS301 (Door Sensor with embedded Temperature and Humidity Sensor)',
174
+ '5': 'WTH301 (Temperature and Humidity Sensor)'
175
+ },
176
+ '11': {
177
+ '0': 'MAG ELA (Door Sensor)'
178
+ },
179
+ '12': {
180
+ '0': 'MLD BLE TPMS (ATP100/ATP102)'
181
+ },
182
+ '13': {
183
+ '0': 'WRL300 (Bluetooth Relay)'
184
+ }
185
+ }
186
+
187
+ /*
188
+ Possible Beacon ID Models
189
+ */
190
+ const beaconModels = {
191
+ '0': 'WKF300',
192
+ '1': 'iBeacon E6',
193
+ '2': 'ID ELA',
194
+ '4': 'WID310'
195
+ }
196
+
197
+ /*
198
+ Possible Beacon Types
199
+ */
200
+ const beaconTypes = {
201
+ '0': 'ID',
202
+ '1': 'iBeacon',
203
+ '2': 'Eddystone'
204
+ }
205
+
206
+ /*
207
+ Possible Driving Time Related States
208
+ */
209
+ const dTimeStates = {
210
+ 0: 'Sin límites alcanzados',
211
+ 1: 'Conducción sobre 4 horas y 15 minutos',
212
+ 2: 'Conducción sobre 4 horas y 30 minutos',
213
+ 3: 'Conducción sobre 8 horas y 45 minutos',
214
+ 4: 'Conducción sobre 9 horas',
215
+ 5: 'Conducción sobre 15 horas y 45 minutos (con descanso menor a 8 horas en las últimas 24 horas)',
216
+ 6: 'Conducción sobre 16 horas',
217
+ 7: 'Otro límite'
218
+ }
219
+
220
+ /*
221
+ Possible Driving Working States
222
+ */
223
+ const dWorkingStates = {
224
+ 0: 'Normal',
225
+ 1: 'En descanso - Durmiendo',
226
+ 2: 'Conductor disponible - Descanso corto',
227
+ 3: 'Conduciendo - En el volante'
228
+ }
229
+
230
+ /*
231
+ Possible port N Types for AU100
232
+ */
233
+ const portNTypes = {
234
+ '0': 'Deshabilitado',
235
+ '1': 'RS232',
236
+ '3': '1-wire'
87
237
  }
88
238
 
89
239
  /*
@@ -112,6 +262,18 @@ const getProtocolVersion = protocol => {
112
262
  }
113
263
  }
114
264
 
265
+ /*
266
+ Gets the software/hardware version
267
+ */
268
+ const getVersion = hexVersion => {
269
+ if (hexVersion === '') {
270
+ return 'no disponible'
271
+ }
272
+ const X = parseInt(hexVersion.substring(0, 2), 16)
273
+ const Y = parseInt(hexVersion.substring(2, 4), 16)
274
+ return `${X}.${Y}`
275
+ }
276
+
115
277
  /*
116
278
  Checks if the location has a valid gps position
117
279
  */
@@ -123,6 +285,14 @@ const checkGps = (lng, lat) => {
123
285
  return false
124
286
  }
125
287
 
288
+ /*
289
+ Returns if the number of satellites is
290
+ included in the report
291
+ */
292
+ const includeSatellites = positionAppendMask => {
293
+ return positionAppendMask === '01'
294
+ }
295
+
126
296
  /*
127
297
  Gets the temperature from AC100 device in celcious degrees
128
298
  */
@@ -138,6 +308,24 @@ const getTempInCelciousDegrees = hexTemp => {
138
308
  return parseFloat(hex2dec(hexTemp)) * 0.0625
139
309
  }
140
310
 
311
+ /*
312
+ Gets the Two's Complement for hex numbers
313
+ */
314
+ const getAccelerationMagnitude = (hexNumber, n) => {
315
+ let binNumber = nHexDigit(hex2bin(hexNumber), n * 4)
316
+ if (binNumber.substring(0, 5) !== '11111') {
317
+ return Number((parseInt(hexNumber, 16) / 82 * 9.80665).toFixed(2))
318
+ }
319
+ return Number(
320
+ (
321
+ (parseInt('F'.repeat(n), 16) - parseInt(hexNumber, 16) + 1) *
322
+ -1 /
323
+ 82 *
324
+ 9.80665
325
+ ).toFixed(2)
326
+ )
327
+ }
328
+
141
329
  /*
142
330
  Gets fuel consumption from string
143
331
  */
@@ -172,6 +360,53 @@ const getHoursForHourmeter = hourmeter => {
172
360
  }
173
361
  }
174
362
 
363
+ /*
364
+ Returns the dBm signal strength
365
+ */
366
+ const getSignalStrength = (networkType, value) => {
367
+ if (value === 99) {
368
+ return null
369
+ }
370
+
371
+ let calc, dBm
372
+ if (networkType === '2G' || networkType === '3G') {
373
+ calc = 2 * value - 113
374
+ dBm = calc < -113 ? 0 : calc > -51 ? 100 : calc
375
+ } else if (networkType === '4G') {
376
+ calc = 96 / 97 * value - 140
377
+ dBm = calc < -140 ? 0 : calc > -44 ? 100 : calc
378
+ } else if (networkType === 'GSM') {
379
+ calc = value - 110
380
+ dBm = calc < -110 ? 0 : calc > -47 ? 100 : calc
381
+ } else {
382
+ dBm = null
383
+ }
384
+
385
+ return dBm
386
+ }
387
+
388
+ /*
389
+ Returns the percentage of signal strength
390
+ */
391
+ const getSignalPercentage = (networkType, value) => {
392
+ if (value === 99) {
393
+ return null
394
+ }
395
+
396
+ let perc
397
+ if (networkType === '2G' || networkType === '3G') {
398
+ perc = value / 31 * 100
399
+ } else if (networkType === '4G') {
400
+ perc = value / 97 * 100
401
+ } else if (networkType === 'GSM') {
402
+ perc = value / 63 * 100
403
+ } else {
404
+ perc = null
405
+ }
406
+
407
+ return Math.round((perc + Number.EPSILON) * 100) / 100
408
+ }
409
+
175
410
  /*
176
411
  Gets the alarm type
177
412
  */
@@ -208,6 +443,13 @@ const getAlarm = (command, report, extra = false) => {
208
443
  }
209
444
  } else if (command === 'GTOPN') {
210
445
  return { type: 'OBDII_Connected', status: true, message: messages[command] }
446
+ } else if (command === 'GTAUR') {
447
+ return {
448
+ id: report[0] !== '' ? parseInt(report[0]) : null,
449
+ type: portNTypes[report[1]],
450
+ status: report[2] === '0',
451
+ message: messages[command]
452
+ }
211
453
  } else if (command === 'GTOPF') {
212
454
  return {
213
455
  type: 'OBDII_Connected',
@@ -229,7 +471,9 @@ const getAlarm = (command, report, extra = false) => {
229
471
  if (extra === true && reportID === 1) {
230
472
  reportID = 2
231
473
  } else if (
232
- ['gv800w', 'gv600w', 'gv300w', 'gv75w', 'GMT100'].includes(extra)
474
+ ['gv800w', 'gv600w', 'gv300w', 'gv310lau', 'gv75w', 'GMT100'].includes(
475
+ extra
476
+ )
233
477
  ) {
234
478
  reportID += 1
235
479
  }
@@ -237,7 +481,7 @@ const getAlarm = (command, report, extra = false) => {
237
481
  type: 'DI',
238
482
  number: reportID,
239
483
  status: reportType === 1,
240
- message: messages[command][reportType].replace('port', reportID)
484
+ message: messages[command][reportType].replace('id',reportID)
241
485
  }
242
486
  } else if (command === 'GTNMR') {
243
487
  const reportType = report[1]
@@ -266,6 +510,27 @@ const getAlarm = (command, report, extra = false) => {
266
510
  status: reportType === 0,
267
511
  message: messages[command][reportType === 0 ? '1' : '0']
268
512
  }
513
+ } else if (command === 'GTVGL') {
514
+ let reportID = parseInt(report[0], 16)
515
+ const reportType = parseInt(report[1], 16)
516
+ if (reportID === 1) {
517
+ reportID = 'por seYansor de movimiento'
518
+ } else if (reportID === 2) {
519
+ reportID = 'por voltaje de batería'
520
+ } else if (reportID === 4) {
521
+ reportID = 'por acelerómetro'
522
+ } else if (reportID === 7) {
523
+ reportID = 'por metodología combinada'
524
+ } else {
525
+ reportID = ''
526
+ }
527
+ return {
528
+ type: 'DI',
529
+ number: 1,
530
+ status: reportType === 0,
531
+ reason: reportID,
532
+ message: messages[command][reportType === 0 ? '1' : '0']
533
+ }
269
534
  } else if (command === 'GTIGN') {
270
535
  const duration = report !== '' ? parseInt(report, 10) : null
271
536
  return {
@@ -284,10 +549,34 @@ const getAlarm = (command, report, extra = false) => {
284
549
  duration: duration,
285
550
  message: messages[command]
286
551
  }
552
+ } else if (command === 'GTVGN') {
553
+ const duration = report[0] !== '' ? parseInt(report[0], 10) : null
554
+ return {
555
+ type: 'DI',
556
+ number: 1,
557
+ status: true,
558
+ duration: duration,
559
+ message: messages[command][report[1]]
560
+ }
561
+ } else if (command === 'GTVGF') {
562
+ const duration = report[0] !== '' ? parseInt(report[0], 10) : null
563
+ return {
564
+ type: 'DI',
565
+ number: 1,
566
+ status: false,
567
+ duration: duration,
568
+ message: messages[command][report[1]]
569
+ }
287
570
  } else if (command === 'GTPNA') {
288
571
  return { type: 'Power', status: true, message: messages[command] }
289
572
  } else if (command === 'GTPFA') {
290
573
  return { type: 'Power', status: false, message: messages[command] }
574
+ } else if (command === 'GTPNR' || command === 'GTPFR') {
575
+ return {
576
+ type: 'Power_Reason',
577
+ status: command === 'GTPNR',
578
+ message: messages[command][report]
579
+ }
291
580
  } else if (command === 'GTMPN' || command === 'GTEPN') {
292
581
  // Change for connected to power supply
293
582
  return { type: 'Charge', status: true, message: messages[command] }
@@ -333,6 +622,12 @@ const getAlarm = (command, report, extra = false) => {
333
622
  }
334
623
  } else if (command === 'GTEPS') {
335
624
  return { type: 'External_Low_battery', message: messages[command] }
625
+ } else if (command === 'GTSVR') {
626
+ return {
627
+ type: 'Stolen_Vehicle_Alarm',
628
+ status: report === '0',
629
+ message: messages[command][report]
630
+ }
336
631
  } else if (command === 'GTAIS' || command === 'GTMAI') {
337
632
  const reportID = parseInt(report[0], 10)
338
633
  const reportType = parseInt(report[1], 10)
@@ -370,6 +665,18 @@ const getAlarm = (command, report, extra = false) => {
370
665
  return { type: 'Motion_State_Changed', message: messages[command] }
371
666
  } else if (command === 'GTPDP') {
372
667
  return { type: 'GPRS_Connection_Established', message: messages[command] }
668
+ } else if (command === 'GTAVC') {
669
+ return {
670
+ type: 'Serial_Communication_Status',
671
+ status: report === '1',
672
+ message: messages[command][report]
673
+ }
674
+ } else if (command === 'GTCRG') {
675
+ return {
676
+ type: 'Crash_Information',
677
+ before: report === '0',
678
+ message: messages[command][report]
679
+ }
373
680
  } else if (command === 'GTGSS') {
374
681
  return {
375
682
  type: 'Gps_Status',
@@ -417,7 +724,16 @@ const getAlarm = (command, report, extra = false) => {
417
724
  type: 'DO',
418
725
  number: outputId,
419
726
  status: outputStatus === '1',
420
- message: messages[command][outputStatus].replace('port', outputId)
727
+ message: messages[command][outputStatus]
728
+ }
729
+ } else if (command === 'GTDOM') {
730
+ const waveShape = report[0] !== '' ? parseInt(report[0]) : null
731
+ const outputId = report[1] !== '' ? parseInt(report[1]) : null
732
+ return {
733
+ type: 'DO',
734
+ number: outputId,
735
+ wave: waveShape,
736
+ message: messages[command]
421
737
  }
422
738
  } else if (command === 'GTDAT') {
423
739
  return {
@@ -428,7 +744,7 @@ const getAlarm = (command, report, extra = false) => {
428
744
  } else if (command === 'GTDTT') {
429
745
  return {
430
746
  type: 'Transparent_Data',
431
- dataType: extra,
747
+ dataType: dataTypes[extra],
432
748
  data: report,
433
749
  message: messages[command]
434
750
  }
@@ -453,30 +769,137 @@ const getAlarm = (command, report, extra = false) => {
453
769
  4: acceleration turning
454
770
  5: unknown harsh behavior
455
771
  */
456
- // const reportID = parseInt(report[0], 10)
772
+ let reportID = parseInt(report[0], 16)
773
+ let vel
774
+ if (reportID === 1) {
775
+ vel = 'baja'
776
+ } else if (reportID === 2) {
777
+ vel = 'media'
778
+ } else if (reportID === 3) {
779
+ vel = 'alta'
780
+ } else {
781
+ vel = ''
782
+ }
457
783
  const reportType = report[1]
458
784
  return {
459
785
  type: 'Harsh_Behavior',
460
786
  status: parseInt(reportType, 10),
787
+ velocity: vel !== '' ? vel : null,
461
788
  message: messages[command][reportType]
462
789
  }
790
+ } else if (command === 'GTHBE') {
791
+ /*
792
+ status:
793
+ 0: braking
794
+ 1: acceleration
795
+ 2: turning
796
+ 3: braking turning
797
+ 4: acceleration turning
798
+ 5: unknown harsh behavior
799
+ */
800
+ let x = getAccelerationMagnitude(extra[0].substring(0, 4), 4)
801
+ let y = getAccelerationMagnitude(extra[0].substring(4, 8), 4)
802
+ let z = getAccelerationMagnitude(extra[0].substring(8, 12), 4)
803
+ return {
804
+ type: 'Harsh_Behavior_Data',
805
+ calibration: report[0] === '2',
806
+ duration: extra[1],
807
+ magnitude: Number(
808
+ Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2)).toFixed(2)
809
+ ).toString(),
810
+ message: messages[command][report[1]]
811
+ }
463
812
  } else if (command === 'GTCRA') {
464
813
  return {
465
814
  type: 'Crash',
466
815
  status: true,
467
- counter: report,
816
+ counter: parseInt(report, 16),
817
+ message: messages[command]
818
+ }
819
+ } else if (command === 'GTCRD') {
820
+ return {
821
+ type: '3Axis_Information ',
822
+ message: messages[command]
823
+ }
824
+ } else if (command === 'GTACC') {
825
+ return {
826
+ type: 'Accelerometer_Info',
468
827
  message: messages[command]
469
828
  }
829
+ } else if (command === 'GTDOG') {
830
+ /*
831
+ status:
832
+ 1: Reboot for time based working mode
833
+ 2: Reboot for ignition on workinkg mode
834
+ 3: Input triggered reboot
835
+ 4: GSM watchdog reboot
836
+ 5: GPRS watchdog reboot
837
+ 6: Reboot because of fail in sending message
838
+ */
839
+ // const reportID = parseInt(report[0], 10)
840
+ const reportType = report[1]
841
+ return {
842
+ type: 'Watchdog_Protocol',
843
+ status: parseInt(reportType, 10),
844
+ message: messages[command][reportType]
845
+ }
470
846
  } else if (command === 'GTGEO') {
471
847
  return {
472
848
  type: 'Device_Geofence'
473
849
  }
474
- } else if (command === 'GTALC' || command === 'GTALM') {
850
+ } else if (
851
+ command === 'GTALC' ||
852
+ command === 'GTALM' ||
853
+ command === 'GTALS'
854
+ ) {
475
855
  return {
476
856
  type: command,
477
857
  status: 'CONFIG',
478
858
  message: report
479
859
  }
860
+ } else if (command === 'GTCID') {
861
+ return {
862
+ type: command,
863
+ status: 'CONFIG',
864
+ message: messages[command].replace('data', report)
865
+ }
866
+ } else if (command === 'GTLBA') {
867
+ let type = report[0]
868
+ let serial = report[1]
869
+ return {
870
+ type: command,
871
+ status: 'BT_Low_Battery',
872
+ serialNumber: serial !== '' ? parseInt(serial, 16) : null,
873
+ message: messages[command][type]
874
+ }
875
+ } else if (command === 'GTCSQ') {
876
+ return {
877
+ type: command,
878
+ status: 'CONFIG',
879
+ // message: messages[command].replace(
880
+ // 'data',
881
+ // report !== '' ? 100 * parseInt(parseFloat(report) / 7, 10) : '--'
882
+ // )
883
+ }
884
+ } else if (command === 'GTVER') {
885
+ return {
886
+ type: command,
887
+ status: 'CONFIG',
888
+ firmware: {raw: report[0], value: parseFloat(getVersion(report[0]))},
889
+ hardware: {raw: report[1], value: parseFloat(getVersion(report[1]))},
890
+ message: messages[command]
891
+ .replace('data0', getVersion(report[0]))
892
+ .replace('data1', getVersion(report[1]))
893
+ }
894
+ } else if (command === 'GTBCS') {
895
+ return { type: 'Bluetooth_Connected', message: messages[command] }
896
+ } else if (command === 'GTBDS') {
897
+ return { type: 'Bluetooth_Disonnected', message: messages[command] }
898
+ } else if (command === 'GTBAA') {
899
+ return {
900
+ type: 'Bluetooth_Alarm',
901
+ message: messages[command][report]
902
+ }
480
903
  } else {
481
904
  return {
482
905
  type: command,
@@ -565,6 +988,18 @@ const nHexDigit = (num, n) => {
565
988
  return hex
566
989
  }
567
990
 
991
+ /*
992
+ Return the sum of ones in hexadecimal number
993
+ */
994
+ const sumOnes = num => {
995
+ let sum = 0
996
+ let hex = hex2bin(num)
997
+ for (let i = 0; i < hex.length; i++) {
998
+ sum += parseInt(hex[i])
999
+ }
1000
+ return sum
1001
+ }
1002
+
568
1003
  /*
569
1004
  Parses date
570
1005
  */
@@ -583,12 +1018,27 @@ module.exports = {
583
1018
  OBDIIProtocols: OBDIIProtocols,
584
1019
  states: states,
585
1020
  uartDeviceTypes: uartDeviceTypes,
1021
+ networkTypes: networkTypes,
1022
+ externalGPSAntennaOptions: externalGPSAntennaOptions,
1023
+ peerRoles: peerRoles,
1024
+ peerAddressesTypes: peerAddressesTypes,
1025
+ disconnectionReasons: disconnectionReasons,
1026
+ bluetoothAccessories: bluetoothAccessories,
1027
+ bluetoothModels: bluetoothModels,
1028
+ beaconModels: beaconModels,
1029
+ beaconTypes: beaconTypes,
1030
+ dTimeStates: dTimeStates,
1031
+ dWorkingStates: dWorkingStates,
586
1032
  getDevice: getDevice,
587
1033
  getProtocolVersion: getProtocolVersion,
588
1034
  checkGps: checkGps,
1035
+ includeSatellites: includeSatellites,
1036
+ getAccelerationMagnitude: getAccelerationMagnitude,
589
1037
  getTempInCelciousDegrees: getTempInCelciousDegrees,
590
1038
  getFuelConsumption: getFuelConsumption,
591
1039
  getHoursForHourmeter: getHoursForHourmeter,
1040
+ getSignalStrength: getSignalStrength,
1041
+ getSignalPercentage: getSignalPercentage,
592
1042
  getAlarm: getAlarm,
593
1043
  bin2dec: bin2dec,
594
1044
  bin2hex: bin2hex,
@@ -597,5 +1047,6 @@ module.exports = {
597
1047
  hex2bin: hex2bin,
598
1048
  hex2dec: hex2dec,
599
1049
  nHexDigit: nHexDigit,
1050
+ sumOnes: sumOnes,
600
1051
  parseDate: parseDate
601
1052
  }