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 +441 -43
- package/dist/index.d.cts +59 -3
- package/dist/index.d.mts +59 -3
- package/dist/index.d.ts +59 -3
- package/dist/index.mjs +441 -43
- package/package.json +1 -1
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
|
|