queclink-parser 1.9.24 → 1.9.26

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
@@ -54,6 +54,7 @@ const devices = {
54
54
  '41': 'GV75W',
55
55
  FC: 'GV600W',
56
56
  '6E': 'GV310LAU',
57
+ '74': 'GV350CEU',
57
58
  '802004': 'GV58LAU',
58
59
  '802006': 'GV57CG',
59
60
  C301: 'GL533CG'
@@ -307,6 +308,30 @@ const dWorkingStates = {
307
308
  3: 'driving'
308
309
  }
309
310
 
311
+ /*
312
+ Possible Driving Working State in Expansion
313
+ */
314
+ const dWorkingStatesExpansion = {
315
+ 0: 'rest',
316
+ 1: 'available',
317
+ 2: 'work',
318
+ 3: 'driving',
319
+ 4: 'reserved',
320
+ 5: 'reserved',
321
+ 6: 'invalid data',
322
+ 7: 'invalid data'
323
+ }
324
+
325
+ /*
326
+ Possible Jamming Sate Types
327
+ */
328
+ const jammingSateTypes = {
329
+ '0': 'Unknown',
330
+ '1': 'No significan jamming',
331
+ '2': 'Potencial for interference',
332
+ '3': 'Interference visible and no fix'
333
+ }
334
+
310
335
  /*
311
336
  Possible port N Types for AU100
312
337
  */
@@ -415,7 +440,7 @@ const checkGps = (lng, lat) => {
415
440
  included in the report
416
441
  */
417
442
  const includeSatellites = positionAppendMask => {
418
- return nHexDigit(hex2bin(positionAppendMask), 4)[3] === '1'
443
+ return nHexDigit(hex2bin(positionAppendMask), 8)[7] === '1'
419
444
  }
420
445
 
421
446
  /*
@@ -423,7 +448,7 @@ const includeSatellites = positionAppendMask => {
423
448
  included in the report
424
449
  */
425
450
  const includeGnssTrigger = positionAppendMask => {
426
- return nHexDigit(hex2bin(positionAppendMask), 4)[2] === '1'
451
+ return nHexDigit(hex2bin(positionAppendMask), 8)[6] === '1'
427
452
  }
428
453
 
429
454
  /*
@@ -431,7 +456,7 @@ const includeGnssTrigger = positionAppendMask => {
431
456
  included in the report
432
457
  */
433
458
  const includeStatus = positionAppendMask => {
434
- return nHexDigit(hex2bin(positionAppendMask), 4)[1] === '1'
459
+ return nHexDigit(hex2bin(positionAppendMask), 8)[5] === '1'
435
460
  }
436
461
 
437
462
  /*
@@ -439,7 +464,15 @@ const includeStatus = positionAppendMask => {
439
464
  included in the report
440
465
  */
441
466
  const includeGnnsAccuracy = positionAppendMask => {
442
- return nHexDigit(hex2bin(positionAppendMask), 4)[0] === '1'
467
+ return nHexDigit(hex2bin(positionAppendMask), 8)[4] === '1'
468
+ }
469
+
470
+ /*
471
+ Returns if the Jamming Sate is
472
+ included in the report
473
+ */
474
+ const includeJammingSate = positionAppendMask => {
475
+ return nHexDigit(hex2bin(positionAppendMask), 8)[3] === '1'
443
476
  }
444
477
 
445
478
  /*
@@ -748,6 +781,35 @@ const parseCanData = (data, key) => {
748
781
  } else {
749
782
  return parseFloat(parseFloat(data).toFixed(2))
750
783
  }
784
+ case 'dtcCodeNumber':
785
+ return parseInt(data, 10) // 0-99
786
+ case 'dpfSootLevel':
787
+ return parseFloat(parseFloat(data.slice(2, 6)).toFixed(2))
788
+ case 'dpgSootLevelUnit':
789
+ return data.slice(0, 2) === 'FE'
790
+ ? 'L'
791
+ : data.slice(0, 2) === 'FF' ? 'P' : '-'
792
+ case 'dtcStatus':
793
+ switch (data) {
794
+ case '00':
795
+ return 'Success'
796
+ case '02':
797
+ return 'No available for this vehicle'
798
+ case '03':
799
+ return 'Unrecognized format'
800
+ case '05':
801
+ return 'Failed'
802
+ case '0A':
803
+ return 'Overflow'
804
+ case '0B':
805
+ return 'DTCs has not been read yet'
806
+ case '0C':
807
+ return 'No available for this vehicle'
808
+ case 'FD':
809
+ return 'Internal error'
810
+ default:
811
+ return 'Unavailable'
812
+ }
751
813
  default:
752
814
  return data
753
815
  }
@@ -755,12 +817,18 @@ const parseCanData = (data, key) => {
755
817
 
756
818
  /*
757
819
  Get CANbus data
820
+ options.deviceType: 'GV350CEU' | 'GV310LAU' | 'GV58LAU' - when 'GV350CEU', GTCAN uses
821
+ protocol 4.8.1 (extra fields after expansion) and the position block start is detected.
758
822
  */
759
- const getCanData = (parsedData, ix, type) => {
823
+ const getCanData = (parsedData, ix, type, options) => {
824
+ options = options || {}
825
+ const isGV350CEU = options && options.deviceType === 'GV350CEU'
826
+
760
827
  let canAppendMask =
761
828
  parsedData[ix + 1] !== ''
762
829
  ? nHexDigit(hex2bin(parsedData[ix + 1]), 32)
763
830
  : null
831
+
764
832
  if (canAppendMask === 0) {
765
833
  return {}
766
834
  }
@@ -788,9 +856,18 @@ const getCanData = (parsedData, ix, type) => {
788
856
  let doorIx = ligIx + parseInt(canAppendMask[12])
789
857
  let osptIx = doorIx + parseInt(canAppendMask[11])
790
858
  let ospeIx = osptIx + parseInt(canAppendMask[10])
791
- // Values from 9 to 3 are reserved
792
- let canxIx = ospeIx + parseInt(canAppendMask[2])
793
-
859
+ // Value 9 is only for hex report
860
+ let ecscdIx = ospeIx + parseInt(canAppendMask[8]) // Engine Cold Starts Count
861
+ let eascIx = ecscdIx + parseInt(canAppendMask[7]) // Engine All Starts Count
862
+ let esicIx = eascIx + parseInt(canAppendMask[6]) // Engine Starts by Ignition Count
863
+ let tecrIx = esicIx + parseInt(canAppendMask[5]) // Total Engine Engine Cold Running Time
864
+ let hbraIx = tecrIx + parseInt(canAppendMask[4]) // Handbrake Applications During Ride Count
865
+ let elIx = hbraIx + parseInt(canAppendMask[3]) // Electric Report Mask
866
+ let canxIx = isGV350CEU
867
+ ? hbraIx + parseInt(canAppendMask[2])
868
+ : elIx + parseInt(canAppendMask[2]) // CAN Expansion Mask
869
+
870
+ // CAN Expansion Mask
794
871
  let canExpansionMask =
795
872
  canAppendMask[2] === '1' && parsedData[canxIx] !== ''
796
873
  ? nHexDigit(hex2bin(parsedData[canxIx]), 32)
@@ -826,7 +903,13 @@ const getCanData = (parsedData, ix, type) => {
826
903
  expansionInformation: canExpansionMask[20] === '1',
827
904
  rapidBrakings: canExpansionMask[21] === '1',
828
905
  rapidAccelerations: canExpansionMask[22] === '1',
829
- engineTorque: canExpansionMask[23] === '1'
906
+ engineTorque: canExpansionMask[23] === '1',
907
+ serviceDistance: canExpansionMask[24] === '1',
908
+ ambientTemperature: canExpansionMask[25] === '1',
909
+ dtcCodes: canExpansionMask[28] === '1',
910
+ gaseousFuelLevel: canExpansionMask[29] === '1',
911
+ tachographInfoExpansion: canExpansionMask[30] === '1',
912
+ canReportExpansionMask1: canExpansionMask[31] === '1'
830
913
  }
831
914
  : null
832
915
 
@@ -854,13 +937,449 @@ const getCanData = (parsedData, ix, type) => {
854
937
  let rbrIx = expbIx + parseInt(canExpansionMask[21])
855
938
  let racIx = rbrIx + parseInt(canExpansionMask[22])
856
939
  let etqIx = racIx + parseInt(canExpansionMask[23])
940
+ let sdIx = etqIx + parseInt(canExpansionMask[24])
941
+ let atIx = sdIx + parseInt(canExpansionMask[25])
942
+ let dtcIx =
943
+ canExpansionMask[28] === '1'
944
+ ? atIx + 1 + parseCanData(canExpansionMask[28], 'dtcCodeNumber') // Revisar
945
+ : atIx
946
+ let gflIx = dtcIx + parseInt(canExpansionMask[29])
947
+ let tieIx = gflIx + parseInt(canExpansionMask[30])
948
+ let crm1Ix = tieIx + parseInt(canExpansionMask[31])
949
+
950
+ // DTC Codes
951
+ let dtcCodeNumber = parseCanData(parsedData[dtcIx], 'dtcCodeNumber')
952
+ let dtcArray = dtcCodeNumber
953
+ ? Array.from({ length: dtcCodeNumber }, (_, i) => i)
954
+ : []
955
+ let dtcCodes =
956
+ dtcArray.length > 0
957
+ ? dtcArray.map(dtcCode => {
958
+ return {
959
+ id: dtcCode + 1, // 1-99
960
+ code: parsedData[dtcIx + dtcCode + 1]
961
+ ? parsedData[dtcIx + dtcCode + 1]
962
+ : null
963
+ }
964
+ })
965
+ : []
966
+
967
+ // Report Expansion Mask 1
968
+ let canRepExpMask1 =
969
+ canExpansionMask[31] === '1' && parsedData[crm1Ix] !== ''
970
+ ? nHexDigit(hex2bin(parsedData[crm1Ix]), 32)
971
+ .split('')
972
+ .reverse()
973
+ .join('')
974
+ : '00000000000000000000000000000000'
975
+
976
+ let retIx = crm1Ix + parseInt(canRepExpMask1[0])
977
+ let pwrmIx = retIx + parseInt(canRepExpMask1[1])
978
+ // bit 2 reserved
979
+ let egsIx = pwrmIx + parseInt(canRepExpMask1[3])
980
+
981
+ // E-GENSET Report Mask
982
+ let egsReportMask =
983
+ canRepExpMask1[3] === '1' && parsedData[egsIx] !== ''
984
+ ? nHexDigit(hex2bin(parsedData[egsIx]), 32)
985
+ .split('')
986
+ .reverse()
987
+ .join('')
988
+ : '00000000000000000000000000000000'
989
+
990
+ let husIx = egsIx + parseInt(egsReportMask[0])
991
+ let sshIx = husIx + parseInt(egsReportMask[1])
992
+ let simIx = sshIx + parseInt(egsReportMask[2])
993
+ let rrIx = simIx + parseInt(egsReportMask[3])
994
+ let ebatTmpIx = rrIx + parseInt(egsReportMask[4])
995
+ let bmsTmpIx = ebatTmpIx + parseInt(egsReportMask[5])
996
+ let ebatVIx = bmsTmpIx + parseInt(egsReportMask[6])
997
+ let minCvIx = ebatVIx + parseInt(egsReportMask[7])
998
+ let maxCvIx = minCvIx + parseInt(egsReportMask[8])
999
+ let maxCtIx = maxCvIx + parseInt(egsReportMask[9])
1000
+ let minCtIx = maxCtIx + parseInt(egsReportMask[10])
1001
+ let mbpwIx = minCtIx + parseInt(egsReportMask[11])
1002
+ let cecuErrIx = mbpwIx + parseInt(egsReportMask[12])
1003
+ let cchIx = cecuErrIx + parseInt(egsReportMask[13])
1004
+ let iacl1Ix = cchIx + parseInt(egsReportMask[14])
1005
+ let iacl2Ix = iacl1Ix + parseInt(egsReportMask[15])
1006
+ let iacl3Ix = iacl2Ix + parseInt(egsReportMask[16])
1007
+ let iatIx = iacl3Ix + parseInt(egsReportMask[17])
1008
+ let iotIx = iatIx + parseInt(egsReportMask[18])
1009
+ let iavl1Ix = iotIx + parseInt(egsReportMask[19])
1010
+ let iavl2Ix = iavl1Ix + parseInt(egsReportMask[20])
1011
+ let iavl3Ix = iavl2Ix + parseInt(egsReportMask[21])
1012
+ let isIx = iavl3Ix + parseInt(egsReportMask[22])
1013
+ let sdrIx = isIx + parseInt(egsReportMask[23])
1014
+ let cutIx = sdrIx + parseInt(egsReportMask[24])
1015
+ let citIx = cutIx + parseInt(egsReportMask[25])
1016
+
1017
+ let oltmIx = citIx + parseInt(canRepExpMask1[4])
1018
+ let ollvIx = oltmIx + parseInt(canRepExpMask1[5])
1019
+ let ax5Ix = ollvIx + parseInt(canRepExpMask1[6])
1020
+ let ax6Ix = ax5Ix + parseInt(canRepExpMask1[7])
1021
+ let ax7Ix = ax6Ix + parseInt(canRepExpMask1[8])
1022
+ let grnIx = ax7Ix + parseInt(canRepExpMask1[9])
1023
+ let dpflvIx = grnIx + parseInt(canRepExpMask1[10])
1024
+ let vintrIx = dpflvIx + parseInt(canRepExpMask1[11])
1025
+ let exp2Ix = vintrIx + parseInt(canRepExpMask1[12])
1026
+ let flidIx = exp2Ix + parseInt(canRepExpMask1[13])
1027
+ let vgrwIx = flidIx + parseInt(canRepExpMask1[14])
1028
+ let tireCount =
1029
+ canRepExpMask1[15] === '1' && parsedData[vgrwIx + 1]
1030
+ ? parseInt(parsedData[vgrwIx + 1], 10)
1031
+ : 0
1032
+ let tprIx = vgrwIx + (canRepExpMask1[15] === '1' ? 1 + tireCount * 4 : 0)
1033
+ let rtsIx = tprIx + parseInt(canRepExpMask1[16])
1034
+ let tfrrIx = rtsIx + parseInt(canRepExpMask1[17])
1035
+ let tgrsIx = tfrrIx + parseInt(canRepExpMask1[18])
1036
+ let dtcsIx = tgrsIx + parseInt(canRepExpMask1[19])
1037
+
1038
+ let tireNumber =
1039
+ canRepExpMask1[15] === '1' && parsedData[tprIx]
1040
+ ? parseInt(parsedData[tprIx], 10)
1041
+ : null
1042
+ let tires = tireNumber ? Array.from({ length: tireNumber }, (_, i) => i) : []
1043
+ let tiresData =
1044
+ tires.length > 0
1045
+ ? tires.map(tire => {
1046
+ return {
1047
+ id: tire + 1,
1048
+ positionOfAnAxle: parsedData[tprIx + (4 * tire + 1)]
1049
+ ? parseInt(parsedData[tprIx + (4 * tire + 1)], 10)
1050
+ : null,
1051
+ pressure: parsedData[tprIx + (4 * tire + 2)]
1052
+ ? parseInt(parsedData[tprIx + (4 * tire + 2)], 10)
1053
+ : null,
1054
+ temperature: parsedData[tprIx + (4 * tire + 3)]
1055
+ ? parseInt(parsedData[tprIx + (4 * tire + 3)], 10)
1056
+ : null,
1057
+ status: parsedData[tprIx + (4 * tire + 4)]
1058
+ ? parseInt(parsedData[tprIx + (4 * tire + 4)], 10)
1059
+ : null
1060
+ }
1061
+ })
1062
+ : []
1063
+
1064
+ let repExpMask1 =
1065
+ canExpansionMask[31] === '1'
1066
+ ? {
1067
+ raw: parsedData[crm1Ix] ? parsedData[crm1Ix] : null,
1068
+ bin: canRepExpMask1,
1069
+ retarderUsage:
1070
+ canRepExpMask1[0] === '1' && parsedData[retIx]
1071
+ ? parseInt(parsedData[retIx], 10)
1072
+ : null, // percentage
1073
+ powerMode:
1074
+ canRepExpMask1[1] === '1' && parsedData[pwrmIx]
1075
+ ? parseInt(parsedData[pwrmIx], 10)
1076
+ : null,
1077
+ // generatorVoltage: parsedData[genIx] ? parseInt(parsedData[genIx], 10) : null,
1078
+ oilTemperature:
1079
+ canRepExpMask1[4] === '1' && parsedData[oltmIx]
1080
+ ? parseInt(parsedData[oltmIx], 10)
1081
+ : null,
1082
+ oilLevel:
1083
+ canRepExpMask1[5] === '1' && parsedData[ollvIx]
1084
+ ? parseInt(parsedData[ollvIx], 10)
1085
+ : null,
1086
+ axleWeight5:
1087
+ canRepExpMask1[6] === '1' && parsedData[ax5Ix]
1088
+ ? parseInt(parsedData[ax5Ix], 10)
1089
+ : null,
1090
+ axleWeight6:
1091
+ canRepExpMask1[7] === '1' && parsedData[ax6Ix]
1092
+ ? parseInt(parsedData[ax6Ix], 10)
1093
+ : null,
1094
+ axleWeight7:
1095
+ canRepExpMask1[8] === '1' && parsedData[ax7Ix]
1096
+ ? parseInt(parsedData[ax7Ix], 10)
1097
+ : null,
1098
+ currentGearNumber:
1099
+ canRepExpMask1[9] === '1' && parsedData[grnIx]
1100
+ ? parseInt(parsedData[grnIx], 10)
1101
+ : null,
1102
+ dpfSootLevel:
1103
+ canRepExpMask1[10] === '1' && parsedData[dpflvIx]
1104
+ ? parseCanData(parsedData[dpflvIx], 'dpfSootLevel')
1105
+ : null,
1106
+ dpgSootLevelUnit:
1107
+ canRepExpMask1[10] === '1' && parsedData[dpflvIx]
1108
+ ? parseCanData(parsedData[dpflvIx], 'dpgSootLevelUnit')
1109
+ : null,
1110
+ vinOfTrailer:
1111
+ canRepExpMask1[11] === '1' && parsedData[vintrIx]
1112
+ ? parsedData[vintrIx]
1113
+ : null,
1114
+ expansionInformation2:
1115
+ canRepExpMask1[12] === '1' && parsedData[exp2Ix]
1116
+ ? { brakeLiningsWornOffIndicator: parsedData[exp2Ix][7] === '1' }
1117
+ : null,
1118
+ vehicleGrossWeight:
1119
+ canRepExpMask1[14] === '1' && parsedData[vgrwIx]
1120
+ ? parseInt(parsedData[vgrwIx], 10)
1121
+ : null,
1122
+ tiresNumber:
1123
+ canRepExpMask1[15] === '1' && parsedData[tprIx]
1124
+ ? parseInt(parsedData[tprIx], 10)
1125
+ : null,
1126
+ tiresData: tiresData,
1127
+ remaininTimeToMaintenanceService:
1128
+ canRepExpMask1[16] === '1' && parsedData[rtsIx]
1129
+ ? parseInt(parsedData[rtsIx], 10)
1130
+ : null, // days
1131
+ totalFuelReadFromVehicleComputer:
1132
+ canRepExpMask1[17] === '1' && parsedData[tfrrIx]
1133
+ ? parseFloat(parsedData[tfrrIx])
1134
+ : null, // liters
1135
+ totalGaseousFuelUsage:
1136
+ canRepExpMask1[18] === '1' && parsedData[tgrsIx]
1137
+ ? parseFloat(parsedData[tgrsIx])
1138
+ : null, // kg
1139
+ dtcStatus:
1140
+ canRepExpMask1[19] === '1' && parsedData[dtcsIx]
1141
+ ? parseCanData(parsedData[dtcsIx], 'dtcStatus')
1142
+ : null,
1143
+ eGensetReport:
1144
+ canRepExpMask1[3] === '1'
1145
+ ? {
1146
+ raw: parsedData[egsIx] ? parsedData[egsIx] : null,
1147
+ binEgsReportMask: egsReportMask,
1148
+ hoursUntilService:
1149
+ egsReportMask[0] === '1' &&
1150
+ parsedData[husIx] &&
1151
+ parsedData[husIx] !== '65535'
1152
+ ? parseInt(parsedData[husIx], 10)
1153
+ : null,
1154
+ systemStatusHealth:
1155
+ egsReportMask[1] === '1' &&
1156
+ parsedData[sshIx] &&
1157
+ parsedData[sshIx] !== 'FFFF'
1158
+ ? parseInt(parsedData[sshIx], 16)
1159
+ : null,
1160
+ statusInverterMode:
1161
+ egsReportMask[2] === '1' &&
1162
+ parsedData[simIx] &&
1163
+ parsedData[simIx] !== '255'
1164
+ ? parseInt(parsedData[simIx], 10)
1165
+ : null,
1166
+ remainingRuntime:
1167
+ egsReportMask[3] === '1' &&
1168
+ parsedData[rrIx] &&
1169
+ parsedData[rrIx] !== '255'
1170
+ ? parseInt(parsedData[rrIx], 10)
1171
+ : null,
1172
+ batteryTemperature:
1173
+ egsReportMask[4] === '1' && parsedData[ebatTmpIx]
1174
+ ? parseInt(parsedData[ebatTmpIx], 10)
1175
+ : null,
1176
+ bmsBoardTemperature:
1177
+ egsReportMask[5] === '1' && parsedData[bmsTmpIx]
1178
+ ? parseInt(parsedData[bmsTmpIx], 10)
1179
+ : null,
1180
+ batteryVoltage:
1181
+ egsReportMask[6] === '1' && parsedData[ebatVIx]
1182
+ ? parseFloat(parsedData[ebatVIx])
1183
+ : null,
1184
+ minimumCellVoltage:
1185
+ egsReportMask[7] === '1' && parsedData[minCvIx]
1186
+ ? parseFloat(parsedData[minCvIx])
1187
+ : null,
1188
+ maximumCellVoltage:
1189
+ egsReportMask[8] === '1' && parsedData[maxCvIx]
1190
+ ? parseFloat(parsedData[maxCvIx])
1191
+ : null,
1192
+ maximumCellTemperature:
1193
+ egsReportMask[9] === '1' && parsedData[maxCtIx]
1194
+ ? parseInt(parsedData[maxCtIx], 10)
1195
+ : null,
1196
+ minimumCellTemperature:
1197
+ egsReportMask[10] === '1' && parsedData[minCtIx]
1198
+ ? parseInt(parsedData[minCtIx], 10)
1199
+ : null,
1200
+ moduleBatteryPrewarning:
1201
+ egsReportMask[11] === '1' && parsedData[mbpwIx]
1202
+ ? parseInt(parsedData[mbpwIx], 10)
1203
+ : null,
1204
+ cecuError:
1205
+ egsReportMask[12] === '1' && parsedData[cecuErrIx]
1206
+ ? parseInt(parsedData[cecuErrIx], 10)
1207
+ : null,
1208
+ cumulativeChargingHours:
1209
+ egsReportMask[13] === '1' && parsedData[cchIx]
1210
+ ? parseFloat(parsedData[cchIx])
1211
+ : null,
1212
+ inverterAcCurrentL1:
1213
+ egsReportMask[14] === '1' && parsedData[iacl1Ix]
1214
+ ? parseFloat(parsedData[iacl1Ix])
1215
+ : null,
1216
+ inverterAcCurrentL2:
1217
+ egsReportMask[15] === '1' && parsedData[iacl2Ix]
1218
+ ? parseFloat(parsedData[iacl2Ix])
1219
+ : null,
1220
+ inverterAcCurrentL3:
1221
+ egsReportMask[16] === '1' && parsedData[iacl3Ix]
1222
+ ? parseFloat(parsedData[iacl3Ix])
1223
+ : null,
1224
+ inverterAmbientTemperature:
1225
+ egsReportMask[17] === '1' && parsedData[iatIx]
1226
+ ? parseInt(parsedData[iatIx], 10)
1227
+ : null,
1228
+ inverterObcTemperature:
1229
+ egsReportMask[18] === '1' && parsedData[iotIx]
1230
+ ? parseInt(parsedData[iotIx], 10)
1231
+ : null,
1232
+ inverterAcVoltageL1:
1233
+ egsReportMask[19] === '1' && parsedData[iavl1Ix]
1234
+ ? parseFloat(parsedData[iavl1Ix])
1235
+ : null,
1236
+ inverterAcVoltageL2:
1237
+ egsReportMask[20] === '1' && parsedData[iavl2Ix]
1238
+ ? parseFloat(parsedData[iavl2Ix])
1239
+ : null,
1240
+ inverterAcVoltageL3:
1241
+ egsReportMask[21] === '1' && parsedData[iavl3Ix]
1242
+ ? parseFloat(parsedData[iavl3Ix])
1243
+ : null,
1244
+ inverterState:
1245
+ egsReportMask[22] === '1' && parsedData[isIx]
1246
+ ? parseInt(parsedData[isIx], 10)
1247
+ : null,
1248
+ shutDownReason:
1249
+ egsReportMask[23] === '1' && parsedData[sdrIx]
1250
+ ? parseInt(parsedData[sdrIx], 10)
1251
+ : null,
1252
+ cumulativeUsageTime:
1253
+ egsReportMask[24] === '1' && parsedData[cutIx]
1254
+ ? parseFloat(parsedData[cutIx])
1255
+ : null,
1256
+ cumulativeIdleTime:
1257
+ egsReportMask[25] === '1' && parsedData[citIx]
1258
+ ? parseFloat(parsedData[citIx])
1259
+ : null
1260
+ }
1261
+ : null
1262
+ }
1263
+ : null
1264
+
1265
+ // Electric Report Mask
1266
+ if (isGV350CEU) {
1267
+ elIx = dtcsIx + parseInt(canAppendMask[3])
1268
+ }
1269
+ let evReportMask =
1270
+ canAppendMask[3] === '1' && parsedData[elIx] !== ''
1271
+ ? nHexDigit(hex2bin(parsedData[elIx]), 32)
1272
+ .split('')
1273
+ .reverse()
1274
+ .join('')
1275
+ : '00000000000000000000000000000000'
1276
+
1277
+ let batIVIx = elIx + parseInt(evReportMask[0])
1278
+ let batCCCx = batIVIx + parseInt(evReportMask[1])
1279
+ let totERIx = batCCCx + parseInt(evReportMask[2])
1280
+ let batCLIx = totERIx + parseInt(evReportMask[6])
1281
+ let batCSIx = batCLIx + parseInt(evReportMask[7])
1282
+ let batTempIx = batCSIx + parseInt(evReportMask[8])
1283
+ let batCCIx = batTempIx + parseInt(evReportMask[9])
1284
+ let batIPIx = batCCIx + parseInt(evReportMask[10])
1285
+ let batSOHx = batIPIx + parseInt(evReportMask[11])
1286
+ let totEIx = batSOHx + parseInt(evReportMask[12])
1287
+ let totEIWIx = totEIx + parseInt(evReportMask[13])
1288
+ let totECIx = totEIWIx + parseInt(evReportMask[14])
1289
+ let csOIx = totECIx + parseInt(evReportMask[16])
1290
+
1291
+ let evReport =
1292
+ canAppendMask[3] === '1' && parsedData[elIx] !== '' && isGV350CEU
1293
+ ? {
1294
+ raw: parsedData[elIx] ? parsedData[elIx] : null,
1295
+ binEvReportMask: evReportMask,
1296
+ batteryInstantaneousVoltage:
1297
+ evReportMask[0] === '1' && parsedData[batIVIx]
1298
+ ? parseFloat(parsedData[batIVIx])
1299
+ : null,
1300
+ batteryChargingCyclesCount:
1301
+ evReportMask[1] === '1' && parsedData[batCCCx]
1302
+ ? parseInt(parsedData[batCCCx], 10)
1303
+ : null,
1304
+ totalEnergyRecuperated:
1305
+ evReportMask[2] === '1' && parsedData[totERIx]
1306
+ ? parseFloat(parsedData[totERIx])
1307
+ : null,
1308
+ batteryChargeLevel:
1309
+ evReportMask[6] === '1' && parsedData[batCLIx]
1310
+ ? parseFloat(parsedData[batCLIx])
1311
+ : null,
1312
+ chargingState:
1313
+ evReportMask[7] === '1' && parsedData[batCSIx]
1314
+ ? parseInt(parsedData[batCSIx], 10)
1315
+ : null,
1316
+ baterryTemperature:
1317
+ evReportMask[8] === '1' && parsedData[batTempIx]
1318
+ ? parseFloat(parsedData[batTempIx])
1319
+ : null,
1320
+ batteryChargingCurrent:
1321
+ evReportMask[9] === '1' && parsedData[batCCIx]
1322
+ ? parseFloat(parsedData[batCCIx])
1323
+ : null,
1324
+ batteryInstantaneousPower:
1325
+ evReportMask[10] === '1' && parsedData[batIPIx]
1326
+ ? parseFloat(parsedData[batIPIx])
1327
+ : null,
1328
+ batteryStateOfHealth:
1329
+ evReportMask[11] === '1' && parsedData[batSOHx]
1330
+ ? parseInt(parsedData[batSOHx], 10)
1331
+ : null,
1332
+ totalEnergyUsed:
1333
+ evReportMask[12] === '1' && parsedData[totEIx]
1334
+ ? parseFloat(parsedData[totEIx])
1335
+ : null,
1336
+ totalEnergyUsedWhenIdling:
1337
+ evReportMask[13] === '1' && parsedData[totEIWIx]
1338
+ ? parseFloat(parsedData[totEIWIx])
1339
+ : null,
1340
+ totalEnergyCharged:
1341
+ evReportMask[14] === '1' && parsedData[totECIx]
1342
+ ? parseFloat(parsedData[totECIx])
1343
+ : null,
1344
+ chargeStateOptimization:
1345
+ evReportMask[16] === '1' && parsedData[csOIx]
1346
+ ? parseInt(parsedData[csOIx], 10)
1347
+ : null
1348
+ }
1349
+ : null
857
1350
 
858
1351
  // Logic for CAN data
859
- let gnnsIx = etqIx + 2 + parseInt(canAppendMask[1])
860
- let gsmIx =
861
- canAppendMask[1] === '1'
862
- ? gnnsIx + parseInt(canAppendMask[0]) + 6
863
- : gnnsIx + parseInt(canAppendMask[0])
1352
+ let evFieldsCount = 0
1353
+ if (isGV350CEU && canAppendMask[3] === '1' && parsedData[elIx] !== '') {
1354
+ for (let i = 0; i < 32; i++) {
1355
+ if (evReportMask[i] === '1') evFieldsCount++
1356
+ }
1357
+ }
1358
+
1359
+ let gnnsIx = -1
1360
+ if (isGV350CEU) {
1361
+ let startIx = crm1Ix + 1
1362
+ for (let i = startIx; i < parsedData.length - 6; i++) {
1363
+ let d = parsedData[i + 6]
1364
+ if (d && d.length === 14 && /^\d{14}$/.test(d)) {
1365
+ if (
1366
+ !isNaN(parseFloat(parsedData[i + 1])) &&
1367
+ !isNaN(parseFloat(parsedData[i + 4]))
1368
+ ) {
1369
+ gnnsIx = i
1370
+ break
1371
+ }
1372
+ }
1373
+ }
1374
+ }
1375
+
1376
+ if (gnnsIx === -1) {
1377
+ gnnsIx = isGV350CEU
1378
+ ? elIx + parseInt(canAppendMask[3]) + evFieldsCount + 2
1379
+ : crm1Ix + 2 + parseInt(canAppendMask[1])
1380
+ }
1381
+
1382
+ let gsmIx = canAppendMask[1] === '1' ? gnnsIx + 7 : gnnsIx
864
1383
 
865
1384
  let moreIx
866
1385
  let gnnsData = null
@@ -919,7 +1438,7 @@ const getCanData = (parsedData, ix, type) => {
919
1438
  }
920
1439
  : null
921
1440
  } else {
922
- moreIx = etqIx + 1
1441
+ moreIx = crm1Ix + 1
923
1442
  }
924
1443
 
925
1444
  let inicatorsBin =
@@ -948,6 +1467,13 @@ const getCanData = (parsedData, ix, type) => {
948
1467
  .reverse()
949
1468
  .join('')
950
1469
  : null
1470
+ let tachographExpBin =
1471
+ canAppendMask[30] === '1' && parsedData[tieIx] !== ''
1472
+ ? nHexDigit(hex2bin(parsedData[tieIx]), 16)
1473
+ .split('')
1474
+ .reverse()
1475
+ .join('')
1476
+ : null
951
1477
 
952
1478
  return [
953
1479
  moreIx,
@@ -1126,6 +1652,26 @@ const getCanData = (parsedData, ix, type) => {
1126
1652
  canAppendMask[10] === '1' && parsedData[ospeIx]
1127
1653
  ? parseFloat(parsedData[ospeIx])
1128
1654
  : null,
1655
+ engineColdStartsCount:
1656
+ canAppendMask[8] === '1' && parsedData[ecscdIx]
1657
+ ? parseInt(parsedData[ecscdIx])
1658
+ : null,
1659
+ engineAllStartsCount:
1660
+ canAppendMask[7] === '1' && parsedData[eascIx]
1661
+ ? parseInt(parsedData[eascIx])
1662
+ : null,
1663
+ engineStartsByIgnitionCount:
1664
+ canAppendMask[6] === '1' && parsedData[esicIx]
1665
+ ? parseInt(parsedData[esicIx])
1666
+ : null,
1667
+ totalEngineColdRunningTime:
1668
+ canAppendMask[5] === '1' && parsedData[tecrIx]
1669
+ ? parseFloat(parsedData[tecrIx])
1670
+ : null,
1671
+ handbrakeApplicationsDuringRideCount:
1672
+ canAppendMask[4] === '1' && parsedData[hbraIx]
1673
+ ? parseInt(parsedData[hbraIx])
1674
+ : null,
1129
1675
  canExpanded: {
1130
1676
  canReportExpansionMask: repExpMask,
1131
1677
  adBlueLevel:
@@ -1253,8 +1799,106 @@ const getCanData = (parsedData, ix, type) => {
1253
1799
  engineTorque:
1254
1800
  repExpMask && repExpMask.engineTorque && parsedData[etqIx]
1255
1801
  ? parseFloat(parsedData[etqIx])
1802
+ : null,
1803
+ serviceDistance:
1804
+ repExpMask && repExpMask.serviceDistance && parsedData[sdIx]
1805
+ ? parseFloat(parsedData[sdIx])
1806
+ : null,
1807
+ ambientTemperature:
1808
+ repExpMask && repExpMask.ambientTemperature && parsedData[atIx]
1809
+ ? parseFloat(parsedData[atIx])
1810
+ : null,
1811
+ dtcCodes:
1812
+ repExpMask && repExpMask.dtcCodes && parsedData[dtcIx]
1813
+ ? dtcCodes
1814
+ : null,
1815
+ gaseousFuelLevel:
1816
+ repExpMask && repExpMask.gaseousFuelLevel && parsedData[gflIx]
1817
+ ? parseInt(parsedData[gflIx])
1818
+ : null,
1819
+ tachographInfoExpansion:
1820
+ repExpMask && repExpMask.tachographInfoExpansion
1821
+ ? {
1822
+ raw: parsedData[tieIx],
1823
+ tachographExpBin: tachographExpBin,
1824
+ outOfScope:
1825
+ tachographExpBin.substring(0, 2) === '00'
1826
+ ? 'normal operation'
1827
+ : tachographExpBin.substring(15, 2) === '01'
1828
+ ? 'out of scope'
1829
+ : 'invalid data',
1830
+ driverWorkingState1:
1831
+ dWorkingStatesExpansion[
1832
+ parseInt(tachographExpBin.substring(2, 5), 2)
1833
+ ],
1834
+ driverWorkingState2:
1835
+ dWorkingStatesExpansion[
1836
+ parseInt(tachographExpBin.substring(5, 8), 2)
1837
+ ],
1838
+ insertedDriverCard1:
1839
+ tachographExpBin.substring(10, 12) === '00'
1840
+ ? 'no driver card'
1841
+ : tachographExpBin.substring(11, 13) === '01'
1842
+ ? 'driver card inserted'
1843
+ : 'invalid data',
1844
+ insertedDriverCard2:
1845
+ tachographExpBin.substring(18, 20) === '00'
1846
+ ? 'no driver card'
1847
+ : tachographExpBin.substring(13, 15) === '01'
1848
+ ? 'driver card inserted'
1849
+ : 'invalid data',
1850
+ drivingTimeState1:
1851
+ dTimeStates[parseInt(tachographExpBin.substring(12, 16), 2)],
1852
+ drivingTimeState2:
1853
+ dTimeStates[parseInt(tachographExpBin.substring(20, 24), 2)],
1854
+ vehicleMotion:
1855
+ tachographExpBin.substring(26, 28) === '00'
1856
+ ? 'not detected'
1857
+ : tachographExpBin.substring(24, 26) === '01'
1858
+ ? 'detected'
1859
+ : 'invalid data',
1860
+ drivingDirection:
1861
+ tachographExpBin.substring(28, 30) === '000'
1862
+ ? 'forward'
1863
+ : tachographExpBin.substring(26, 29) === '001'
1864
+ ? 'backward'
1865
+ : tachographExpBin.substring(26, 29) === '010'
1866
+ ? 'left'
1867
+ : tachographExpBin.substring(26, 29) === '011'
1868
+ ? 'right'
1869
+ : 'invalid data',
1870
+ overspeed:
1871
+ tachographExpBin.substring(30, 32) === '00'
1872
+ ? 'not detected'
1873
+ : tachographExpBin.substring(29, 31) === '01'
1874
+ ? 'detected'
1875
+ : 'invalid data'
1876
+ }
1877
+ : null,
1878
+ canReportExpansionMask1:
1879
+ repExpMask && repExpMask.canReportExpansionMask1 && parsedData[crm1Ix]
1880
+ ? repExpMask1
1256
1881
  : null
1257
- }
1882
+ },
1883
+ electricVehicles: evReport
1884
+ ? {
1885
+ raw: evReport.raw,
1886
+ binevReportMask: evReport.binevReportMask,
1887
+ chargeStateOptimization: evReport.chargeStateOptimization,
1888
+ totalEnergyCharged: evReport.totalEnergyCharged
1889
+ ? parseFloat(evReport.totalEnergyCharged)
1890
+ : null,
1891
+ totalEnergyUsedWhenIdling: evReport.totalEnergyUsedWhenIdling
1892
+ ? parseFloat(evReport.totalEnergyUsedWhenIdling)
1893
+ : null,
1894
+ totalEnergyUsed: evReport.totalEnergyUsed
1895
+ ? parseFloat(evReport.totalEnergyUsed)
1896
+ : null,
1897
+ batteryStateOfHealth: evReport.batteryStateOfHealth
1898
+ ? parseFloat(evReport.batteryStateOfHealth)
1899
+ : null
1900
+ }
1901
+ : null
1258
1902
  }
1259
1903
  ]
1260
1904
  }
@@ -1851,7 +2495,6 @@ const getAlarm = (command, report, extra = false) => {
1851
2495
  let y = getAccelerationMagnitude(extra[0].substring(4, 8), 4)
1852
2496
  let z = getAccelerationMagnitude(extra[0].substring(8, 12), 4)
1853
2497
  let duration = extra[1]
1854
- let speed = extra[2]
1855
2498
  let magnitude = Number(
1856
2499
  Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2)).toFixed(2)
1857
2500
  ).toString()
@@ -1860,12 +2503,10 @@ const getAlarm = (command, report, extra = false) => {
1860
2503
  status: parseInt(report[1], 10),
1861
2504
  calibration: report[0] === '2',
1862
2505
  duration: duration,
1863
- speed: speed,
1864
2506
  magnitude: magnitude,
1865
2507
  xyz: { x: x, y: y, z: z },
1866
2508
  message: messages[command][report[1]]
1867
2509
  .replace('X', magnitude)
1868
- .replace('Y', speed)
1869
2510
  .replace('Z', duration)
1870
2511
  }
1871
2512
  } else if (command === 'GTCRA') {
@@ -1911,9 +2552,13 @@ const getAlarm = (command, report, extra = false) => {
1911
2552
  command === 'GTALM' ||
1912
2553
  command === 'GTALS'
1913
2554
  ) {
2555
+ const instruction =
2556
+ command === 'GTALS'
2557
+ ? report.split(',')[4]
2558
+ : command === 'GTALM' ? report.split(',')[6] : report.split(',')[7]
1914
2559
  return {
1915
2560
  type: command,
1916
- status: 'CONFIG',
2561
+ status: instruction,
1917
2562
  message: report
1918
2563
  }
1919
2564
  } else if (command === 'GTCID') {
@@ -2198,10 +2843,12 @@ module.exports = {
2198
2843
  dTimeStates: dTimeStates,
2199
2844
  dWorkingStates: dWorkingStates,
2200
2845
  gnssTriggerTypes: gnssTriggerTypes,
2846
+ jammingSateTypes: jammingSateTypes,
2201
2847
  latamMcc: latamMcc,
2202
2848
  getDevice: getDevice,
2203
2849
  getProtocolVersion: getProtocolVersion,
2204
2850
  checkGps: checkGps,
2851
+ includeJammingSate: includeJammingSate,
2205
2852
  includeSatellites: includeSatellites,
2206
2853
  includeGnssTrigger: includeGnssTrigger,
2207
2854
  includeStatus: includeStatus,