tirecheck-device-sdk 0.2.21 → 0.2.23

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
@@ -47,6 +47,8 @@ const store = {
47
47
  // undefined => connecting => connected => paired => disconnecting => undefined
48
48
  /** some bridge commands require bridge reboot to be completed */
49
49
  bridgeRebootRequired: {},
50
+ /** Torque wrench properties, about device settings, mainly used for unit conversion */
51
+ torqueWrenchProperties: {},
50
52
  //** Ios uses generated device Id, bridges send mac address in advertising so internaly we always use mac address but when real device id is needed we check mapping table for it */
51
53
  deviceIdMapingTable: {},
52
54
  /** Used to change device state in store, also notifies app via calback. Every undefined state should have its reason so that app can handle it accordingly */
@@ -104,6 +106,10 @@ function stringToArrayBuffer(string) {
104
106
  }
105
107
  return array.buffer;
106
108
  }
109
+ function decimalToHex(decimal, padStart = 2) {
110
+ const hex = decimal.toString(16);
111
+ return hex.padStart(padStart, "0");
112
+ }
107
113
  const toolsSvc = {
108
114
  delay,
109
115
  setIntervalImmediate,
@@ -518,8 +524,26 @@ const deviceMeta = {
518
524
  },
519
525
  getDeviceInfoFromAdvertising: bridgeOtaAdvertisingParser.getDeviceInfoFromAdvertising
520
526
  },
527
+ // flexiGauge: {
528
+ // nameRegex: /^Flexi.*v.*/,
529
+ // communication: {
530
+ // serviceId: '4880c12c-fdcb-4077-8920-a450d7f9b907',
531
+ // characteristicId: 'fec26ec4-6d71-4442-9f81-55bc21d658d6',
532
+ // },
533
+ // battery: {
534
+ // serviceId: '180f',
535
+ // characteristicId: '2a19',
536
+ // },
537
+ // getDeviceInfoFromAdvertising: (device: PeripheralData) => {
538
+ // const bleDevice: BleDevice = {
539
+ // ...device,
540
+ // type: 'flexiGauge',
541
+ // }
542
+ // return bleDevice
543
+ // },
544
+ // },
521
545
  flexiGaugeTpms: {
522
- nameRegex: /^Flexi.*/,
546
+ nameRegex: /^Flexi.*TPMS.*/,
523
547
  communication: {
524
548
  serviceId: "4880c12c-fdcb-4077-8920-a450d7f9b907",
525
549
  characteristicId: "fec26ec4-6d71-4442-9f81-55bc21d658d6"
@@ -534,9 +558,7 @@ const deviceMeta = {
534
558
  type: "flexiGaugeTpms"
535
559
  };
536
560
  return bleDevice;
537
- },
538
- reconnect: true
539
- // Do we need it here?
561
+ }
540
562
  },
541
563
  pressureStick: {
542
564
  nameRegex: /Pressure Stick.*/,
@@ -551,6 +573,42 @@ const deviceMeta = {
551
573
  };
552
574
  return bleDevice;
553
575
  }
576
+ },
577
+ // ateq: {
578
+ // nameRegex: /ATEQ.*/,
579
+ // communication: {
580
+ // serviceId: 'a002',
581
+ // characteristicId: 'c305',
582
+ // },
583
+ // indicate: {
584
+ // serviceId: 'a002',
585
+ // characteristicId: 'c306',
586
+ // },
587
+ // getDeviceInfoFromAdvertising: (device: PeripheralData) => {
588
+ // const bleDevice: BleDevice = {
589
+ // ...device,
590
+ // type: 'ateq',
591
+ // }
592
+ // return bleDevice
593
+ // },
594
+ // },
595
+ torqueWrench: {
596
+ nameRegex: /^\d+(lbft|NM)-\d+$/i,
597
+ communication: {
598
+ serviceId: "49535343-fe7d-4ae5-8fa9-9fafd205e455",
599
+ characteristicId: "49535343-1e4d-4bd9-ba61-23c647249616"
600
+ },
601
+ battery: {
602
+ serviceId: "180f",
603
+ characteristicId: "2a19"
604
+ },
605
+ getDeviceInfoFromAdvertising: (device) => {
606
+ const bleDevice = {
607
+ ...device,
608
+ type: "torqueWrench"
609
+ };
610
+ return bleDevice;
611
+ }
554
612
  }
555
613
  };
556
614
 
@@ -1524,26 +1582,26 @@ const bridgeSecurity = {
1524
1582
  };
1525
1583
 
1526
1584
  const bridgeMeta = deviceMeta.bridge;
