queclink-parser 1.9.13 → 1.9.15

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
@@ -211,13 +211,24 @@ const bluetoothModels = {
211
211
  '0': 'MAG ELA (Door Sensor)'
212
212
  },
213
213
  '12': {
214
- '0': 'MLD BLE TPMS (ATP100/ATP102)'
214
+ '0': 'ATP100/ATP102'
215
215
  },
216
216
  '13': {
217
217
  '0': 'WRL300 (Bluetooth Relay)'
218
218
  }
219
219
  }
220
220
 
221
+ /*
222
+ BLE Temp & Hum sensors
223
+ */
224
+ const bleTempHumSensors = {
225
+ 'AC100': '0',
226
+ 'WTH300': '2',
227
+ 'RHT ELA': '3',
228
+ 'WMS301': '4',
229
+ 'WTH301': '5'
230
+ }
231
+
221
232
  /*
222
233
  Possible Beacon ID Models
223
234
  */
@@ -234,7 +245,19 @@ const beaconModels = {
234
245
  const beaconTypes = {
235
246
  '0': 'ID',
236
247
  '1': 'iBeacon',
237
- '2': 'Eddystone'
248
+ '2': 'Eddystone',
249
+ '3': 'Queclink'
250
+ }
251
+
252
+ /*
253
+ Possible Relay BLE config results
254
+ */
255
+ const relayBLEResults = {
256
+ 0: 'Success',
257
+ 1: 'Error connecting',
258
+ 2: 'Incorrect BLE password',
259
+ 3: 'Error updating BLE password',
260
+ 4: 'Error'
238
261
  }
239
262
 
240
263
  /*
@@ -408,12 +431,46 @@ const getTempInCelciousDegrees = hexTemp => {
408
431
  }
409
432
 
410
433
  /*
411
- Gets the temperature and humidity from bluetooth device
434
+ Gets the temperature from BLE devices in celcious degrees
435
+ */
436
+ const getBleTempInCelciousDegrees = (device, hexData) => {
437
+ if (device === 'WTH300') {
438
+ let intTemp = parseInt(hexData.substring(0, 2), 16)
439
+ let decTemp = parseInt(hexData.substring(2, 4), 16)
440
+ return intTemp + decTemp / 256
441
+ } else if (['WTH301', 'WMS301'].includes(device)) {
442
+ let intTemp = parseInt(hexData.substring(0, 2), 16)
443
+ let decTemp = parseInt(hexData.substring(2, 4), 16)
444
+ return intTemp + decTemp / 100
445
+ } else if (device === 'ATP100/ATP102') {
446
+ let temp = parseInt(hexData.substring(4, 6), 16)
447
+ return temp - 40
448
+ } else {
449
+ return null
450
+ }
451
+ }
452
+
453
+ /*
454
+ Gets the humidity from BLE devices in rh
412
455
  */
413
- const getBtTempHumData = hexTemp => {
414
- var int = parseInt(hexTemp.substring(0, 2), 16)
415
- var dec = parseInt(hexTemp.substring(2, 4), 16)
416
- return int + dec / 256
456
+ const getBleHumidityInRH = (device, hexData) => {
457
+ let intHum = parseInt(hexData.substring(4, 6), 16)
458
+ let decHum = parseInt(hexData.substring(6, 8), 16)
459
+ if (device === 'WTH300') {
460
+ return intHum + decHum / 256
461
+ } else if (['WTH301', 'WMS301'].includes(device)) {
462
+ return intHum + decHum / 100
463
+ } else {
464
+ return null
465
+ }
466
+ }
467
+
468
+ /*
469
+ Gets the humidity from BLE devices in rh
470
+ */
471
+ const getTirePressureInPSI = hexData => {
472
+ let tirePress = parseInt(hexData.substring(2, 4), 16) * 2.5 // In kPa
473
+ return tirePress / 6.895 // In PSI
417
474
  }
418
475
 
419
476
  /*
@@ -851,14 +908,14 @@ const getCanData = (parsedData, ix) => {
851
908
  ? expansionBin[2] === '1'
852
909
  : null,
853
910
  batteryIndicator: expansionBin ? expansionBin[3] === '1' : null,
854
- brakeSystemaFailureIndicator: expansionBin
911
+ brakeSystemFailureIndicator: expansionBin
855
912
  ? expansionBin[4] === '1'
856
913
  : null,
857
914
  oilPressureIndicator: expansionBin ? expansionBin[5] === '1' : null,
858
915
  engineHotIndicator: expansionBin ? expansionBin[6] === '1' : null,
859
916
  ABSFailureIndicator: expansionBin ? expansionBin[7] === '1' : null,
860
917
  checkEngineIndicator: expansionBin ? expansionBin[9] === '1' : null,
861
- aribagsIndicator: expansionBin ? expansionBin[10] === '1' : null,
918
+ airbagsIndicator: expansionBin ? expansionBin[10] === '1' : null,
862
919
  serviceCallIndicator: expansionBin
863
920
  ? expansionBin[11] === '1'
864
921
  : null,
@@ -871,6 +928,177 @@ const getCanData = (parsedData, ix) => {
871
928
  }
872
929
  }
873
930
 
931
+
932
+ /*
933
+ Get Bluetooth data
934
+ */
935
+ const getBleData = (parsedData, btIndex) => {
936
+ let btDevices = []
937
+ let cnt = btIndex + 1
938
+ let btNum = parsedData[btIndex] !== '' ? parseInt(parsedData[btIndex]) : 1
939
+
940
+ for (let c = 0; c < btNum; c++) {
941
+ if (!['FE', 'FF'].includes(parsedData[cnt])) {
942
+ let appendMask = nHexDigit(hex2bin(parsedData[cnt + 4]), 16)
943
+ let aNameIx = cnt + 4 + parseInt(appendMask[15])
944
+ let aMacIx = aNameIx + parseInt(appendMask[14])
945
+ let aStatIx = aMacIx + parseInt(appendMask[13])
946
+ let aBatIx = aStatIx + parseInt(appendMask[12])
947
+ let aTmpIx = aBatIx + parseInt(appendMask[11])
948
+ let aHumIx = aTmpIx + parseInt(appendMask[10])
949
+ let ioIx = aHumIx + parseInt(appendMask[8])
950
+ let aEvIx = appendMask[8] === '1' && appendMask[7] === '1'
951
+ ? ioIx + 3 : ioIx + parseInt(appendMask[7])
952
+ let pressIx = appendMask[7] === '1' && appendMask[6] === '1'
953
+ ? aEvIx + 2 : aEvIx + parseInt(appendMask[6])
954
+ let timeIx = pressIx + parseInt(appendMask[5])
955
+ let eTmpIx = timeIx + parseInt(appendMask[4])
956
+ let magIx = eTmpIx + parseInt(appendMask[3])
957
+ let aBatpIx = appendMask[3] === '1' && appendMask[2] === '1'
958
+ ? magIx + 3 : magIx + parseInt(appendMask[2])
959
+ let relIx = aBatpIx + parseInt(appendMask[1])
960
+
961
+ let bleType = bluetoothAccessories[parsedData[cnt + 1]]
962
+ let bleModel = parsedData[cnt + 2] !== ''
963
+ ? bluetoothModels[parsedData[cnt + 1]][parsedData[cnt + 2]]
964
+ : null
965
+ let rawAppendMask = parsedData[cnt + 4]
966
+
967
+ btDevices.push({
968
+ index: parsedData[cnt],
969
+ type: bleType,
970
+ model: bleModel,
971
+ appendMask: rawAppendMask,
972
+ name:
973
+ parsedData[aNameIx] !== '' && appendMask[15] === '1'
974
+ ? parsedData[aNameIx]
975
+ : null,
976
+ mac:
977
+ parsedData[aMacIx] !== '' && appendMask[14] === '1'
978
+ ? parsedData[aMacIx]
979
+ : null,
980
+ status:
981
+ parsedData[aStatIx] !== '' && appendMask[13] === '1'
982
+ ? parseInt(parsedData[aStatIx])
983
+ : null,
984
+ batteryLevel:
985
+ parsedData[aBatIx] !== '' && appendMask[12] === '1'
986
+ ? parseInt(parsedData[aBatIx])
987
+ : null,
988
+ batteryPercentage:
989
+ parsedData[aBatpIx] !== '' && appendMask[2] === '1'
990
+ ? parseFloat(parsedData[aBatpIx])
991
+ : null,
992
+ accessoryData: {
993
+ data: parsedData[cnt + 3] !== '' ? {
994
+ raw: parsedData[cnt + 3],
995
+ temperature: getBleTempInCelciousDegrees(bleModel, parsedData[cnt + 3]),
996
+ humidity: getBleHumidityInRH(bleModel, parsedData[cnt + 3]),
997
+ relayState: bleModel === 'WRL300' ? parseInt(parsedData[cnt + 3]) === 1 ? 'Connected' : 'Disconnected' : null,
998
+ tirePresure: getTirePressureInPSI(parsedData[cnt + 3]),
999
+ productModel: bleModel === 'ATP100/ATP102' ? parsedData[cnt + 3].substring(6, 7) : null,
1000
+ fwVersion: bleModel === 'ATP100/ATP102' ? parsedData[cnt + 3].substring(7, 8) : null,
1001
+ } : null,
1002
+ temperature:
1003
+ parsedData[aTmpIx] !== '' && appendMask[11] === '1'
1004
+ ? parseInt(parsedData[aTmpIx])
1005
+ : null,
1006
+ humidity:
1007
+ parsedData[aHumIx] !== '' && appendMask[10] === '1'
1008
+ ? parseInt(parsedData[aHumIx])
1009
+ : null,
1010
+ outputStatus:
1011
+ parsedData[ioIx] !== '' && appendMask[8] === '1'
1012
+ ? parsedData[ioIx]
1013
+ : null,
1014
+ inputStatus:
1015
+ parsedData[ioIx + 1] !== '' && appendMask[8] === '1'
1016
+ ? parsedData[ioIx + 1]
1017
+ : null,
1018
+ analogInputStatus:
1019
+ parsedData[ioIx + 2] !== '' && appendMask[8] === '1'
1020
+ ? parsedData[ioIx + 2]
1021
+ : null,
1022
+ event:
1023
+ parsedData[aEvIx] !== '' && appendMask[7] === '1'
1024
+ ? parseInt(parsedData[aEvIx])
1025
+ : null,
1026
+ tirePresure:
1027
+ parsedData[pressIx] !== '' && appendMask[6] === '1'
1028
+ ? parseInt(parsedData[pressIx]) / 6.895
1029
+ : null,
1030
+ timestamp:
1031
+ parsedData[timeIx] !== '' && appendMask[5] === '1'
1032
+ ? parseDate(parsedData[timeIx])
1033
+ : null,
1034
+ enhancedTemperature:
1035
+ parsedData[eTmpIx] !== '' && appendMask[4] === '1'
1036
+ ? parseFloat(parsedData[eTmpIx])
1037
+ : null,
1038
+ magDevice: {
1039
+ id:
1040
+ parsedData[magIx] !== '' && appendMask[3] === '1'
1041
+ ? parsedData[magIx]
1042
+ : null,
1043
+ eventCounter:
1044
+ parsedData[magIx + 1] !== '' && appendMask[3] === '1'
1045
+ ? parseInt(parsedData[magIx + 1])
1046
+ : null,
1047
+ magnetState:
1048
+ parsedData[magIx + 2] !== '' && appendMask[3] === '1'
1049
+ ? parseInt(parsedData[magIx + 2])
1050
+ : null
1051
+ },
1052
+ relay: {
1053
+ state:
1054
+ parsedData[relIx] !== '' && appendMask[1] === '1'
1055
+ ? parseInt(parsedData[relIx])
1056
+ : null
1057
+ }
1058
+ }
1059
+ })
1060
+ cnt = relIx + 1
1061
+ } else {
1062
+ let appendMask = nHexDigit(hex2bin(parsedData[cnt + 3]), 8)
1063
+ let aMacIx = cnt + 3 + parseInt(appendMask[6])
1064
+ let aBatIx = aMacIx + parseInt(appendMask[4])
1065
+ let aSigIx = aBatIx + parseInt(appendMask[1])
1066
+ let bTypeIx = aSigIx + parseInt(appendMask[0])
1067
+
1068
+ btDevices.push({
1069
+ index: parsedData[cnt],
1070
+ type: beaconTypes[parsedData[cnt + 1]],
1071
+ model: parsedData[cnt + 2] !== ''
1072
+ ? beaconModels[parsedData[cnt + 2]]
1073
+ : null,
1074
+ appendMask: parsedData[cnt + 3],
1075
+ mac:
1076
+ parsedData[aMacIx] !== '' && appendMask[6] === '1'
1077
+ ? parsedData[aMacIx]
1078
+ : null,
1079
+ batteryLevel:
1080
+ parsedData[aBatIx] !== '' && appendMask[4] === '1'
1081
+ ? parseInt(parsedData[aBatIx])
1082
+ : null,
1083
+ SignalStrength:
1084
+ parsedData[aSigIx] !== '' && appendMask[1] === '1'
1085
+ ? parseInt(parsedData[aSigIx])
1086
+ : null,
1087
+ beaconType:
1088
+ parsedData[bTypeIx] !== '' && appendMask[0] === '1'
1089
+ ? parseInt(parsedData[bTypeIx])
1090
+ : null,
1091
+ beaconData:
1092
+ parsedData[bTypeIx + 1] !== '' && appendMask[0] === '1'
1093
+ ? parseInt(parsedData[bTypeIx + 1])
1094
+ : null,
1095
+ })
1096
+ cnt = bTypeIx + 1 + parseInt(appendMask[1])
1097
+ }
1098
+ }
1099
+ return btDevices
1100
+ }
1101
+
874
1102
  /*
875
1103
  Gets the alarm type
876
1104
  */
@@ -1375,10 +1603,67 @@ const getAlarm = (command, report, extra = false) => {
1375
1603
  } else if (command === 'GTBDS') {
1376
1604
  return { type: 'Bluetooth_Disonnected', message: messages[command] }
1377
1605
  } else if (command === 'GTBAA') {
1378
- return {
1379
- type: 'Bluetooth_Alarm',
1380
- message: messages[command][report]
1606
+ if (['01', '02', '03'].includes(report)) {
1607
+ const number = parseInt(extra[0])
1608
+ const mac = extra[1]
1609
+ const temperature = extra[2].enhancedTemperature ? extra[2].enhancedTemperature : extra[2].temperature
1610
+ const status = report !== '03' // 01 & 02 means outside range, 03 means inside range
1611
+ return {
1612
+ type: 'Outside_Temperature',
1613
+ number: number,
1614
+ deviceID: mac,
1615
+ status: status,
1616
+ temperature: temperature,
1617
+ message: messages[command][report].replace('()', `(${temperature}°C)`)
1618
+ }
1619
+ } else if (['07', '08', '09'].includes(report)) {
1620
+ const number = parseInt(extra[0])
1621
+ const mac = extra[1]
1622
+ const humidity = extra[2].humidity ? extra[2].humidity : null
1623
+ const status = report !== '09' // 07 & 08 means outside range, 09 means inside range
1624
+ return {
1625
+ type: 'Outside_Humidity',
1626
+ number: number,
1627
+ deviceID: mac,
1628
+ status: status,
1629
+ humidity: humidity,
1630
+ message: messages[command][report].replace('()', `(${humidity}%)`)
1631
+ }
1632
+ } else if (['0E', '0F', '10'].includes(report)) {
1633
+ const number = parseInt(extra[0])
1634
+ const mac = extra[1]
1635
+ const pressure = extra[2].tirePresure ? extra[2].tirePresure : null
1636
+ const status = report !== '10' // 0E & 0F means outside range, 10 means inside range
1637
+ return {
1638
+ type: 'Outside_Tire_Pressure',
1639
+ number: number,
1640
+ deviceID: mac,
1641
+ status: status,
1642
+ pressure: pressure,
1643
+ message: messages[command][report].replace('()', `(${pressure}kPa)`)
1644
+ }
1645
+ } else if (report === '15') {
1646
+ const number = parseInt(extra[0])
1647
+ const mac = extra[1]
1648
+ const status = extra[2].relay.state === 1
1649
+ const humanStatus = status ? 'activado' : 'desactivado'
1650
+ const configResult = extra[2].relay.configResult ? extra[2].relay.configResult : null
1651
+ return {
1652
+ type: 'Relay_BLE',
1653
+ number: number,
1654
+ deviceID: mac,
1655
+ status: status,
1656
+ configResult: configResult,
1657
+ message: messages[command][report].replace('__', `${humanStatus}`)
1658
+ }
1659
+ } else {
1660
+ return {
1661
+ type: 'Bluetooth_Alarm',
1662
+ message: messages[command][report]
1663
+ }
1381
1664
  }
1665
+
1666
+
1382
1667
  } else {
1383
1668
  return {
1384
1669
  type: command,
@@ -1505,8 +1790,10 @@ module.exports = {
1505
1790
  disconnectionReasons: disconnectionReasons,
1506
1791
  bluetoothAccessories: bluetoothAccessories,
1507
1792
  bluetoothModels: bluetoothModels,
1793
+ bleTempHumSensors: bleTempHumSensors,
1508
1794
  beaconModels: beaconModels,
1509
1795
  beaconTypes: beaconTypes,
1796
+ relayBLEResults: relayBLEResults,
1510
1797
  dTimeStates: dTimeStates,
1511
1798
  dWorkingStates: dWorkingStates,
1512
1799
  gnssTriggerTypes: gnssTriggerTypes,
@@ -1520,12 +1807,12 @@ module.exports = {
1520
1807
  includeGnnsAccuracy: includeGnnsAccuracy,
1521
1808
  getAccelerationMagnitude: getAccelerationMagnitude,
1522
1809
  getTempInCelciousDegrees: getTempInCelciousDegrees,
1523
- getBtTempHumData: getBtTempHumData,
1524
1810
  getFuelConsumption: getFuelConsumption,
1525
1811
  getHoursForHourmeter: getHoursForHourmeter,
1526
1812
  getSignalStrength: getSignalStrength,
1527
1813
  getSignalPercentage: getSignalPercentage,
1528
1814
  getCanData: getCanData,
1815
+ getBleData: getBleData,
1529
1816
  getAlarm: getAlarm,
1530
1817
  bin2dec: bin2dec,
1531
1818
  bin2hex: bin2hex,