tirecheck-device-sdk 0.2.2 → 0.2.22
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 +385 -39
- package/dist/index.d.cts +17 -0
- package/dist/index.d.mts +17 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.mjs +385 -39
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -104,6 +104,10 @@ function stringToArrayBuffer(string) {
|
|
|
104
104
|
}
|
|
105
105
|
return array.buffer;
|
|
106
106
|
}
|
|
107
|
+
function decimalToHex(decimal, padStart = 2) {
|
|
108
|
+
const hex = decimal.toString(16);
|
|
109
|
+
return hex.padStart(padStart, "0");
|
|
110
|
+
}
|
|
107
111
|
const toolsSvc = {
|
|
108
112
|
delay,
|
|
109
113
|
setIntervalImmediate,
|
|
@@ -1524,26 +1528,26 @@ const bridgeSecurity = {
|
|
|
1524
1528
|
};
|
|
1525
1529
|
|
|
1526
1530
|
const bridgeMeta = deviceMeta.bridge;
|
|
1527
|
-
const devicePromiseQueue = {};
|
|
1528
|
-
const deviceCurrentResolve = {};
|
|
1529
|
-
const deviceCurrentReject = {};
|
|
1530
|
-
const deviceResponseIdentifier = {};
|
|
1531
|
+
const devicePromiseQueue$1 = {};
|
|
1532
|
+
const deviceCurrentResolve$1 = {};
|
|
1533
|
+
const deviceCurrentReject$1 = {};
|
|
1534
|
+
const deviceResponseIdentifier$1 = {};
|
|
1531
1535
|
const promiseQueue = {
|
|
1532
1536
|
clearQueue(deviceId, message) {
|
|
1533
|
-
if (deviceCurrentReject[deviceId]) {
|
|
1534
|
-
deviceCurrentReject[deviceId](new Error(message ?? "Stopped sending commands"));
|
|
1537
|
+
if (deviceCurrentReject$1[deviceId]) {
|
|
1538
|
+
deviceCurrentReject$1[deviceId](new Error(message ?? "Stopped sending commands"));
|
|
1535
1539
|
}
|
|
1536
|
-
devicePromiseQueue[deviceId] = Promise.resolve();
|
|
1537
|
-
deviceResponseIdentifier[deviceId] = [];
|
|
1540
|
+
devicePromiseQueue$1[deviceId] = Promise.resolve();
|
|
1541
|
+
deviceResponseIdentifier$1[deviceId] = [];
|
|
1538
1542
|
},
|
|
1539
1543
|
async enqueue(device, payload) {
|
|
1540
|
-
if (devicePromiseQueue[device.id] === void 0) devicePromiseQueue[device.id] = Promise.resolve();
|
|
1541
|
-
devicePromiseQueue[device.id] = devicePromiseQueue[device.id].then(() => {
|
|
1544
|
+
if (devicePromiseQueue$1[device.id] === void 0) devicePromiseQueue$1[device.id] = Promise.resolve();
|
|
1545
|
+
devicePromiseQueue$1[device.id] = devicePromiseQueue$1[device.id].then(() => {
|
|
1542
1546
|
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]];
|
|
1547
|
+
deviceCurrentResolve$1[device.id] = resolve;
|
|
1548
|
+
deviceCurrentReject$1[device.id] = reject;
|
|
1549
|
+
const isKeepAlive = payload[3] === commandIds$1.keepAlive;
|
|
1550
|
+
deviceResponseIdentifier$1[device.id] = [isKeepAlive ? 126 : 0, payload[4]];
|
|
1547
1551
|
const signedData = bridgeSecurity.getSignedCommand(device, payload);
|
|
1548
1552
|
if (!toolsSvc.canCommunicateWith(device.id)) return reject(new Error("Bridge not connected"));
|
|
1549
1553
|
if (signedData.length > 110) {
|
|
@@ -1569,21 +1573,21 @@ const promiseQueue = {
|
|
|
1569
1573
|
);
|
|
1570
1574
|
}
|
|
1571
1575
|
});
|
|
1572
|
-
return withTimeout(promise, 5e3, `Command timed out ${deviceResponseIdentifier[device.id]}, ${device.id}`);
|
|
1576
|
+
return withTimeout(promise, 5e3, `Command timed out ${deviceResponseIdentifier$1[device.id]}, ${device.id}`);
|
|
1573
1577
|
});
|
|
1574
|
-
return devicePromiseQueue[device.id];
|
|
1578
|
+
return devicePromiseQueue$1[device.id];
|
|
1575
1579
|
},
|
|
1576
1580
|
async processMessage(deviceId, payload) {
|
|
1577
1581
|
const numberArray = Array.from(new Uint8Array(payload));
|
|
1578
1582
|
if (numberArray[3] === 127) {
|
|
1579
1583
|
console.error(numberArray);
|
|
1580
|
-
return deviceCurrentReject[deviceId](new Error(`Command not succesful: ${numberArray[4]}`));
|
|
1584
|
+
return deviceCurrentReject$1[deviceId](new Error(`Command not succesful: ${numberArray[4]}`));
|
|
1581
1585
|
}
|
|
1582
1586
|
if ([226, 81].includes(numberArray[3]) && numberArray[4] && toolsSvc.canCommunicateWith(deviceId)) {
|
|
1583
1587
|
store.bridgeRebootRequired[deviceId] = true;
|
|
1584
1588
|
}
|
|
1585
|
-
if ((!deviceResponseIdentifier[deviceId][0] || numberArray[3] === deviceResponseIdentifier[deviceId][0]) && (!deviceResponseIdentifier[deviceId][1] || numberArray[4] === deviceResponseIdentifier[deviceId][1])) {
|
|
1586
|
-
return deviceCurrentResolve[deviceId](numberArray);
|
|
1589
|
+
if ((!deviceResponseIdentifier$1[deviceId][0] || numberArray[3] === deviceResponseIdentifier$1[deviceId][0]) && (!deviceResponseIdentifier$1[deviceId][1] || numberArray[4] === deviceResponseIdentifier$1[deviceId][1])) {
|
|
1590
|
+
return deviceCurrentResolve$1[deviceId](numberArray);
|
|
1587
1591
|
}
|
|
1588
1592
|
console.warn("message from the device not belonging to the pending promise: ", numberArray);
|
|
1589
1593
|
}
|
|
@@ -1600,7 +1604,7 @@ const messageTypeIds = {
|
|
|
1600
1604
|
command: 0,
|
|
1601
1605
|
response: 1
|
|
1602
1606
|
};
|
|
1603
|
-
const commandIds = {
|
|
1607
|
+
const commandIds$1 = {
|
|
1604
1608
|
readData: 34,
|
|
1605
1609
|
writeData: 46,
|
|
1606
1610
|
keepAlive: 62,
|
|
@@ -1649,7 +1653,7 @@ const subCommandIds = {
|
|
|
1649
1653
|
autolearnIdStatus: 176,
|
|
1650
1654
|
autolearnUnknownSensors: 192
|
|
1651
1655
|
};
|
|
1652
|
-
___default.invert(commandIds);
|
|
1656
|
+
___default.invert(commandIds$1);
|
|
1653
1657
|
___default.invert(subCommandIds);
|
|
1654
1658
|
const keepAliveTimer = {};
|
|
1655
1659
|
const bridgeCommands = {
|
|
@@ -1660,7 +1664,7 @@ const bridgeCommands = {
|
|
|
1660
1664
|
},
|
|
1661
1665
|
async setAxlesPressure(deviceId, data) {
|
|
1662
1666
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
1663
|
-
await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.pressurePerAxle, data);
|
|
1667
|
+
await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.pressurePerAxle, data);
|
|
1664
1668
|
},
|
|
1665
1669
|
async setVehicleLayout(deviceId, structurizedPayload) {
|
|
1666
1670
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
@@ -1669,7 +1673,7 @@ const bridgeCommands = {
|
|
|
1669
1673
|
structurizedPayload,
|
|
1670
1674
|
deviceData.advertisingData.fwVersion
|
|
1671
1675
|
);
|
|
1672
|
-
await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.vehicleLayout, payload);
|
|
1676
|
+
await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.vehicleLayout, payload);
|
|
1673
1677
|
},
|
|
1674
1678
|
async getCustomerCANSettings(deviceId) {
|
|
1675
1679
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
@@ -1722,18 +1726,18 @@ const bridgeCommands = {
|
|
|
1722
1726
|
return { ...structurized, isFactory: result.isFactory };
|
|
1723
1727
|
},
|
|
1724
1728
|
async sendKeepAliveCommand(device) {
|
|
1725
|
-
return this.promisify(device, [...this.getCommandHeader(device), 2, commandIds.keepAlive, 0]);
|
|
1729
|
+
return this.promisify(device, [...this.getCommandHeader(device), 2, commandIds$1.keepAlive, 0]);
|
|
1726
1730
|
},
|
|
1727
1731
|
async sendOtaRequest(deviceId) {
|
|
1728
1732
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
1729
|
-
const command = [commandIds.otaRequest, 0];
|
|
1733
|
+
const command = [commandIds$1.otaRequest, 0];
|
|
1730
1734
|
const result = await this.promisify(deviceData, [...this.getCommandHeader(deviceData), command.length, ...command]);
|
|
1731
1735
|
return result;
|
|
1732
1736
|
},
|
|
1733
1737
|
async sendPinCommand(deviceId) {
|
|
1734
1738
|
const deviceData = await bridgeTools.getBridgeFromStore(deviceId);
|
|
1735
1739
|
const pin = await bridgeSecurity.getPin(deviceId);
|
|
1736
|
-
return this.promisify(deviceData, [...this.getCommandHeader(deviceData), 18, commandIds.pin, 0, ...pin]);
|
|
1740
|
+
return this.promisify(deviceData, [...this.getCommandHeader(deviceData), 18, commandIds$1.pin, 0, ...pin]);
|
|
1737
1741
|
},
|
|
1738
1742
|
async setBridgeToRestart(deviceId) {
|
|
1739
1743
|
if (store.bridgeRebootRequired[deviceId]) return;
|
|
@@ -1742,7 +1746,7 @@ const bridgeCommands = {
|
|
|
1742
1746
|
await this.promisify(deviceData, [
|
|
1743
1747
|
...this.getCommandHeader(deviceData),
|
|
1744
1748
|
2,
|
|
1745
|
-
useNewCommand ? commandIds.ecuReset : commandIds.reboot,
|
|
1749
|
+
useNewCommand ? commandIds$1.ecuReset : commandIds$1.reboot,
|
|
1746
1750
|
useNewCommand ? subCommandIds.ecuResetSubCommand : subCommandIds.rebootSubCommand
|
|
1747
1751
|
]);
|
|
1748
1752
|
},
|
|
@@ -1753,7 +1757,7 @@ const bridgeCommands = {
|
|
|
1753
1757
|
structurizedPayload,
|
|
1754
1758
|
deviceData.advertisingData.fwVersion
|
|
1755
1759
|
);
|
|
1756
|
-
return await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.customerCanSettings, payload);
|
|
1760
|
+
return await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.customerCanSettings, payload);
|
|
1757
1761
|
},
|
|
1758
1762
|
async setWorkshopCANSettings(deviceId, structurizedPayload) {
|
|
1759
1763
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
@@ -1762,7 +1766,7 @@ const bridgeCommands = {
|
|
|
1762
1766
|
structurizedPayload,
|
|
1763
1767
|
deviceData.advertisingData.fwVersion
|
|
1764
1768
|
);
|
|
1765
|
-
return await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.workshopCanSettings, payload);
|
|
1769
|
+
return await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.workshopCanSettings, payload);
|
|
1766
1770
|
},
|
|
1767
1771
|
async setCustomerPressureThresholds(deviceId, structurizedPayload) {
|
|
1768
1772
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
@@ -1771,7 +1775,7 @@ const bridgeCommands = {
|
|
|
1771
1775
|
structurizedPayload,
|
|
1772
1776
|
deviceData.advertisingData.fwVersion
|
|
1773
1777
|
);
|
|
1774
|
-
return await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.customerPressureThresholds, payload);
|
|
1778
|
+
return await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.customerPressureThresholds, payload);
|
|
1775
1779
|
},
|
|
1776
1780
|
async setCustomerTemperatureThresholds(deviceId, structurizedPayload) {
|
|
1777
1781
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
@@ -1782,7 +1786,7 @@ const bridgeCommands = {
|
|
|
1782
1786
|
);
|
|
1783
1787
|
return await this.writeCommand(
|
|
1784
1788
|
deviceData,
|
|
1785
|
-
commandIds.writeData,
|
|
1789
|
+
commandIds$1.writeData,
|
|
1786
1790
|
subCommandIds.customerTemperatureThresholds,
|
|
1787
1791
|
payload
|
|
1788
1792
|
);
|
|
@@ -1794,7 +1798,7 @@ const bridgeCommands = {
|
|
|
1794
1798
|
structurizedPayload,
|
|
1795
1799
|
deviceData.advertisingData.fwVersion
|
|
1796
1800
|
);
|
|
1797
|
-
return await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.customerImbalanceThresholds, payload);
|
|
1801
|
+
return await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.customerImbalanceThresholds, payload);
|
|
1798
1802
|
},
|
|
1799
1803
|
async getAutolearnSettings(deviceId) {
|
|
1800
1804
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
@@ -1823,7 +1827,7 @@ const bridgeCommands = {
|
|
|
1823
1827
|
structurizedPayload,
|
|
1824
1828
|
deviceData.advertisingData.fwVersion
|
|
1825
1829
|
);
|
|
1826
|
-
return await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.autolearnSettings, payload);
|
|
1830
|
+
return await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.autolearnSettings, payload);
|
|
1827
1831
|
},
|
|
1828
1832
|
async setAutolearnIdStatus(deviceId, structurizedPayload) {
|
|
1829
1833
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
@@ -1832,7 +1836,7 @@ const bridgeCommands = {
|
|
|
1832
1836
|
structurizedPayload,
|
|
1833
1837
|
deviceData.advertisingData.fwVersion
|
|
1834
1838
|
);
|
|
1835
|
-
return await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.autolearnIdStatus, payload);
|
|
1839
|
+
return await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.autolearnIdStatus, payload);
|
|
1836
1840
|
},
|
|
1837
1841
|
async getAutolearnUnknownSensors(device) {
|
|
1838
1842
|
const result = await this.readCommand(device, subCommandIds.autolearnUnknownSensors);
|
|
@@ -1853,7 +1857,7 @@ const bridgeCommands = {
|
|
|
1853
1857
|
// move logic to bridge svc
|
|
1854
1858
|
async setAxleInfo(deviceId, axleIndex, data) {
|
|
1855
1859
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
1856
|
-
await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.idsPerWheel(axleIndex), data);
|
|
1860
|
+
await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.idsPerWheel(axleIndex), data);
|
|
1857
1861
|
},
|
|
1858
1862
|
async getAxlesPressure(deviceId) {
|
|
1859
1863
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
@@ -1877,7 +1881,7 @@ const bridgeCommands = {
|
|
|
1877
1881
|
structurizedPayload,
|
|
1878
1882
|
deviceData.advertisingData.fwVersion
|
|
1879
1883
|
);
|
|
1880
|
-
return await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.pressurePerAxle, payload);
|
|
1884
|
+
return await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.pressurePerAxle, payload);
|
|
1881
1885
|
},
|
|
1882
1886
|
// // async setPressureThresholds(device: BleBridge, rules: any) {
|
|
1883
1887
|
// // // https://tirecheck.atlassian.net/wiki/spaces/HWPRG/pages/6547767302/Technical+Design+Document+BLE+CAN+Bridge+Krone#Example.1
|
|
@@ -1920,7 +1924,7 @@ const bridgeCommands = {
|
|
|
1920
1924
|
}
|
|
1921
1925
|
const result = await this.writeCommand(
|
|
1922
1926
|
deviceData,
|
|
1923
|
-
commandIds.sensorMeasurement,
|
|
1927
|
+
commandIds$1.sensorMeasurement,
|
|
1924
1928
|
subCommandIds.sensorMeasurementPerWheel(axlePosition, tyrePosition, isTwinTyre, isSpare),
|
|
1925
1929
|
[]
|
|
1926
1930
|
);
|
|
@@ -1931,7 +1935,7 @@ const bridgeCommands = {
|
|
|
1931
1935
|
const result = await this.promisify(device, [
|
|
1932
1936
|
...this.getCommandHeader(device),
|
|
1933
1937
|
commandLength,
|
|
1934
|
-
commandIds.readData,
|
|
1938
|
+
commandIds$1.readData,
|
|
1935
1939
|
subCommandId
|
|
1936
1940
|
]);
|
|
1937
1941
|
const data = result.slice(19, result.length - 8);
|
|
@@ -2896,6 +2900,344 @@ const pressureStick = {
|
|
|
2896
2900
|
onPressure: pressureStickService.onPressure
|
|
2897
2901
|
};
|
|
2898
2902
|
|
|
2903
|
+
const devicePromiseQueue = {};
|
|
2904
|
+
const deviceCurrentResolve = {};
|
|
2905
|
+
const deviceCurrentReject = {};
|
|
2906
|
+
const deviceResponseIdentifier = {};
|
|
2907
|
+
const deviceCurrentPartialMessage = {};
|
|
2908
|
+
const torqueWrenchPromiseQueue = {
|
|
2909
|
+
clearQueue(deviceId, message) {
|
|
2910
|
+
if (deviceCurrentReject[deviceId]) {
|
|
2911
|
+
deviceCurrentReject[deviceId](new Error(message ?? "Stopped sending commands"));
|
|
2912
|
+
}
|
|
2913
|
+
devicePromiseQueue[deviceId] = Promise.resolve();
|
|
2914
|
+
deviceResponseIdentifier[deviceId] = void 0;
|
|
2915
|
+
},
|
|
2916
|
+
async enqueue(deviceId, communication, payload, responseIdentifier, mtu = 20) {
|
|
2917
|
+
if (devicePromiseQueue[deviceId] === void 0) devicePromiseQueue[deviceId] = Promise.resolve();
|
|
2918
|
+
devicePromiseQueue[deviceId] = devicePromiseQueue[deviceId].then(() => {
|
|
2919
|
+
const promise = new Promise((resolve, reject) => {
|
|
2920
|
+
deviceCurrentResolve[deviceId] = resolve;
|
|
2921
|
+
deviceCurrentReject[deviceId] = reject;
|
|
2922
|
+
deviceResponseIdentifier[deviceId] = responseIdentifier;
|
|
2923
|
+
deviceCurrentPartialMessage[deviceId] = [];
|
|
2924
|
+
if (!toolsSvc.canCommunicateWith(deviceId)) return reject(new Error("Torque wrench not connected"));
|
|
2925
|
+
const chunks = [];
|
|
2926
|
+
for (let i = 0; i < payload.length; i += mtu) {
|
|
2927
|
+
chunks.push(payload.slice(i, i + mtu));
|
|
2928
|
+
}
|
|
2929
|
+
for (const chunk of chunks) {
|
|
2930
|
+
const convertedChunk = new Uint8Array(chunk).buffer;
|
|
2931
|
+
bluetooth.write(deviceId, communication.serviceId, communication.characteristicId, convertedChunk);
|
|
2932
|
+
}
|
|
2933
|
+
});
|
|
2934
|
+
return withTimeout(promise, 5e3, `Command timed out ${deviceResponseIdentifier[deviceId]}, ${deviceId}`);
|
|
2935
|
+
});
|
|
2936
|
+
return devicePromiseQueue[deviceId];
|
|
2937
|
+
},
|
|
2938
|
+
async processMessage(deviceId, payload, getIdentifier, isComplete, isError) {
|
|
2939
|
+
const numberArray = Array.from(new Uint8Array(payload));
|
|
2940
|
+
if (!deviceCurrentPartialMessage[deviceId]) deviceCurrentPartialMessage[deviceId] = [];
|
|
2941
|
+
deviceCurrentPartialMessage[deviceId] = ___default.concat(deviceCurrentPartialMessage[deviceId], numberArray);
|
|
2942
|
+
if (!isComplete(deviceCurrentPartialMessage[deviceId])) {
|
|
2943
|
+
return;
|
|
2944
|
+
}
|
|
2945
|
+
if (isError(deviceCurrentPartialMessage[deviceId])) {
|
|
2946
|
+
return deviceCurrentReject[deviceId](
|
|
2947
|
+
new Error("Error response", { cause: deviceCurrentPartialMessage[deviceId] })
|
|
2948
|
+
);
|
|
2949
|
+
}
|
|
2950
|
+
const identifier = getIdentifier(deviceCurrentPartialMessage[deviceId]);
|
|
2951
|
+
if (deviceResponseIdentifier[deviceId] === identifier) {
|
|
2952
|
+
deviceCurrentResolve[deviceId](deviceCurrentPartialMessage[deviceId]);
|
|
2953
|
+
}
|
|
2954
|
+
}
|
|
2955
|
+
};
|
|
2956
|
+
|
|
2957
|
+
const commandStart = "$9";
|
|
2958
|
+
const commandEnd = "*";
|
|
2959
|
+
const commandIds = {
|
|
2960
|
+
error: "004",
|
|
2961
|
+
acknowledge: "005",
|
|
2962
|
+
commTest: "100",
|
|
2963
|
+
getProperties: "120",
|
|
2964
|
+
startJob: "204",
|
|
2965
|
+
stopJob: "206",
|
|
2966
|
+
getNumberOfReadings: "224",
|
|
2967
|
+
getReading: "200",
|
|
2968
|
+
// Can only be called once for each reading.
|
|
2969
|
+
getReadingAgain: "202",
|
|
2970
|
+
getBattery: "150",
|
|
2971
|
+
getTime: "209",
|
|
2972
|
+
setTime: "208"
|
|
2973
|
+
};
|
|
2974
|
+
const errors = {
|
|
2975
|
+
"01": "Bad string",
|
|
2976
|
+
"02": "Bad checksum",
|
|
2977
|
+
"03": "Unknown command",
|
|
2978
|
+
"04": "No device present for command to act on",
|
|
2979
|
+
"05": "Invalid sample speed",
|
|
2980
|
+
"06": "Torque module offset difference bigger than 25%",
|
|
2981
|
+
"07": "Torque module gain outside 0.9 to 1.1",
|
|
2982
|
+
"08": "No RF properties",
|
|
2983
|
+
"09": "No reply from RF",
|
|
2984
|
+
"0A": "RF device already paired on this device",
|
|
2985
|
+
"0C": "Invalid frequency",
|
|
2986
|
+
"0D": "Invalid LED selection",
|
|
2987
|
+
"0F": "Transducer preloaded",
|
|
2988
|
+
"10": "No more readings",
|
|
2989
|
+
"11": "Job already loaded",
|
|
2990
|
+
"12": "No trace stored",
|
|
2991
|
+
"13": "Wrong transducers selected for Multi Start Mode",
|
|
2992
|
+
"14": "No short trace stored",
|
|
2993
|
+
"15": "Job finished",
|
|
2994
|
+
"16": "Missing time and date",
|
|
2995
|
+
"17": "Bad units for wrench type",
|
|
2996
|
+
"18": "Battery low"
|
|
2997
|
+
};
|
|
2998
|
+
const twMeta = deviceMeta.torqueWrench;
|
|
2999
|
+
const torqueWrenchCommands = {
|
|
3000
|
+
async sendCommand(deviceId, command, params) {
|
|
3001
|
+
const commandId = commandIds[command];
|
|
3002
|
+
let message = `${commandStart}${commandId}`;
|
|
3003
|
+
if (params?.length) {
|
|
3004
|
+
message += `,${params.join(",")}`;
|
|
3005
|
+
}
|
|
3006
|
+
message += commandEnd;
|
|
3007
|
+
const crc = getChecksum(message);
|
|
3008
|
+
message += `${crc}\r`;
|
|
3009
|
+
const array = new Uint8Array(message.length);
|
|
3010
|
+
for (let i = 0, l = message.length; i < l; i++) {
|
|
3011
|
+
array[i] = message.charCodeAt(i);
|
|
3012
|
+
}
|
|
3013
|
+
const decimalArray = Array.from(array);
|
|
3014
|
+
let result;
|
|
3015
|
+
try {
|
|
3016
|
+
result = await torqueWrenchPromiseQueue.enqueue(deviceId, twMeta.communication, decimalArray, commandIds[command]);
|
|
3017
|
+
} catch (error) {
|
|
3018
|
+
const formattedError = formatError(error);
|
|
3019
|
+
throw new Error(formattedError);
|
|
3020
|
+
}
|
|
3021
|
+
return result.map((num) => String.fromCharCode(num)).join("");
|
|
3022
|
+
},
|
|
3023
|
+
processMessage(deviceId, payload) {
|
|
3024
|
+
torqueWrenchPromiseQueue.processMessage(deviceId, payload, getIdentifier, isComplete, isError);
|
|
3025
|
+
}
|
|
3026
|
+
};
|
|
3027
|
+
function isComplete(message) {
|
|
3028
|
+
const completeReading = message[0] === 123 && message.at(-1) === 13;
|
|
3029
|
+
const completeCommand = message[0] === 36 && message.at(-1) === 13;
|
|
3030
|
+
return completeReading || completeCommand;
|
|
3031
|
+
}
|
|
3032
|
+
function isError(message) {
|
|
3033
|
+
return message[4] === 52;
|
|
3034
|
+
}
|
|
3035
|
+
function getIdentifier(message) {
|
|
3036
|
+
if (message[0] === 123) return "200";
|
|
3037
|
+
return message.slice(6, 9).map((num) => String.fromCharCode(num)).join("");
|
|
3038
|
+
}
|
|
3039
|
+
function getChecksum(message) {
|
|
3040
|
+
let checksum = 0;
|
|
3041
|
+
for (const ch of message) {
|
|
3042
|
+
checksum ^= ch.charCodeAt(0);
|
|
3043
|
+
}
|
|
3044
|
+
return decimalToHex(checksum).toUpperCase();
|
|
3045
|
+
}
|
|
3046
|
+
function formatError(error) {
|
|
3047
|
+
if (!error.cause) throw new Error(error);
|
|
3048
|
+
const message = error.cause.slice(6, 8);
|
|
3049
|
+
const errorId = message.map((num) => String.fromCharCode(num)).join("");
|
|
3050
|
+
return errors[errorId] || "Unknown error";
|
|
3051
|
+
}
|
|
3052
|
+
|
|
3053
|
+
let jobInterval = null;
|
|
3054
|
+
const torqueWrenchService = {
|
|
3055
|
+
onReading(callback) {
|
|
3056
|
+
simulatorSvc.registerEvent("tw:reading", callback);
|
|
3057
|
+
},
|
|
3058
|
+
async getProperties(deviceId) {
|
|
3059
|
+
const result = {
|
|
3060
|
+
serialNumber: "",
|
|
3061
|
+
span: 0,
|
|
3062
|
+
calibrationDate: "",
|
|
3063
|
+
ppr: 0,
|
|
3064
|
+
units: "Nm",
|
|
3065
|
+
threshold: 10
|
|
3066
|
+
};
|
|
3067
|
+
const message = await torqueWrenchCommands.sendCommand(deviceId, "getProperties");
|
|
3068
|
+
const params = getMessageParams(message);
|
|
3069
|
+
if (params[4] === "3") result.units = "Nm";
|
|
3070
|
+
else if (params[4] === "7") result.units = "lb-ft";
|
|
3071
|
+
result.serialNumber = params[0];
|
|
3072
|
+
result.span = Number.parseInt(params[1]);
|
|
3073
|
+
if (result.units === "lb-ft") result.span = Math.floor(result.span * 0.738);
|
|
3074
|
+
result.calibrationDate = params[2];
|
|
3075
|
+
result.ppr = Number.parseInt(params[3]);
|
|
3076
|
+
return result;
|
|
3077
|
+
},
|
|
3078
|
+
async startJob(deviceId, params) {
|
|
3079
|
+
await this.stopJob(deviceId);
|
|
3080
|
+
const { units, span, ppr, threshold } = store.torqueWrenchProperties[deviceId];
|
|
3081
|
+
console.log("\u{1F680} ~ startJob ~ units:", units);
|
|
3082
|
+
const { torqueMin, torqueMax, angleMin, angleMax, direction, jobTimeout } = params;
|
|
3083
|
+
const msgParams = {
|
|
3084
|
+
id: "01",
|
|
3085
|
+
nuts: decimalToHex(params.nuts),
|
|
3086
|
+
mode: units === "lb-ft" ? "20" : "1",
|
|
3087
|
+
// Peak measurement mode
|
|
3088
|
+
cycle: "7",
|
|
3089
|
+
// 10 seconds cycle (probably for measurements - not sure what it does exactly, not specified in docs)
|
|
3090
|
+
control: torqueMin != null || torqueMax != null ? "0" : "1",
|
|
3091
|
+
direction: direction === "counter-clockwise" ? "1" : "0",
|
|
3092
|
+
minTorqueThreshold: torqueToAdcParam(threshold, span, units),
|
|
3093
|
+
torqueMin: torqueToAdcParam(torqueMin ?? 0, span, units),
|
|
3094
|
+
torqueMax: torqueToAdcParam(torqueMax ?? -1, span, units),
|
|
3095
|
+
clickThreshold: torqueToAdcParam(threshold, span, units),
|
|
3096
|
+
// Probably not used in our case (for this specified mode).
|
|
3097
|
+
angleMin: angleToPulsesParam(angleMin ?? 0, ppr),
|
|
3098
|
+
angleMax: angleToPulsesParam(angleMax ?? -1, ppr),
|
|
3099
|
+
frequency: "0542"
|
|
3100
|
+
// No idea
|
|
3101
|
+
};
|
|
3102
|
+
const paramsString = Object.values(msgParams);
|
|
3103
|
+
await torqueWrenchCommands.sendCommand(deviceId, "startJob", paramsString);
|
|
3104
|
+
jobInterval = setInterval(async () => {
|
|
3105
|
+
const numberOfReading = await this.getNumberOfReadings(deviceId);
|
|
3106
|
+
console.log("\u{1F680} ~ jobInterval=setInterval ~ numberOfReading:", numberOfReading);
|
|
3107
|
+
if (numberOfReading.count > 0) this.getReading(deviceId);
|
|
3108
|
+
}, 1e3);
|
|
3109
|
+
if (jobTimeout) {
|
|
3110
|
+
await new Promise(
|
|
3111
|
+
(resolve) => setTimeout(() => {
|
|
3112
|
+
console.log("job terminated");
|
|
3113
|
+
clearInterval(jobInterval);
|
|
3114
|
+
this.stopJob(deviceId);
|
|
3115
|
+
resolve("");
|
|
3116
|
+
}, jobTimeout * 1e3)
|
|
3117
|
+
);
|
|
3118
|
+
}
|
|
3119
|
+
},
|
|
3120
|
+
async stopJob(deviceId) {
|
|
3121
|
+
return torqueWrenchCommands.sendCommand(deviceId, "stopJob");
|
|
3122
|
+
},
|
|
3123
|
+
async getNumberOfReadings(deviceId) {
|
|
3124
|
+
const message = await torqueWrenchCommands.sendCommand(deviceId, "getNumberOfReadings");
|
|
3125
|
+
const params = getMessageParams(message);
|
|
3126
|
+
return { count: Number(params[0]), jobId: params[1] };
|
|
3127
|
+
},
|
|
3128
|
+
async getReading(deviceId) {
|
|
3129
|
+
const reading = await torqueWrenchCommands.sendCommand(deviceId, "getReading");
|
|
3130
|
+
const properties = {
|
|
3131
|
+
jobId: reading.slice(2, 4),
|
|
3132
|
+
nut: reading.slice(4, 6),
|
|
3133
|
+
torqueAdc: reading.slice(6, 10),
|
|
3134
|
+
anglePulses: reading.slice(10, 14),
|
|
3135
|
+
duration: reading.slice(14, 18)
|
|
3136
|
+
};
|
|
3137
|
+
const torque = adcToTorque(
|
|
3138
|
+
properties.torqueAdc,
|
|
3139
|
+
store.torqueWrenchProperties[deviceId].span,
|
|
3140
|
+
store.torqueWrenchProperties[deviceId].units
|
|
3141
|
+
);
|
|
3142
|
+
const angle = pulsesToAngle(properties.anglePulses, store.torqueWrenchProperties[deviceId].ppr);
|
|
3143
|
+
const formattedReading = {
|
|
3144
|
+
jobId: Number.parseInt(properties.jobId, 16),
|
|
3145
|
+
nut: Number.parseInt(properties.nut, 16),
|
|
3146
|
+
torque,
|
|
3147
|
+
angle,
|
|
3148
|
+
duration: Number.parseInt(properties.duration, 16) / 1e3
|
|
3149
|
+
};
|
|
3150
|
+
simulatorSvc.triggerEvent("tw:reading", deviceId, formattedReading);
|
|
3151
|
+
},
|
|
3152
|
+
// getReadingAgain(deviceId: string) {
|
|
3153
|
+
// return torqueWrenchCommands.sendCommand(deviceId, 'getNumberOfReadings')
|
|
3154
|
+
// },
|
|
3155
|
+
async getBattery(deviceId) {
|
|
3156
|
+
const message = await torqueWrenchCommands.sendCommand(deviceId, "getBattery");
|
|
3157
|
+
const params = getMessageParams(message);
|
|
3158
|
+
return Number(params[0]);
|
|
3159
|
+
},
|
|
3160
|
+
async getTime(deviceId) {
|
|
3161
|
+
const message = await torqueWrenchCommands.sendCommand(deviceId, "getTime");
|
|
3162
|
+
const match = message.match(/209,([^*]*)\*/);
|
|
3163
|
+
console.log("\u{1F680} ~ getTime ~ match:", match);
|
|
3164
|
+
if (!match[1]) throw new Error("Invalid time response");
|
|
3165
|
+
const hh = match[1].substring(0, 2);
|
|
3166
|
+
const mm = match[1].substring(2, 4);
|
|
3167
|
+
const ss = match[1].substring(4, 6);
|
|
3168
|
+
const dd = match[1].substring(6, 8);
|
|
3169
|
+
const MM = match[1].substring(8, 10);
|
|
3170
|
+
const yy = match[1].substring(10, 12);
|
|
3171
|
+
const fullYear = `20${yy}`;
|
|
3172
|
+
return /* @__PURE__ */ new Date(`${fullYear}-${MM}-${dd}T${hh}:${mm}:${ss}Z`);
|
|
3173
|
+
},
|
|
3174
|
+
setTime(deviceId, date) {
|
|
3175
|
+
const hours = String(date.getHours()).padStart(2, "0");
|
|
3176
|
+
const minutes = String(date.getMinutes()).padStart(2, "0");
|
|
3177
|
+
const seconds = String(date.getSeconds()).padStart(2, "0");
|
|
3178
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
3179
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
3180
|
+
const year = String(date.getFullYear()).slice(-2);
|
|
3181
|
+
const params = [hours, minutes, seconds, day, month, year];
|
|
3182
|
+
return torqueWrenchCommands.sendCommand(deviceId, "setTime", params);
|
|
3183
|
+
}
|
|
3184
|
+
};
|
|
3185
|
+
function torqueToAdcParam(value, span, deviceUnits) {
|
|
3186
|
+
if (value < 0) return "FFFF";
|
|
3187
|
+
if (deviceUnits !== "Nm") value = value * 0.738;
|
|
3188
|
+
const adc = Math.round(value / span * 16384);
|
|
3189
|
+
return decimalToHex(adc, 4).toUpperCase();
|
|
3190
|
+
}
|
|
3191
|
+
function angleToPulsesParam(value, ppr) {
|
|
3192
|
+
if (value < 0) return "FFFF";
|
|
3193
|
+
const pulses = Math.round(value * ppr / 90);
|
|
3194
|
+
return decimalToHex(pulses, 4).toUpperCase();
|
|
3195
|
+
}
|
|
3196
|
+
function getMessageParams(message) {
|
|
3197
|
+
return message.match(/^\$[^,]+,[^,]+,(.*)\*/)?.[1].split(",") || [];
|
|
3198
|
+
}
|
|
3199
|
+
function adcToTorque(value, span, units) {
|
|
3200
|
+
const torque = Number.parseInt(value, 16) * span / 16384;
|
|
3201
|
+
if (units !== "Nm") return torque / 0.738;
|
|
3202
|
+
return torque;
|
|
3203
|
+
}
|
|
3204
|
+
function pulsesToAngle(value, ppr) {
|
|
3205
|
+
return Number.parseInt(value, 16) * 90 / ppr;
|
|
3206
|
+
}
|
|
3207
|
+
|
|
3208
|
+
const torqueWrench = {
|
|
3209
|
+
async connect(deviceId) {
|
|
3210
|
+
const twMeta = deviceMeta.torqueWrench;
|
|
3211
|
+
await bluetooth.connect(deviceId, this.disconnect);
|
|
3212
|
+
await ble.startNotification(
|
|
3213
|
+
deviceId,
|
|
3214
|
+
twMeta.communication.serviceId,
|
|
3215
|
+
twMeta.communication.characteristicId,
|
|
3216
|
+
(notification) => {
|
|
3217
|
+
torqueWrenchCommands.processMessage(deviceId, notification);
|
|
3218
|
+
},
|
|
3219
|
+
(error) => console.warn("ble.startNotification error", error)
|
|
3220
|
+
);
|
|
3221
|
+
const properties = await torqueWrenchService.getProperties(deviceId);
|
|
3222
|
+
store.torqueWrenchProperties[deviceId] = properties;
|
|
3223
|
+
store.setState(deviceId, "paired");
|
|
3224
|
+
},
|
|
3225
|
+
async disconnect(deviceId, reason) {
|
|
3226
|
+
store.setState(deviceId, "disconnecting");
|
|
3227
|
+
await bluetooth.disconnect(deviceId);
|
|
3228
|
+
store.setState(deviceId, void 0, reason ?? "manualDisconnection");
|
|
3229
|
+
},
|
|
3230
|
+
getProperties: torqueWrenchService.getProperties,
|
|
3231
|
+
setTime: torqueWrenchService.setTime,
|
|
3232
|
+
startJob: torqueWrenchService.startJob,
|
|
3233
|
+
stopJob: torqueWrenchService.stopJob,
|
|
3234
|
+
getNumberOfReadings: torqueWrenchService.getNumberOfReadings,
|
|
3235
|
+
getReading: torqueWrenchService.getReading,
|
|
3236
|
+
getBattery: torqueWrenchService.getBattery,
|
|
3237
|
+
getTime: torqueWrenchService.getTime,
|
|
3238
|
+
onReading: torqueWrenchService.onReading
|
|
3239
|
+
};
|
|
3240
|
+
|
|
2899
3241
|
const bridgeSimulator = {
|
|
2900
3242
|
isRebootRequired(deviceId) {
|
|
2901
3243
|
return store.bridgeRebootRequired[deviceId];
|
|
@@ -3496,10 +3838,14 @@ function createTirecheckDeviceSdk(platform, bleImplementation, securityKeys) {
|
|
|
3496
3838
|
bridgeOta,
|
|
3497
3839
|
/** Methods for working with Tirecheck TPMS FlexiGauge */
|
|
3498
3840
|
flexiGaugeTpms,
|
|
3841
|
+
// flexiGauge,
|
|
3499
3842
|
/** Methods for working with Tirecheck Pressure Stick */
|
|
3500
3843
|
pressureStick,
|
|
3844
|
+
// ateq,
|
|
3501
3845
|
/** Allows simulating devices without actually using bluetooth */
|
|
3502
|
-
simulator
|
|
3846
|
+
simulator,
|
|
3847
|
+
/** Methods for working with Tirecheck Torque Wrench */
|
|
3848
|
+
torqueWrench
|
|
3503
3849
|
};
|
|
3504
3850
|
}
|
|
3505
3851
|
|
package/dist/index.d.cts
CHANGED
|
@@ -900,6 +900,23 @@ declare function createTirecheckDeviceSdk(platform: DevicePlatform, bleImplement
|
|
|
900
900
|
getSimulatedDevices(): Record<string, BleDeviceSimulated>;
|
|
901
901
|
triggerEvent: (eventName: EventName, deviceId: string, payload?: any) => void;
|
|
902
902
|
};
|
|
903
|
+
/** Methods for working with Tirecheck Torque Wrench */
|
|
904
|
+
torqueWrench: {
|
|
905
|
+
connect(deviceId: string): Promise<void>;
|
|
906
|
+
disconnect(deviceId: string, reason?: StateReason): Promise<void>;
|
|
907
|
+
getProperties: (deviceId: string) => Promise<TorqueWrenchProperties>;
|
|
908
|
+
setTime: (deviceId: string, date: Date) => Promise<any>;
|
|
909
|
+
startJob: (deviceId: string, params: TorqueWrenchStartJobParams) => Promise<void>;
|
|
910
|
+
stopJob: (deviceId: string) => Promise<any>;
|
|
911
|
+
getNumberOfReadings: (deviceId: string) => Promise<{
|
|
912
|
+
count: number;
|
|
913
|
+
jobId: string;
|
|
914
|
+
}>;
|
|
915
|
+
getReading: (deviceId: string) => Promise<void>;
|
|
916
|
+
getBattery: (deviceId: string) => Promise<number>;
|
|
917
|
+
getTime: (deviceId: string) => Promise<Date>;
|
|
918
|
+
onReading: (callback: (deviceId: string, value: TorqueWrenchReading) => void) => void;
|
|
919
|
+
};
|
|
903
920
|
};
|
|
904
921
|
|
|
905
922
|
export { type BleBridge, type BleBridgeAdvertisingData, type BleBridgeOta, type BleBridgeSimulated, type BleDevice, type BleDeviceBase, type BleDeviceSimulated, type BleDeviceStatus, type BleDeviceType, type BleFlexiGaugeTpms, type BleFlexiGaugeTpmsSimulated, type BlePressureStick, type BleSecurityKeys, 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 Wrapper, createTirecheckDeviceSdk };
|
package/dist/index.d.mts
CHANGED
|
@@ -900,6 +900,23 @@ declare function createTirecheckDeviceSdk(platform: DevicePlatform, bleImplement
|
|
|
900
900
|
getSimulatedDevices(): Record<string, BleDeviceSimulated>;
|
|
901
901
|
triggerEvent: (eventName: EventName, deviceId: string, payload?: any) => void;
|
|
902
902
|
};
|
|
903
|
+
/** Methods for working with Tirecheck Torque Wrench */
|
|
904
|
+
torqueWrench: {
|
|
905
|
+
connect(deviceId: string): Promise<void>;
|
|
906
|
+
disconnect(deviceId: string, reason?: StateReason): Promise<void>;
|
|
907
|
+
getProperties: (deviceId: string) => Promise<TorqueWrenchProperties>;
|
|
908
|
+
setTime: (deviceId: string, date: Date) => Promise<any>;
|
|
909
|
+
startJob: (deviceId: string, params: TorqueWrenchStartJobParams) => Promise<void>;
|
|
910
|
+
stopJob: (deviceId: string) => Promise<any>;
|
|
911
|
+
getNumberOfReadings: (deviceId: string) => Promise<{
|
|
912
|
+
count: number;
|
|
913
|
+
jobId: string;
|
|
914
|
+
}>;
|
|
915
|
+
getReading: (deviceId: string) => Promise<void>;
|
|
916
|
+
getBattery: (deviceId: string) => Promise<number>;
|
|
917
|
+
getTime: (deviceId: string) => Promise<Date>;
|
|
918
|
+
onReading: (callback: (deviceId: string, value: TorqueWrenchReading) => void) => void;
|
|
919
|
+
};
|
|
903
920
|
};
|
|
904
921
|
|
|
905
922
|
export { type BleBridge, type BleBridgeAdvertisingData, type BleBridgeOta, type BleBridgeSimulated, type BleDevice, type BleDeviceBase, type BleDeviceSimulated, type BleDeviceStatus, type BleDeviceType, type BleFlexiGaugeTpms, type BleFlexiGaugeTpmsSimulated, type BlePressureStick, type BleSecurityKeys, 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 Wrapper, createTirecheckDeviceSdk };
|
package/dist/index.d.ts
CHANGED
|
@@ -900,6 +900,23 @@ declare function createTirecheckDeviceSdk(platform: DevicePlatform, bleImplement
|
|
|
900
900
|
getSimulatedDevices(): Record<string, BleDeviceSimulated>;
|
|
901
901
|
triggerEvent: (eventName: EventName, deviceId: string, payload?: any) => void;
|
|
902
902
|
};
|
|
903
|
+
/** Methods for working with Tirecheck Torque Wrench */
|
|
904
|
+
torqueWrench: {
|
|
905
|
+
connect(deviceId: string): Promise<void>;
|
|
906
|
+
disconnect(deviceId: string, reason?: StateReason): Promise<void>;
|
|
907
|
+
getProperties: (deviceId: string) => Promise<TorqueWrenchProperties>;
|
|
908
|
+
setTime: (deviceId: string, date: Date) => Promise<any>;
|
|
909
|
+
startJob: (deviceId: string, params: TorqueWrenchStartJobParams) => Promise<void>;
|
|
910
|
+
stopJob: (deviceId: string) => Promise<any>;
|
|
911
|
+
getNumberOfReadings: (deviceId: string) => Promise<{
|
|
912
|
+
count: number;
|
|
913
|
+
jobId: string;
|
|
914
|
+
}>;
|
|
915
|
+
getReading: (deviceId: string) => Promise<void>;
|
|
916
|
+
getBattery: (deviceId: string) => Promise<number>;
|
|
917
|
+
getTime: (deviceId: string) => Promise<Date>;
|
|
918
|
+
onReading: (callback: (deviceId: string, value: TorqueWrenchReading) => void) => void;
|
|
919
|
+
};
|
|
903
920
|
};
|
|
904
921
|
|
|
905
922
|
export { type BleBridge, type BleBridgeAdvertisingData, type BleBridgeOta, type BleBridgeSimulated, type BleDevice, type BleDeviceBase, type BleDeviceSimulated, type BleDeviceStatus, type BleDeviceType, type BleFlexiGaugeTpms, type BleFlexiGaugeTpmsSimulated, type BlePressureStick, type BleSecurityKeys, 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 Wrapper, createTirecheckDeviceSdk };
|
package/dist/index.mjs
CHANGED
|
@@ -97,6 +97,10 @@ function stringToArrayBuffer(string) {
|
|
|
97
97
|
}
|
|
98
98
|
return array.buffer;
|
|
99
99
|
}
|
|
100
|
+
function decimalToHex(decimal, padStart = 2) {
|
|
101
|
+
const hex = decimal.toString(16);
|
|
102
|
+
return hex.padStart(padStart, "0");
|
|
103
|
+
}
|
|
100
104
|
const toolsSvc = {
|
|
101
105
|
delay,
|
|
102
106
|
setIntervalImmediate,
|
|
@@ -1517,26 +1521,26 @@ const bridgeSecurity = {
|
|
|
1517
1521
|
};
|
|
1518
1522
|
|
|
1519
1523
|
const bridgeMeta = deviceMeta.bridge;
|
|
1520
|
-
const devicePromiseQueue = {};
|
|
1521
|
-
const deviceCurrentResolve = {};
|
|
1522
|
-
const deviceCurrentReject = {};
|
|
1523
|
-
const deviceResponseIdentifier = {};
|
|
1524
|
+
const devicePromiseQueue$1 = {};
|
|
1525
|
+
const deviceCurrentResolve$1 = {};
|
|
1526
|
+
const deviceCurrentReject$1 = {};
|
|
1527
|
+
const deviceResponseIdentifier$1 = {};
|
|
1524
1528
|
const promiseQueue = {
|
|
1525
1529
|
clearQueue(deviceId, message) {
|
|
1526
|
-
if (deviceCurrentReject[deviceId]) {
|
|
1527
|
-
deviceCurrentReject[deviceId](new Error(message ?? "Stopped sending commands"));
|
|
1530
|
+
if (deviceCurrentReject$1[deviceId]) {
|
|
1531
|
+
deviceCurrentReject$1[deviceId](new Error(message ?? "Stopped sending commands"));
|
|
1528
1532
|
}
|
|
1529
|
-
devicePromiseQueue[deviceId] = Promise.resolve();
|
|
1530
|
-
deviceResponseIdentifier[deviceId] = [];
|
|
1533
|
+
devicePromiseQueue$1[deviceId] = Promise.resolve();
|
|
1534
|
+
deviceResponseIdentifier$1[deviceId] = [];
|
|
1531
1535
|
},
|
|
1532
1536
|
async enqueue(device, payload) {
|
|
1533
|
-
if (devicePromiseQueue[device.id] === void 0) devicePromiseQueue[device.id] = Promise.resolve();
|
|
1534
|
-
devicePromiseQueue[device.id] = devicePromiseQueue[device.id].then(() => {
|
|
1537
|
+
if (devicePromiseQueue$1[device.id] === void 0) devicePromiseQueue$1[device.id] = Promise.resolve();
|
|
1538
|
+
devicePromiseQueue$1[device.id] = devicePromiseQueue$1[device.id].then(() => {
|
|
1535
1539
|
const promise = new Promise((resolve, reject) => {
|
|
1536
|
-
deviceCurrentResolve[device.id] = resolve;
|
|
1537
|
-
deviceCurrentReject[device.id] = reject;
|
|
1538
|
-
const isKeepAlive = payload[3] === commandIds.keepAlive;
|
|
1539
|
-
deviceResponseIdentifier[device.id] = [isKeepAlive ? 126 : 0, payload[4]];
|
|
1540
|
+
deviceCurrentResolve$1[device.id] = resolve;
|
|
1541
|
+
deviceCurrentReject$1[device.id] = reject;
|
|
1542
|
+
const isKeepAlive = payload[3] === commandIds$1.keepAlive;
|
|
1543
|
+
deviceResponseIdentifier$1[device.id] = [isKeepAlive ? 126 : 0, payload[4]];
|
|
1540
1544
|
const signedData = bridgeSecurity.getSignedCommand(device, payload);
|
|
1541
1545
|
if (!toolsSvc.canCommunicateWith(device.id)) return reject(new Error("Bridge not connected"));
|
|
1542
1546
|
if (signedData.length > 110) {
|
|
@@ -1562,21 +1566,21 @@ const promiseQueue = {
|
|
|
1562
1566
|
);
|
|
1563
1567
|
}
|
|
1564
1568
|
});
|
|
1565
|
-
return withTimeout(promise, 5e3, `Command timed out ${deviceResponseIdentifier[device.id]}, ${device.id}`);
|
|
1569
|
+
return withTimeout(promise, 5e3, `Command timed out ${deviceResponseIdentifier$1[device.id]}, ${device.id}`);
|
|
1566
1570
|
});
|
|
1567
|
-
return devicePromiseQueue[device.id];
|
|
1571
|
+
return devicePromiseQueue$1[device.id];
|
|
1568
1572
|
},
|
|
1569
1573
|
async processMessage(deviceId, payload) {
|
|
1570
1574
|
const numberArray = Array.from(new Uint8Array(payload));
|
|
1571
1575
|
if (numberArray[3] === 127) {
|
|
1572
1576
|
console.error(numberArray);
|
|
1573
|
-
return deviceCurrentReject[deviceId](new Error(`Command not succesful: ${numberArray[4]}`));
|
|
1577
|
+
return deviceCurrentReject$1[deviceId](new Error(`Command not succesful: ${numberArray[4]}`));
|
|
1574
1578
|
}
|
|
1575
1579
|
if ([226, 81].includes(numberArray[3]) && numberArray[4] && toolsSvc.canCommunicateWith(deviceId)) {
|
|
1576
1580
|
store.bridgeRebootRequired[deviceId] = true;
|
|
1577
1581
|
}
|
|
1578
|
-
if ((!deviceResponseIdentifier[deviceId][0] || numberArray[3] === deviceResponseIdentifier[deviceId][0]) && (!deviceResponseIdentifier[deviceId][1] || numberArray[4] === deviceResponseIdentifier[deviceId][1])) {
|
|
1579
|
-
return deviceCurrentResolve[deviceId](numberArray);
|
|
1582
|
+
if ((!deviceResponseIdentifier$1[deviceId][0] || numberArray[3] === deviceResponseIdentifier$1[deviceId][0]) && (!deviceResponseIdentifier$1[deviceId][1] || numberArray[4] === deviceResponseIdentifier$1[deviceId][1])) {
|
|
1583
|
+
return deviceCurrentResolve$1[deviceId](numberArray);
|
|
1580
1584
|
}
|
|
1581
1585
|
console.warn("message from the device not belonging to the pending promise: ", numberArray);
|
|
1582
1586
|
}
|
|
@@ -1593,7 +1597,7 @@ const messageTypeIds = {
|
|
|
1593
1597
|
command: 0,
|
|
1594
1598
|
response: 1
|
|
1595
1599
|
};
|
|
1596
|
-
const commandIds = {
|
|
1600
|
+
const commandIds$1 = {
|
|
1597
1601
|
readData: 34,
|
|
1598
1602
|
writeData: 46,
|
|
1599
1603
|
keepAlive: 62,
|
|
@@ -1642,7 +1646,7 @@ const subCommandIds = {
|
|
|
1642
1646
|
autolearnIdStatus: 176,
|
|
1643
1647
|
autolearnUnknownSensors: 192
|
|
1644
1648
|
};
|
|
1645
|
-
_.invert(commandIds);
|
|
1649
|
+
_.invert(commandIds$1);
|
|
1646
1650
|
_.invert(subCommandIds);
|
|
1647
1651
|
const keepAliveTimer = {};
|
|
1648
1652
|
const bridgeCommands = {
|
|
@@ -1653,7 +1657,7 @@ const bridgeCommands = {
|
|
|
1653
1657
|
},
|
|
1654
1658
|
async setAxlesPressure(deviceId, data) {
|
|
1655
1659
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
1656
|
-
await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.pressurePerAxle, data);
|
|
1660
|
+
await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.pressurePerAxle, data);
|
|
1657
1661
|
},
|
|
1658
1662
|
async setVehicleLayout(deviceId, structurizedPayload) {
|
|
1659
1663
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
@@ -1662,7 +1666,7 @@ const bridgeCommands = {
|
|
|
1662
1666
|
structurizedPayload,
|
|
1663
1667
|
deviceData.advertisingData.fwVersion
|
|
1664
1668
|
);
|
|
1665
|
-
await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.vehicleLayout, payload);
|
|
1669
|
+
await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.vehicleLayout, payload);
|
|
1666
1670
|
},
|
|
1667
1671
|
async getCustomerCANSettings(deviceId) {
|
|
1668
1672
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
@@ -1715,18 +1719,18 @@ const bridgeCommands = {
|
|
|
1715
1719
|
return { ...structurized, isFactory: result.isFactory };
|
|
1716
1720
|
},
|
|
1717
1721
|
async sendKeepAliveCommand(device) {
|
|
1718
|
-
return this.promisify(device, [...this.getCommandHeader(device), 2, commandIds.keepAlive, 0]);
|
|
1722
|
+
return this.promisify(device, [...this.getCommandHeader(device), 2, commandIds$1.keepAlive, 0]);
|
|
1719
1723
|
},
|
|
1720
1724
|
async sendOtaRequest(deviceId) {
|
|
1721
1725
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
1722
|
-
const command = [commandIds.otaRequest, 0];
|
|
1726
|
+
const command = [commandIds$1.otaRequest, 0];
|
|
1723
1727
|
const result = await this.promisify(deviceData, [...this.getCommandHeader(deviceData), command.length, ...command]);
|
|
1724
1728
|
return result;
|
|
1725
1729
|
},
|
|
1726
1730
|
async sendPinCommand(deviceId) {
|
|
1727
1731
|
const deviceData = await bridgeTools.getBridgeFromStore(deviceId);
|
|
1728
1732
|
const pin = await bridgeSecurity.getPin(deviceId);
|
|
1729
|
-
return this.promisify(deviceData, [...this.getCommandHeader(deviceData), 18, commandIds.pin, 0, ...pin]);
|
|
1733
|
+
return this.promisify(deviceData, [...this.getCommandHeader(deviceData), 18, commandIds$1.pin, 0, ...pin]);
|
|
1730
1734
|
},
|
|
1731
1735
|
async setBridgeToRestart(deviceId) {
|
|
1732
1736
|
if (store.bridgeRebootRequired[deviceId]) return;
|
|
@@ -1735,7 +1739,7 @@ const bridgeCommands = {
|
|
|
1735
1739
|
await this.promisify(deviceData, [
|
|
1736
1740
|
...this.getCommandHeader(deviceData),
|
|
1737
1741
|
2,
|
|
1738
|
-
useNewCommand ? commandIds.ecuReset : commandIds.reboot,
|
|
1742
|
+
useNewCommand ? commandIds$1.ecuReset : commandIds$1.reboot,
|
|
1739
1743
|
useNewCommand ? subCommandIds.ecuResetSubCommand : subCommandIds.rebootSubCommand
|
|
1740
1744
|
]);
|
|
1741
1745
|
},
|
|
@@ -1746,7 +1750,7 @@ const bridgeCommands = {
|
|
|
1746
1750
|
structurizedPayload,
|
|
1747
1751
|
deviceData.advertisingData.fwVersion
|
|
1748
1752
|
);
|
|
1749
|
-
return await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.customerCanSettings, payload);
|
|
1753
|
+
return await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.customerCanSettings, payload);
|
|
1750
1754
|
},
|
|
1751
1755
|
async setWorkshopCANSettings(deviceId, structurizedPayload) {
|
|
1752
1756
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
@@ -1755,7 +1759,7 @@ const bridgeCommands = {
|
|
|
1755
1759
|
structurizedPayload,
|
|
1756
1760
|
deviceData.advertisingData.fwVersion
|
|
1757
1761
|
);
|
|
1758
|
-
return await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.workshopCanSettings, payload);
|
|
1762
|
+
return await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.workshopCanSettings, payload);
|
|
1759
1763
|
},
|
|
1760
1764
|
async setCustomerPressureThresholds(deviceId, structurizedPayload) {
|
|
1761
1765
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
@@ -1764,7 +1768,7 @@ const bridgeCommands = {
|
|
|
1764
1768
|
structurizedPayload,
|
|
1765
1769
|
deviceData.advertisingData.fwVersion
|
|
1766
1770
|
);
|
|
1767
|
-
return await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.customerPressureThresholds, payload);
|
|
1771
|
+
return await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.customerPressureThresholds, payload);
|
|
1768
1772
|
},
|
|
1769
1773
|
async setCustomerTemperatureThresholds(deviceId, structurizedPayload) {
|
|
1770
1774
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
@@ -1775,7 +1779,7 @@ const bridgeCommands = {
|
|
|
1775
1779
|
);
|
|
1776
1780
|
return await this.writeCommand(
|
|
1777
1781
|
deviceData,
|
|
1778
|
-
commandIds.writeData,
|
|
1782
|
+
commandIds$1.writeData,
|
|
1779
1783
|
subCommandIds.customerTemperatureThresholds,
|
|
1780
1784
|
payload
|
|
1781
1785
|
);
|
|
@@ -1787,7 +1791,7 @@ const bridgeCommands = {
|
|
|
1787
1791
|
structurizedPayload,
|
|
1788
1792
|
deviceData.advertisingData.fwVersion
|
|
1789
1793
|
);
|
|
1790
|
-
return await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.customerImbalanceThresholds, payload);
|
|
1794
|
+
return await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.customerImbalanceThresholds, payload);
|
|
1791
1795
|
},
|
|
1792
1796
|
async getAutolearnSettings(deviceId) {
|
|
1793
1797
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
@@ -1816,7 +1820,7 @@ const bridgeCommands = {
|
|
|
1816
1820
|
structurizedPayload,
|
|
1817
1821
|
deviceData.advertisingData.fwVersion
|
|
1818
1822
|
);
|
|
1819
|
-
return await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.autolearnSettings, payload);
|
|
1823
|
+
return await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.autolearnSettings, payload);
|
|
1820
1824
|
},
|
|
1821
1825
|
async setAutolearnIdStatus(deviceId, structurizedPayload) {
|
|
1822
1826
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
@@ -1825,7 +1829,7 @@ const bridgeCommands = {
|
|
|
1825
1829
|
structurizedPayload,
|
|
1826
1830
|
deviceData.advertisingData.fwVersion
|
|
1827
1831
|
);
|
|
1828
|
-
return await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.autolearnIdStatus, payload);
|
|
1832
|
+
return await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.autolearnIdStatus, payload);
|
|
1829
1833
|
},
|
|
1830
1834
|
async getAutolearnUnknownSensors(device) {
|
|
1831
1835
|
const result = await this.readCommand(device, subCommandIds.autolearnUnknownSensors);
|
|
@@ -1846,7 +1850,7 @@ const bridgeCommands = {
|
|
|
1846
1850
|
// move logic to bridge svc
|
|
1847
1851
|
async setAxleInfo(deviceId, axleIndex, data) {
|
|
1848
1852
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
1849
|
-
await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.idsPerWheel(axleIndex), data);
|
|
1853
|
+
await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.idsPerWheel(axleIndex), data);
|
|
1850
1854
|
},
|
|
1851
1855
|
async getAxlesPressure(deviceId) {
|
|
1852
1856
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
@@ -1870,7 +1874,7 @@ const bridgeCommands = {
|
|
|
1870
1874
|
structurizedPayload,
|
|
1871
1875
|
deviceData.advertisingData.fwVersion
|
|
1872
1876
|
);
|
|
1873
|
-
return await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.pressurePerAxle, payload);
|
|
1877
|
+
return await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.pressurePerAxle, payload);
|
|
1874
1878
|
},
|
|
1875
1879
|
// // async setPressureThresholds(device: BleBridge, rules: any) {
|
|
1876
1880
|
// // // https://tirecheck.atlassian.net/wiki/spaces/HWPRG/pages/6547767302/Technical+Design+Document+BLE+CAN+Bridge+Krone#Example.1
|
|
@@ -1913,7 +1917,7 @@ const bridgeCommands = {
|
|
|
1913
1917
|
}
|
|
1914
1918
|
const result = await this.writeCommand(
|
|
1915
1919
|
deviceData,
|
|
1916
|
-
commandIds.sensorMeasurement,
|
|
1920
|
+
commandIds$1.sensorMeasurement,
|
|
1917
1921
|
subCommandIds.sensorMeasurementPerWheel(axlePosition, tyrePosition, isTwinTyre, isSpare),
|
|
1918
1922
|
[]
|
|
1919
1923
|
);
|
|
@@ -1924,7 +1928,7 @@ const bridgeCommands = {
|
|
|
1924
1928
|
const result = await this.promisify(device, [
|
|
1925
1929
|
...this.getCommandHeader(device),
|
|
1926
1930
|
commandLength,
|
|
1927
|
-
commandIds.readData,
|
|
1931
|
+
commandIds$1.readData,
|
|
1928
1932
|
subCommandId
|
|
1929
1933
|
]);
|
|
1930
1934
|
const data = result.slice(19, result.length - 8);
|
|
@@ -2889,6 +2893,344 @@ const pressureStick = {
|
|
|
2889
2893
|
onPressure: pressureStickService.onPressure
|
|
2890
2894
|
};
|
|
2891
2895
|
|
|
2896
|
+
const devicePromiseQueue = {};
|
|
2897
|
+
const deviceCurrentResolve = {};
|
|
2898
|
+
const deviceCurrentReject = {};
|
|
2899
|
+
const deviceResponseIdentifier = {};
|
|
2900
|
+
const deviceCurrentPartialMessage = {};
|
|
2901
|
+
const torqueWrenchPromiseQueue = {
|
|
2902
|
+
clearQueue(deviceId, message) {
|
|
2903
|
+
if (deviceCurrentReject[deviceId]) {
|
|
2904
|
+
deviceCurrentReject[deviceId](new Error(message ?? "Stopped sending commands"));
|
|
2905
|
+
}
|
|
2906
|
+
devicePromiseQueue[deviceId] = Promise.resolve();
|
|
2907
|
+
deviceResponseIdentifier[deviceId] = void 0;
|
|
2908
|
+
},
|
|
2909
|
+
async enqueue(deviceId, communication, payload, responseIdentifier, mtu = 20) {
|
|
2910
|
+
if (devicePromiseQueue[deviceId] === void 0) devicePromiseQueue[deviceId] = Promise.resolve();
|
|
2911
|
+
devicePromiseQueue[deviceId] = devicePromiseQueue[deviceId].then(() => {
|
|
2912
|
+
const promise = new Promise((resolve, reject) => {
|
|
2913
|
+
deviceCurrentResolve[deviceId] = resolve;
|
|
2914
|
+
deviceCurrentReject[deviceId] = reject;
|
|
2915
|
+
deviceResponseIdentifier[deviceId] = responseIdentifier;
|
|
2916
|
+
deviceCurrentPartialMessage[deviceId] = [];
|
|
2917
|
+
if (!toolsSvc.canCommunicateWith(deviceId)) return reject(new Error("Torque wrench not connected"));
|
|
2918
|
+
const chunks = [];
|
|
2919
|
+
for (let i = 0; i < payload.length; i += mtu) {
|
|
2920
|
+
chunks.push(payload.slice(i, i + mtu));
|
|
2921
|
+
}
|
|
2922
|
+
for (const chunk of chunks) {
|
|
2923
|
+
const convertedChunk = new Uint8Array(chunk).buffer;
|
|
2924
|
+
bluetooth.write(deviceId, communication.serviceId, communication.characteristicId, convertedChunk);
|
|
2925
|
+
}
|
|
2926
|
+
});
|
|
2927
|
+
return withTimeout(promise, 5e3, `Command timed out ${deviceResponseIdentifier[deviceId]}, ${deviceId}`);
|
|
2928
|
+
});
|
|
2929
|
+
return devicePromiseQueue[deviceId];
|
|
2930
|
+
},
|
|
2931
|
+
async processMessage(deviceId, payload, getIdentifier, isComplete, isError) {
|
|
2932
|
+
const numberArray = Array.from(new Uint8Array(payload));
|
|
2933
|
+
if (!deviceCurrentPartialMessage[deviceId]) deviceCurrentPartialMessage[deviceId] = [];
|
|
2934
|
+
deviceCurrentPartialMessage[deviceId] = _.concat(deviceCurrentPartialMessage[deviceId], numberArray);
|
|
2935
|
+
if (!isComplete(deviceCurrentPartialMessage[deviceId])) {
|
|
2936
|
+
return;
|
|
2937
|
+
}
|
|
2938
|
+
if (isError(deviceCurrentPartialMessage[deviceId])) {
|
|
2939
|
+
return deviceCurrentReject[deviceId](
|
|
2940
|
+
new Error("Error response", { cause: deviceCurrentPartialMessage[deviceId] })
|
|
2941
|
+
);
|
|
2942
|
+
}
|
|
2943
|
+
const identifier = getIdentifier(deviceCurrentPartialMessage[deviceId]);
|
|
2944
|
+
if (deviceResponseIdentifier[deviceId] === identifier) {
|
|
2945
|
+
deviceCurrentResolve[deviceId](deviceCurrentPartialMessage[deviceId]);
|
|
2946
|
+
}
|
|
2947
|
+
}
|
|
2948
|
+
};
|
|
2949
|
+
|
|
2950
|
+
const commandStart = "$9";
|
|
2951
|
+
const commandEnd = "*";
|
|
2952
|
+
const commandIds = {
|
|
2953
|
+
error: "004",
|
|
2954
|
+
acknowledge: "005",
|
|
2955
|
+
commTest: "100",
|
|
2956
|
+
getProperties: "120",
|
|
2957
|
+
startJob: "204",
|
|
2958
|
+
stopJob: "206",
|
|
2959
|
+
getNumberOfReadings: "224",
|
|
2960
|
+
getReading: "200",
|
|
2961
|
+
// Can only be called once for each reading.
|
|
2962
|
+
getReadingAgain: "202",
|
|
2963
|
+
getBattery: "150",
|
|
2964
|
+
getTime: "209",
|
|
2965
|
+
setTime: "208"
|
|
2966
|
+
};
|
|
2967
|
+
const errors = {
|
|
2968
|
+
"01": "Bad string",
|
|
2969
|
+
"02": "Bad checksum",
|
|
2970
|
+
"03": "Unknown command",
|
|
2971
|
+
"04": "No device present for command to act on",
|
|
2972
|
+
"05": "Invalid sample speed",
|
|
2973
|
+
"06": "Torque module offset difference bigger than 25%",
|
|
2974
|
+
"07": "Torque module gain outside 0.9 to 1.1",
|
|
2975
|
+
"08": "No RF properties",
|
|
2976
|
+
"09": "No reply from RF",
|
|
2977
|
+
"0A": "RF device already paired on this device",
|
|
2978
|
+
"0C": "Invalid frequency",
|
|
2979
|
+
"0D": "Invalid LED selection",
|
|
2980
|
+
"0F": "Transducer preloaded",
|
|
2981
|
+
"10": "No more readings",
|
|
2982
|
+
"11": "Job already loaded",
|
|
2983
|
+
"12": "No trace stored",
|
|
2984
|
+
"13": "Wrong transducers selected for Multi Start Mode",
|
|
2985
|
+
"14": "No short trace stored",
|
|
2986
|
+
"15": "Job finished",
|
|
2987
|
+
"16": "Missing time and date",
|
|
2988
|
+
"17": "Bad units for wrench type",
|
|
2989
|
+
"18": "Battery low"
|
|
2990
|
+
};
|
|
2991
|
+
const twMeta = deviceMeta.torqueWrench;
|
|
2992
|
+
const torqueWrenchCommands = {
|
|
2993
|
+
async sendCommand(deviceId, command, params) {
|
|
2994
|
+
const commandId = commandIds[command];
|
|
2995
|
+
let message = `${commandStart}${commandId}`;
|
|
2996
|
+
if (params?.length) {
|
|
2997
|
+
message += `,${params.join(",")}`;
|
|
2998
|
+
}
|
|
2999
|
+
message += commandEnd;
|
|
3000
|
+
const crc = getChecksum(message);
|
|
3001
|
+
message += `${crc}\r`;
|
|
3002
|
+
const array = new Uint8Array(message.length);
|
|
3003
|
+
for (let i = 0, l = message.length; i < l; i++) {
|
|
3004
|
+
array[i] = message.charCodeAt(i);
|
|
3005
|
+
}
|
|
3006
|
+
const decimalArray = Array.from(array);
|
|
3007
|
+
let result;
|
|
3008
|
+
try {
|
|
3009
|
+
result = await torqueWrenchPromiseQueue.enqueue(deviceId, twMeta.communication, decimalArray, commandIds[command]);
|
|
3010
|
+
} catch (error) {
|
|
3011
|
+
const formattedError = formatError(error);
|
|
3012
|
+
throw new Error(formattedError);
|
|
3013
|
+
}
|
|
3014
|
+
return result.map((num) => String.fromCharCode(num)).join("");
|
|
3015
|
+
},
|
|
3016
|
+
processMessage(deviceId, payload) {
|
|
3017
|
+
torqueWrenchPromiseQueue.processMessage(deviceId, payload, getIdentifier, isComplete, isError);
|
|
3018
|
+
}
|
|
3019
|
+
};
|
|
3020
|
+
function isComplete(message) {
|
|
3021
|
+
const completeReading = message[0] === 123 && message.at(-1) === 13;
|
|
3022
|
+
const completeCommand = message[0] === 36 && message.at(-1) === 13;
|
|
3023
|
+
return completeReading || completeCommand;
|
|
3024
|
+
}
|
|
3025
|
+
function isError(message) {
|
|
3026
|
+
return message[4] === 52;
|
|
3027
|
+
}
|
|
3028
|
+
function getIdentifier(message) {
|
|
3029
|
+
if (message[0] === 123) return "200";
|
|
3030
|
+
return message.slice(6, 9).map((num) => String.fromCharCode(num)).join("");
|
|
3031
|
+
}
|
|
3032
|
+
function getChecksum(message) {
|
|
3033
|
+
let checksum = 0;
|
|
3034
|
+
for (const ch of message) {
|
|
3035
|
+
checksum ^= ch.charCodeAt(0);
|
|
3036
|
+
}
|
|
3037
|
+
return decimalToHex(checksum).toUpperCase();
|
|
3038
|
+
}
|
|
3039
|
+
function formatError(error) {
|
|
3040
|
+
if (!error.cause) throw new Error(error);
|
|
3041
|
+
const message = error.cause.slice(6, 8);
|
|
3042
|
+
const errorId = message.map((num) => String.fromCharCode(num)).join("");
|
|
3043
|
+
return errors[errorId] || "Unknown error";
|
|
3044
|
+
}
|
|
3045
|
+
|
|
3046
|
+
let jobInterval = null;
|
|
3047
|
+
const torqueWrenchService = {
|
|
3048
|
+
onReading(callback) {
|
|
3049
|
+
simulatorSvc.registerEvent("tw:reading", callback);
|
|
3050
|
+
},
|
|
3051
|
+
async getProperties(deviceId) {
|
|
3052
|
+
const result = {
|
|
3053
|
+
serialNumber: "",
|
|
3054
|
+
span: 0,
|
|
3055
|
+
calibrationDate: "",
|
|
3056
|
+
ppr: 0,
|
|
3057
|
+
units: "Nm",
|
|
3058
|
+
threshold: 10
|
|
3059
|
+
};
|
|
3060
|
+
const message = await torqueWrenchCommands.sendCommand(deviceId, "getProperties");
|
|
3061
|
+
const params = getMessageParams(message);
|
|
3062
|
+
if (params[4] === "3") result.units = "Nm";
|
|
3063
|
+
else if (params[4] === "7") result.units = "lb-ft";
|
|
3064
|
+
result.serialNumber = params[0];
|
|
3065
|
+
result.span = Number.parseInt(params[1]);
|
|
3066
|
+
if (result.units === "lb-ft") result.span = Math.floor(result.span * 0.738);
|
|
3067
|
+
result.calibrationDate = params[2];
|
|
3068
|
+
result.ppr = Number.parseInt(params[3]);
|
|
3069
|
+
return result;
|
|
3070
|
+
},
|
|
3071
|
+
async startJob(deviceId, params) {
|
|
3072
|
+
await this.stopJob(deviceId);
|
|
3073
|
+
const { units, span, ppr, threshold } = store.torqueWrenchProperties[deviceId];
|
|
3074
|
+
console.log("\u{1F680} ~ startJob ~ units:", units);
|
|
3075
|
+
const { torqueMin, torqueMax, angleMin, angleMax, direction, jobTimeout } = params;
|
|
3076
|
+
const msgParams = {
|
|
3077
|
+
id: "01",
|
|
3078
|
+
nuts: decimalToHex(params.nuts),
|
|
3079
|
+
mode: units === "lb-ft" ? "20" : "1",
|
|
3080
|
+
// Peak measurement mode
|
|
3081
|
+
cycle: "7",
|
|
3082
|
+
// 10 seconds cycle (probably for measurements - not sure what it does exactly, not specified in docs)
|
|
3083
|
+
control: torqueMin != null || torqueMax != null ? "0" : "1",
|
|
3084
|
+
direction: direction === "counter-clockwise" ? "1" : "0",
|
|
3085
|
+
minTorqueThreshold: torqueToAdcParam(threshold, span, units),
|
|
3086
|
+
torqueMin: torqueToAdcParam(torqueMin ?? 0, span, units),
|
|
3087
|
+
torqueMax: torqueToAdcParam(torqueMax ?? -1, span, units),
|
|
3088
|
+
clickThreshold: torqueToAdcParam(threshold, span, units),
|
|
3089
|
+
// Probably not used in our case (for this specified mode).
|
|
3090
|
+
angleMin: angleToPulsesParam(angleMin ?? 0, ppr),
|
|
3091
|
+
angleMax: angleToPulsesParam(angleMax ?? -1, ppr),
|
|
3092
|
+
frequency: "0542"
|
|
3093
|
+
// No idea
|
|
3094
|
+
};
|
|
3095
|
+
const paramsString = Object.values(msgParams);
|
|
3096
|
+
await torqueWrenchCommands.sendCommand(deviceId, "startJob", paramsString);
|
|
3097
|
+
jobInterval = setInterval(async () => {
|
|
3098
|
+
const numberOfReading = await this.getNumberOfReadings(deviceId);
|
|
3099
|
+
console.log("\u{1F680} ~ jobInterval=setInterval ~ numberOfReading:", numberOfReading);
|
|
3100
|
+
if (numberOfReading.count > 0) this.getReading(deviceId);
|
|
3101
|
+
}, 1e3);
|
|
3102
|
+
if (jobTimeout) {
|
|
3103
|
+
await new Promise(
|
|
3104
|
+
(resolve) => setTimeout(() => {
|
|
3105
|
+
console.log("job terminated");
|
|
3106
|
+
clearInterval(jobInterval);
|
|
3107
|
+
this.stopJob(deviceId);
|
|
3108
|
+
resolve("");
|
|
3109
|
+
}, jobTimeout * 1e3)
|
|
3110
|
+
);
|
|
3111
|
+
}
|
|
3112
|
+
},
|
|
3113
|
+
async stopJob(deviceId) {
|
|
3114
|
+
return torqueWrenchCommands.sendCommand(deviceId, "stopJob");
|
|
3115
|
+
},
|
|
3116
|
+
async getNumberOfReadings(deviceId) {
|
|
3117
|
+
const message = await torqueWrenchCommands.sendCommand(deviceId, "getNumberOfReadings");
|
|
3118
|
+
const params = getMessageParams(message);
|
|
3119
|
+
return { count: Number(params[0]), jobId: params[1] };
|
|
3120
|
+
},
|
|
3121
|
+
async getReading(deviceId) {
|
|
3122
|
+
const reading = await torqueWrenchCommands.sendCommand(deviceId, "getReading");
|
|
3123
|
+
const properties = {
|
|
3124
|
+
jobId: reading.slice(2, 4),
|
|
3125
|
+
nut: reading.slice(4, 6),
|
|
3126
|
+
torqueAdc: reading.slice(6, 10),
|
|
3127
|
+
anglePulses: reading.slice(10, 14),
|
|
3128
|
+
duration: reading.slice(14, 18)
|
|
3129
|
+
};
|
|
3130
|
+
const torque = adcToTorque(
|
|
3131
|
+
properties.torqueAdc,
|
|
3132
|
+
store.torqueWrenchProperties[deviceId].span,
|
|
3133
|
+
store.torqueWrenchProperties[deviceId].units
|
|
3134
|
+
);
|
|
3135
|
+
const angle = pulsesToAngle(properties.anglePulses, store.torqueWrenchProperties[deviceId].ppr);
|
|
3136
|
+
const formattedReading = {
|
|
3137
|
+
jobId: Number.parseInt(properties.jobId, 16),
|
|
3138
|
+
nut: Number.parseInt(properties.nut, 16),
|
|
3139
|
+
torque,
|
|
3140
|
+
angle,
|
|
3141
|
+
duration: Number.parseInt(properties.duration, 16) / 1e3
|
|
3142
|
+
};
|
|
3143
|
+
simulatorSvc.triggerEvent("tw:reading", deviceId, formattedReading);
|
|
3144
|
+
},
|
|
3145
|
+
// getReadingAgain(deviceId: string) {
|
|
3146
|
+
// return torqueWrenchCommands.sendCommand(deviceId, 'getNumberOfReadings')
|
|
3147
|
+
// },
|
|
3148
|
+
async getBattery(deviceId) {
|
|
3149
|
+
const message = await torqueWrenchCommands.sendCommand(deviceId, "getBattery");
|
|
3150
|
+
const params = getMessageParams(message);
|
|
3151
|
+
return Number(params[0]);
|
|
3152
|
+
},
|
|
3153
|
+
async getTime(deviceId) {
|
|
3154
|
+
const message = await torqueWrenchCommands.sendCommand(deviceId, "getTime");
|
|
3155
|
+
const match = message.match(/209,([^*]*)\*/);
|
|
3156
|
+
console.log("\u{1F680} ~ getTime ~ match:", match);
|
|
3157
|
+
if (!match[1]) throw new Error("Invalid time response");
|
|
3158
|
+
const hh = match[1].substring(0, 2);
|
|
3159
|
+
const mm = match[1].substring(2, 4);
|
|
3160
|
+
const ss = match[1].substring(4, 6);
|
|
3161
|
+
const dd = match[1].substring(6, 8);
|
|
3162
|
+
const MM = match[1].substring(8, 10);
|
|
3163
|
+
const yy = match[1].substring(10, 12);
|
|
3164
|
+
const fullYear = `20${yy}`;
|
|
3165
|
+
return /* @__PURE__ */ new Date(`${fullYear}-${MM}-${dd}T${hh}:${mm}:${ss}Z`);
|
|
3166
|
+
},
|
|
3167
|
+
setTime(deviceId, date) {
|
|
3168
|
+
const hours = String(date.getHours()).padStart(2, "0");
|
|
3169
|
+
const minutes = String(date.getMinutes()).padStart(2, "0");
|
|
3170
|
+
const seconds = String(date.getSeconds()).padStart(2, "0");
|
|
3171
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
3172
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
3173
|
+
const year = String(date.getFullYear()).slice(-2);
|
|
3174
|
+
const params = [hours, minutes, seconds, day, month, year];
|
|
3175
|
+
return torqueWrenchCommands.sendCommand(deviceId, "setTime", params);
|
|
3176
|
+
}
|
|
3177
|
+
};
|
|
3178
|
+
function torqueToAdcParam(value, span, deviceUnits) {
|
|
3179
|
+
if (value < 0) return "FFFF";
|
|
3180
|
+
if (deviceUnits !== "Nm") value = value * 0.738;
|
|
3181
|
+
const adc = Math.round(value / span * 16384);
|
|
3182
|
+
return decimalToHex(adc, 4).toUpperCase();
|
|
3183
|
+
}
|
|
3184
|
+
function angleToPulsesParam(value, ppr) {
|
|
3185
|
+
if (value < 0) return "FFFF";
|
|
3186
|
+
const pulses = Math.round(value * ppr / 90);
|
|
3187
|
+
return decimalToHex(pulses, 4).toUpperCase();
|
|
3188
|
+
}
|
|
3189
|
+
function getMessageParams(message) {
|
|
3190
|
+
return message.match(/^\$[^,]+,[^,]+,(.*)\*/)?.[1].split(",") || [];
|
|
3191
|
+
}
|
|
3192
|
+
function adcToTorque(value, span, units) {
|
|
3193
|
+
const torque = Number.parseInt(value, 16) * span / 16384;
|
|
3194
|
+
if (units !== "Nm") return torque / 0.738;
|
|
3195
|
+
return torque;
|
|
3196
|
+
}
|
|
3197
|
+
function pulsesToAngle(value, ppr) {
|
|
3198
|
+
return Number.parseInt(value, 16) * 90 / ppr;
|
|
3199
|
+
}
|
|
3200
|
+
|
|
3201
|
+
const torqueWrench = {
|
|
3202
|
+
async connect(deviceId) {
|
|
3203
|
+
const twMeta = deviceMeta.torqueWrench;
|
|
3204
|
+
await bluetooth.connect(deviceId, this.disconnect);
|
|
3205
|
+
await ble.startNotification(
|
|
3206
|
+
deviceId,
|
|
3207
|
+
twMeta.communication.serviceId,
|
|
3208
|
+
twMeta.communication.characteristicId,
|
|
3209
|
+
(notification) => {
|
|
3210
|
+
torqueWrenchCommands.processMessage(deviceId, notification);
|
|
3211
|
+
},
|
|
3212
|
+
(error) => console.warn("ble.startNotification error", error)
|
|
3213
|
+
);
|
|
3214
|
+
const properties = await torqueWrenchService.getProperties(deviceId);
|
|
3215
|
+
store.torqueWrenchProperties[deviceId] = properties;
|
|
3216
|
+
store.setState(deviceId, "paired");
|
|
3217
|
+
},
|
|
3218
|
+
async disconnect(deviceId, reason) {
|
|
3219
|
+
store.setState(deviceId, "disconnecting");
|
|
3220
|
+
await bluetooth.disconnect(deviceId);
|
|
3221
|
+
store.setState(deviceId, void 0, reason ?? "manualDisconnection");
|
|
3222
|
+
},
|
|
3223
|
+
getProperties: torqueWrenchService.getProperties,
|
|
3224
|
+
setTime: torqueWrenchService.setTime,
|
|
3225
|
+
startJob: torqueWrenchService.startJob,
|
|
3226
|
+
stopJob: torqueWrenchService.stopJob,
|
|
3227
|
+
getNumberOfReadings: torqueWrenchService.getNumberOfReadings,
|
|
3228
|
+
getReading: torqueWrenchService.getReading,
|
|
3229
|
+
getBattery: torqueWrenchService.getBattery,
|
|
3230
|
+
getTime: torqueWrenchService.getTime,
|
|
3231
|
+
onReading: torqueWrenchService.onReading
|
|
3232
|
+
};
|
|
3233
|
+
|
|
2892
3234
|
const bridgeSimulator = {
|
|
2893
3235
|
isRebootRequired(deviceId) {
|
|
2894
3236
|
return store.bridgeRebootRequired[deviceId];
|
|
@@ -3489,10 +3831,14 @@ function createTirecheckDeviceSdk(platform, bleImplementation, securityKeys) {
|
|
|
3489
3831
|
bridgeOta,
|
|
3490
3832
|
/** Methods for working with Tirecheck TPMS FlexiGauge */
|
|
3491
3833
|
flexiGaugeTpms,
|
|
3834
|
+
// flexiGauge,
|
|
3492
3835
|
/** Methods for working with Tirecheck Pressure Stick */
|
|
3493
3836
|
pressureStick,
|
|
3837
|
+
// ateq,
|
|
3494
3838
|
/** Allows simulating devices without actually using bluetooth */
|
|
3495
|
-
simulator
|
|
3839
|
+
simulator,
|
|
3840
|
+
/** Methods for working with Tirecheck Torque Wrench */
|
|
3841
|
+
torqueWrench
|
|
3496
3842
|
};
|
|
3497
3843
|
}
|
|
3498
3844
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tirecheck-device-sdk",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.22",
|
|
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",
|