1527
- const devicePromiseQueue = {};
1528
- const deviceCurrentResolve = {};
1529
- const deviceCurrentReject = {};
1530
- const deviceResponseIdentifier = {};
1585
+ const devicePromiseQueue$1 = {};
1586
+ const deviceCurrentResolve$1 = {};
1587
+ const deviceCurrentReject$1 = {};
1588
+ const deviceResponseIdentifier$1 = {};
1531
1589
  const promiseQueue = {
1532
1590
  clearQueue(deviceId, message) {
1533
- if (deviceCurrentReject[deviceId]) {
1534
- deviceCurrentReject[deviceId](new Error(message ?? "Stopped sending commands"));
1591
+ if (deviceCurrentReject$1[deviceId]) {
1592
+ deviceCurrentReject$1[deviceId](new Error(message ?? "Stopped sending commands"));
1535
1593
  }
1536
- devicePromiseQueue[deviceId] = Promise.resolve();
1537
- deviceResponseIdentifier[deviceId] = [];
1594
+ devicePromiseQueue$1[deviceId] = Promise.resolve();
1595
+ deviceResponseIdentifier$1[deviceId] = [];
1538
1596
  },
1539
1597
  async enqueue(device, payload) {
1540
- if (devicePromiseQueue[device.id] === void 0) devicePromiseQueue[device.id] = Promise.resolve();
1541
- devicePromiseQueue[device.id] = devicePromiseQueue[device.id].then(() => {
1598
+ if (devicePromiseQueue$1[device.id] === void 0) devicePromiseQueue$1[device.id] = Promise.resolve();
1599
+ devicePromiseQueue$1[device.id] = devicePromiseQueue$1[device.id].then(() => {
1542
1600
  const promise = new Promise((resolve, reject) => {
1543
- deviceCurrentResolve[device.id] = resolve;
1544
- deviceCurrentReject[device.id] = reject;
1545
- const isKeepAlive = payload[3] === commandIds.keepAlive;
1546
- deviceResponseIdentifier[device.id] = [isKeepAlive ? 126 : 0, payload[4]];
1601
+ deviceCurrentResolve$1[device.id] = resolve;
1602
+ deviceCurrentReject$1[device.id] = reject;
1603
+ const isKeepAlive = payload[3] === commandIds$1.keepAlive;
1604
+ deviceResponseIdentifier$1[device.id] = [isKeepAlive ? 126 : 0, payload[4]];
1547
1605
  const signedData = bridgeSecurity.getSignedCommand(device, payload);
1548
1606
  if (!toolsSvc.canCommunicateWith(device.id)) return reject(new Error("Bridge not connected"));
1549
1607
  if (signedData.length > 110) {
@@ -1569,21 +1627,21 @@ const promiseQueue = {
1569
1627
  );
1570
1628
  }
1571
1629
  });
1572
- return withTimeout(promise, 5e3, `Command timed out ${deviceResponseIdentifier[device.id]}, ${device.id}`);
1630
+ return withTimeout(promise, 5e3, `Command timed out ${deviceResponseIdentifier$1[device.id]}, ${device.id}`);
1573
1631
  });
1574
- return devicePromiseQueue[device.id];
1632
+ return devicePromiseQueue$1[device.id];
1575
1633
  },
1576
1634
  async processMessage(deviceId, payload) {
1577
1635
  const numberArray = Array.from(new Uint8Array(payload));
1578
1636
  if (numberArray[3] === 127) {
1579
1637
  console.error(numberArray);
1580
- return deviceCurrentReject[deviceId](new Error(`Command not succesful: ${numberArray[4]}`));
1638
+ return deviceCurrentReject$1[deviceId](new Error(`Command not succesful: ${numberArray[4]}`));
1581
1639
  }
1582
1640
  if ([226, 81].includes(numberArray[3]) && numberArray[4] && toolsSvc.canCommunicateWith(deviceId)) {
1583
1641
  store.bridgeRebootRequired[deviceId] = true;
1584
1642
  }
1585
- if ((!deviceResponseIdentifier[deviceId][0] || numberArray[3] === deviceResponseIdentifier[deviceId][0]) && (!deviceResponseIdentifier[deviceId][1] || numberArray[4] === deviceResponseIdentifier[deviceId][1])) {
1586
- return deviceCurrentResolve[deviceId](numberArray);
1643
+ if ((!deviceResponseIdentifier$1[deviceId][0] || numberArray[3] === deviceResponseIdentifier$1[deviceId][0]) && (!deviceResponseIdentifier$1[deviceId][1] || numberArray[4] === deviceResponseIdentifier$1[deviceId][1])) {
1644
+ return deviceCurrentResolve$1[deviceId](numberArray);
1587
1645
  }
1588
1646
  console.warn("message from the device not belonging to the pending promise: ", numberArray);
1589
1647
  }
@@ -1600,7 +1658,7 @@ const messageTypeIds = {
1600
1658
  command: 0,
1601
1659
  response: 1
1602
1660
  };
1603
- const commandIds = {
1661
+ const commandIds$1 = {
1604
1662
  readData: 34,
1605
1663
  writeData: 46,
1606
1664
  keepAlive: 62,
@@ -1649,7 +1707,7 @@ const subCommandIds = {
1649
1707
  autolearnIdStatus: 176,
1650
1708
  autolearnUnknownSensors: 192
1651
1709
  };
1652
- ___default.invert(commandIds);
1710
+ ___default.invert(commandIds$1);
1653
1711
  ___default.invert(subCommandIds);
1654
1712
  const keepAliveTimer = {};
1655
1713
  const bridgeCommands = {
@@ -1660,7 +1718,7 @@ const bridgeCommands = {
1660
1718
  },
1661
1719
  async setAxlesPressure(deviceId, data) {
1662
1720
  const deviceData = bridgeTools.getBridgeFromStore(deviceId);
1663
- await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.pressurePerAxle, data);
1721
+ await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.pressurePerAxle, data);
1664
1722
  },
1665
1723
  async setVehicleLayout(deviceId, structurizedPayload) {
1666
1724
  const deviceData = bridgeTools.getBridgeFromStore(deviceId);
@@ -1669,7 +1727,7 @@ const bridgeCommands = {
1669
1727
  structurizedPayload,
1670
1728
  deviceData.advertisingData.fwVersion
1671
1729
  );
1672
- await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.vehicleLayout, payload);
1730
+ await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.vehicleLayout, payload);
1673
1731
  },
1674
1732
  async getCustomerCANSettings(deviceId) {
1675
1733
  const deviceData = bridgeTools.getBridgeFromStore(deviceId);
@@ -1722,18 +1780,18 @@ const bridgeCommands = {
1722
1780
  return { ...structurized, isFactory: result.isFactory };
1723
1781
  },
1724
1782
  async sendKeepAliveCommand(device) {
1725
- return this.promisify(device, [...this.getCommandHeader(device), 2, commandIds.keepAlive, 0]);
1783
+ return this.promisify(device, [...this.getCommandHeader(device), 2, commandIds$1.keepAlive, 0]);
1726
1784
  },
1727
1785
  async sendOtaRequest(deviceId) {
1728
1786
  const deviceData = bridgeTools.getBridgeFromStore(deviceId);
1729
- const command = [commandIds.otaRequest, 0];
1787
+ const command = [commandIds$1.otaRequest, 0];
1730
1788
  const result = await this.promisify(deviceData, [...this.getCommandHeader(deviceData), command.length, ...command]);
1731
1789
  return result;
1732
1790
  },
1733
1791
  async sendPinCommand(deviceId) {
1734
1792
  const deviceData = await bridgeTools.getBridgeFromStore(deviceId);
1735
1793
  const pin = await bridgeSecurity.getPin(deviceId);
1736
- return this.promisify(deviceData, [...this.getCommandHeader(deviceData), 18, commandIds.pin, 0, ...pin]);
1794
+ return this.promisify(deviceData, [...this.getCommandHeader(deviceData), 18, commandIds$1.pin, 0, ...pin]);
1737
1795
  },
1738
1796
  async setBridgeToRestart(deviceId) {
1739
1797
  if (store.bridgeRebootRequired[deviceId]) return;
@@ -1742,7 +1800,7 @@ const bridgeCommands = {
1742
1800
  await this.promisify(deviceData, [
1743
1801
  ...this.getCommandHeader(deviceData),
1744
1802
  2,
1745
- useNewCommand ? commandIds.ecuReset : commandIds.reboot,
1803
+ useNewCommand ? commandIds$1.ecuReset : commandIds$1.reboot,
1746
1804
  useNewCommand ? subCommandIds.ecuResetSubCommand : subCommandIds.rebootSubCommand
1747
1805
  ]);
1748
1806
  },
@@ -1753,7 +1811,7 @@ const bridgeCommands = {
1753
1811
  structurizedPayload,
1754
1812
  deviceData.advertisingData.fwVersion
1755
1813
  );
1756
- return await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.customerCanSettings, payload);
1814
+ return await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.customerCanSettings, payload);
1757
1815
  },
1758
1816
  async setWorkshopCANSettings(deviceId, structurizedPayload) {
1759
1817
  const deviceData = bridgeTools.getBridgeFromStore(deviceId);
@@ -1762,7 +1820,7 @@ const bridgeCommands = {
1762
1820
  structurizedPayload,
1763
1821
  deviceData.advertisingData.fwVersion
1764
1822
  );
1765
- return await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.workshopCanSettings, payload);
1823
+ return await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.workshopCanSettings, payload);
1766
1824
  },
1767
1825
  async setCustomerPressureThresholds(deviceId, structurizedPayload) {
1768
1826
  const deviceData = bridgeTools.getBridgeFromStore(deviceId);
@@ -1771,7 +1829,7 @@ const bridgeCommands = {
1771
1829
  structurizedPayload,
1772
1830
  deviceData.advertisingData.fwVersion
1773
1831
  );
1774
- return await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.customerPressureThresholds, payload);
1832
+ return await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.customerPressureThresholds, payload);
1775
1833
  },
