tirecheck-device-sdk 0.2.44 → 0.2.46

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/dist/index.cjs CHANGED
@@ -114,15 +114,19 @@ function stringToDecimalArray(string) {
114
114
  return Array.from(array);
115
115
  }
116
116
  function decimalToHex(decimal, padStart = 2) {
117
- const hex = decimal.toString(16);
117
+ const hex = decimal.toString(16).toUpperCase();
118
118
  return hex.padStart(padStart, "0");
119
119
  }
120
+ function removeEndLine(string) {
121
+ return string.replace("\r\n", "");
122
+ }
120
123
  const toolsSvc = {
121
124
  delay,
122
125
  setIntervalImmediate,
123
126
  waitUntil,
124
127
  withTimeout,
125
- canCommunicateWith
128
+ canCommunicateWith,
129
+ removeEndLine
126
130
  };
127
131
  function normalizeError(error) {
128
132
  if (!error) return new Error("Operation timed out");
@@ -192,7 +196,7 @@ const bridgeTools = {
192
196
  decodeData(data, displayUnits) {
193
197
  const _data = ___default.clone(data);
194
198
  if (displayUnits === "ascii") {
195
- return _data.filter((d) => d).map((x) => String.fromCharCode(x)).join("");
199
+ return String.fromCharCode(..._data.filter((d) => d));
196
200
  }
197
201
  const _reversedData = _data.reverse();
198
202
  if (displayUnits === "decimal") {
@@ -2053,6 +2057,10 @@ const vehicleLayoutAxleTypes = {
2053
2057
  twoTyresAxleSpare: "0380",
2054
2058
  fourTyresAxle: "06C0",
2055
2059
  fourTyresAxleSpare: "07C0",
2060
+ sixTyresAxle: "0EE0",
2061
+ sixTyresAxleSpare: "0FE0",
2062
+ eightTyresAxle: "1EF0",
2063
+ eightTyresAxleSpare: "1FF0",
2056
2064
  spareTyreAxle: "0001"
2057
2065
  };
2058
2066
  const bridgeService = {
@@ -2066,7 +2074,8 @@ const bridgeService = {
2066
2074
  resetAutolearnStatuses,
2067
2075
  getAutolearnStatuses,
2068
2076
  isRebootRequired,
2069
- sendPinCommand
2077
+ sendPinCommand,
2078
+ setVehicleLayout
2070
2079
  };
2071
2080
  async function sendPinCommand(deviceId) {
2072
2081
  if (!canCommunicateWith(deviceId)) throw new Error("Bridge not connected");
@@ -2087,6 +2096,7 @@ async function updateFirmware(deviceId, bootloader, firmware, reportStatus) {
2087
2096
  }
2088
2097
  async function setVehicleLayout(deviceId, tcVehicle) {
2089
2098
  const spareAxles = tcVehicle.axles?.filter((axle) => axle.isSpare);
2099
+ if (spareAxles.length > 2) console.warn("Bridge supports max 2 spare axles, extra spare axles will be ignored");
2090
2100
  let spareAxlesCount = Math.min(spareAxles?.length || 0, 2);
2091
2101
  const result = {
2092
2102
  axle01: "0000",
@@ -2107,28 +2117,25 @@ async function setVehicleLayout(deviceId, tcVehicle) {
2107
2117
  vin: tcVehicle.vin || "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
2108
2118
  vinExtension: tcVehicle.vinExtension || "\0"
2109
2119
  };
2110
- for (let index = 0; index < 15; index++) {
2120
+ for (const [index, axle] of tcVehicle.axles.entries()) {
2111
2121
  const resultKey = Object.keys(result)[index];
2112
- const tyreCount = tcVehicle.axles[index]?.tyresCount;
2113
- if (tyreCount === 2) {
2114
- if (spareAxlesCount) {
2115
- result[resultKey] = vehicleLayoutAxleTypes.twoTyresAxleSpare;
2116
- spareAxlesCount -= 1;
2117
- } else {
2118
- result[resultKey] = vehicleLayoutAxleTypes.twoTyresAxle;
2119
- }
2122
+ const tyreCount = axle.tyresCount;
2123
+ if (spareAxlesCount) {
2124
+ if (tyreCount === 2) result[resultKey] = vehicleLayoutAxleTypes.twoTyresAxleSpare;
2125
+ else if (tyreCount === 4) result[resultKey] = vehicleLayoutAxleTypes.fourTyresAxleSpare;
2126
+ else if (tyreCount === 6) result[resultKey] = vehicleLayoutAxleTypes.sixTyresAxleSpare;
2127
+ else if (tyreCount === 8) result[resultKey] = vehicleLayoutAxleTypes.eightTyresAxleSpare;
2128
+ else if (tyreCount === 0) result[resultKey] = vehicleLayoutAxleTypes.spareTyreAxle;
2129
+ else throw new Error(`Axle with unsupported tyre count: ${tyreCount}`);
2130
+ spareAxlesCount -= 1;
2120
2131
  continue;
2121
2132
  }
2122
- if (tyreCount === 4) {
2123
- if (spareAxlesCount) {
2124
- result[resultKey] = vehicleLayoutAxleTypes.fourTyresAxleSpare;
2125
- spareAxlesCount -= 1;
2126
- } else {
2127
- result[resultKey] = vehicleLayoutAxleTypes.fourTyresAxle;
2128
- }
2129
- continue;
2130
- }
2131
- result[resultKey] = vehicleLayoutAxleTypes.noAxle;
2133
+ if (tyreCount === 2) result[resultKey] = vehicleLayoutAxleTypes.twoTyresAxle;
2134
+ else if (tyreCount === 4) result[resultKey] = vehicleLayoutAxleTypes.fourTyresAxle;
2135
+ else if (tyreCount === 6) result[resultKey] = vehicleLayoutAxleTypes.sixTyresAxle;
2136
+ else if (tyreCount === 8) result[resultKey] = vehicleLayoutAxleTypes.eightTyresAxle;
2137
+ else if (tyreCount === 0) result[resultKey] = vehicleLayoutAxleTypes.noAxle;
2138
+ else throw new Error(`Axle with unsupported tyre count: ${tyreCount}`);
2132
2139
  }
2133
2140
  await bridgeCommands.setVehicleLayout(deviceId, result);
2134
2141
  }
@@ -2843,7 +2850,7 @@ const flexiGaugeTpmsService$1 = {
2843
2850
  icon: "icon-flexigauge",
2844
2851
  processMessage(deviceId, message) {
2845
2852
  const numberArray = Array.from(new Uint8Array(message));
2846
- const stringFromBytes = String.fromCharCode.apply(null, numberArray).replace("\r\n", "");
2853
+ const stringFromBytes = removeEndLine(String.fromCharCode(...numberArray));
2847
2854
  for (const capability of capabilities$2) {
2848
2855
  if (capability.regex.test(stringFromBytes)) {
2849
2856
  return capability.processFn(deviceId, stringFromBytes);
@@ -2916,8 +2923,8 @@ const promiseQueue = {
2916
2923
  chunks.push(payload.slice(i, i + mtu));
2917
2924
  }
2918
2925
  for (const chunk of chunks) {
2919
- const convertedChunk = new Uint8Array(chunk).buffer;
2920
- bluetooth.write(deviceId, communication.serviceId, communication.characteristicId, convertedChunk);
2926
+ const convertedChunk = new Uint8Array(chunk);
2927
+ bluetooth.write(deviceId, communication.serviceId, communication.characteristicId, convertedChunk.buffer);
2921
2928
  }
2922
2929
  });
2923
2930
  return withTimeout(promise, 5e3, `Command timed out ${deviceResponseIdentifier[deviceId]}, ${deviceId}`);
@@ -3001,8 +3008,28 @@ const flexiGaugeTpmsCommands = {
3001
3008
  vdaRequestCommandsAccess,
3002
3009
  vdaRequestWriteAccess,
3003
3010
  processMessage,
3004
- getFirmwareVersion: getFirmwareVersion$1
3011
+ getFirmwareVersion: getFirmwareVersion$2,
3012
+ getConfig,
3013
+ setConfig,
3014
+ getTpmsConfig,
3015
+ setTpmsConfig
3005
3016
  };
3017
+ async function getConfig(deviceId) {
3018
+ const msg = "*CONFIG?";
3019
+ return sendCommand(deviceId, msg);
3020
+ }
3021
+ async function setConfig(deviceId, config) {
3022
+ const msg = `*CONFIG ${config}`;
3023
+ return sendCommand(deviceId, msg);
3024
+ }
3025
+ async function getTpmsConfig(deviceId) {
3026
+ const msg = "*TPMS CONFIG?";
3027
+ return sendCommand(deviceId, msg);
3028
+ }
3029
+ async function setTpmsConfig(deviceId, config) {
3030
+ const msg = `*TPMS CONFIG ${config}`;
3031
+ return sendCommand(deviceId, msg);
3032
+ }
3006
3033
  async function startTpmsScan(deviceId) {
3007
3034
  if (!canCommunicateWith(deviceId)) throw new Error("Flexi Gauge not connected");
3008
3035
  const scanMsg = stringToArrayBuffer("*TPMS ON TIME=10\r\n");
@@ -3022,9 +3049,9 @@ async function getBattery(deviceId) {
3022
3049
  const battery = Array.from(new Uint8Array(batteryValue))[0];
3023
3050
  return battery;
3024
3051
  }
3025
- async function getFirmwareVersion$1(deviceId) {
3052
+ async function getFirmwareVersion$2(deviceId) {
3026
3053
  const msg = "*FWVER?";
3027
- return sendCommand(deviceId, msg, "FWV");
3054
+ return sendCommand(deviceId, msg);
3028
3055
  }
3029
3056
  async function vdaRequestSensor(deviceId) {
3030
3057
  const scanMsg = "*VDA_LF_SEND SID=A0 LID=1A";
@@ -3064,9 +3091,10 @@ async function vdaSendConfiguration(deviceId, configuration) {
3064
3091
  const scanMsg = `*VDA_LF_SEND SID=A0 LID=EA PAR=17 DATA=${configuration}${crc}`;
3065
3092
  return sendCommand(deviceId, scanMsg);
3066
3093
  }
3067
- async function sendCommand(deviceId, command, identifier = "VDA") {
3094
+ async function sendCommand(deviceId, command) {
3068
3095
  const message = `${command}\r
3069
3096
  `;
3097
+ const identifier = getIdentifier$1(message);
3070
3098
  const decimalArray = stringToDecimalArray(message);
3071
3099
  let result;
3072
3100
  try {
@@ -3075,7 +3103,7 @@ async function sendCommand(deviceId, command, identifier = "VDA") {
3075
3103
  flexiGaugeTpms.disconnect(deviceId, "lostConnection");
3076
3104
  throw error;
3077
3105
  }
3078
- return result.map((num) => String.fromCharCode(num)).join("");
3106
+ return String.fromCharCode(...result);
3079
3107
  }
3080
3108
  function processMessage(deviceId, payload) {
3081
3109
  promiseQueue.processMessage(deviceId, payload, getIdentifier$1, isComplete$1, isError$1);
@@ -3088,13 +3116,163 @@ function isError$1(message) {
3088
3116
  return false;
3089
3117
  }
3090
3118
  function getIdentifier$1(message) {
3091
- const messageString = message.map((num) => String.fromCharCode(num)).join("");
3092
- return messageString.slice(0, 3);
3119
+ const messageString = typeof message === "string" ? message : String.fromCharCode(...message);
3120
+ const [, commands] = removeEndLine(messageString).match(/\*?([^=|^?]+)/) || [];
3121
+ const [identifier, subIdentifier] = commands.split(" ") || [];
3122
+ return identifier === "TPMS" && subIdentifier ? `${identifier} ${subIdentifier}` : identifier;
3093
3123
  }
3094
3124
  function getReversedSensorId(sensorId) {
3095
3125
  return sensorId.match(/.{1,2}/g).reverse().join("");
3096
3126
  }
3097
3127
 
3128
+ const fgConfigPressureUnits = ["bar", "psi", "kpa"];
3129
+ const fgConfigTdUnits = ["mm", "thirtySecondOfInch"];
3130
+ const fgConfigNeedleLengths = [15, 30, 40, 100, 130];
3131
+ const fgConfigRegions = ["eu", "us"];
3132
+ const fgConfigPressureDisplay = ["measured", "compensated"];
3133
+ const fgConfigTemperatureUnits = ["fahrenheit", "celsius"];
3134
+ const configToJsonMapping = {
3135
+ ML: (v) => ({ menuLock: v === "1" }),
3136
+ PU: (v) => ({ pressureUnit: fgConfigPressureUnits[Number(v)] }),
3137
+ TU: (v) => ({ tdUnit: fgConfigTdUnits[Number(v)] }),
3138
+ NL: (v) => ({ needleLength: fgConfigNeedleLengths[Number(v)] }),
3139
+ BE: (v) => ({ beep: v === "1" }),
3140
+ RS: (v) => ({ region: fgConfigRegions[Number(v)] }),
3141
+ PS: (v) => ({ powerSave: Number(v) }),
3142
+ PD: (v) => ({ pressureDisplay: fgConfigPressureDisplay[Number(v)] }),
3143
+ FW: (v) => ({ fwUpdate: v === "1" }),
3144
+ TT: (v) => ({ temperatureUnit: fgConfigTemperatureUnits[Number(v)] })
3145
+ };
3146
+ const configFromJsonMapping = {
3147
+ menuLock: (v) => `ML=${v ? "1" : "0"}`,
3148
+ pressureUnit: (v) => `PU=${getIndex(fgConfigPressureUnits, v)}`,
3149
+ tdUnit: (v) => `TU=${getIndex(fgConfigTdUnits, v)}`,
3150
+ needleLength: (v) => `NL=${getIndex(fgConfigNeedleLengths, v)}`,
3151
+ beep: (v) => `BE=${v ? "1" : "0"}`,
3152
+ region: (v) => `RS=${getIndex(fgConfigRegions, v)}`,
3153
+ powerSave: (v) => `PS=${v.toString()}`,
3154
+ pressureDisplay: (v) => `PD=${getIndex(fgConfigPressureDisplay, v)}`,
3155
+ fwUpdate: (v) => `FW=${v ? "1" : "0"}`,
3156
+ temperatureUnit: (v) => `TT=${getIndex(fgConfigTemperatureUnits, v)}`
3157
+ };
3158
+ const fgTpmsConfigProtocols = [
3159
+ "pwmTirecheck",
3160
+ "vdaTirecheck",
3161
+ "pwmWabco",
3162
+ "vdaLdl",
3163
+ "vdaContinental",
3164
+ "vdaSchrader"
3165
+ ];
3166
+ const flexiGaugeTpmsServiceMapping = {
3167
+ getDefaultConfigJson() {
3168
+ return {
3169
+ menuLock: false,
3170
+ pressureUnit: "bar",
3171
+ tdUnit: "mm",
3172
+ needleLength: 40,
3173
+ beep: true,
3174
+ region: "eu",
3175
+ powerSave: 15,
3176
+ pressureDisplay: "measured",
3177
+ fwUpdate: false,
3178
+ temperatureUnit: "fahrenheit"
3179
+ };
3180
+ },
3181
+ getDefaultTpmsConfigJson() {
3182
+ return ___default.cloneDeep({
3183
+ protocols: fgTpmsConfigProtocols.map((id) => ({ id, time: 5 }))
3184
+ });
3185
+ },
3186
+ /**
3187
+ * @param configString example: `CONFIG ML=0 PU=0 TU=0 NL=2 BE=1 RS=0 PS=15 PD=0 FW=0 TT=0\r\n`
3188
+ */
3189
+ getConfigJson(configString) {
3190
+ let config = this.getDefaultConfigJson();
3191
+ const parts = toolsSvc.removeEndLine(configString).split(" ").slice(1).map((v) => v.split("="));
3192
+ for (const [name, value] of parts) {
3193
+ const toJsonFn = configToJsonMapping[name];
3194
+ config = { ...config, ...toJsonFn(value) };
3195
+ }
3196
+ return config;
3197
+ },
3198
+ /**
3199
+ * @returns example: `ML=0 PU=0 TU=0 NL=2 BE=1 RS=0 PS=15 PD=0 FW=0 TT=0`
3200
+ */
3201
+ getConfig(configJson) {
3202
+ const configString = Object.entries(configJson).map(([key, value]) => {
3203
+ const fromJsonFn = configFromJsonMapping[key];
3204
+ return fromJsonFn(value);
3205
+ }).join(" ");
3206
+ return configString;
3207
+ },
3208
+ /**
3209
+ * @param configString example: `TPMS CONFIG ALG=0001020304050000 TIME=5050505050500000\r\n`
3210
+ *
3211
+ * - every protocol/time is 2 bytes
3212
+ * - we only support 6 protocols, rest is empty
3213
+ * - time is stored as n*100ms (`50` = 50x100ms = 5s)
3214
+ * - protocols can be duplicate when set in Fg Menu
3215
+ *
3216
+ * protocol codes:
3217
+ * - `00` - PWM Tirecheck - `pwmTirecheck`
3218
+ * - `01` - VDA Tirecheck - `vdaTirecheck`
3219
+ * - `02` - PWM WABCO - `pwmWabco`
3220
+ * - `03` - VDA LDL - `vdaLdl`
3221
+ * - `04` - VDA Continental - `vdaContinental`
3222
+ * - `05` - VDA Schrader - `vdaSchrader`
3223
+ */
3224
+ getTpmsConfigJson(configString) {
3225
+ const config = this.getDefaultTpmsConfigJson();
3226
+ const parts = toolsSvc.removeEndLine(configString).split(" ").slice(2).map((v) => {
3227
+ const [name, value] = v.split("=");
3228
+ if (name === "ALG") return ["protocols", getTpmsConfigProtocolList(value)];
3229
+ if (name === "TIME") return ["times", getTpmsConfigProtocolTimeList(value)];
3230
+ throw new Error(`Unknown Fg Tpms config part: ${name}`);
3231
+ });
3232
+ const pairs = ___default.fromPairs(parts);
3233
+ const zipped = ___default.zipObject(pairs.protocols, pairs.times);
3234
+ if (pairs.protocols.length) config.protocols = [];
3235
+ for (const [protocol, time] of Object.entries(zipped)) {
3236
+ config.protocols.push({ id: protocol, time: time / 10 });
3237
+ }
3238
+ if (config.protocols.length < 6) {
3239
+ const missingProtocols = fgTpmsConfigProtocols.filter((id) => !config.protocols.find((p) => p.id === id));
3240
+ for (const protocol of missingProtocols) {
3241
+ config.protocols.push({ id: protocol, time: 0 });
3242
+ }
3243
+ }
3244
+ return config;
3245
+ },
3246
+ /**
3247
+ * @returns example: `ALG=0001020304050000 TIME=5050505050500000`
3248
+ */
3249
+ getTpmsConfig(tpmsConfigJson) {
3250
+ const unzipped = tpmsConfigJson.protocols.reduce(
3251
+ (acc, { id, time }) => {
3252
+ acc.protocols.push(getIndex(fgTpmsConfigProtocols, id).padStart(2, "0"));
3253
+ if (time >= 10) throw new Error(`Fg Tpms config time value out of range: ${time}`);
3254
+ acc.times.push(
3255
+ Math.round(time * 10).toString().padStart(2, "0")
3256
+ );
3257
+ return acc;
3258
+ },
3259
+ { protocols: [], times: [] }
3260
+ );
3261
+ const protocols = unzipped.protocols.join("").padEnd(16, "0");
3262
+ const times = unzipped.times.join("").padEnd(16, "0");
3263
+ return `ALG=${protocols} TIME=${times}`;
3264
+ }
3265
+ };
3266
+ function getIndex(array, value) {
3267
+ return array.indexOf(value).toString();
3268
+ }
3269
+ function getTpmsConfigProtocolList(configString) {
3270
+ return configString.match(/(\d{2})/g)?.slice(0, 6).map((v) => fgTpmsConfigProtocols[Number.parseInt(v)]);
3271
+ }
3272
+ function getTpmsConfigProtocolTimeList(configString) {
3273
+ return configString.match(/(\d{2})/g)?.slice(0, 6).map((v) => Number.parseInt(v));
3274
+ }
3275
+
3098
3276
  let sensorReadings = [];
3099
3277
  const capabilities$1 = [
3100
3278
  {
@@ -3111,7 +3289,7 @@ const capabilities$1 = [
3111
3289
  {
3112
3290
  id: "tpms",
3113
3291
  processFn: processTpms,
3114
- regex: /^\*?TPMS.*/
3292
+ regex: /^\*?TPMS (ISON|DATA|ENDSCANNING).*/
3115
3293
  }
3116
3294
  ];
3117
3295
  const flexiGaugeTpmsService = {
@@ -3133,7 +3311,7 @@ const flexiGaugeTpmsService = {
3133
3311
  icon: "icon-flexigauge",
3134
3312
  processMessage(deviceId, message) {
3135
3313
  const numberArray = Array.from(new Uint8Array(message));
3136
- const stringFromBytes = String.fromCharCode.apply(null, numberArray).replace("\r\n", "");
3314
+ const stringFromBytes = removeEndLine(String.fromCharCode(...numberArray));
3137
3315
  for (const capability of capabilities$1) {
3138
3316
  if (capability.regex.test(stringFromBytes)) {
3139
3317
  return capability.processFn(deviceId, stringFromBytes);
@@ -3141,8 +3319,28 @@ const flexiGaugeTpmsService = {
3141
3319
  }
3142
3320
  flexiGaugeTpmsCommands.processMessage(deviceId, message);
3143
3321
  },
3322
+ async getConfig(deviceId) {
3323
+ const response = await flexiGaugeTpmsCommands.getConfig(deviceId);
3324
+ return flexiGaugeTpmsServiceMapping.getConfigJson(response);
3325
+ },
3326
+ async setConfig(deviceId, configJson) {
3327
+ const fw = await getFirmwareVersion$1(deviceId);
3328
+ if (fw < "1.4.4") throw new Error("Config change is not supported on this firmware version");
3329
+ const config = flexiGaugeTpmsServiceMapping.getConfig(configJson);
3330
+ await flexiGaugeTpmsCommands.setConfig(deviceId, config);
3331
+ },
3332
+ async getTpmsConfig(deviceId) {
3333
+ const response = await flexiGaugeTpmsCommands.getTpmsConfig(deviceId);
3334
+ return flexiGaugeTpmsServiceMapping.getTpmsConfigJson(response);
3335
+ },
3336
+ async setTpmsConfig(deviceId, configJson) {
3337
+ const fw = await getFirmwareVersion$1(deviceId);
3338
+ if (fw < "1.4.4") throw new Error("TPMS Config change is not supported on this firmware version");
3339
+ const config = flexiGaugeTpmsServiceMapping.getTpmsConfig(configJson);
3340
+ await flexiGaugeTpmsCommands.setTpmsConfig(deviceId, config);
3341
+ },
3144
3342
  setSensorDisplayId,
3145
- getFirmwareVersion
3343
+ getFirmwareVersion: getFirmwareVersion$1
3146
3344
  };
3147
3345
  function processTreadDepth(deviceId, value) {
3148
3346
  const treadDepth = value.match(/\d+/)?.[0];
@@ -3182,7 +3380,7 @@ function processTpms(deviceId, value) {
3182
3380
  }
3183
3381
  }
3184
3382
  async function setSensorDisplayId(deviceId, oldSensorId, newSensorId) {
3185
- const fw = await getFirmwareVersion(deviceId);
3383
+ const fw = await getFirmwareVersion$1(deviceId);
3186
3384
  if (fw < "1.4.4") throw new Error("Programming sensors is not supported on this firmware version");
3187
3385
  await findSensor(deviceId, oldSensorId);
3188
3386
  const seed = await getSeed(deviceId, oldSensorId);
@@ -3231,10 +3429,10 @@ async function vdaRepeat(fn) {
3231
3429
  }
3232
3430
  throw new Error("VDA Timeout");
3233
3431
  }
3234
- async function getFirmwareVersion(deviceId) {
3432
+ async function getFirmwareVersion$1(deviceId) {
3235
3433
  const response = await flexiGaugeTpmsCommands.getFirmwareVersion(deviceId);
3236
- const groupedValue = response.split(" ");
3237
- return groupedValue[1];
3434
+ const [, version] = removeEndLine(response).split(" ");
3435
+ return version;
3238
3436
  }
3239
3437
 
3240
3438
  const flexiGaugeTpms = {
@@ -3264,7 +3462,11 @@ const flexiGaugeTpms = {
3264
3462
  getFirmwareVersion: flexiGaugeTpmsService.getFirmwareVersion,
3265
3463
  startTpmsScan: flexiGaugeTpmsService.startTpmsScan,
3266
3464
  setSensorDisplayId: flexiGaugeTpmsService.setSensorDisplayId,
3267
- resetSensorDisplayId: (deviceId, sensorId) => flexiGaugeTpmsService.setSensorDisplayId(deviceId, sensorId, "00000000")
3465
+ resetSensorDisplayId: (deviceId, sensorId) => flexiGaugeTpmsService.setSensorDisplayId(deviceId, sensorId, "00000000"),
3466
+ getConfig: flexiGaugeTpmsService.getConfig,
3467
+ setConfig: flexiGaugeTpmsService.setConfig,
3468
+ getTpmsConfig: flexiGaugeTpmsService.getTpmsConfig,
3469
+ setTpmsConfig: flexiGaugeTpmsService.setTpmsConfig
3268
3470
  };
3269
3471
 
3270
3472
  const capabilities = [
@@ -3280,7 +3482,7 @@ const pressureStickService = {
3280
3482
  },
3281
3483
  processMessage(deviceId, message) {
3282
3484
  const numberArray = Array.from(new Uint8Array(message));
3283
- const stringFromBytes = String.fromCharCode.apply(null, numberArray).replace("\r\n", "");
3485
+ const stringFromBytes = removeEndLine(String.fromCharCode(...numberArray));
3284
3486
  for (const capability of capabilities) {
3285
3487
  if (capability.regex.test(stringFromBytes)) {
3286
3488
  return capability.processFn(deviceId, stringFromBytes);
@@ -3380,7 +3582,7 @@ const torqueWrenchCommands = {
3380
3582
  const formattedError = formatError(error);
3381
3583
  throw new Error(formattedError);
3382
3584
  }
3383
- return result.map((num) => String.fromCharCode(num)).join("");
3585
+ return String.fromCharCode(...result);
3384
3586
  },
3385
3587
  processMessage(deviceId, payload) {
3386
3588
  promiseQueue.processMessage(deviceId, payload, getIdentifier, isComplete, isError);
@@ -3396,7 +3598,7 @@ function isError(message) {
3396
3598
  }
3397
3599
  function getIdentifier(message) {
3398
3600
  if (message[0] === 123) return "200";
3399
- return message.slice(6, 9).map((num) => String.fromCharCode(num)).join("");
3601
+ return String.fromCharCode(...message.slice(6, 9));
3400
3602
  }
3401
3603
  function getChecksum(message) {
3402
3604
  let checksum = 0;
@@ -3408,7 +3610,7 @@ function getChecksum(message) {
3408
3610
  function formatError(error) {
3409
3611
  if (!error.cause) throw error;
3410
3612
  const message = error.cause.slice(6, 8);
3411
- const errorId = message.map((num) => String.fromCharCode(num)).join("");
3613
+ const errorId = String.fromCharCode(...message);
3412
3614
  return errors[errorId] || "Unknown error";
3413
3615
  }
3414
3616
 
@@ -3944,10 +4146,45 @@ const flexiGaugeTpmsSimulator = {
3944
4146
  resetSensorDisplayId(deviceId, sensorId) {
3945
4147
  return new Promise((resolve) => resolve());
3946
4148
  },
3947
- async getFirmwareVersion(deviceId) {
4149
+ async getConfig(deviceId) {
4150
+ const fg = getSimulatedFg(deviceId);
4151
+ await toolsSvc.delay(100);
4152
+ const fwVersion = await getFirmwareVersion(deviceId);
4153
+ if (fwVersion >= "1.4.4") {
4154
+ return { ...fg.simulatorData.config };
4155
+ }
4156
+ throw new Error(`Getting Fg config is not supported on firmware version ${fwVersion}, min 1.4.4 required`);
4157
+ },
4158
+ async setConfig(deviceId, configJson) {
4159
+ const fg = getSimulatedFg(deviceId);
4160
+ await toolsSvc.delay(100);
4161
+ const fwVersion = await getFirmwareVersion(deviceId);
4162
+ if (fwVersion >= "1.4.4") {
4163
+ fg.simulatorData.config = { ...configJson };
4164
+ return;
4165
+ }
4166
+ throw new Error(`Setting Fg config is not supported on firmware version ${fwVersion}, min 1.4.4 required`);
4167
+ },
4168
+ async getTpmsConfig(deviceId) {
4169
+ const fg = getSimulatedFg(deviceId);
4170
+ await toolsSvc.delay(100);
4171
+ const fwVersion = await getFirmwareVersion(deviceId);
4172
+ if (fwVersion >= "1.4.4") {
4173
+ return ___default.cloneDeep(fg.simulatorData.tpmsConfig);
4174
+ }
4175
+ throw new Error(`Getting Fg TPMS config is not supported on firmware version ${fwVersion}, min 1.4.4 required`);
4176
+ },
4177
+ async setTpmsConfig(deviceId, tpmsConfig) {
4178
+ const fg = getSimulatedFg(deviceId);
3948
4179
  await toolsSvc.delay(100);
3949
- return "9.9.9";
4180
+ const fwVersion = await getFirmwareVersion(deviceId);
4181
+ if (fwVersion >= "1.4.4") {
4182
+ fg.simulatorData.tpmsConfig = ___default.cloneDeep(tpmsConfig);
4183
+ return;
4184
+ }
4185
+ throw new Error(`Setting Fg TPMS config is not supported on firmware version ${fwVersion}, min 1.4.4 required`);
3950
4186
  },
4187
+ getFirmwareVersion,
3951
4188
  onButtonPress(callback) {
3952
4189
  },
3953
4190
  onTpms(callback) {
@@ -3955,6 +4192,11 @@ const flexiGaugeTpmsSimulator = {
3955
4192
  onTreadDepth(callback) {
3956
4193
  }
3957
4194
  };
4195
+ async function getFirmwareVersion(deviceId) {
4196
+ const fg = getSimulatedFg(deviceId);
4197
+ await toolsSvc.delay(100);
4198
+ return fg.simulatorData.fwVersion;
4199
+ }
3958
4200
  function getSimulatedFg(deviceId) {
3959
4201
  const simulatedDevice = store.simulatedDevices[deviceId];
3960
4202
  if (!simulatedDevice) throw new Error(`Simulated bridge was not found: ${deviceId}`);
@@ -3968,12 +4210,12 @@ function getSimulatedFgTemplate() {
3968
4210
  type: "flexiGaugeTpms",
3969
4211
  rssi: -50,
3970
4212
  simulatorData: {
4213
+ fwVersion: "1.4.4",
3971
4214
  battery: 45,
3972
4215
  events: {
3973
4216
  "fg:button": "L",
3974
4217
  "fg:tpms": {
3975
- // TODO: replace with realistic values
3976
- ID: "FFFF1212",
4218
+ ID: generateEAN(268431361, 268435455),
3977
4219
  Rssi: "-50",
3978
4220
  PC: 12,
3979
4221
  T: 15,
@@ -3982,10 +4224,22 @@ function getSimulatedFgTemplate() {
3982
4224
  S: "S"
3983
4225
  },
3984
4226
  "fg:treadDepth": 5.2
3985
- }
4227
+ },
4228
+ config: flexiGaugeTpmsServiceMapping.getDefaultConfigJson(),
4229
+ tpmsConfig: flexiGaugeTpmsServiceMapping.getDefaultTpmsConfigJson()
3986
4230
  }
3987
4231
  };
3988
4232
  }
4233
+ function generateEAN(min, max) {
4234
+ const serial = Math.round(min + Math.random() * (max - min)).toString(16);
4235
+ let p1 = 0;
4236
+ for (let i = 0; i < serial.length; i++) {
4237
+ p1 += Number.parseInt(serial[i], 16) * (i % 2 === 1 ? 1 : 3);
4238
+ }
4239
+ const p2 = Math.ceil(p1 / 16) * 16;
4240
+ const check = p2 - p1;
4241
+ return `${serial}${check.toString(16)}`.toUpperCase();
4242
+ }
3989
4243
 
3990
4244
  const deviceServicesAndSimulators = [
3991
4245
  [bridge, bridgeSimulator],
package/dist/index.d.cts CHANGED
@@ -680,6 +680,34 @@ interface FgSensorReading {
680
680
  T: number;
681
681
  S?: string;
682
682
  }
683
+ type FgConfigPressureUnit = 'bar' | 'psi' | 'kpa';
684
+ type FgConfigTdUnit = 'mm' | 'thirtySecondOfInch';
685
+ type FgConfigNeedleLength = 15 | 30 | 40 | 100 | 130;
686
+ type FgConfigRegion = 'eu' | 'us';
687
+ type FgConfigPressureDisplay = 'measured' | 'compensated';
688
+ type FgConfigTemperatureUnit = 'fahrenheit' | 'celsius';
689
+ interface FgConfig {
690
+ menuLock?: boolean;
691
+ pressureUnit?: FgConfigPressureUnit;
692
+ tdUnit?: FgConfigTdUnit;
693
+ needleLength?: FgConfigNeedleLength;
694
+ beep?: boolean;
695
+ region?: FgConfigRegion;
696
+ /** `0-500` minutes, `0` = disabled */
697
+ powerSave?: number;
698
+ pressureDisplay?: FgConfigPressureDisplay;
699
+ fwUpdate?: boolean;
700
+ temperatureUnit?: FgConfigTemperatureUnit;
701
+ }
702
+ type FgTpmsConfigProtocol = 'pwmTirecheck' | 'vdaTirecheck' | 'pwmWabco' | 'vdaLdl' | 'vdaContinental' | 'vdaSchrader';
703
+ interface FgTpmsConfigProtocolSetting {
704
+ id: FgTpmsConfigProtocol;
705
+ /** Time in seconds */
706
+ time: number;
707
+ }
708
+ interface FgTpmsConfig {
709
+ protocols: FgTpmsConfigProtocolSetting[];
710
+ }
683
711
  declare class BridgeTcVehicleAxle {
684
712
  targetPressure?: number;
685
713
  tyresCount: number;
@@ -818,6 +846,7 @@ interface BleBridgeSimulated extends BleBridge {
818
846
  interface BleFlexiGaugeTpmsSimulated extends BleFlexiGaugeTpms {
819
847
  isDisabled?: boolean;
820
848
  simulatorData: {
849
+ fwVersion: string;
821
850
  battery: number;
822
851
  events: {
823
852
  /** 'L' | 'R' | 'C' | 'T' | 'B' */
@@ -826,6 +855,8 @@ interface BleFlexiGaugeTpmsSimulated extends BleFlexiGaugeTpms {
826
855
  /** In mm */
827
856
  'fg:treadDepth': number;
828
857
  };
858
+ config: FgConfig;
859
+ tpmsConfig: FgTpmsConfig;
829
860
  };
830
861
  }
831
862
  type Simulator<Service extends Record<string, any>, SimulatedDeviceType extends BleDeviceSimulated> = Service & {
@@ -951,6 +982,10 @@ declare function createTirecheckDeviceSdk(platform: DevicePlatform, bleImplement
951
982
  startTpmsScan: (deviceId: string) => void;
952
983
  setSensorDisplayId: (deviceId: string, oldSensorId: string, newSensorId: string) => Promise<void>;
953
984
  resetSensorDisplayId: (deviceId: string, sensorId: string) => Promise<void>;
985
+ getConfig: (deviceId: string) => Promise<FgConfig>;
986
+ setConfig: (deviceId: string, configJson: FgConfig) => Promise<void>;
987
+ getTpmsConfig: (deviceId: string) => Promise<FgTpmsConfig>;
988
+ setTpmsConfig: (deviceId: string, configJson: FgTpmsConfig) => Promise<void>;
954
989
  };
955
990
  flexiGauge: {
956
991
  connect(deviceId: string): Promise<void>;
@@ -994,4 +1029,4 @@ declare function createTirecheckDeviceSdk(platform: DevicePlatform, bleImplement
994
1029
  };
995
1030
  };
996
1031
 
997
- export { type BleBridge, type BleBridgeAdvertisingData, type BleBridgeOta, type BleBridgeSimulated, type BleDevice, type BleDeviceBase, type BleDeviceSimulated, type BleDeviceStatus, type BleDeviceType, type BleFlexiGauge, type BleFlexiGaugeTpms, type BleFlexiGaugeTpmsSimulated, type BlePressureStick, type BleSecurityKeys, type BleTorqueWrench, type BridgeAccessLevel, type BridgeAutolearnStatus, type BridgeCommandStructure, type BridgeCommandStructureProperties, type BridgeCommandStructurized, type BridgeConfiguration, type BridgeReading, type BridgeTcIssue, type BridgeTcTyre, type BridgeTcVehicle, BridgeTcVehicleAxle, type DeepPartial, type DevicePlatform, type DeviceState, type EventHandlers, type EventName, type FgSensorReading, type PositionInfo, type ReportStatusFn, type Simulator, type StateReason, type TorqueWrenchProperties, type TorqueWrenchReading, type TorqueWrenchStartJobParams, type Wrapper, createTirecheckDeviceSdk };
1032
+ export { type BleBridge, type BleBridgeAdvertisingData, type BleBridgeOta, type BleBridgeSimulated, type BleDevice, type BleDeviceBase, type BleDeviceSimulated, type BleDeviceStatus, type BleDeviceType, type BleFlexiGauge, type BleFlexiGaugeTpms, type BleFlexiGaugeTpmsSimulated, type BlePressureStick, type BleSecurityKeys, type BleTorqueWrench, type BridgeAccessLevel, type BridgeAutolearnStatus, type BridgeCommandStructure, type BridgeCommandStructureProperties, type BridgeCommandStructurized, type BridgeConfiguration, type BridgeReading, type BridgeTcIssue, type BridgeTcTyre, type BridgeTcVehicle, BridgeTcVehicleAxle, type DeepPartial, type DevicePlatform, type DeviceState, type EventHandlers, type EventName, type FgConfig, type FgConfigNeedleLength, type FgConfigPressureDisplay, type FgConfigPressureUnit, type FgConfigRegion, type FgConfigTdUnit, type FgConfigTemperatureUnit, type FgSensorReading, type FgTpmsConfig, type FgTpmsConfigProtocol, type FgTpmsConfigProtocolSetting, type PositionInfo, type ReportStatusFn, type Simulator, type StateReason, type TorqueWrenchProperties, type TorqueWrenchReading, type TorqueWrenchStartJobParams, type Wrapper, createTirecheckDeviceSdk };
package/dist/index.d.mts CHANGED
@@ -680,6 +680,34 @@ interface FgSensorReading {
680
680
  T: number;
681
681
  S?: string;
682
682
  }
683
+ type FgConfigPressureUnit = 'bar' | 'psi' | 'kpa';
684
+ type FgConfigTdUnit = 'mm' | 'thirtySecondOfInch';
685
+ type FgConfigNeedleLength = 15 | 30 | 40 | 100 | 130;
686
+ type FgConfigRegion = 'eu' | 'us';
687
+ type FgConfigPressureDisplay = 'measured' | 'compensated';
688
+ type FgConfigTemperatureUnit = 'fahrenheit' | 'celsius';
689
+ interface FgConfig {
690
+ menuLock?: boolean;
691
+ pressureUnit?: FgConfigPressureUnit;
692
+ tdUnit?: FgConfigTdUnit;
693
+ needleLength?: FgConfigNeedleLength;
694
+ beep?: boolean;
695
+ region?: FgConfigRegion;
696
+ /** `0-500` minutes, `0` = disabled */
697
+ powerSave?: number;
698
+ pressureDisplay?: FgConfigPressureDisplay;
699
+ fwUpdate?: boolean;
700
+ temperatureUnit?: FgConfigTemperatureUnit;
701
+ }
702
+ type FgTpmsConfigProtocol = 'pwmTirecheck' | 'vdaTirecheck' | 'pwmWabco' | 'vdaLdl' | 'vdaContinental' | 'vdaSchrader';
703
+ interface FgTpmsConfigProtocolSetting {
704
+ id: FgTpmsConfigProtocol;
705
+ /** Time in seconds */
706
+ time: number;
707
+ }
708
+ interface FgTpmsConfig {
709
+ protocols: FgTpmsConfigProtocolSetting[];
710
+ }
683
711
  declare class BridgeTcVehicleAxle {
684
712
  targetPressure?: number;
685
713
  tyresCount: number;
@@ -818,6 +846,7 @@ interface BleBridgeSimulated extends BleBridge {
818
846
  interface BleFlexiGaugeTpmsSimulated extends BleFlexiGaugeTpms {
819
847
  isDisabled?: boolean;
820
848
  simulatorData: {
849
+ fwVersion: string;
821
850
  battery: number;
822
851
  events: {
823
852
  /** 'L' | 'R' | 'C' | 'T' | 'B' */
@@ -826,6 +855,8 @@ interface BleFlexiGaugeTpmsSimulated extends BleFlexiGaugeTpms {
826
855
  /** In mm */
827
856
  'fg:treadDepth': number;
828
857
  };
858
+ config: FgConfig;
859
+ tpmsConfig: FgTpmsConfig;
829
860
  };
830
861
  }
831
862
  type Simulator<Service extends Record<string, any>, SimulatedDeviceType extends BleDeviceSimulated> = Service & {
@@ -951,6 +982,10 @@ declare function createTirecheckDeviceSdk(platform: DevicePlatform, bleImplement
951
982
  startTpmsScan: (deviceId: string) => void;
952
983
  setSensorDisplayId: (deviceId: string, oldSensorId: string, newSensorId: string) => Promise<void>;
953
984
  resetSensorDisplayId: (deviceId: string, sensorId: string) => Promise<void>;
985
+ getConfig: (deviceId: string) => Promise<FgConfig>;
986
+ setConfig: (deviceId: string, configJson: FgConfig) => Promise<void>;
987
+ getTpmsConfig: (deviceId: string) => Promise<FgTpmsConfig>;
988
+ setTpmsConfig: (deviceId: string, configJson: FgTpmsConfig) => Promise<void>;
954
989
  };
955
990
  flexiGauge: {
956
991
  connect(deviceId: string): Promise<void>;
@@ -994,4 +1029,4 @@ declare function createTirecheckDeviceSdk(platform: DevicePlatform, bleImplement
994
1029
  };
995
1030
  };
996
1031
 
997
- export { type BleBridge, type BleBridgeAdvertisingData, type BleBridgeOta, type BleBridgeSimulated, type BleDevice, type BleDeviceBase, type BleDeviceSimulated, type BleDeviceStatus, type BleDeviceType, type BleFlexiGauge, type BleFlexiGaugeTpms, type BleFlexiGaugeTpmsSimulated, type BlePressureStick, type BleSecurityKeys, type BleTorqueWrench, type BridgeAccessLevel, type BridgeAutolearnStatus, type BridgeCommandStructure, type BridgeCommandStructureProperties, type BridgeCommandStructurized, type BridgeConfiguration, type BridgeReading, type BridgeTcIssue, type BridgeTcTyre, type BridgeTcVehicle, BridgeTcVehicleAxle, type DeepPartial, type DevicePlatform, type DeviceState, type EventHandlers, type EventName, type FgSensorReading, type PositionInfo, type ReportStatusFn, type Simulator, type StateReason, type TorqueWrenchProperties, type TorqueWrenchReading, type TorqueWrenchStartJobParams, type Wrapper, createTirecheckDeviceSdk };
1032
+ export { type BleBridge, type BleBridgeAdvertisingData, type BleBridgeOta, type BleBridgeSimulated, type BleDevice, type BleDeviceBase, type BleDeviceSimulated, type BleDeviceStatus, type BleDeviceType, type BleFlexiGauge, type BleFlexiGaugeTpms, type BleFlexiGaugeTpmsSimulated, type BlePressureStick, type BleSecurityKeys, type BleTorqueWrench, type BridgeAccessLevel, type BridgeAutolearnStatus, type BridgeCommandStructure, type BridgeCommandStructureProperties, type BridgeCommandStructurized, type BridgeConfiguration, type BridgeReading, type BridgeTcIssue, type BridgeTcTyre, type BridgeTcVehicle, BridgeTcVehicleAxle, type DeepPartial, type DevicePlatform, type DeviceState, type EventHandlers, type EventName, type FgConfig, type FgConfigNeedleLength, type FgConfigPressureDisplay, type FgConfigPressureUnit, type FgConfigRegion, type FgConfigTdUnit, type FgConfigTemperatureUnit, type FgSensorReading, type FgTpmsConfig, type FgTpmsConfigProtocol, type FgTpmsConfigProtocolSetting, type PositionInfo, type ReportStatusFn, type Simulator, type StateReason, type TorqueWrenchProperties, type TorqueWrenchReading, type TorqueWrenchStartJobParams, type Wrapper, createTirecheckDeviceSdk };
package/dist/index.d.ts CHANGED
@@ -680,6 +680,34 @@ interface FgSensorReading {
680
680
  T: number;
681
681
  S?: string;
682
682
  }
683
+ type FgConfigPressureUnit = 'bar' | 'psi' | 'kpa';
684
+ type FgConfigTdUnit = 'mm' | 'thirtySecondOfInch';
685
+ type FgConfigNeedleLength = 15 | 30 | 40 | 100 | 130;
686
+ type FgConfigRegion = 'eu' | 'us';
687
+ type FgConfigPressureDisplay = 'measured' | 'compensated';
688
+ type FgConfigTemperatureUnit = 'fahrenheit' | 'celsius';
689
+ interface FgConfig {
690
+ menuLock?: boolean;
691
+ pressureUnit?: FgConfigPressureUnit;
692
+ tdUnit?: FgConfigTdUnit;
693
+ needleLength?: FgConfigNeedleLength;
694
+ beep?: boolean;
695
+ region?: FgConfigRegion;
696
+ /** `0-500` minutes, `0` = disabled */
697
+ powerSave?: number;
698
+ pressureDisplay?: FgConfigPressureDisplay;
699
+ fwUpdate?: boolean;
700
+ temperatureUnit?: FgConfigTemperatureUnit;
701
+ }
702
+ type FgTpmsConfigProtocol = 'pwmTirecheck' | 'vdaTirecheck' | 'pwmWabco' | 'vdaLdl' | 'vdaContinental' | 'vdaSchrader';
703
+ interface FgTpmsConfigProtocolSetting {
704
+ id: FgTpmsConfigProtocol;
705
+ /** Time in seconds */
706
+ time: number;
707
+ }
708
+ interface FgTpmsConfig {
709
+ protocols: FgTpmsConfigProtocolSetting[];
710
+ }
683
711
  declare class BridgeTcVehicleAxle {
684
712
  targetPressure?: number;
685
713
  tyresCount: number;
@@ -818,6 +846,7 @@ interface BleBridgeSimulated extends BleBridge {
818
846
  interface BleFlexiGaugeTpmsSimulated extends BleFlexiGaugeTpms {
819
847
  isDisabled?: boolean;
820
848
  simulatorData: {
849
+ fwVersion: string;
821
850
  battery: number;
822
851
  events: {
823
852
  /** 'L' | 'R' | 'C' | 'T' | 'B' */
@@ -826,6 +855,8 @@ interface BleFlexiGaugeTpmsSimulated extends BleFlexiGaugeTpms {
826
855
  /** In mm */
827
856
  'fg:treadDepth': number;
828
857
  };
858
+ config: FgConfig;
859
+ tpmsConfig: FgTpmsConfig;
829
860
  };
830
861
  }
831
862
  type Simulator<Service extends Record<string, any>, SimulatedDeviceType extends BleDeviceSimulated> = Service & {
@@ -951,6 +982,10 @@ declare function createTirecheckDeviceSdk(platform: DevicePlatform, bleImplement
951
982
  startTpmsScan: (deviceId: string) => void;
952
983
  setSensorDisplayId: (deviceId: string, oldSensorId: string, newSensorId: string) => Promise<void>;
953
984
  resetSensorDisplayId: (deviceId: string, sensorId: string) => Promise<void>;
985
+ getConfig: (deviceId: string) => Promise<FgConfig>;
986
+ setConfig: (deviceId: string, configJson: FgConfig) => Promise<void>;
987
+ getTpmsConfig: (deviceId: string) => Promise<FgTpmsConfig>;
988
+ setTpmsConfig: (deviceId: string, configJson: FgTpmsConfig) => Promise<void>;
954
989
  };
955
990
  flexiGauge: {
956
991
  connect(deviceId: string): Promise<void>;
@@ -994,4 +1029,4 @@ declare function createTirecheckDeviceSdk(platform: DevicePlatform, bleImplement
994
1029
  };
995
1030
  };
996
1031
 
997
- export { type BleBridge, type BleBridgeAdvertisingData, type BleBridgeOta, type BleBridgeSimulated, type BleDevice, type BleDeviceBase, type BleDeviceSimulated, type BleDeviceStatus, type BleDeviceType, type BleFlexiGauge, type BleFlexiGaugeTpms, type BleFlexiGaugeTpmsSimulated, type BlePressureStick, type BleSecurityKeys, type BleTorqueWrench, type BridgeAccessLevel, type BridgeAutolearnStatus, type BridgeCommandStructure, type BridgeCommandStructureProperties, type BridgeCommandStructurized, type BridgeConfiguration, type BridgeReading, type BridgeTcIssue, type BridgeTcTyre, type BridgeTcVehicle, BridgeTcVehicleAxle, type DeepPartial, type DevicePlatform, type DeviceState, type EventHandlers, type EventName, type FgSensorReading, type PositionInfo, type ReportStatusFn, type Simulator, type StateReason, type TorqueWrenchProperties, type TorqueWrenchReading, type TorqueWrenchStartJobParams, type Wrapper, createTirecheckDeviceSdk };
1032
+ export { type BleBridge, type BleBridgeAdvertisingData, type BleBridgeOta, type BleBridgeSimulated, type BleDevice, type BleDeviceBase, type BleDeviceSimulated, type BleDeviceStatus, type BleDeviceType, type BleFlexiGauge, type BleFlexiGaugeTpms, type BleFlexiGaugeTpmsSimulated, type BlePressureStick, type BleSecurityKeys, type BleTorqueWrench, type BridgeAccessLevel, type BridgeAutolearnStatus, type BridgeCommandStructure, type BridgeCommandStructureProperties, type BridgeCommandStructurized, type BridgeConfiguration, type BridgeReading, type BridgeTcIssue, type BridgeTcTyre, type BridgeTcVehicle, BridgeTcVehicleAxle, type DeepPartial, type DevicePlatform, type DeviceState, type EventHandlers, type EventName, type FgConfig, type FgConfigNeedleLength, type FgConfigPressureDisplay, type FgConfigPressureUnit, type FgConfigRegion, type FgConfigTdUnit, type FgConfigTemperatureUnit, type FgSensorReading, type FgTpmsConfig, type FgTpmsConfigProtocol, type FgTpmsConfigProtocolSetting, type PositionInfo, type ReportStatusFn, type Simulator, type StateReason, type TorqueWrenchProperties, type TorqueWrenchReading, type TorqueWrenchStartJobParams, type Wrapper, createTirecheckDeviceSdk };
package/dist/index.mjs CHANGED
@@ -107,15 +107,19 @@ function stringToDecimalArray(string) {
107
107
  return Array.from(array);
108
108
  }
109
109
  function decimalToHex(decimal, padStart = 2) {
110
- const hex = decimal.toString(16);
110
+ const hex = decimal.toString(16).toUpperCase();
111
111
  return hex.padStart(padStart, "0");
112
112
  }
113
+ function removeEndLine(string) {
114
+ return string.replace("\r\n", "");
115
+ }
113
116
  const toolsSvc = {
114
117
  delay,
115
118
  setIntervalImmediate,
116
119
  waitUntil,
117
120
  withTimeout,
118
- canCommunicateWith
121
+ canCommunicateWith,
122
+ removeEndLine
119
123
  };
120
124
  function normalizeError(error) {
121
125
  if (!error) return new Error("Operation timed out");
@@ -185,7 +189,7 @@ const bridgeTools = {
185
189
  decodeData(data, displayUnits) {
186
190
  const _data = _.clone(data);
187
191
  if (displayUnits === "ascii") {
188
- return _data.filter((d) => d).map((x) => String.fromCharCode(x)).join("");
192
+ return String.fromCharCode(..._data.filter((d) => d));
189
193
  }
190
194
  const _reversedData = _data.reverse();
191
195
  if (displayUnits === "decimal") {
@@ -2046,6 +2050,10 @@ const vehicleLayoutAxleTypes = {
2046
2050
  twoTyresAxleSpare: "0380",
2047
2051
  fourTyresAxle: "06C0",
2048
2052
  fourTyresAxleSpare: "07C0",
2053
+ sixTyresAxle: "0EE0",
2054
+ sixTyresAxleSpare: "0FE0",
2055
+ eightTyresAxle: "1EF0",
2056
+ eightTyresAxleSpare: "1FF0",
2049
2057
  spareTyreAxle: "0001"
2050
2058
  };
2051
2059
  const bridgeService = {
@@ -2059,7 +2067,8 @@ const bridgeService = {
2059
2067
  resetAutolearnStatuses,
2060
2068
  getAutolearnStatuses,
2061
2069
  isRebootRequired,
2062
- sendPinCommand
2070
+ sendPinCommand,
2071
+ setVehicleLayout
2063
2072
  };
2064
2073
  async function sendPinCommand(deviceId) {
2065
2074
  if (!canCommunicateWith(deviceId)) throw new Error("Bridge not connected");
@@ -2080,6 +2089,7 @@ async function updateFirmware(deviceId, bootloader, firmware, reportStatus) {
2080
2089
  }
2081
2090
  async function setVehicleLayout(deviceId, tcVehicle) {
2082
2091
  const spareAxles = tcVehicle.axles?.filter((axle) => axle.isSpare);
2092
+ if (spareAxles.length > 2) console.warn("Bridge supports max 2 spare axles, extra spare axles will be ignored");
2083
2093
  let spareAxlesCount = Math.min(spareAxles?.length || 0, 2);
2084
2094
  const result = {
2085
2095
  axle01: "0000",
@@ -2100,28 +2110,25 @@ async function setVehicleLayout(deviceId, tcVehicle) {
2100
2110
  vin: tcVehicle.vin || "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
2101
2111
  vinExtension: tcVehicle.vinExtension || "\0"
2102
2112
  };
2103
- for (let index = 0; index < 15; index++) {
2113
+ for (const [index, axle] of tcVehicle.axles.entries()) {
2104
2114
  const resultKey = Object.keys(result)[index];
2105
- const tyreCount = tcVehicle.axles[index]?.tyresCount;
2106
- if (tyreCount === 2) {
2107
- if (spareAxlesCount) {
2108
- result[resultKey] = vehicleLayoutAxleTypes.twoTyresAxleSpare;
2109
- spareAxlesCount -= 1;
2110
- } else {
2111
- result[resultKey] = vehicleLayoutAxleTypes.twoTyresAxle;
2112
- }
2115
+ const tyreCount = axle.tyresCount;
2116
+ if (spareAxlesCount) {
2117
+ if (tyreCount === 2) result[resultKey] = vehicleLayoutAxleTypes.twoTyresAxleSpare;
2118
+ else if (tyreCount === 4) result[resultKey] = vehicleLayoutAxleTypes.fourTyresAxleSpare;
2119
+ else if (tyreCount === 6) result[resultKey] = vehicleLayoutAxleTypes.sixTyresAxleSpare;
2120
+ else if (tyreCount === 8) result[resultKey] = vehicleLayoutAxleTypes.eightTyresAxleSpare;
2121
+ else if (tyreCount === 0) result[resultKey] = vehicleLayoutAxleTypes.spareTyreAxle;
2122
+ else throw new Error(`Axle with unsupported tyre count: ${tyreCount}`);
2123
+ spareAxlesCount -= 1;
2113
2124
  continue;
2114
2125
  }
2115
- if (tyreCount === 4) {
2116
- if (spareAxlesCount) {
2117
- result[resultKey] = vehicleLayoutAxleTypes.fourTyresAxleSpare;
2118
- spareAxlesCount -= 1;
2119
- } else {
2120
- result[resultKey] = vehicleLayoutAxleTypes.fourTyresAxle;
2121
- }
2122
- continue;
2123
- }
2124
- result[resultKey] = vehicleLayoutAxleTypes.noAxle;
2126
+ if (tyreCount === 2) result[resultKey] = vehicleLayoutAxleTypes.twoTyresAxle;
2127
+ else if (tyreCount === 4) result[resultKey] = vehicleLayoutAxleTypes.fourTyresAxle;
2128
+ else if (tyreCount === 6) result[resultKey] = vehicleLayoutAxleTypes.sixTyresAxle;
2129
+ else if (tyreCount === 8) result[resultKey] = vehicleLayoutAxleTypes.eightTyresAxle;
2130
+ else if (tyreCount === 0) result[resultKey] = vehicleLayoutAxleTypes.noAxle;
2131
+ else throw new Error(`Axle with unsupported tyre count: ${tyreCount}`);
2125
2132
  }
2126
2133
  await bridgeCommands.setVehicleLayout(deviceId, result);
2127
2134
  }
@@ -2836,7 +2843,7 @@ const flexiGaugeTpmsService$1 = {
2836
2843
  icon: "icon-flexigauge",
2837
2844
  processMessage(deviceId, message) {
2838
2845
  const numberArray = Array.from(new Uint8Array(message));
2839
- const stringFromBytes = String.fromCharCode.apply(null, numberArray).replace("\r\n", "");
2846
+ const stringFromBytes = removeEndLine(String.fromCharCode(...numberArray));
2840
2847
  for (const capability of capabilities$2) {
2841
2848
  if (capability.regex.test(stringFromBytes)) {
2842
2849
  return capability.processFn(deviceId, stringFromBytes);
@@ -2909,8 +2916,8 @@ const promiseQueue = {
2909
2916
  chunks.push(payload.slice(i, i + mtu));
2910
2917
  }
2911
2918
  for (const chunk of chunks) {
2912
- const convertedChunk = new Uint8Array(chunk).buffer;
2913
- bluetooth.write(deviceId, communication.serviceId, communication.characteristicId, convertedChunk);
2919
+ const convertedChunk = new Uint8Array(chunk);
2920
+ bluetooth.write(deviceId, communication.serviceId, communication.characteristicId, convertedChunk.buffer);
2914
2921
  }
2915
2922
  });
2916
2923
  return withTimeout(promise, 5e3, `Command timed out ${deviceResponseIdentifier[deviceId]}, ${deviceId}`);
@@ -2994,8 +3001,28 @@ const flexiGaugeTpmsCommands = {
2994
3001
  vdaRequestCommandsAccess,
2995
3002
  vdaRequestWriteAccess,
2996
3003
  processMessage,
2997
- getFirmwareVersion: getFirmwareVersion$1
3004
+ getFirmwareVersion: getFirmwareVersion$2,
3005
+ getConfig,
3006
+ setConfig,
3007
+ getTpmsConfig,
3008
+ setTpmsConfig
2998
3009
  };
3010
+ async function getConfig(deviceId) {
3011
+ const msg = "*CONFIG?";
3012
+ return sendCommand(deviceId, msg);
3013
+ }
3014
+ async function setConfig(deviceId, config) {
3015
+ const msg = `*CONFIG ${config}`;
3016
+ return sendCommand(deviceId, msg);
3017
+ }
3018
+ async function getTpmsConfig(deviceId) {
3019
+ const msg = "*TPMS CONFIG?";
3020
+ return sendCommand(deviceId, msg);
3021
+ }
3022
+ async function setTpmsConfig(deviceId, config) {
3023
+ const msg = `*TPMS CONFIG ${config}`;
3024
+ return sendCommand(deviceId, msg);
3025
+ }
2999
3026
  async function startTpmsScan(deviceId) {
3000
3027
  if (!canCommunicateWith(deviceId)) throw new Error("Flexi Gauge not connected");
3001
3028
  const scanMsg = stringToArrayBuffer("*TPMS ON TIME=10\r\n");
@@ -3015,9 +3042,9 @@ async function getBattery(deviceId) {
3015
3042
  const battery = Array.from(new Uint8Array(batteryValue))[0];
3016
3043
  return battery;
3017
3044
  }
3018
- async function getFirmwareVersion$1(deviceId) {
3045
+ async function getFirmwareVersion$2(deviceId) {
3019
3046
  const msg = "*FWVER?";
3020
- return sendCommand(deviceId, msg, "FWV");
3047
+ return sendCommand(deviceId, msg);
3021
3048
  }
3022
3049
  async function vdaRequestSensor(deviceId) {
3023
3050
  const scanMsg = "*VDA_LF_SEND SID=A0 LID=1A";
@@ -3057,9 +3084,10 @@ async function vdaSendConfiguration(deviceId, configuration) {
3057
3084
  const scanMsg = `*VDA_LF_SEND SID=A0 LID=EA PAR=17 DATA=${configuration}${crc}`;
3058
3085
  return sendCommand(deviceId, scanMsg);
3059
3086
  }
3060
- async function sendCommand(deviceId, command, identifier = "VDA") {
3087
+ async function sendCommand(deviceId, command) {
3061
3088
  const message = `${command}\r
3062
3089
  `;
3090
+ const identifier = getIdentifier$1(message);
3063
3091
  const decimalArray = stringToDecimalArray(message);
3064
3092
  let result;
3065
3093
  try {
@@ -3068,7 +3096,7 @@ async function sendCommand(deviceId, command, identifier = "VDA") {
3068
3096
  flexiGaugeTpms.disconnect(deviceId, "lostConnection");
3069
3097
  throw error;
3070
3098
  }
3071
- return result.map((num) => String.fromCharCode(num)).join("");
3099
+ return String.fromCharCode(...result);
3072
3100
  }
3073
3101
  function processMessage(deviceId, payload) {
3074
3102
  promiseQueue.processMessage(deviceId, payload, getIdentifier$1, isComplete$1, isError$1);
@@ -3081,13 +3109,163 @@ function isError$1(message) {
3081
3109
  return false;
3082
3110
  }
3083
3111
  function getIdentifier$1(message) {
3084
- const messageString = message.map((num) => String.fromCharCode(num)).join("");
3085
- return messageString.slice(0, 3);
3112
+ const messageString = typeof message === "string" ? message : String.fromCharCode(...message);
3113
+ const [, commands] = removeEndLine(messageString).match(/\*?([^=|^?]+)/) || [];
3114
+ const [identifier, subIdentifier] = commands.split(" ") || [];
3115
+ return identifier === "TPMS" && subIdentifier ? `${identifier} ${subIdentifier}` : identifier;
3086
3116
  }
3087
3117
  function getReversedSensorId(sensorId) {
3088
3118
  return sensorId.match(/.{1,2}/g).reverse().join("");
3089
3119
  }
3090
3120
 
3121
+ const fgConfigPressureUnits = ["bar", "psi", "kpa"];
3122
+ const fgConfigTdUnits = ["mm", "thirtySecondOfInch"];
3123
+ const fgConfigNeedleLengths = [15, 30, 40, 100, 130];
3124
+ const fgConfigRegions = ["eu", "us"];
3125
+ const fgConfigPressureDisplay = ["measured", "compensated"];
3126
+ const fgConfigTemperatureUnits = ["fahrenheit", "celsius"];
3127
+ const configToJsonMapping = {
3128
+ ML: (v) => ({ menuLock: v === "1" }),
3129
+ PU: (v) => ({ pressureUnit: fgConfigPressureUnits[Number(v)] }),
3130
+ TU: (v) => ({ tdUnit: fgConfigTdUnits[Number(v)] }),
3131
+ NL: (v) => ({ needleLength: fgConfigNeedleLengths[Number(v)] }),
3132
+ BE: (v) => ({ beep: v === "1" }),
3133
+ RS: (v) => ({ region: fgConfigRegions[Number(v)] }),
3134
+ PS: (v) => ({ powerSave: Number(v) }),
3135
+ PD: (v) => ({ pressureDisplay: fgConfigPressureDisplay[Number(v)] }),
3136
+ FW: (v) => ({ fwUpdate: v === "1" }),
3137
+ TT: (v) => ({ temperatureUnit: fgConfigTemperatureUnits[Number(v)] })
3138
+ };
3139
+ const configFromJsonMapping = {
3140
+ menuLock: (v) => `ML=${v ? "1" : "0"}`,
3141
+ pressureUnit: (v) => `PU=${getIndex(fgConfigPressureUnits, v)}`,
3142
+ tdUnit: (v) => `TU=${getIndex(fgConfigTdUnits, v)}`,
3143
+ needleLength: (v) => `NL=${getIndex(fgConfigNeedleLengths, v)}`,
3144
+ beep: (v) => `BE=${v ? "1" : "0"}`,
3145
+ region: (v) => `RS=${getIndex(fgConfigRegions, v)}`,
3146
+ powerSave: (v) => `PS=${v.toString()}`,
3147
+ pressureDisplay: (v) => `PD=${getIndex(fgConfigPressureDisplay, v)}`,
3148
+ fwUpdate: (v) => `FW=${v ? "1" : "0"}`,
3149
+ temperatureUnit: (v) => `TT=${getIndex(fgConfigTemperatureUnits, v)}`
3150
+ };
3151
+ const fgTpmsConfigProtocols = [
3152
+ "pwmTirecheck",
3153
+ "vdaTirecheck",
3154
+ "pwmWabco",
3155
+ "vdaLdl",
3156
+ "vdaContinental",
3157
+ "vdaSchrader"
3158
+ ];
3159
+ const flexiGaugeTpmsServiceMapping = {
3160
+ getDefaultConfigJson() {
3161
+ return {
3162
+ menuLock: false,
3163
+ pressureUnit: "bar",
3164
+ tdUnit: "mm",
3165
+ needleLength: 40,
3166
+ beep: true,
3167
+ region: "eu",
3168
+ powerSave: 15,
3169
+ pressureDisplay: "measured",
3170
+ fwUpdate: false,
3171
+ temperatureUnit: "fahrenheit"
3172
+ };
3173
+ },
3174
+ getDefaultTpmsConfigJson() {
3175
+ return _.cloneDeep({
3176
+ protocols: fgTpmsConfigProtocols.map((id) => ({ id, time: 5 }))
3177
+ });
3178
+ },
3179
+ /**
3180
+ * @param configString example: `CONFIG ML=0 PU=0 TU=0 NL=2 BE=1 RS=0 PS=15 PD=0 FW=0 TT=0\r\n`
3181
+ */
3182
+ getConfigJson(configString) {
3183
+ let config = this.getDefaultConfigJson();
3184
+ const parts = toolsSvc.removeEndLine(configString).split(" ").slice(1).map((v) => v.split("="));
3185
+ for (const [name, value] of parts) {
3186
+ const toJsonFn = configToJsonMapping[name];
3187
+ config = { ...config, ...toJsonFn(value) };
3188
+ }
3189
+ return config;
3190
+ },
3191
+ /**
3192
+ * @returns example: `ML=0 PU=0 TU=0 NL=2 BE=1 RS=0 PS=15 PD=0 FW=0 TT=0`
3193
+ */
3194
+ getConfig(configJson) {
3195
+ const configString = Object.entries(configJson).map(([key, value]) => {
3196
+ const fromJsonFn = configFromJsonMapping[key];
3197
+ return fromJsonFn(value);
3198
+ }).join(" ");
3199
+ return configString;
3200
+ },
3201
+ /**
3202
+ * @param configString example: `TPMS CONFIG ALG=0001020304050000 TIME=5050505050500000\r\n`
3203
+ *
3204
+ * - every protocol/time is 2 bytes
3205
+ * - we only support 6 protocols, rest is empty
3206
+ * - time is stored as n*100ms (`50` = 50x100ms = 5s)
3207
+ * - protocols can be duplicate when set in Fg Menu
3208
+ *
3209
+ * protocol codes:
3210
+ * - `00` - PWM Tirecheck - `pwmTirecheck`
3211
+ * - `01` - VDA Tirecheck - `vdaTirecheck`
3212
+ * - `02` - PWM WABCO - `pwmWabco`
3213
+ * - `03` - VDA LDL - `vdaLdl`
3214
+ * - `04` - VDA Continental - `vdaContinental`
3215
+ * - `05` - VDA Schrader - `vdaSchrader`
3216
+ */
3217
+ getTpmsConfigJson(configString) {
3218
+ const config = this.getDefaultTpmsConfigJson();
3219
+ const parts = toolsSvc.removeEndLine(configString).split(" ").slice(2).map((v) => {
3220
+ const [name, value] = v.split("=");
3221
+ if (name === "ALG") return ["protocols", getTpmsConfigProtocolList(value)];
3222
+ if (name === "TIME") return ["times", getTpmsConfigProtocolTimeList(value)];
3223
+ throw new Error(`Unknown Fg Tpms config part: ${name}`);
3224
+ });
3225
+ const pairs = _.fromPairs(parts);
3226
+ const zipped = _.zipObject(pairs.protocols, pairs.times);
3227
+ if (pairs.protocols.length) config.protocols = [];
3228
+ for (const [protocol, time] of Object.entries(zipped)) {
3229
+ config.protocols.push({ id: protocol, time: time / 10 });
3230
+ }
3231
+ if (config.protocols.length < 6) {
3232
+ const missingProtocols = fgTpmsConfigProtocols.filter((id) => !config.protocols.find((p) => p.id === id));
3233
+ for (const protocol of missingProtocols) {
3234
+ config.protocols.push({ id: protocol, time: 0 });
3235
+ }
3236
+ }
3237
+ return config;
3238
+ },
3239
+ /**
3240
+ * @returns example: `ALG=0001020304050000 TIME=5050505050500000`
3241
+ */
3242
+ getTpmsConfig(tpmsConfigJson) {
3243
+ const unzipped = tpmsConfigJson.protocols.reduce(
3244
+ (acc, { id, time }) => {
3245
+ acc.protocols.push(getIndex(fgTpmsConfigProtocols, id).padStart(2, "0"));
3246
+ if (time >= 10) throw new Error(`Fg Tpms config time value out of range: ${time}`);
3247
+ acc.times.push(
3248
+ Math.round(time * 10).toString().padStart(2, "0")
3249
+ );
3250
+ return acc;
3251
+ },
3252
+ { protocols: [], times: [] }
3253
+ );
3254
+ const protocols = unzipped.protocols.join("").padEnd(16, "0");
3255
+ const times = unzipped.times.join("").padEnd(16, "0");
3256
+ return `ALG=${protocols} TIME=${times}`;
3257
+ }
3258
+ };
3259
+ function getIndex(array, value) {
3260
+ return array.indexOf(value).toString();
3261
+ }
3262
+ function getTpmsConfigProtocolList(configString) {
3263
+ return configString.match(/(\d{2})/g)?.slice(0, 6).map((v) => fgTpmsConfigProtocols[Number.parseInt(v)]);
3264
+ }
3265
+ function getTpmsConfigProtocolTimeList(configString) {
3266
+ return configString.match(/(\d{2})/g)?.slice(0, 6).map((v) => Number.parseInt(v));
3267
+ }
3268
+
3091
3269
  let sensorReadings = [];
3092
3270
  const capabilities$1 = [
3093
3271
  {
@@ -3104,7 +3282,7 @@ const capabilities$1 = [
3104
3282
  {
3105
3283
  id: "tpms",
3106
3284
  processFn: processTpms,
3107
- regex: /^\*?TPMS.*/
3285
+ regex: /^\*?TPMS (ISON|DATA|ENDSCANNING).*/
3108
3286
  }
3109
3287
  ];
3110
3288
  const flexiGaugeTpmsService = {
@@ -3126,7 +3304,7 @@ const flexiGaugeTpmsService = {
3126
3304
  icon: "icon-flexigauge",
3127
3305
  processMessage(deviceId, message) {
3128
3306
  const numberArray = Array.from(new Uint8Array(message));
3129
- const stringFromBytes = String.fromCharCode.apply(null, numberArray).replace("\r\n", "");
3307
+ const stringFromBytes = removeEndLine(String.fromCharCode(...numberArray));
3130
3308
  for (const capability of capabilities$1) {
3131
3309
  if (capability.regex.test(stringFromBytes)) {
3132
3310
  return capability.processFn(deviceId, stringFromBytes);
@@ -3134,8 +3312,28 @@ const flexiGaugeTpmsService = {
3134
3312
  }
3135
3313
  flexiGaugeTpmsCommands.processMessage(deviceId, message);
3136
3314
  },
3315
+ async getConfig(deviceId) {
3316
+ const response = await flexiGaugeTpmsCommands.getConfig(deviceId);
3317
+ return flexiGaugeTpmsServiceMapping.getConfigJson(response);
3318
+ },
3319
+ async setConfig(deviceId, configJson) {
3320
+ const fw = await getFirmwareVersion$1(deviceId);
3321
+ if (fw < "1.4.4") throw new Error("Config change is not supported on this firmware version");
3322
+ const config = flexiGaugeTpmsServiceMapping.getConfig(configJson);
3323
+ await flexiGaugeTpmsCommands.setConfig(deviceId, config);
3324
+ },
3325
+ async getTpmsConfig(deviceId) {
3326
+ const response = await flexiGaugeTpmsCommands.getTpmsConfig(deviceId);
3327
+ return flexiGaugeTpmsServiceMapping.getTpmsConfigJson(response);
3328
+ },
3329
+ async setTpmsConfig(deviceId, configJson) {
3330
+ const fw = await getFirmwareVersion$1(deviceId);
3331
+ if (fw < "1.4.4") throw new Error("TPMS Config change is not supported on this firmware version");
3332
+ const config = flexiGaugeTpmsServiceMapping.getTpmsConfig(configJson);
3333
+ await flexiGaugeTpmsCommands.setTpmsConfig(deviceId, config);
3334
+ },
3137
3335
  setSensorDisplayId,
3138
- getFirmwareVersion
3336
+ getFirmwareVersion: getFirmwareVersion$1
3139
3337
  };
3140
3338
  function processTreadDepth(deviceId, value) {
3141
3339
  const treadDepth = value.match(/\d+/)?.[0];
@@ -3175,7 +3373,7 @@ function processTpms(deviceId, value) {
3175
3373
  }
3176
3374
  }
3177
3375
  async function setSensorDisplayId(deviceId, oldSensorId, newSensorId) {
3178
- const fw = await getFirmwareVersion(deviceId);
3376
+ const fw = await getFirmwareVersion$1(deviceId);
3179
3377
  if (fw < "1.4.4") throw new Error("Programming sensors is not supported on this firmware version");
3180
3378
  await findSensor(deviceId, oldSensorId);
3181
3379
  const seed = await getSeed(deviceId, oldSensorId);
@@ -3224,10 +3422,10 @@ async function vdaRepeat(fn) {
3224
3422
  }
3225
3423
  throw new Error("VDA Timeout");
3226
3424
  }
3227
- async function getFirmwareVersion(deviceId) {
3425
+ async function getFirmwareVersion$1(deviceId) {
3228
3426
  const response = await flexiGaugeTpmsCommands.getFirmwareVersion(deviceId);
3229
- const groupedValue = response.split(" ");
3230
- return groupedValue[1];
3427
+ const [, version] = removeEndLine(response).split(" ");
3428
+ return version;
3231
3429
  }
3232
3430
 
3233
3431
  const flexiGaugeTpms = {
@@ -3257,7 +3455,11 @@ const flexiGaugeTpms = {
3257
3455
  getFirmwareVersion: flexiGaugeTpmsService.getFirmwareVersion,
3258
3456
  startTpmsScan: flexiGaugeTpmsService.startTpmsScan,
3259
3457
  setSensorDisplayId: flexiGaugeTpmsService.setSensorDisplayId,
3260
- resetSensorDisplayId: (deviceId, sensorId) => flexiGaugeTpmsService.setSensorDisplayId(deviceId, sensorId, "00000000")
3458
+ resetSensorDisplayId: (deviceId, sensorId) => flexiGaugeTpmsService.setSensorDisplayId(deviceId, sensorId, "00000000"),
3459
+ getConfig: flexiGaugeTpmsService.getConfig,
3460
+ setConfig: flexiGaugeTpmsService.setConfig,
3461
+ getTpmsConfig: flexiGaugeTpmsService.getTpmsConfig,
3462
+ setTpmsConfig: flexiGaugeTpmsService.setTpmsConfig
3261
3463
  };
3262
3464
 
3263
3465
  const capabilities = [
@@ -3273,7 +3475,7 @@ const pressureStickService = {
3273
3475
  },
3274
3476
  processMessage(deviceId, message) {
3275
3477
  const numberArray = Array.from(new Uint8Array(message));
3276
- const stringFromBytes = String.fromCharCode.apply(null, numberArray).replace("\r\n", "");
3478
+ const stringFromBytes = removeEndLine(String.fromCharCode(...numberArray));
3277
3479
  for (const capability of capabilities) {
3278
3480
  if (capability.regex.test(stringFromBytes)) {
3279
3481
  return capability.processFn(deviceId, stringFromBytes);
@@ -3373,7 +3575,7 @@ const torqueWrenchCommands = {
3373
3575
  const formattedError = formatError(error);
3374
3576
  throw new Error(formattedError);
3375
3577
  }
3376
- return result.map((num) => String.fromCharCode(num)).join("");
3578
+ return String.fromCharCode(...result);
3377
3579
  },
3378
3580
  processMessage(deviceId, payload) {
3379
3581
  promiseQueue.processMessage(deviceId, payload, getIdentifier, isComplete, isError);
@@ -3389,7 +3591,7 @@ function isError(message) {
3389
3591
  }
3390
3592
  function getIdentifier(message) {
3391
3593
  if (message[0] === 123) return "200";
3392
- return message.slice(6, 9).map((num) => String.fromCharCode(num)).join("");
3594
+ return String.fromCharCode(...message.slice(6, 9));
3393
3595
  }
3394
3596
  function getChecksum(message) {
3395
3597
  let checksum = 0;
@@ -3401,7 +3603,7 @@ function getChecksum(message) {
3401
3603
  function formatError(error) {
3402
3604
  if (!error.cause) throw error;
3403
3605
  const message = error.cause.slice(6, 8);
3404
- const errorId = message.map((num) => String.fromCharCode(num)).join("");
3606
+ const errorId = String.fromCharCode(...message);
3405
3607
  return errors[errorId] || "Unknown error";
3406
3608
  }
3407
3609
 
@@ -3937,10 +4139,45 @@ const flexiGaugeTpmsSimulator = {
3937
4139
  resetSensorDisplayId(deviceId, sensorId) {
3938
4140
  return new Promise((resolve) => resolve());
3939
4141
  },
3940
- async getFirmwareVersion(deviceId) {
4142
+ async getConfig(deviceId) {
4143
+ const fg = getSimulatedFg(deviceId);
4144
+ await toolsSvc.delay(100);
4145
+ const fwVersion = await getFirmwareVersion(deviceId);
4146
+ if (fwVersion >= "1.4.4") {
4147
+ return { ...fg.simulatorData.config };
4148
+ }
4149
+ throw new Error(`Getting Fg config is not supported on firmware version ${fwVersion}, min 1.4.4 required`);
4150
+ },
4151
+ async setConfig(deviceId, configJson) {
4152
+ const fg = getSimulatedFg(deviceId);
4153
+ await toolsSvc.delay(100);
4154
+ const fwVersion = await getFirmwareVersion(deviceId);
4155
+ if (fwVersion >= "1.4.4") {
4156
+ fg.simulatorData.config = { ...configJson };
4157
+ return;
4158
+ }
4159
+ throw new Error(`Setting Fg config is not supported on firmware version ${fwVersion}, min 1.4.4 required`);
4160
+ },
4161
+ async getTpmsConfig(deviceId) {
4162
+ const fg = getSimulatedFg(deviceId);
4163
+ await toolsSvc.delay(100);
4164
+ const fwVersion = await getFirmwareVersion(deviceId);
4165
+ if (fwVersion >= "1.4.4") {
4166
+ return _.cloneDeep(fg.simulatorData.tpmsConfig);
4167
+ }
4168
+ throw new Error(`Getting Fg TPMS config is not supported on firmware version ${fwVersion}, min 1.4.4 required`);
4169
+ },
4170
+ async setTpmsConfig(deviceId, tpmsConfig) {
4171
+ const fg = getSimulatedFg(deviceId);
3941
4172
  await toolsSvc.delay(100);
3942
- return "9.9.9";
4173
+ const fwVersion = await getFirmwareVersion(deviceId);
4174
+ if (fwVersion >= "1.4.4") {
4175
+ fg.simulatorData.tpmsConfig = _.cloneDeep(tpmsConfig);
4176
+ return;
4177
+ }
4178
+ throw new Error(`Setting Fg TPMS config is not supported on firmware version ${fwVersion}, min 1.4.4 required`);
3943
4179
  },
4180
+ getFirmwareVersion,
3944
4181
  onButtonPress(callback) {
3945
4182
  },
3946
4183
  onTpms(callback) {
@@ -3948,6 +4185,11 @@ const flexiGaugeTpmsSimulator = {
3948
4185
  onTreadDepth(callback) {
3949
4186
  }
3950
4187
  };
4188
+ async function getFirmwareVersion(deviceId) {
4189
+ const fg = getSimulatedFg(deviceId);
4190
+ await toolsSvc.delay(100);
4191
+ return fg.simulatorData.fwVersion;
4192
+ }
3951
4193
  function getSimulatedFg(deviceId) {
3952
4194
  const simulatedDevice = store.simulatedDevices[deviceId];
3953
4195
  if (!simulatedDevice) throw new Error(`Simulated bridge was not found: ${deviceId}`);
@@ -3961,12 +4203,12 @@ function getSimulatedFgTemplate() {
3961
4203
  type: "flexiGaugeTpms",
3962
4204
  rssi: -50,
3963
4205
  simulatorData: {
4206
+ fwVersion: "1.4.4",
3964
4207
  battery: 45,
3965
4208
  events: {
3966
4209
  "fg:button": "L",
3967
4210
  "fg:tpms": {
3968
- // TODO: replace with realistic values
3969
- ID: "FFFF1212",
4211
+ ID: generateEAN(268431361, 268435455),
3970
4212
  Rssi: "-50",
3971
4213
  PC: 12,
3972
4214
  T: 15,
@@ -3975,10 +4217,22 @@ function getSimulatedFgTemplate() {
3975
4217
  S: "S"
3976
4218
  },
3977
4219
  "fg:treadDepth": 5.2
3978
- }
4220
+ },
4221
+ config: flexiGaugeTpmsServiceMapping.getDefaultConfigJson(),
4222
+ tpmsConfig: flexiGaugeTpmsServiceMapping.getDefaultTpmsConfigJson()
3979
4223
  }
3980
4224
  };
3981
4225
  }
4226
+ function generateEAN(min, max) {
4227
+ const serial = Math.round(min + Math.random() * (max - min)).toString(16);
4228
+ let p1 = 0;
4229
+ for (let i = 0; i < serial.length; i++) {
4230
+ p1 += Number.parseInt(serial[i], 16) * (i % 2 === 1 ? 1 : 3);
4231
+ }
4232
+ const p2 = Math.ceil(p1 / 16) * 16;
4233
+ const check = p2 - p1;
4234
+ return `${serial}${check.toString(16)}`.toUpperCase();
4235
+ }
3982
4236
 
3983
4237
  const deviceServicesAndSimulators = [
3984
4238
  [bridge, bridgeSimulator],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tirecheck-device-sdk",
3
- "version": "0.2.44",
3
+ "version": "0.2.46",
4
4
  "description": "SDK for working with various devices produced by Tirecheck via Bluetooth (CAN Bridge, Routers, Sensors, FlexiGauge, PressureStick, etc)",
5
5
  "author": "Leonid Buneev <leonid.buneev@tirecheck.com>",
6
6
  "license": "ISC",