tirecheck-device-sdk 0.2.45 → 0.2.47

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
@@ -117,12 +117,16 @@ function decimalToHex(decimal, padStart = 2) {
117
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") {
@@ -2071,7 +2075,8 @@ const bridgeService = {
2071
2075
  getAutolearnStatuses,
2072
2076
  isRebootRequired,
2073
2077
  sendPinCommand,
2074
- setVehicleLayout
2078
+ setVehicleLayout,
2079
+ setAxleInfo
2075
2080
  };
2076
2081
  async function sendPinCommand(deviceId) {
2077
2082
  if (!canCommunicateWith(deviceId)) throw new Error("Bridge not connected");
@@ -2272,8 +2277,13 @@ async function getAxlesWithAutolearnSettings(deviceId) {
2272
2277
  }
2273
2278
  async function setAxleInfo(deviceId, tcVehicle) {
2274
2279
  if (!tcVehicle.axles?.length) throw new Error("Vehicle has no axles");
2275
- const spareTyres = tcVehicle.tcTyres?.filter((t) => String(t.mountedOn?.positionId).endsWith("0")) || [];
2276
- for (let axleIndex = 0; axleIndex < tcVehicle.axles.length; axleIndex++) {
2280
+ const tyresWithInfo = tcVehicle.tcTyres.map((tyre) => ({
2281
+ tcTpmsSensor: tyre.tcTpmsSensor,
2282
+ ...bridgeTools.getPositionInfo(tyre.mountedOn?.positionId || 0)
2283
+ }));
2284
+ const tyresWithSensors = tyresWithInfo.filter((tyre) => tyre.tcTpmsSensor && !tyre.isSpareTyre);
2285
+ const spareTyres = tyresWithInfo.filter((tyre) => tyre.isSpareTyre);
2286
+ for (let axleIndex = 1; axleIndex <= 16; axleIndex++) {
2277
2287
  const tyres = [
2278
2288
  "00000000",
2279
2289
  "00000000",
@@ -2296,30 +2306,14 @@ async function setAxleInfo(deviceId, tcVehicle) {
2296
2306
  "00000000",
2297
2307
  "00000000"
2298
2308
  ];
2299
- const axle = tcVehicle.axles[axleIndex];
2300
- const spareTyre = spareTyres[axleIndex];
2301
- if (spareTyre && spareTyre.tcTpmsSensor?.id) {
2302
- tyres[7] = bridgeTools.convertSensorIdForBridge(spareTyre.tcTpmsSensor?.id);
2303
- }
2304
- let axleTyres = tcVehicle.tcTyres?.filter(
2305
- (t) => t.mountedOn?.positionId ? bridgeTools.getPositionInfo(t.mountedOn?.positionId).axlePosition === axleIndex + 1 && spareTyre?.mountedOn?.positionId !== t.mountedOn?.positionId : false
2306
- ) || [];
2307
- axleTyres = axleTyres.sort((a, b) => (a.mountedOn?.positionId || 0) - (b.mountedOn?.positionId || 0));
2308
- for (const [tyreIndex, tyre] of axleTyres.entries()) {
2309
- const tyrePosition = tyre.mountedOn && bridgeTools.getPositionInfo(tyre.mountedOn.positionId).tyrePosition;
2310
- const realTyreIndex = tyrePosition ? tyrePosition - 1 : tyreIndex;
2311
- const sensorId = tyre.tcTpmsSensor?.id;
2312
- if (!sensorId) continue;
2313
- if (axle.isSpare) continue;
2314
- const isTwinTyre = axle.tyresCount === 4;
2315
- let bridgeTyreIndex = 0;
2316
- if (isTwinTyre && realTyreIndex === 0) bridgeTyreIndex = 5;
2317
- if (isTwinTyre && realTyreIndex === 1 || !isTwinTyre && realTyreIndex === 0) bridgeTyreIndex = 6;
2318
- if (isTwinTyre && realTyreIndex === 3) bridgeTyreIndex = 9;
2319
- if (isTwinTyre && realTyreIndex === 2 || !isTwinTyre && realTyreIndex === 1) bridgeTyreIndex = 8;
2320
- tyres[bridgeTyreIndex] = bridgeTools.convertSensorIdForBridge(sensorId);
2309
+ const axleTyres = tyresWithSensors.filter((tyre) => tyre.axlePosition === axleIndex);
2310
+ const spareTyre = spareTyres[axleIndex - 1];
2311
+ if (!axleTyres.length && !spareTyre) continue;
2312
+ for (const tyre of axleTyres) {
2313
+ const bridgeIndex = getBridgeIndexFromPositionId(tyre.positionId, 7);
2314
+ tyres[bridgeIndex] = tyre.tcTpmsSensor.id;
2321
2315
  }
2322
- if (!___default.inRange(axleIndex, 0, 16)) return;
2316
+ if (spareTyre && spareTyre.tcTpmsSensor) tyres[7] = spareTyre.tcTpmsSensor.id;
2323
2317
  const numberArray = tyres.map((x) => x.match(/.{2}/g)?.reverse()).flat().map((n) => n ? Number.parseInt(n, 16) : 0);
2324
2318
  await bridgeCommands.setAxleInfo(deviceId, axleIndex, numberArray);
2325
2319
  }
@@ -2846,7 +2840,7 @@ const flexiGaugeTpmsService$1 = {
2846
2840
  icon: "icon-flexigauge",
2847
2841
  processMessage(deviceId, message) {
2848
2842
  const numberArray = Array.from(new Uint8Array(message));
2849
- const stringFromBytes = String.fromCharCode.apply(null, numberArray).replace("\r\n", "");
2843
+ const stringFromBytes = removeEndLine(String.fromCharCode(...numberArray));
2850
2844
  for (const capability of capabilities$2) {
2851
2845
  if (capability.regex.test(stringFromBytes)) {
2852
2846
  return capability.processFn(deviceId, stringFromBytes);
@@ -2919,8 +2913,8 @@ const promiseQueue = {
2919
2913
  chunks.push(payload.slice(i, i + mtu));
2920
2914
  }
2921
2915
  for (const chunk of chunks) {
2922
- const convertedChunk = new Uint8Array(chunk).buffer;
2923
- bluetooth.write(deviceId, communication.serviceId, communication.characteristicId, convertedChunk);
2916
+ const convertedChunk = new Uint8Array(chunk);
2917
+ bluetooth.write(deviceId, communication.serviceId, communication.characteristicId, convertedChunk.buffer);
2924
2918
  }
2925
2919
  });
2926
2920
  return withTimeout(promise, 5e3, `Command timed out ${deviceResponseIdentifier[deviceId]}, ${deviceId}`);
@@ -3004,8 +2998,28 @@ const flexiGaugeTpmsCommands = {
3004
2998
  vdaRequestCommandsAccess,
3005
2999
  vdaRequestWriteAccess,
3006
3000
  processMessage,
3007
- getFirmwareVersion: getFirmwareVersion$1
3001
+ getFirmwareVersion: getFirmwareVersion$2,
3002
+ getConfig,
3003
+ setConfig,
3004
+ getTpmsConfig,
3005
+ setTpmsConfig
3008
3006
  };
3007
+ async function getConfig(deviceId) {
3008
+ const msg = "*CONFIG?";
3009
+ return sendCommand(deviceId, msg);
3010
+ }
3011
+ async function setConfig(deviceId, config) {
3012
+ const msg = `*CONFIG ${config}`;
3013
+ return sendCommand(deviceId, msg);
3014
+ }
3015
+ async function getTpmsConfig(deviceId) {
3016
+ const msg = "*TPMS CONFIG?";
3017
+ return sendCommand(deviceId, msg);
3018
+ }
3019
+ async function setTpmsConfig(deviceId, config) {
3020
+ const msg = `*TPMS CONFIG ${config}`;
3021
+ return sendCommand(deviceId, msg);
3022
+ }
3009
3023
  async function startTpmsScan(deviceId) {
3010
3024
  if (!canCommunicateWith(deviceId)) throw new Error("Flexi Gauge not connected");
3011
3025
  const scanMsg = stringToArrayBuffer("*TPMS ON TIME=10\r\n");
@@ -3025,9 +3039,9 @@ async function getBattery(deviceId) {
3025
3039
  const battery = Array.from(new Uint8Array(batteryValue))[0];
3026
3040
  return battery;
3027
3041
  }
3028
- async function getFirmwareVersion$1(deviceId) {
3042
+ async function getFirmwareVersion$2(deviceId) {
3029
3043
  const msg = "*FWVER?";
3030
- return sendCommand(deviceId, msg, "FWV");
3044
+ return sendCommand(deviceId, msg);
3031
3045
  }
3032
3046
  async function vdaRequestSensor(deviceId) {
3033
3047
  const scanMsg = "*VDA_LF_SEND SID=A0 LID=1A";
@@ -3067,9 +3081,10 @@ async function vdaSendConfiguration(deviceId, configuration) {
3067
3081
  const scanMsg = `*VDA_LF_SEND SID=A0 LID=EA PAR=17 DATA=${configuration}${crc}`;
3068
3082
  return sendCommand(deviceId, scanMsg);
3069
3083
  }
3070
- async function sendCommand(deviceId, command, identifier = "VDA") {
3084
+ async function sendCommand(deviceId, command) {
3071
3085
  const message = `${command}\r
3072
3086
  `;
3087
+ const identifier = getIdentifier$1(message);
3073
3088
  const decimalArray = stringToDecimalArray(message);
3074
3089
  let result;
3075
3090
  try {
@@ -3078,7 +3093,7 @@ async function sendCommand(deviceId, command, identifier = "VDA") {
3078
3093
  flexiGaugeTpms.disconnect(deviceId, "lostConnection");
3079
3094
  throw error;
3080
3095
  }
3081
- return result.map((num) => String.fromCharCode(num)).join("");
3096
+ return String.fromCharCode(...result);
3082
3097
  }
3083
3098
  function processMessage(deviceId, payload) {
3084
3099
  promiseQueue.processMessage(deviceId, payload, getIdentifier$1, isComplete$1, isError$1);
@@ -3091,13 +3106,163 @@ function isError$1(message) {
3091
3106
  return false;
3092
3107
  }
3093
3108
  function getIdentifier$1(message) {
3094
- const messageString = message.map((num) => String.fromCharCode(num)).join("");
3095
- return messageString.slice(0, 3);
3109
+ const messageString = typeof message === "string" ? message : String.fromCharCode(...message);
3110
+ const [, commands] = removeEndLine(messageString).match(/\*?([^=|^?]+)/) || [];
3111
+ const [identifier, subIdentifier] = commands.split(" ") || [];
3112
+ return identifier === "TPMS" && subIdentifier ? `${identifier} ${subIdentifier}` : identifier;
3096
3113
  }
3097
3114
  function getReversedSensorId(sensorId) {
3098
3115
  return sensorId.match(/.{1,2}/g).reverse().join("");
3099
3116
  }
3100
3117
 
3118
+ const fgConfigPressureUnits = ["bar", "psi", "kpa"];
3119
+ const fgConfigTdUnits = ["mm", "thirtySecondOfInch"];
3120
+ const fgConfigNeedleLengths = [15, 30, 40, 100, 130];
3121
+ const fgConfigRegions = ["eu", "us"];
3122
+ const fgConfigPressureDisplay = ["measured", "compensated"];
3123
+ const fgConfigTemperatureUnits = ["fahrenheit", "celsius"];
3124
+ const configToJsonMapping = {
3125
+ ML: (v) => ({ menuLock: v === "1" }),
3126
+ PU: (v) => ({ pressureUnit: fgConfigPressureUnits[Number(v)] }),
3127
+ TU: (v) => ({ tdUnit: fgConfigTdUnits[Number(v)] }),
3128
+ NL: (v) => ({ needleLength: fgConfigNeedleLengths[Number(v)] }),
3129
+ BE: (v) => ({ beep: v === "1" }),
3130
+ RS: (v) => ({ region: fgConfigRegions[Number(v)] }),
3131
+ PS: (v) => ({ powerSave: Number(v) }),
3132
+ PD: (v) => ({ pressureDisplay: fgConfigPressureDisplay[Number(v)] }),
3133
+ FW: (v) => ({ fwUpdate: v === "1" }),
3134
+ TT: (v) => ({ temperatureUnit: fgConfigTemperatureUnits[Number(v)] })
3135
+ };
3136
+ const configFromJsonMapping = {
3137
+ menuLock: (v) => `ML=${v ? "1" : "0"}`,
3138
+ pressureUnit: (v) => `PU=${getIndex(fgConfigPressureUnits, v)}`,
3139
+ tdUnit: (v) => `TU=${getIndex(fgConfigTdUnits, v)}`,
3140
+ needleLength: (v) => `NL=${getIndex(fgConfigNeedleLengths, v)}`,
3141
+ beep: (v) => `BE=${v ? "1" : "0"}`,
3142
+ region: (v) => `RS=${getIndex(fgConfigRegions, v)}`,
3143
+ powerSave: (v) => `PS=${v.toString()}`,
3144
+ pressureDisplay: (v) => `PD=${getIndex(fgConfigPressureDisplay, v)}`,
3145
+ fwUpdate: (v) => `FW=${v ? "1" : "0"}`,
3146
+ temperatureUnit: (v) => `TT=${getIndex(fgConfigTemperatureUnits, v)}`
3147
+ };
3148
+ const fgTpmsConfigProtocols = [
3149
+ "pwmTirecheck",
3150
+ "vdaTirecheck",
3151
+ "pwmWabco",
3152
+ "vdaLdl",
3153
+ "vdaContinental",
3154
+ "vdaSchrader"
3155
+ ];
3156
+ const flexiGaugeTpmsServiceMapping = {
3157
+ getDefaultConfigJson() {
3158
+ return {
3159
+ menuLock: false,
3160
+ pressureUnit: "bar",
3161
+ tdUnit: "mm",
3162
+ needleLength: 40,
3163
+ beep: true,
3164
+ region: "eu",
3165
+ powerSave: 15,
3166
+ pressureDisplay: "measured",
3167
+ fwUpdate: false,
3168
+ temperatureUnit: "fahrenheit"
3169
+ };
3170
+ },
3171
+ getDefaultTpmsConfigJson() {
3172
+ return ___default.cloneDeep({
3173
+ protocols: fgTpmsConfigProtocols.map((id) => ({ id, time: 5 }))
3174
+ });
3175
+ },
3176
+ /**
3177
+ * @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`
3178
+ */
3179
+ getConfigJson(configString) {
3180
+ let config = this.getDefaultConfigJson();
3181
+ const parts = toolsSvc.removeEndLine(configString).split(" ").slice(1).map((v) => v.split("="));
3182
+ for (const [name, value] of parts) {
3183
+ const toJsonFn = configToJsonMapping[name];
3184
+ config = { ...config, ...toJsonFn(value) };
3185
+ }
3186
+ return config;
3187
+ },
3188
+ /**
3189
+ * @returns example: `ML=0 PU=0 TU=0 NL=2 BE=1 RS=0 PS=15 PD=0 FW=0 TT=0`
3190
+ */
3191
+ getConfig(configJson) {
3192
+ const configString = Object.entries(configJson).map(([key, value]) => {
3193
+ const fromJsonFn = configFromJsonMapping[key];
3194
+ return fromJsonFn(value);
3195
+ }).join(" ");
3196
+ return configString;
3197
+ },
3198
+ /**
3199
+ * @param configString example: `TPMS CONFIG ALG=0001020304050000 TIME=5050505050500000\r\n`
3200
+ *
3201
+ * - every protocol/time is 2 bytes
3202
+ * - we only support 6 protocols, rest is empty
3203
+ * - time is stored as n*100ms (`50` = 50x100ms = 5s)
3204
+ * - protocols can be duplicate when set in Fg Menu
3205
+ *
3206
+ * protocol codes:
3207
+ * - `00` - PWM Tirecheck - `pwmTirecheck`
3208
+ * - `01` - VDA Tirecheck - `vdaTirecheck`
3209
+ * - `02` - PWM WABCO - `pwmWabco`
3210
+ * - `03` - VDA LDL - `vdaLdl`
3211
+ * - `04` - VDA Continental - `vdaContinental`
3212
+ * - `05` - VDA Schrader - `vdaSchrader`
3213
+ */
3214
+ getTpmsConfigJson(configString) {
3215
+ const config = this.getDefaultTpmsConfigJson();
3216
+ const parts = toolsSvc.removeEndLine(configString).split(" ").slice(2).map((v) => {
3217
+ const [name, value] = v.split("=");
3218
+ if (name === "ALG") return ["protocols", getTpmsConfigProtocolList(value)];
3219
+ if (name === "TIME") return ["times", getTpmsConfigProtocolTimeList(value)];
3220
+ throw new Error(`Unknown Fg Tpms config part: ${name}`);
3221
+ });
3222
+ const pairs = ___default.fromPairs(parts);
3223
+ const zipped = ___default.zipObject(pairs.protocols, pairs.times);
3224
+ if (pairs.protocols.length) config.protocols = [];
3225
+ for (const [protocol, time] of Object.entries(zipped)) {
3226
+ config.protocols.push({ id: protocol, time: time / 10 });
3227
+ }
3228
+ if (config.protocols.length < 6) {
3229
+ const missingProtocols = fgTpmsConfigProtocols.filter((id) => !config.protocols.find((p) => p.id === id));
3230
+ for (const protocol of missingProtocols) {
3231
+ config.protocols.push({ id: protocol, time: 0 });
3232
+ }
3233
+ }
3234
+ return config;
3235
+ },
3236
+ /**
3237
+ * @returns example: `ALG=0001020304050000 TIME=5050505050500000`
3238
+ */
3239
+ getTpmsConfig(tpmsConfigJson) {
3240
+ const unzipped = tpmsConfigJson.protocols.reduce(
3241
+ (acc, { id, time }) => {
3242
+ acc.protocols.push(getIndex(fgTpmsConfigProtocols, id).padStart(2, "0"));
3243
+ if (time >= 10) throw new Error(`Fg Tpms config time value out of range: ${time}`);
3244
+ acc.times.push(
3245
+ Math.round(time * 10).toString().padStart(2, "0")
3246
+ );
3247
+ return acc;
3248
+ },
3249
+ { protocols: [], times: [] }
3250
+ );
3251
+ const protocols = unzipped.protocols.join("").padEnd(16, "0");
3252
+ const times = unzipped.times.join("").padEnd(16, "0");
3253
+ return `ALG=${protocols} TIME=${times}`;
3254
+ }
3255
+ };
3256
+ function getIndex(array, value) {
3257
+ return array.indexOf(value).toString();
3258
+ }
3259
+ function getTpmsConfigProtocolList(configString) {
3260
+ return configString.match(/(\d{2})/g)?.slice(0, 6).map((v) => fgTpmsConfigProtocols[Number.parseInt(v)]);
3261
+ }
3262
+ function getTpmsConfigProtocolTimeList(configString) {
3263
+ return configString.match(/(\d{2})/g)?.slice(0, 6).map((v) => Number.parseInt(v));
3264
+ }
3265
+
3101
3266
  let sensorReadings = [];
3102
3267
  const capabilities$1 = [
3103
3268
  {
@@ -3114,7 +3279,7 @@ const capabilities$1 = [
3114
3279
  {
3115
3280
  id: "tpms",
3116
3281
  processFn: processTpms,
3117
- regex: /^\*?TPMS.*/
3282
+ regex: /^\*?TPMS (ISON|DATA|ENDSCANNING).*/
3118
3283
  }
3119
3284
  ];
3120
3285
  const flexiGaugeTpmsService = {
@@ -3136,7 +3301,7 @@ const flexiGaugeTpmsService = {
3136
3301
  icon: "icon-flexigauge",
3137
3302
  processMessage(deviceId, message) {
3138
3303
  const numberArray = Array.from(new Uint8Array(message));
3139
- const stringFromBytes = String.fromCharCode.apply(null, numberArray).replace("\r\n", "");
3304
+ const stringFromBytes = removeEndLine(String.fromCharCode(...numberArray));
3140
3305
  for (const capability of capabilities$1) {
3141
3306
  if (capability.regex.test(stringFromBytes)) {
3142
3307
  return capability.processFn(deviceId, stringFromBytes);
@@ -3144,8 +3309,28 @@ const flexiGaugeTpmsService = {
3144
3309
  }
3145
3310
  flexiGaugeTpmsCommands.processMessage(deviceId, message);
3146
3311
  },
3312
+ async getConfig(deviceId) {
3313
+ const response = await flexiGaugeTpmsCommands.getConfig(deviceId);
3314
+ return flexiGaugeTpmsServiceMapping.getConfigJson(response);
3315
+ },
3316
+ async setConfig(deviceId, configJson) {
3317
+ const fw = await getFirmwareVersion$1(deviceId);
3318
+ if (fw < "1.4.4") throw new Error("Config change is not supported on this firmware version");
3319
+ const config = flexiGaugeTpmsServiceMapping.getConfig(configJson);
3320
+ await flexiGaugeTpmsCommands.setConfig(deviceId, config);
3321
+ },
3322
+ async getTpmsConfig(deviceId) {
3323
+ const response = await flexiGaugeTpmsCommands.getTpmsConfig(deviceId);
3324
+ return flexiGaugeTpmsServiceMapping.getTpmsConfigJson(response);
3325
+ },
3326
+ async setTpmsConfig(deviceId, configJson) {
3327
+ const fw = await getFirmwareVersion$1(deviceId);
3328
+ if (fw < "1.4.4") throw new Error("TPMS Config change is not supported on this firmware version");
3329
+ const config = flexiGaugeTpmsServiceMapping.getTpmsConfig(configJson);
3330
+ await flexiGaugeTpmsCommands.setTpmsConfig(deviceId, config);
3331
+ },
3147
3332
  setSensorDisplayId,
3148
- getFirmwareVersion
3333
+ getFirmwareVersion: getFirmwareVersion$1
3149
3334
  };
3150
3335
  function processTreadDepth(deviceId, value) {
3151
3336
  const treadDepth = value.match(/\d+/)?.[0];
@@ -3185,7 +3370,7 @@ function processTpms(deviceId, value) {
3185
3370
  }
3186
3371
  }
3187
3372
  async function setSensorDisplayId(deviceId, oldSensorId, newSensorId) {
3188
- const fw = await getFirmwareVersion(deviceId);
3373
+ const fw = await getFirmwareVersion$1(deviceId);
3189
3374
  if (fw < "1.4.4") throw new Error("Programming sensors is not supported on this firmware version");
3190
3375
  await findSensor(deviceId, oldSensorId);
3191
3376
  const seed = await getSeed(deviceId, oldSensorId);
@@ -3234,10 +3419,10 @@ async function vdaRepeat(fn) {
3234
3419
  }
3235
3420
  throw new Error("VDA Timeout");
3236
3421
  }
3237
- async function getFirmwareVersion(deviceId) {
3422
+ async function getFirmwareVersion$1(deviceId) {
3238
3423
  const response = await flexiGaugeTpmsCommands.getFirmwareVersion(deviceId);
3239
- const groupedValue = response.split(" ");
3240
- return groupedValue[1];
3424
+ const [, version] = removeEndLine(response).split(" ");
3425
+ return version;
3241
3426
  }
3242
3427
 
3243
3428
  const flexiGaugeTpms = {
@@ -3267,7 +3452,11 @@ const flexiGaugeTpms = {
3267
3452
  getFirmwareVersion: flexiGaugeTpmsService.getFirmwareVersion,
3268
3453
  startTpmsScan: flexiGaugeTpmsService.startTpmsScan,
3269
3454
  setSensorDisplayId: flexiGaugeTpmsService.setSensorDisplayId,
3270
- resetSensorDisplayId: (deviceId, sensorId) => flexiGaugeTpmsService.setSensorDisplayId(deviceId, sensorId, "00000000")
3455
+ resetSensorDisplayId: (deviceId, sensorId) => flexiGaugeTpmsService.setSensorDisplayId(deviceId, sensorId, "00000000"),
3456
+ getConfig: flexiGaugeTpmsService.getConfig,
3457
+ setConfig: flexiGaugeTpmsService.setConfig,
3458
+ getTpmsConfig: flexiGaugeTpmsService.getTpmsConfig,
3459
+ setTpmsConfig: flexiGaugeTpmsService.setTpmsConfig
3271
3460
  };
3272
3461
 
3273
3462
  const capabilities = [
@@ -3283,7 +3472,7 @@ const pressureStickService = {
3283
3472
  },
3284
3473
  processMessage(deviceId, message) {
3285
3474
  const numberArray = Array.from(new Uint8Array(message));
3286
- const stringFromBytes = String.fromCharCode.apply(null, numberArray).replace("\r\n", "");
3475
+ const stringFromBytes = removeEndLine(String.fromCharCode(...numberArray));
3287
3476
  for (const capability of capabilities) {
3288
3477
  if (capability.regex.test(stringFromBytes)) {
3289
3478
  return capability.processFn(deviceId, stringFromBytes);
@@ -3383,7 +3572,7 @@ const torqueWrenchCommands = {
3383
3572
  const formattedError = formatError(error);
3384
3573
  throw new Error(formattedError);
3385
3574
  }
3386
- return result.map((num) => String.fromCharCode(num)).join("");
3575
+ return String.fromCharCode(...result);
3387
3576
  },
3388
3577
  processMessage(deviceId, payload) {
3389
3578
  promiseQueue.processMessage(deviceId, payload, getIdentifier, isComplete, isError);
@@ -3399,7 +3588,7 @@ function isError(message) {
3399
3588
  }
3400
3589
  function getIdentifier(message) {
3401
3590
  if (message[0] === 123) return "200";
3402
- return message.slice(6, 9).map((num) => String.fromCharCode(num)).join("");
3591
+ return String.fromCharCode(...message.slice(6, 9));
3403
3592
  }
3404
3593
  function getChecksum(message) {
3405
3594
  let checksum = 0;
@@ -3411,7 +3600,7 @@ function getChecksum(message) {
3411
3600
  function formatError(error) {
3412
3601
  if (!error.cause) throw error;
3413
3602
  const message = error.cause.slice(6, 8);
3414
- const errorId = message.map((num) => String.fromCharCode(num)).join("");
3603
+ const errorId = String.fromCharCode(...message);
3415
3604
  return errors[errorId] || "Unknown error";
3416
3605
  }
3417
3606
 
@@ -3947,10 +4136,45 @@ const flexiGaugeTpmsSimulator = {
3947
4136
  resetSensorDisplayId(deviceId, sensorId) {
3948
4137
  return new Promise((resolve) => resolve());
3949
4138
  },
3950
- async getFirmwareVersion(deviceId) {
4139
+ async getConfig(deviceId) {
4140
+ const fg = getSimulatedFg(deviceId);
3951
4141
  await toolsSvc.delay(100);
3952
- return "9.9.9";
4142
+ const fwVersion = await getFirmwareVersion(deviceId);
4143
+ if (fwVersion >= "1.4.4") {
4144
+ return { ...fg.simulatorData.config };
4145
+ }
4146
+ throw new Error(`Getting Fg config is not supported on firmware version ${fwVersion}, min 1.4.4 required`);
3953
4147
  },
4148
+ async setConfig(deviceId, configJson) {
4149
+ const fg = getSimulatedFg(deviceId);
4150
+ await toolsSvc.delay(100);
4151
+ const fwVersion = await getFirmwareVersion(deviceId);
4152
+ if (fwVersion >= "1.4.4") {
4153
+ fg.simulatorData.config = { ...configJson };
4154
+ return;
4155
+ }
4156
+ throw new Error(`Setting Fg config is not supported on firmware version ${fwVersion}, min 1.4.4 required`);
4157
+ },
4158
+ async getTpmsConfig(deviceId) {
4159
+ const fg = getSimulatedFg(deviceId);
4160
+ await toolsSvc.delay(100);
4161
+ const fwVersion = await getFirmwareVersion(deviceId);
4162
+ if (fwVersion >= "1.4.4") {
4163
+ return ___default.cloneDeep(fg.simulatorData.tpmsConfig);
4164
+ }
4165
+ throw new Error(`Getting Fg TPMS config is not supported on firmware version ${fwVersion}, min 1.4.4 required`);
4166
+ },
4167
+ async setTpmsConfig(deviceId, tpmsConfig) {
4168
+ const fg = getSimulatedFg(deviceId);
4169
+ await toolsSvc.delay(100);
4170
+ const fwVersion = await getFirmwareVersion(deviceId);
4171
+ if (fwVersion >= "1.4.4") {
4172
+ fg.simulatorData.tpmsConfig = ___default.cloneDeep(tpmsConfig);
4173
+ return;
4174
+ }
4175
+ throw new Error(`Setting Fg TPMS config is not supported on firmware version ${fwVersion}, min 1.4.4 required`);
4176
+ },
4177
+ getFirmwareVersion,
3954
4178
  onButtonPress(callback) {
3955
4179
  },
3956
4180
  onTpms(callback) {
@@ -3958,6 +4182,11 @@ const flexiGaugeTpmsSimulator = {
3958
4182
  onTreadDepth(callback) {
3959
4183
  }
3960
4184
  };
4185
+ async function getFirmwareVersion(deviceId) {
4186
+ const fg = getSimulatedFg(deviceId);
4187
+ await toolsSvc.delay(100);
4188
+ return fg.simulatorData.fwVersion;
4189
+ }
3961
4190
  function getSimulatedFg(deviceId) {
3962
4191
  const simulatedDevice = store.simulatedDevices[deviceId];
3963
4192
  if (!simulatedDevice) throw new Error(`Simulated bridge was not found: ${deviceId}`);
@@ -3971,12 +4200,12 @@ function getSimulatedFgTemplate() {
3971
4200
  type: "flexiGaugeTpms",
3972
4201
  rssi: -50,
3973
4202
  simulatorData: {
4203
+ fwVersion: "1.4.4",
3974
4204
  battery: 45,
3975
4205
  events: {
3976
4206
  "fg:button": "L",
3977
4207
  "fg:tpms": {
3978
- // TODO: replace with realistic values
3979
- ID: "FFFF1212",
4208
+ ID: generateEAN(268431361, 268435455),
3980
4209
  Rssi: "-50",
3981
4210
  PC: 12,
3982
4211
  T: 15,
@@ -3985,10 +4214,22 @@ function getSimulatedFgTemplate() {
3985
4214
  S: "S"
3986
4215
  },
3987
4216
  "fg:treadDepth": 5.2
3988
- }
4217
+ },
4218
+ config: flexiGaugeTpmsServiceMapping.getDefaultConfigJson(),
4219
+ tpmsConfig: flexiGaugeTpmsServiceMapping.getDefaultTpmsConfigJson()
3989
4220
  }
3990
4221
  };
3991
4222
  }
4223
+ function generateEAN(min, max) {
4224
+ const serial = Math.round(min + Math.random() * (max - min)).toString(16);
4225
+ let p1 = 0;
4226
+ for (let i = 0; i < serial.length; i++) {
4227
+ p1 += Number.parseInt(serial[i], 16) * (i % 2 === 1 ? 1 : 3);
4228
+ }
4229
+ const p2 = Math.ceil(p1 / 16) * 16;
4230
+ const check = p2 - p1;
4231
+ return `${serial}${check.toString(16)}`.toUpperCase();
4232
+ }
3992
4233
 
3993
4234
  const deviceServicesAndSimulators = [
3994
4235
  [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
@@ -110,12 +110,16 @@ function decimalToHex(decimal, padStart = 2) {
110
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") {
@@ -2064,7 +2068,8 @@ const bridgeService = {
2064
2068
  getAutolearnStatuses,
2065
2069
  isRebootRequired,
2066
2070
  sendPinCommand,
2067
- setVehicleLayout
2071
+ setVehicleLayout,
2072
+ setAxleInfo
2068
2073
  };
2069
2074
  async function sendPinCommand(deviceId) {
2070
2075
  if (!canCommunicateWith(deviceId)) throw new Error("Bridge not connected");
@@ -2265,8 +2270,13 @@ async function getAxlesWithAutolearnSettings(deviceId) {
2265
2270
  }
2266
2271
  async function setAxleInfo(deviceId, tcVehicle) {
2267
2272
  if (!tcVehicle.axles?.length) throw new Error("Vehicle has no axles");
2268
- const spareTyres = tcVehicle.tcTyres?.filter((t) => String(t.mountedOn?.positionId).endsWith("0")) || [];
2269
- for (let axleIndex = 0; axleIndex < tcVehicle.axles.length; axleIndex++) {
2273
+ const tyresWithInfo = tcVehicle.tcTyres.map((tyre) => ({
2274
+ tcTpmsSensor: tyre.tcTpmsSensor,
2275
+ ...bridgeTools.getPositionInfo(tyre.mountedOn?.positionId || 0)
2276
+ }));
2277
+ const tyresWithSensors = tyresWithInfo.filter((tyre) => tyre.tcTpmsSensor && !tyre.isSpareTyre);
2278
+ const spareTyres = tyresWithInfo.filter((tyre) => tyre.isSpareTyre);
2279
+ for (let axleIndex = 1; axleIndex <= 16; axleIndex++) {
2270
2280
  const tyres = [
2271
2281
  "00000000",
2272
2282
  "00000000",
@@ -2289,30 +2299,14 @@ async function setAxleInfo(deviceId, tcVehicle) {
2289
2299
  "00000000",
2290
2300
  "00000000"
2291
2301
  ];
2292
- const axle = tcVehicle.axles[axleIndex];
2293
- const spareTyre = spareTyres[axleIndex];
2294
- if (spareTyre && spareTyre.tcTpmsSensor?.id) {
2295
- tyres[7] = bridgeTools.convertSensorIdForBridge(spareTyre.tcTpmsSensor?.id);
2296
- }
2297
- let axleTyres = tcVehicle.tcTyres?.filter(
2298
- (t) => t.mountedOn?.positionId ? bridgeTools.getPositionInfo(t.mountedOn?.positionId).axlePosition === axleIndex + 1 && spareTyre?.mountedOn?.positionId !== t.mountedOn?.positionId : false
2299
- ) || [];
2300
- axleTyres = axleTyres.sort((a, b) => (a.mountedOn?.positionId || 0) - (b.mountedOn?.positionId || 0));
2301
- for (const [tyreIndex, tyre] of axleTyres.entries()) {
2302
- const tyrePosition = tyre.mountedOn && bridgeTools.getPositionInfo(tyre.mountedOn.positionId).tyrePosition;
2303
- const realTyreIndex = tyrePosition ? tyrePosition - 1 : tyreIndex;
2304
- const sensorId = tyre.tcTpmsSensor?.id;
2305
- if (!sensorId) continue;
2306
- if (axle.isSpare) continue;
2307
- const isTwinTyre = axle.tyresCount === 4;
2308
- let bridgeTyreIndex = 0;
2309
- if (isTwinTyre && realTyreIndex === 0) bridgeTyreIndex = 5;
2310
- if (isTwinTyre && realTyreIndex === 1 || !isTwinTyre && realTyreIndex === 0) bridgeTyreIndex = 6;
2311
- if (isTwinTyre && realTyreIndex === 3) bridgeTyreIndex = 9;
2312
- if (isTwinTyre && realTyreIndex === 2 || !isTwinTyre && realTyreIndex === 1) bridgeTyreIndex = 8;
2313
- tyres[bridgeTyreIndex] = bridgeTools.convertSensorIdForBridge(sensorId);
2302
+ const axleTyres = tyresWithSensors.filter((tyre) => tyre.axlePosition === axleIndex);
2303
+ const spareTyre = spareTyres[axleIndex - 1];
2304
+ if (!axleTyres.length && !spareTyre) continue;
2305
+ for (const tyre of axleTyres) {
2306
+ const bridgeIndex = getBridgeIndexFromPositionId(tyre.positionId, 7);
2307
+ tyres[bridgeIndex] = tyre.tcTpmsSensor.id;
2314
2308
  }
2315
- if (!_.inRange(axleIndex, 0, 16)) return;
2309
+ if (spareTyre && spareTyre.tcTpmsSensor) tyres[7] = spareTyre.tcTpmsSensor.id;
2316
2310
  const numberArray = tyres.map((x) => x.match(/.{2}/g)?.reverse()).flat().map((n) => n ? Number.parseInt(n, 16) : 0);
2317
2311
  await bridgeCommands.setAxleInfo(deviceId, axleIndex, numberArray);
2318
2312
  }
@@ -2839,7 +2833,7 @@ const flexiGaugeTpmsService$1 = {
2839
2833
  icon: "icon-flexigauge",
2840
2834
  processMessage(deviceId, message) {
2841
2835
  const numberArray = Array.from(new Uint8Array(message));
2842
- const stringFromBytes = String.fromCharCode.apply(null, numberArray).replace("\r\n", "");
2836
+ const stringFromBytes = removeEndLine(String.fromCharCode(...numberArray));
2843
2837
  for (const capability of capabilities$2) {
2844
2838
  if (capability.regex.test(stringFromBytes)) {
2845
2839
  return capability.processFn(deviceId, stringFromBytes);
@@ -2912,8 +2906,8 @@ const promiseQueue = {
2912
2906
  chunks.push(payload.slice(i, i + mtu));
2913
2907
  }
2914
2908
  for (const chunk of chunks) {
2915
- const convertedChunk = new Uint8Array(chunk).buffer;
2916
- bluetooth.write(deviceId, communication.serviceId, communication.characteristicId, convertedChunk);
2909
+ const convertedChunk = new Uint8Array(chunk);
2910
+ bluetooth.write(deviceId, communication.serviceId, communication.characteristicId, convertedChunk.buffer);
2917
2911
  }
2918
2912
  });
2919
2913
  return withTimeout(promise, 5e3, `Command timed out ${deviceResponseIdentifier[deviceId]}, ${deviceId}`);
@@ -2997,8 +2991,28 @@ const flexiGaugeTpmsCommands = {
2997
2991
  vdaRequestCommandsAccess,
2998
2992
  vdaRequestWriteAccess,
2999
2993
  processMessage,
3000
- getFirmwareVersion: getFirmwareVersion$1
2994
+ getFirmwareVersion: getFirmwareVersion$2,
2995
+ getConfig,
2996
+ setConfig,
2997
+ getTpmsConfig,
2998
+ setTpmsConfig
3001
2999
  };
3000
+ async function getConfig(deviceId) {
3001
+ const msg = "*CONFIG?";
3002
+ return sendCommand(deviceId, msg);
3003
+ }
3004
+ async function setConfig(deviceId, config) {
3005
+ const msg = `*CONFIG ${config}`;
3006
+ return sendCommand(deviceId, msg);
3007
+ }
3008
+ async function getTpmsConfig(deviceId) {
3009
+ const msg = "*TPMS CONFIG?";
3010
+ return sendCommand(deviceId, msg);
3011
+ }
3012
+ async function setTpmsConfig(deviceId, config) {
3013
+ const msg = `*TPMS CONFIG ${config}`;
3014
+ return sendCommand(deviceId, msg);
3015
+ }
3002
3016
  async function startTpmsScan(deviceId) {
3003
3017
  if (!canCommunicateWith(deviceId)) throw new Error("Flexi Gauge not connected");
3004
3018
  const scanMsg = stringToArrayBuffer("*TPMS ON TIME=10\r\n");
@@ -3018,9 +3032,9 @@ async function getBattery(deviceId) {
3018
3032
  const battery = Array.from(new Uint8Array(batteryValue))[0];
3019
3033
  return battery;
3020
3034
  }
3021
- async function getFirmwareVersion$1(deviceId) {
3035
+ async function getFirmwareVersion$2(deviceId) {
3022
3036
  const msg = "*FWVER?";
3023
- return sendCommand(deviceId, msg, "FWV");
3037
+ return sendCommand(deviceId, msg);
3024
3038
  }
3025
3039
  async function vdaRequestSensor(deviceId) {
3026
3040
  const scanMsg = "*VDA_LF_SEND SID=A0 LID=1A";
@@ -3060,9 +3074,10 @@ async function vdaSendConfiguration(deviceId, configuration) {
3060
3074
  const scanMsg = `*VDA_LF_SEND SID=A0 LID=EA PAR=17 DATA=${configuration}${crc}`;
3061
3075
  return sendCommand(deviceId, scanMsg);
3062
3076
  }
3063
- async function sendCommand(deviceId, command, identifier = "VDA") {
3077
+ async function sendCommand(deviceId, command) {
3064
3078
  const message = `${command}\r
3065
3079
  `;
3080
+ const identifier = getIdentifier$1(message);
3066
3081
  const decimalArray = stringToDecimalArray(message);
3067
3082
  let result;
3068
3083
  try {
@@ -3071,7 +3086,7 @@ async function sendCommand(deviceId, command, identifier = "VDA") {
3071
3086
  flexiGaugeTpms.disconnect(deviceId, "lostConnection");
3072
3087
  throw error;
3073
3088
  }
3074
- return result.map((num) => String.fromCharCode(num)).join("");
3089
+ return String.fromCharCode(...result);
3075
3090
  }
3076
3091
  function processMessage(deviceId, payload) {
3077
3092
  promiseQueue.processMessage(deviceId, payload, getIdentifier$1, isComplete$1, isError$1);
@@ -3084,13 +3099,163 @@ function isError$1(message) {
3084
3099
  return false;
3085
3100
  }
3086
3101
  function getIdentifier$1(message) {
3087
- const messageString = message.map((num) => String.fromCharCode(num)).join("");
3088
- return messageString.slice(0, 3);
3102
+ const messageString = typeof message === "string" ? message : String.fromCharCode(...message);
3103
+ const [, commands] = removeEndLine(messageString).match(/\*?([^=|^?]+)/) || [];
3104
+ const [identifier, subIdentifier] = commands.split(" ") || [];
3105
+ return identifier === "TPMS" && subIdentifier ? `${identifier} ${subIdentifier}` : identifier;
3089
3106
  }
3090
3107
  function getReversedSensorId(sensorId) {
3091
3108
  return sensorId.match(/.{1,2}/g).reverse().join("");
3092
3109
  }
3093
3110
 
3111
+ const fgConfigPressureUnits = ["bar", "psi", "kpa"];
3112
+ const fgConfigTdUnits = ["mm", "thirtySecondOfInch"];
3113
+ const fgConfigNeedleLengths = [15, 30, 40, 100, 130];
3114
+ const fgConfigRegions = ["eu", "us"];
3115
+ const fgConfigPressureDisplay = ["measured", "compensated"];
3116
+ const fgConfigTemperatureUnits = ["fahrenheit", "celsius"];
3117
+ const configToJsonMapping = {
3118
+ ML: (v) => ({ menuLock: v === "1" }),
3119
+ PU: (v) => ({ pressureUnit: fgConfigPressureUnits[Number(v)] }),
3120
+ TU: (v) => ({ tdUnit: fgConfigTdUnits[Number(v)] }),
3121
+ NL: (v) => ({ needleLength: fgConfigNeedleLengths[Number(v)] }),
3122
+ BE: (v) => ({ beep: v === "1" }),
3123
+ RS: (v) => ({ region: fgConfigRegions[Number(v)] }),
3124
+ PS: (v) => ({ powerSave: Number(v) }),
3125
+ PD: (v) => ({ pressureDisplay: fgConfigPressureDisplay[Number(v)] }),
3126
+ FW: (v) => ({ fwUpdate: v === "1" }),
3127
+ TT: (v) => ({ temperatureUnit: fgConfigTemperatureUnits[Number(v)] })
3128
+ };
3129
+ const configFromJsonMapping = {
3130
+ menuLock: (v) => `ML=${v ? "1" : "0"}`,
3131
+ pressureUnit: (v) => `PU=${getIndex(fgConfigPressureUnits, v)}`,
3132
+ tdUnit: (v) => `TU=${getIndex(fgConfigTdUnits, v)}`,
3133
+ needleLength: (v) => `NL=${getIndex(fgConfigNeedleLengths, v)}`,
3134
+ beep: (v) => `BE=${v ? "1" : "0"}`,
3135
+ region: (v) => `RS=${getIndex(fgConfigRegions, v)}`,
3136
+ powerSave: (v) => `PS=${v.toString()}`,
3137
+ pressureDisplay: (v) => `PD=${getIndex(fgConfigPressureDisplay, v)}`,
3138
+ fwUpdate: (v) => `FW=${v ? "1" : "0"}`,
3139
+ temperatureUnit: (v) => `TT=${getIndex(fgConfigTemperatureUnits, v)}`
3140
+ };
3141
+ const fgTpmsConfigProtocols = [
3142
+ "pwmTirecheck",
3143
+ "vdaTirecheck",
3144
+ "pwmWabco",
3145
+ "vdaLdl",
3146
+ "vdaContinental",
3147
+ "vdaSchrader"
3148
+ ];
3149
+ const flexiGaugeTpmsServiceMapping = {
3150
+ getDefaultConfigJson() {
3151
+ return {
3152
+ menuLock: false,
3153
+ pressureUnit: "bar",
3154
+ tdUnit: "mm",
3155
+ needleLength: 40,
3156
+ beep: true,
3157
+ region: "eu",
3158
+ powerSave: 15,
3159
+ pressureDisplay: "measured",
3160
+ fwUpdate: false,
3161
+ temperatureUnit: "fahrenheit"
3162
+ };
3163
+ },
3164
+ getDefaultTpmsConfigJson() {
3165
+ return _.cloneDeep({
3166
+ protocols: fgTpmsConfigProtocols.map((id) => ({ id, time: 5 }))
3167
+ });
3168
+ },
3169
+ /**
3170
+ * @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`
3171
+ */
3172
+ getConfigJson(configString) {
3173
+ let config = this.getDefaultConfigJson();
3174
+ const parts = toolsSvc.removeEndLine(configString).split(" ").slice(1).map((v) => v.split("="));
3175
+ for (const [name, value] of parts) {
3176
+ const toJsonFn = configToJsonMapping[name];
3177
+ config = { ...config, ...toJsonFn(value) };
3178
+ }
3179
+ return config;
3180
+ },
3181
+ /**
3182
+ * @returns example: `ML=0 PU=0 TU=0 NL=2 BE=1 RS=0 PS=15 PD=0 FW=0 TT=0`
3183
+ */
3184
+ getConfig(configJson) {
3185
+ const configString = Object.entries(configJson).map(([key, value]) => {
3186
+ const fromJsonFn = configFromJsonMapping[key];
3187
+ return fromJsonFn(value);
3188
+ }).join(" ");
3189
+ return configString;
3190
+ },
3191
+ /**
3192
+ * @param configString example: `TPMS CONFIG ALG=0001020304050000 TIME=5050505050500000\r\n`
3193
+ *
3194
+ * - every protocol/time is 2 bytes
3195
+ * - we only support 6 protocols, rest is empty
3196
+ * - time is stored as n*100ms (`50` = 50x100ms = 5s)
3197
+ * - protocols can be duplicate when set in Fg Menu
3198
+ *
3199
+ * protocol codes:
3200
+ * - `00` - PWM Tirecheck - `pwmTirecheck`
3201
+ * - `01` - VDA Tirecheck - `vdaTirecheck`
3202
+ * - `02` - PWM WABCO - `pwmWabco`
3203
+ * - `03` - VDA LDL - `vdaLdl`
3204
+ * - `04` - VDA Continental - `vdaContinental`
3205
+ * - `05` - VDA Schrader - `vdaSchrader`
3206
+ */
3207
+ getTpmsConfigJson(configString) {
3208
+ const config = this.getDefaultTpmsConfigJson();
3209
+ const parts = toolsSvc.removeEndLine(configString).split(" ").slice(2).map((v) => {
3210
+ const [name, value] = v.split("=");
3211
+ if (name === "ALG") return ["protocols", getTpmsConfigProtocolList(value)];
3212
+ if (name === "TIME") return ["times", getTpmsConfigProtocolTimeList(value)];
3213
+ throw new Error(`Unknown Fg Tpms config part: ${name}`);
3214
+ });
3215
+ const pairs = _.fromPairs(parts);
3216
+ const zipped = _.zipObject(pairs.protocols, pairs.times);
3217
+ if (pairs.protocols.length) config.protocols = [];
3218
+ for (const [protocol, time] of Object.entries(zipped)) {
3219
+ config.protocols.push({ id: protocol, time: time / 10 });
3220
+ }
3221
+ if (config.protocols.length < 6) {
3222
+ const missingProtocols = fgTpmsConfigProtocols.filter((id) => !config.protocols.find((p) => p.id === id));
3223
+ for (const protocol of missingProtocols) {
3224
+ config.protocols.push({ id: protocol, time: 0 });
3225
+ }
3226
+ }
3227
+ return config;
3228
+ },
3229
+ /**
3230
+ * @returns example: `ALG=0001020304050000 TIME=5050505050500000`
3231
+ */
3232
+ getTpmsConfig(tpmsConfigJson) {
3233
+ const unzipped = tpmsConfigJson.protocols.reduce(
3234
+ (acc, { id, time }) => {
3235
+ acc.protocols.push(getIndex(fgTpmsConfigProtocols, id).padStart(2, "0"));
3236
+ if (time >= 10) throw new Error(`Fg Tpms config time value out of range: ${time}`);
3237
+ acc.times.push(
3238
+ Math.round(time * 10).toString().padStart(2, "0")
3239
+ );
3240
+ return acc;
3241
+ },
3242
+ { protocols: [], times: [] }
3243
+ );
3244
+ const protocols = unzipped.protocols.join("").padEnd(16, "0");
3245
+ const times = unzipped.times.join("").padEnd(16, "0");
3246
+ return `ALG=${protocols} TIME=${times}`;
3247
+ }
3248
+ };
3249
+ function getIndex(array, value) {
3250
+ return array.indexOf(value).toString();
3251
+ }
3252
+ function getTpmsConfigProtocolList(configString) {
3253
+ return configString.match(/(\d{2})/g)?.slice(0, 6).map((v) => fgTpmsConfigProtocols[Number.parseInt(v)]);
3254
+ }
3255
+ function getTpmsConfigProtocolTimeList(configString) {
3256
+ return configString.match(/(\d{2})/g)?.slice(0, 6).map((v) => Number.parseInt(v));
3257
+ }
3258
+
3094
3259
  let sensorReadings = [];
3095
3260
  const capabilities$1 = [
3096
3261
  {
@@ -3107,7 +3272,7 @@ const capabilities$1 = [
3107
3272
  {
3108
3273
  id: "tpms",
3109
3274
  processFn: processTpms,
3110
- regex: /^\*?TPMS.*/
3275
+ regex: /^\*?TPMS (ISON|DATA|ENDSCANNING).*/
3111
3276
  }
3112
3277
  ];
3113
3278
  const flexiGaugeTpmsService = {
@@ -3129,7 +3294,7 @@ const flexiGaugeTpmsService = {
3129
3294
  icon: "icon-flexigauge",
3130
3295
  processMessage(deviceId, message) {
3131
3296
  const numberArray = Array.from(new Uint8Array(message));
3132
- const stringFromBytes = String.fromCharCode.apply(null, numberArray).replace("\r\n", "");
3297
+ const stringFromBytes = removeEndLine(String.fromCharCode(...numberArray));
3133
3298
  for (const capability of capabilities$1) {
3134
3299
  if (capability.regex.test(stringFromBytes)) {
3135
3300
  return capability.processFn(deviceId, stringFromBytes);
@@ -3137,8 +3302,28 @@ const flexiGaugeTpmsService = {
3137
3302
  }
3138
3303
  flexiGaugeTpmsCommands.processMessage(deviceId, message);
3139
3304
  },
3305
+ async getConfig(deviceId) {
3306
+ const response = await flexiGaugeTpmsCommands.getConfig(deviceId);
3307
+ return flexiGaugeTpmsServiceMapping.getConfigJson(response);
3308
+ },
3309
+ async setConfig(deviceId, configJson) {
3310
+ const fw = await getFirmwareVersion$1(deviceId);
3311
+ if (fw < "1.4.4") throw new Error("Config change is not supported on this firmware version");
3312
+ const config = flexiGaugeTpmsServiceMapping.getConfig(configJson);
3313
+ await flexiGaugeTpmsCommands.setConfig(deviceId, config);
3314
+ },
3315
+ async getTpmsConfig(deviceId) {
3316
+ const response = await flexiGaugeTpmsCommands.getTpmsConfig(deviceId);
3317
+ return flexiGaugeTpmsServiceMapping.getTpmsConfigJson(response);
3318
+ },
3319
+ async setTpmsConfig(deviceId, configJson) {
3320
+ const fw = await getFirmwareVersion$1(deviceId);
3321
+ if (fw < "1.4.4") throw new Error("TPMS Config change is not supported on this firmware version");
3322
+ const config = flexiGaugeTpmsServiceMapping.getTpmsConfig(configJson);
3323
+ await flexiGaugeTpmsCommands.setTpmsConfig(deviceId, config);
3324
+ },
3140
3325
  setSensorDisplayId,
3141
- getFirmwareVersion
3326
+ getFirmwareVersion: getFirmwareVersion$1
3142
3327
  };
3143
3328
  function processTreadDepth(deviceId, value) {
3144
3329
  const treadDepth = value.match(/\d+/)?.[0];
@@ -3178,7 +3363,7 @@ function processTpms(deviceId, value) {
3178
3363
  }
3179
3364
  }
3180
3365
  async function setSensorDisplayId(deviceId, oldSensorId, newSensorId) {
3181
- const fw = await getFirmwareVersion(deviceId);
3366
+ const fw = await getFirmwareVersion$1(deviceId);
3182
3367
  if (fw < "1.4.4") throw new Error("Programming sensors is not supported on this firmware version");
3183
3368
  await findSensor(deviceId, oldSensorId);
3184
3369
  const seed = await getSeed(deviceId, oldSensorId);
@@ -3227,10 +3412,10 @@ async function vdaRepeat(fn) {
3227
3412
  }
3228
3413
  throw new Error("VDA Timeout");
3229
3414
  }
3230
- async function getFirmwareVersion(deviceId) {
3415
+ async function getFirmwareVersion$1(deviceId) {
3231
3416
  const response = await flexiGaugeTpmsCommands.getFirmwareVersion(deviceId);
3232
- const groupedValue = response.split(" ");
3233
- return groupedValue[1];
3417
+ const [, version] = removeEndLine(response).split(" ");
3418
+ return version;
3234
3419
  }
3235
3420
 
3236
3421
  const flexiGaugeTpms = {
@@ -3260,7 +3445,11 @@ const flexiGaugeTpms = {
3260
3445
  getFirmwareVersion: flexiGaugeTpmsService.getFirmwareVersion,
3261
3446
  startTpmsScan: flexiGaugeTpmsService.startTpmsScan,
3262
3447
  setSensorDisplayId: flexiGaugeTpmsService.setSensorDisplayId,
3263
- resetSensorDisplayId: (deviceId, sensorId) => flexiGaugeTpmsService.setSensorDisplayId(deviceId, sensorId, "00000000")
3448
+ resetSensorDisplayId: (deviceId, sensorId) => flexiGaugeTpmsService.setSensorDisplayId(deviceId, sensorId, "00000000"),
3449
+ getConfig: flexiGaugeTpmsService.getConfig,
3450
+ setConfig: flexiGaugeTpmsService.setConfig,
3451
+ getTpmsConfig: flexiGaugeTpmsService.getTpmsConfig,
3452
+ setTpmsConfig: flexiGaugeTpmsService.setTpmsConfig
3264
3453
  };
3265
3454
 
3266
3455
  const capabilities = [
@@ -3276,7 +3465,7 @@ const pressureStickService = {
3276
3465
  },
3277
3466
  processMessage(deviceId, message) {
3278
3467
  const numberArray = Array.from(new Uint8Array(message));
3279
- const stringFromBytes = String.fromCharCode.apply(null, numberArray).replace("\r\n", "");
3468
+ const stringFromBytes = removeEndLine(String.fromCharCode(...numberArray));
3280
3469
  for (const capability of capabilities) {
3281
3470
  if (capability.regex.test(stringFromBytes)) {
3282
3471
  return capability.processFn(deviceId, stringFromBytes);
@@ -3376,7 +3565,7 @@ const torqueWrenchCommands = {
3376
3565
  const formattedError = formatError(error);
3377
3566
  throw new Error(formattedError);
3378
3567
  }
3379
- return result.map((num) => String.fromCharCode(num)).join("");
3568
+ return String.fromCharCode(...result);
3380
3569
  },
3381
3570
  processMessage(deviceId, payload) {
3382
3571
  promiseQueue.processMessage(deviceId, payload, getIdentifier, isComplete, isError);
@@ -3392,7 +3581,7 @@ function isError(message) {
3392
3581
  }
3393
3582
  function getIdentifier(message) {
3394
3583
  if (message[0] === 123) return "200";
3395
- return message.slice(6, 9).map((num) => String.fromCharCode(num)).join("");
3584
+ return String.fromCharCode(...message.slice(6, 9));
3396
3585
  }
3397
3586
  function getChecksum(message) {
3398
3587
  let checksum = 0;
@@ -3404,7 +3593,7 @@ function getChecksum(message) {
3404
3593
  function formatError(error) {
3405
3594
  if (!error.cause) throw error;
3406
3595
  const message = error.cause.slice(6, 8);
3407
- const errorId = message.map((num) => String.fromCharCode(num)).join("");
3596
+ const errorId = String.fromCharCode(...message);
3408
3597
  return errors[errorId] || "Unknown error";
3409
3598
  }
3410
3599
 
@@ -3940,10 +4129,45 @@ const flexiGaugeTpmsSimulator = {
3940
4129
  resetSensorDisplayId(deviceId, sensorId) {
3941
4130
  return new Promise((resolve) => resolve());
3942
4131
  },
3943
- async getFirmwareVersion(deviceId) {
4132
+ async getConfig(deviceId) {
4133
+ const fg = getSimulatedFg(deviceId);
3944
4134
  await toolsSvc.delay(100);
3945
- return "9.9.9";
4135
+ const fwVersion = await getFirmwareVersion(deviceId);
4136
+ if (fwVersion >= "1.4.4") {
4137
+ return { ...fg.simulatorData.config };
4138
+ }
4139
+ throw new Error(`Getting Fg config is not supported on firmware version ${fwVersion}, min 1.4.4 required`);
3946
4140
  },
4141
+ async setConfig(deviceId, configJson) {
4142
+ const fg = getSimulatedFg(deviceId);
4143
+ await toolsSvc.delay(100);
4144
+ const fwVersion = await getFirmwareVersion(deviceId);
4145
+ if (fwVersion >= "1.4.4") {
4146
+ fg.simulatorData.config = { ...configJson };
4147
+ return;
4148
+ }
4149
+ throw new Error(`Setting Fg config is not supported on firmware version ${fwVersion}, min 1.4.4 required`);
4150
+ },
4151
+ async getTpmsConfig(deviceId) {
4152
+ const fg = getSimulatedFg(deviceId);
4153
+ await toolsSvc.delay(100);
4154
+ const fwVersion = await getFirmwareVersion(deviceId);
4155
+ if (fwVersion >= "1.4.4") {
4156
+ return _.cloneDeep(fg.simulatorData.tpmsConfig);
4157
+ }
4158
+ throw new Error(`Getting Fg TPMS config is not supported on firmware version ${fwVersion}, min 1.4.4 required`);
4159
+ },
4160
+ async setTpmsConfig(deviceId, tpmsConfig) {
4161
+ const fg = getSimulatedFg(deviceId);
4162
+ await toolsSvc.delay(100);
4163
+ const fwVersion = await getFirmwareVersion(deviceId);
4164
+ if (fwVersion >= "1.4.4") {
4165
+ fg.simulatorData.tpmsConfig = _.cloneDeep(tpmsConfig);
4166
+ return;
4167
+ }
4168
+ throw new Error(`Setting Fg TPMS config is not supported on firmware version ${fwVersion}, min 1.4.4 required`);
4169
+ },
4170
+ getFirmwareVersion,
3947
4171
  onButtonPress(callback) {
3948
4172
  },
3949
4173
  onTpms(callback) {
@@ -3951,6 +4175,11 @@ const flexiGaugeTpmsSimulator = {
3951
4175
  onTreadDepth(callback) {
3952
4176
  }
3953
4177
  };
4178
+ async function getFirmwareVersion(deviceId) {
4179
+ const fg = getSimulatedFg(deviceId);
4180
+ await toolsSvc.delay(100);
4181
+ return fg.simulatorData.fwVersion;
4182
+ }
3954
4183
  function getSimulatedFg(deviceId) {
3955
4184
  const simulatedDevice = store.simulatedDevices[deviceId];
3956
4185
  if (!simulatedDevice) throw new Error(`Simulated bridge was not found: ${deviceId}`);
@@ -3964,12 +4193,12 @@ function getSimulatedFgTemplate() {
3964
4193
  type: "flexiGaugeTpms",
3965
4194
  rssi: -50,
3966
4195
  simulatorData: {
4196
+ fwVersion: "1.4.4",
3967
4197
  battery: 45,
3968
4198
  events: {
3969
4199
  "fg:button": "L",
3970
4200
  "fg:tpms": {
3971
- // TODO: replace with realistic values
3972
- ID: "FFFF1212",
4201
+ ID: generateEAN(268431361, 268435455),
3973
4202
  Rssi: "-50",
3974
4203
  PC: 12,
3975
4204
  T: 15,
@@ -3978,10 +4207,22 @@ function getSimulatedFgTemplate() {
3978
4207
  S: "S"
3979
4208
  },
3980
4209
  "fg:treadDepth": 5.2
3981
- }
4210
+ },
4211
+ config: flexiGaugeTpmsServiceMapping.getDefaultConfigJson(),
4212
+ tpmsConfig: flexiGaugeTpmsServiceMapping.getDefaultTpmsConfigJson()
3982
4213
  }
3983
4214
  };
3984
4215
  }
4216
+ function generateEAN(min, max) {
4217
+ const serial = Math.round(min + Math.random() * (max - min)).toString(16);
4218
+ let p1 = 0;
4219
+ for (let i = 0; i < serial.length; i++) {
4220
+ p1 += Number.parseInt(serial[i], 16) * (i % 2 === 1 ? 1 : 3);
4221
+ }
4222
+ const p2 = Math.ceil(p1 / 16) * 16;
4223
+ const check = p2 - p1;
4224
+ return `${serial}${check.toString(16)}`.toUpperCase();
4225
+ }
3985
4226
 
3986
4227
  const deviceServicesAndSimulators = [
3987
4228
  [bridge, bridgeSimulator],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tirecheck-device-sdk",
3
- "version": "0.2.45",
3
+ "version": "0.2.47",
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",