1776
1834
  async setCustomerTemperatureThresholds(deviceId, structurizedPayload) {
1777
1835
  const deviceData = bridgeTools.getBridgeFromStore(deviceId);
@@ -1782,7 +1840,7 @@ const bridgeCommands = {
1782
1840
  );
1783
1841
  return await this.writeCommand(
1784
1842
  deviceData,
1785
- commandIds.writeData,
1843
+ commandIds$1.writeData,
1786
1844
  subCommandIds.customerTemperatureThresholds,
1787
1845
  payload
1788
1846
  );
@@ -1794,7 +1852,7 @@ const bridgeCommands = {
1794
1852
  structurizedPayload,
1795
1853
  deviceData.advertisingData.fwVersion
1796
1854
  );
1797
- return await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.customerImbalanceThresholds, payload);
1855
+ return await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.customerImbalanceThresholds, payload);
1798
1856
  },
1799
1857
  async getAutolearnSettings(deviceId) {
1800
1858
  const deviceData = bridgeTools.getBridgeFromStore(deviceId);
@@ -1823,7 +1881,7 @@ const bridgeCommands = {
1823
1881
  structurizedPayload,
1824
1882
  deviceData.advertisingData.fwVersion
1825
1883
  );
1826
- return await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.autolearnSettings, payload);
1884
+ return await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.autolearnSettings, payload);
1827
1885
  },
1828
1886
  async setAutolearnIdStatus(deviceId, structurizedPayload) {
1829
1887
  const deviceData = bridgeTools.getBridgeFromStore(deviceId);
@@ -1832,7 +1890,7 @@ const bridgeCommands = {
1832
1890
  structurizedPayload,
1833
1891
  deviceData.advertisingData.fwVersion
1834
1892
  );
1835
- return await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.autolearnIdStatus, payload);
1893
+ return await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.autolearnIdStatus, payload);
1836
1894
  },
1837
1895
  async getAutolearnUnknownSensors(device) {
1838
1896
  const result = await this.readCommand(device, subCommandIds.autolearnUnknownSensors);
@@ -1853,7 +1911,7 @@ const bridgeCommands = {
1853
1911
  // move logic to bridge svc
1854
1912
  async setAxleInfo(deviceId, axleIndex, data) {
1855
1913
  const deviceData = bridgeTools.getBridgeFromStore(deviceId);
1856
- await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.idsPerWheel(axleIndex), data);
1914
+ await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.idsPerWheel(axleIndex), data);
1857
1915
  },
1858
1916
  async getAxlesPressure(deviceId) {
1859
1917
  const deviceData = bridgeTools.getBridgeFromStore(deviceId);
@@ -1877,7 +1935,7 @@ const bridgeCommands = {
1877
1935
  structurizedPayload,
1878
1936
  deviceData.advertisingData.fwVersion
1879
1937
  );
1880
- return await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.pressurePerAxle, payload);
1938
+ return await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.pressurePerAxle, payload);
1881
1939
  },
1882
1940
  // // async setPressureThresholds(device: BleBridge, rules: any) {
1883
1941
  // // // https://tirecheck.atlassian.net/wiki/spaces/HWPRG/pages/6547767302/Technical+Design+Document+BLE+CAN+Bridge+Krone#Example.1
@@ -1920,7 +1978,7 @@ const bridgeCommands = {
1920
1978
  }
1921
1979
  const result = await this.writeCommand(
1922
1980
  deviceData,
1923
- commandIds.sensorMeasurement,
1981
+ commandIds$1.sensorMeasurement,
1924
1982
  subCommandIds.sensorMeasurementPerWheel(axlePosition, tyrePosition, isTwinTyre, isSpare),
1925
1983
  []
1926
1984
  );
@@ -1931,7 +1989,7 @@ const bridgeCommands = {
1931
1989
  const result = await this.promisify(device, [
1932
1990
  ...this.getCommandHeader(device),
1933
1991
  commandLength,
1934
- commandIds.readData,
1992
+ commandIds$1.readData,
1935
1993
  subCommandId
1936
1994
  ]);
1937
1995
  const data = result.slice(19, result.length - 8);
@@ -2896,6 +2954,342 @@ const pressureStick = {
2896
2954
  onPressure: pressureStickService.onPressure
2897
2955
  };
2898
2956
 
2957
+ const devicePromiseQueue = {};
2958
+ const deviceCurrentResolve = {};
2959
+ const deviceCurrentReject = {};
2960
+ const deviceResponseIdentifier = {};
2961
+ const deviceCurrentPartialMessage = {};
2962
+ const torqueWrenchPromiseQueue = {
2963
+ clearQueue(deviceId, message) {
2964
+ if (deviceCurrentReject[deviceId]) {
2965
+ deviceCurrentReject[deviceId](new Error(message ?? "Stopped sending commands"));
2966
+ }
2967
+ devicePromiseQueue[deviceId] = Promise.resolve();
2968
+ deviceResponseIdentifier[deviceId] = void 0;
2969
+ },
2970
+ async enqueue(deviceId, communication, payload, responseIdentifier, mtu = 20) {
2971
+ if (devicePromiseQueue[deviceId] === void 0) devicePromiseQueue[deviceId] = Promise.resolve();
2972
+ devicePromiseQueue[deviceId] = devicePromiseQueue[deviceId].then(() => {
2973
+ const promise = new Promise((resolve, reject) => {
2974
+ deviceCurrentResolve[deviceId] = resolve;
2975
+ deviceCurrentReject[deviceId] = reject;
2976
+ deviceResponseIdentifier[deviceId] = responseIdentifier;
2977
+ deviceCurrentPartialMessage[deviceId] = [];
2978
+ if (!toolsSvc.canCommunicateWith(deviceId)) return reject(new Error("Torque wrench not connected"));
2979
+ const chunks = [];
2980
+ for (let i = 0; i < payload.length; i += mtu) {
2981
+ chunks.push(payload.slice(i, i + mtu));
2982
+ }
2983
+ for (const chunk of chunks) {
2984
+ const convertedChunk = new Uint8Array(chunk).buffer;
2985
+ bluetooth.write(deviceId, communication.serviceId, communication.characteristicId, convertedChunk);
2986
+ }
2987
+ });
2988
+ return withTimeout(promise, 5e3, `Command timed out ${deviceResponseIdentifier[deviceId]}, ${deviceId}`);
2989
+ });
2990
+ return devicePromiseQueue[deviceId];
2991
+ },
2992
+ async processMessage(deviceId, payload, getIdentifier, isComplete, isError) {
2993
+ const numberArray = Array.from(new Uint8Array(payload));
2994
+ if (!deviceCurrentPartialMessage[deviceId]) deviceCurrentPartialMessage[deviceId] = [];
2995
+ deviceCurrentPartialMessage[deviceId] = ___default.concat(deviceCurrentPartialMessage[deviceId], numberArray);
2996
+ if (!isComplete(deviceCurrentPartialMessage[deviceId])) {
2997
+ return;
2998
+ }
2999
+ if (isError(deviceCurrentPartialMessage[deviceId])) {
3000
+ return deviceCurrentReject[deviceId](
3001
+ new Error("Error response", { cause: deviceCurrentPartialMessage[deviceId] })
3002
+ );
3003
+ }
3004
+ const identifier = getIdentifier(deviceCurrentPartialMessage[deviceId]);
3005
+ if (deviceResponseIdentifier[deviceId] === identifier) {
3006
+ deviceCurrentResolve[deviceId](deviceCurrentPartialMessage[deviceId]);
3007
+ }
3008
+ }
3009
+ };
3010
+
3011
+ const commandStart = "$9";
3012
+ const commandEnd = "*";
3013
+ const commandIds = {
3014
+ error: "004",
3015
+ acknowledge: "005",
3016
+ commTest: "100",
3017
+ getProperties: "120",
3018
+ startJob: "204",
3019
+ stopJob: "206",
3020
+ getNumberOfReadings: "224",
3021
+ getReading: "200",
3022
+ // Can only be called once for each reading.
3023
+ getReadingAgain: "202",
3024
+ getBattery: "150",
3025
+ getTime: "209",
3026
+ setTime: "208"
3027
+ };
3028
+ const errors = {
3029
+ "01": "Bad string",
3030
+ "02": "Bad checksum",
3031
+ "03": "Unknown command",
3032
+ "04": "No device present for command to act on",
3033
+ "05": "Invalid sample speed",
3034
+ "06": "Torque module offset difference bigger than 25%",
3035
+ "07": "Torque module gain outside 0.9 to 1.1",
3036
+ "08": "No RF properties",
3037
+ "09": "No reply from RF",
3038
+ "0A": "RF device already paired on this device",
3039
+ "0C": "Invalid frequency",
3040
+ "0D": "Invalid LED selection",
3041
+ "0F": "Transducer preloaded",
3042
+ "10": "No more readings",
3043
+ "11": "Job already loaded",
3044
+ "12": "No trace stored",
3045
+ "13": "Wrong transducers selected for Multi Start Mode",
3046
+ "14": "No short trace stored",
3047
+ "15": "Job finished",
3048
+ "16": "Missing time and date",
3049
+ "17": "Bad units for wrench type",
3050
+ "18": "Battery low"
3051
+ };
3052
+ const twMeta = deviceMeta.torqueWrench;
3053
+ const torqueWrenchCommands = {
3054
+ async sendCommand(deviceId, command, params) {
3055
+ const commandId = commandIds[command];
3056
+ let message = `${commandStart}${commandId}`;
3057
+ if (params?.length) {
3058
+ message += `,${params.join(",")}`;
3059
+ }
3060
+ message += commandEnd;
3061
+ const crc = getChecksum(message);
3062
+ message += `${crc}\r`;
3063
+ const array = new Uint8Array(message.length);
3064
+ for (let i = 0, l = message.length; i < l; i++) {
3065
+ array[i] = message.charCodeAt(i);
3066
+ }
3067
+ const decimalArray = Array.from(array);
3068
+ let result;
3069
+ try {
3070
+ result = await torqueWrenchPromiseQueue.enqueue(deviceId, twMeta.communication, decimalArray, commandIds[command]);
3071
+ } catch (error) {
3072
+ const formattedError = formatError(error);
3073
+ throw new Error(formattedError);
3074
+ }
3075
+ return result.map((num) => String.fromCharCode(num)).join("");
3076
+ },
3077
+ processMessage(deviceId, payload) {
3078
+ torqueWrenchPromiseQueue.processMessage(deviceId, payload, getIdentifier, isComplete, isError);
3079
+ }
3080
+ };
3081
+ function isComplete(message) {
3082
+ const completeReading = message[0] === 123 && message.at(-1) === 13;
3083
+ const completeCommand = message[0] === 36 && message.at(-1) === 13;
3084
+ return completeReading || completeCommand;
3085
+ }
3086
+ function isError(message) {
3087
+ return message[4] === 52;
3088
+ }
3089
+ function getIdentifier(message) {
3090
+ if (message[0] === 123) return "200";
3091
+ return message.slice(6, 9).map((num) => String.fromCharCode(num)).join("");
3092
+ }
3093
+ function getChecksum(message) {
3094
+ let checksum = 0;
3095
+ for (const ch of message) {
3096
+ checksum ^= ch.charCodeAt(0);
3097
+ }
3098
+ return decimalToHex(checksum).toUpperCase();
3099
+ }
3100
+ function formatError(error) {
3101
+ if (!error.cause) throw new Error(error);
3102
+ const message = error.cause.slice(6, 8);
3103
+ const errorId = message.map((num) => String.fromCharCode(num)).join("");
3104
+ return errors[errorId] || "Unknown error";
3105
+ }
3106
+
3107
+ let jobInterval = null;
3108
+ const torqueWrenchService = {
3109
+ onReading(callback) {
3110
+ simulatorSvc.registerEvent("tw:reading", callback);
3111
+ },
3112
+ async getProperties(deviceId) {
3113
+ const result = {
3114
+ serialNumber: "",
3115
+ span: 0,
3116
+ calibrationDate: "",
3117
+ ppr: 0,
3118
+ units: "Nm",
3119
+ threshold: 10
3120
+ };
3121
+ const message = await torqueWrenchCommands.sendCommand(deviceId, "getProperties");
3122
+ const params = getMessageParams(message);
3123
+ if (params[4] === "3") result.units = "Nm";
3124
+ else if (params[4] === "7") result.units = "lb-ft";
3125
+ result.serialNumber = params[0];
3126
+ result.span = Number.parseInt(params[1]);
3127
+ if (result.units === "lb-ft") result.span = Math.floor(result.span * 0.738);
3128
+ result.calibrationDate = params[2];
3129
+ result.ppr = Number.parseInt(params[3]);
3130
+ return result;
3131
+ },
3132
+ async startJob(deviceId, params) {
3133
+ await this.stopJob(deviceId);
3134
+ const { units, span, ppr, threshold } = store.torqueWrenchProperties[deviceId];
3135
+ const { torqueMin, torqueMax, angleMin, angleMax, direction, jobTimeout } = params;
3136
+ const msgParams = {
3137
+ id: "01",
3138
+ nuts: decimalToHex(params.nuts),
3139
+ mode: units === "lb-ft" ? "20" : "1",
3140
+ // Peak measurement mode
3141
+ cycle: "7",
3142
+ // 10 seconds cycle (probably for measurements - not sure what it does exactly, not specified in docs)
3143
+ control: torqueMin != null || torqueMax != null ? "0" : "1",
3144
+ direction: direction === "counter-clockwise" ? "1" : "0",
3145
+ minTorqueThreshold: torqueToAdcParam(threshold, span, units),
3146
+ torqueMin: torqueToAdcParam(torqueMin ?? 0, span, units),
3147
+ torqueMax: torqueToAdcParam(torqueMax ?? -1, span, units),
3148
+ clickThreshold: torqueToAdcParam(threshold, span, units),
3149
+ // Probably not used in our case (for this specified mode).
3150
+ angleMin: angleToPulsesParam(angleMin ?? 0, ppr),
3151
+ angleMax: angleToPulsesParam(angleMax ?? -1, ppr),
3152
+ frequency: "0542"
3153
+ // No idea
3154
+ };
3155
+ const paramsString = Object.values(msgParams);
3156
+ await torqueWrenchCommands.sendCommand(deviceId, "startJob", paramsString);
3157
+ jobInterval = setInterval(async () => {
3158
+ const numberOfReading = await this.getNumberOfReadings(deviceId);
3159
+ if (numberOfReading.count > 0) this.getReading(deviceId);
3160
+ }, 2e3);
3161
+ if (jobTimeout) {
3162
+ await new Promise(
3163
+ (resolve) => setTimeout(() => {
3164
+ this.stopJob(deviceId);
3165
+ resolve("");
3166
+ }, jobTimeout * 1e3)
3167
+ );
3168
+ }
3169
+ },
3170
+ async stopJob(deviceId) {
3171
+ clearInterval(jobInterval);
3172
+ return torqueWrenchCommands.sendCommand(deviceId, "stopJob");
3173
+ },
3174
+ async getNumberOfReadings(deviceId) {
3175
+ const message = await torqueWrenchCommands.sendCommand(deviceId, "getNumberOfReadings");
3176
+ const params = getMessageParams(message);
3177
+ return { count: Number(params[0]), jobId: params[1] };
3178
+ },
3179
+ async getReading(deviceId) {
3180
+ const reading = await torqueWrenchCommands.sendCommand(deviceId, "getReading");
3181
+ const properties = {
3182
+ jobId: reading.slice(2, 4),
3183
+ nut: reading.slice(4, 6),
3184
+ torqueAdc: reading.slice(6, 10),
3185
+ anglePulses: reading.slice(10, 14),
3186
+ duration: reading.slice(14, 18)
3187
+ };
3188
+ const torque = adcToTorque(
3189
+ properties.torqueAdc,
3190
+ store.torqueWrenchProperties[deviceId].span,
3191
+ store.torqueWrenchProperties[deviceId].units
3192
+ );
3193
+ const angle = pulsesToAngle(properties.anglePulses, store.torqueWrenchProperties[deviceId].ppr);
3194
+ const formattedReading = {
3195
+ jobId: Number.parseInt(properties.jobId, 16),
3196
+ nut: Number.parseInt(properties.nut, 16),
3197
+ torque,
3198
+ angle,
3199
+ duration: Number.parseInt(properties.duration, 16) / 1e3
3200
+ };
3201
+ simulatorSvc.triggerEvent("tw:reading", deviceId, formattedReading);
3202
+ },
3203
+ // getReadingAgain(deviceId: string) {
3204
+ // return torqueWrenchCommands.sendCommand(deviceId, 'getNumberOfReadings')
3205
+ // },
3206
+ async getBattery(deviceId) {
3207
+ const message = await torqueWrenchCommands.sendCommand(deviceId, "getBattery");
3208
+ const params = getMessageParams(message);
3209
+ return Number(params[0]);
3210
+ },
3211
+ async getTime(deviceId) {
3212
+ const message = await torqueWrenchCommands.sendCommand(deviceId, "getTime");
3213
+ const match = message.match(/209,([^*]*)\*/);
3214
+ console.log("\u{1F680} ~ getTime ~ match:", match);
3215
+ if (!match[1]) throw new Error("Invalid time response");
3216
+ const hh = match[1].substring(0, 2);
3217
+ const mm = match[1].substring(2, 4);
3218
+ const ss = match[1].substring(4, 6);
3219
+ const dd = match[1].substring(6, 8);
3220
+ const MM = match[1].substring(8, 10);
3221
+ const yy = match[1].substring(10, 12);
3222
+ const fullYear = `20${yy}`;
3223
+ return /* @__PURE__ */ new Date(`${fullYear}-${MM}-${dd}T${hh}:${mm}:${ss}Z`);
3224
+ },
3225
+ setTime(deviceId, date) {
3226
+ const hours = String(date.getHours()).padStart(2, "0");
3227
+ const minutes = String(date.getMinutes()).padStart(2, "0");
3228
+ const seconds = String(date.getSeconds()).padStart(2, "0");
3229
+ const day = String(date.getDate()).padStart(2, "0");
3230
+ const month = String(date.getMonth() + 1).padStart(2, "0");
3231
+ const year = String(date.getFullYear()).slice(-2);
3232
+ const params = [hours, minutes, seconds, day, month, year];
3233
+ return torqueWrenchCommands.sendCommand(deviceId, "setTime", params);
3234
+ }
3235
+ };
3236
+ function torqueToAdcParam(value, span, deviceUnits) {
3237
+ if (value < 0) return "FFFF";
3238
+ if (deviceUnits !== "Nm") value = value * 0.738;
3239
+ const adc = Math.round(value / span * 16384);
3240
+ return decimalToHex(adc, 4).toUpperCase();
3241
+ }
3242
+ function angleToPulsesParam(value, ppr) {
3243
+ if (value < 0) return "FFFF";
3244
+ const pulses = Math.round(value * ppr / 90);
3245
+ return decimalToHex(pulses, 4).toUpperCase();
3246
+ }
3247
+ function getMessageParams(message) {
3248
+ return message.match(/^\$[^,]+,[^,]+,(.*)\*/)?.[1].split(",") || [];
3249
+ }
3250
+ function adcToTorque(value, span, units) {
3251
+ const torque = Number.parseInt(value, 16) * span / 16384;
3252
+ if (units !== "Nm") return torque / 0.738;
3253
+ return torque;
3254
+ }
3255
+ function pulsesToAngle(value, ppr) {
3256
+ return Number.parseInt(value, 16) * 90 / ppr;
3257
+ }
3258
+
3259
+ const torqueWrench = {
3260
+ async connect(deviceId) {
3261
+ const twMeta = deviceMeta.torqueWrench;
3262
+ await bluetooth.connect(deviceId, this.disconnect);
3263
+ await ble.startNotification(
3264
+ deviceId,
3265
+ twMeta.communication.serviceId,
3266
+ twMeta.communication.characteristicId,
3267
+ (notification) => {
3268
+ torqueWrenchCommands.processMessage(deviceId, notification);
3269
+ },
3270
+ (error) => console.warn("ble.startNotification error", error)
3271
+ );
3272
+ const properties = await torqueWrenchService.getProperties(deviceId);
3273
+ store.torqueWrenchProperties[deviceId] = properties;
3274
+ store.setState(deviceId, "paired");
3275
+ },
3276
+ async disconnect(deviceId, reason) {
3277
+ store.setState(deviceId, "disconnecting");
3278
+ await torqueWrenchService.stopJob(deviceId);
3279
+ await bluetooth.disconnect(deviceId);
3280
+ store.setState(deviceId, void 0, reason ?? "manualDisconnection");
3281
+ },
3282
+ getProperties: torqueWrenchService.getProperties,
3283
+ setTime: torqueWrenchService.setTime,
3284
+ startJob: torqueWrenchService.startJob,
3285
+ stopJob: torqueWrenchService.stopJob,
3286
+ getNumberOfReadings: torqueWrenchService.getNumberOfReadings,
3287
+ getReading: torqueWrenchService.getReading,
3288
+ getBattery: torqueWrenchService.getBattery,
3289
+ getTime: torqueWrenchService.getTime,
3290
+ onReading: torqueWrenchService.onReading
3291
+ };
3292
+
2899
3293
  const bridgeSimulator = {
2900
3294
  isRebootRequired(deviceId) {
2901
3295
  return store.bridgeRebootRequired[deviceId];
@@ -3496,10 +3890,14 @@ function createTirecheckDeviceSdk(platform, bleImplementation, securityKeys) {
3496
3890
  bridgeOta,
3497
3891
  /** Methods for working with Tirecheck TPMS FlexiGauge */
3498
3892
  flexiGaugeTpms,
3893
+ // flexiGauge,
3499
3894
  /** Methods for working with Tirecheck Pressure Stick */
3500
3895
  pressureStick,
3896
+ // ateq,
3501
3897
  /** Allows simulating devices without actually using bluetooth */
3502
- simulator
3898
+ simulator,
3899
+ /** Methods for working with Tirecheck Torque Wrench */
3900
+ torqueWrench
3503
3901
  };
3504
3902
  }
3505
3903