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.mjs
CHANGED
|
@@ -40,6 +40,8 @@ const store = {
|
|
|
40
40
|
// undefined => connecting => connected => paired => disconnecting => undefined
|
|
41
41
|
/** some bridge commands require bridge reboot to be completed */
|
|
42
42
|
bridgeRebootRequired: {},
|
|
43
|
+
/** Torque wrench properties, about device settings, mainly used for unit conversion */
|
|
44
|
+
torqueWrenchProperties: {},
|
|
43
45
|
//** 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 */
|
|
44
46
|
deviceIdMapingTable: {},
|
|
45
47
|
/** 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 */
|
|
@@ -97,6 +99,10 @@ function stringToArrayBuffer(string) {
|
|
|
97
99
|
}
|
|
98
100
|
return array.buffer;
|
|
99
101
|
}
|
|
102
|
+
function decimalToHex(decimal, padStart = 2) {
|
|
103
|
+
const hex = decimal.toString(16);
|
|
104
|
+
return hex.padStart(padStart, "0");
|
|
105
|
+
}
|
|
100
106
|
const toolsSvc = {
|
|
101
107
|
delay,
|
|
102
108
|
setIntervalImmediate,
|
|
@@ -511,8 +517,26 @@ const deviceMeta = {
|
|
|
511
517
|
},
|
|
512
518
|
getDeviceInfoFromAdvertising: bridgeOtaAdvertisingParser.getDeviceInfoFromAdvertising
|
|
513
519
|
},
|
|
520
|
+
// flexiGauge: {
|
|
521
|
+
// nameRegex: /^Flexi.*v.*/,
|
|
522
|
+
// communication: {
|
|
523
|
+
// serviceId: '4880c12c-fdcb-4077-8920-a450d7f9b907',
|
|
524
|
+
// characteristicId: 'fec26ec4-6d71-4442-9f81-55bc21d658d6',
|
|
525
|
+
// },
|
|
526
|
+
// battery: {
|
|
527
|
+
// serviceId: '180f',
|
|
528
|
+
// characteristicId: '2a19',
|
|
529
|
+
// },
|
|
530
|
+
// getDeviceInfoFromAdvertising: (device: PeripheralData) => {
|
|
531
|
+
// const bleDevice: BleDevice = {
|
|
532
|
+
// ...device,
|
|
533
|
+
// type: 'flexiGauge',
|
|
534
|
+
// }
|
|
535
|
+
// return bleDevice
|
|
536
|
+
// },
|
|
537
|
+
// },
|
|
514
538
|
flexiGaugeTpms: {
|
|
515
|
-
nameRegex: /^Flexi.*/,
|
|
539
|
+
nameRegex: /^Flexi.*TPMS.*/,
|
|
516
540
|
communication: {
|
|
517
541
|
serviceId: "4880c12c-fdcb-4077-8920-a450d7f9b907",
|
|
518
542
|
characteristicId: "fec26ec4-6d71-4442-9f81-55bc21d658d6"
|
|
@@ -527,9 +551,7 @@ const deviceMeta = {
|
|
|
527
551
|
type: "flexiGaugeTpms"
|
|
528
552
|
};
|
|
529
553
|
return bleDevice;
|
|
530
|
-
}
|
|
531
|
-
reconnect: true
|
|
532
|
-
// Do we need it here?
|
|
554
|
+
}
|
|
533
555
|
},
|
|
534
556
|
pressureStick: {
|
|
535
557
|
nameRegex: /Pressure Stick.*/,
|
|
@@ -544,6 +566,42 @@ const deviceMeta = {
|
|
|
544
566
|
};
|
|
545
567
|
return bleDevice;
|
|
546
568
|
}
|
|
569
|
+
},
|
|
570
|
+
// ateq: {
|
|
571
|
+
// nameRegex: /ATEQ.*/,
|
|
572
|
+
// communication: {
|
|
573
|
+
// serviceId: 'a002',
|
|
574
|
+
// characteristicId: 'c305',
|
|
575
|
+
// },
|
|
576
|
+
// indicate: {
|
|
577
|
+
// serviceId: 'a002',
|
|
578
|
+
// characteristicId: 'c306',
|
|
579
|
+
// },
|
|
580
|
+
// getDeviceInfoFromAdvertising: (device: PeripheralData) => {
|
|
581
|
+
// const bleDevice: BleDevice = {
|
|
582
|
+
// ...device,
|
|
583
|
+
// type: 'ateq',
|
|
584
|
+
// }
|
|
585
|
+
// return bleDevice
|
|
586
|
+
// },
|
|
587
|
+
// },
|
|
588
|
+
torqueWrench: {
|
|
589
|
+
nameRegex: /^\d+(lbft|NM)-\d+$/i,
|
|
590
|
+
communication: {
|
|
591
|
+
serviceId: "49535343-fe7d-4ae5-8fa9-9fafd205e455",
|
|
592
|
+
characteristicId: "49535343-1e4d-4bd9-ba61-23c647249616"
|
|
593
|
+
},
|
|
594
|
+
battery: {
|
|
595
|
+
serviceId: "180f",
|
|
596
|
+
characteristicId: "2a19"
|
|
597
|
+
},
|
|
598
|
+
getDeviceInfoFromAdvertising: (device) => {
|
|
599
|
+
const bleDevice = {
|
|
600
|
+
...device,
|
|
601
|
+
type: "torqueWrench"
|
|
602
|
+
};
|
|
603
|
+
return bleDevice;
|
|
604
|
+
}
|
|
547
605
|
}
|
|
548
606
|
};
|
|
549
607
|
|
|
@@ -1517,26 +1575,26 @@ const bridgeSecurity = {
|
|
|
1517
1575
|
};
|
|
1518
1576
|
|
|
1519
1577
|
const bridgeMeta = deviceMeta.bridge;
|
|
1520
|
-
const devicePromiseQueue = {};
|
|
1521
|
-
const deviceCurrentResolve = {};
|
|
1522
|
-
const deviceCurrentReject = {};
|
|
1523
|
-
const deviceResponseIdentifier = {};
|
|
1578
|
+
const devicePromiseQueue$1 = {};
|
|
1579
|
+
const deviceCurrentResolve$1 = {};
|
|
1580
|
+
const deviceCurrentReject$1 = {};
|
|
1581
|
+
const deviceResponseIdentifier$1 = {};
|
|
1524
1582
|
const promiseQueue = {
|
|
1525
1583
|
clearQueue(deviceId, message) {
|
|
1526
|
-
if (deviceCurrentReject[deviceId]) {
|
|
1527
|
-
deviceCurrentReject[deviceId](new Error(message ?? "Stopped sending commands"));
|
|
1584
|
+
if (deviceCurrentReject$1[deviceId]) {
|
|
1585
|
+
deviceCurrentReject$1[deviceId](new Error(message ?? "Stopped sending commands"));
|
|
1528
1586
|
}
|
|
1529
|
-
devicePromiseQueue[deviceId] = Promise.resolve();
|
|
1530
|
-
deviceResponseIdentifier[deviceId] = [];
|
|
1587
|
+
devicePromiseQueue$1[deviceId] = Promise.resolve();
|
|
1588
|
+
deviceResponseIdentifier$1[deviceId] = [];
|
|
1531
1589
|
},
|
|
1532
1590
|
async enqueue(device, payload) {
|
|
1533
|
-
if (devicePromiseQueue[device.id] === void 0) devicePromiseQueue[device.id] = Promise.resolve();
|
|
1534
|
-
devicePromiseQueue[device.id] = devicePromiseQueue[device.id].then(() => {
|
|
1591
|
+
if (devicePromiseQueue$1[device.id] === void 0) devicePromiseQueue$1[device.id] = Promise.resolve();
|
|
1592
|
+
devicePromiseQueue$1[device.id] = devicePromiseQueue$1[device.id].then(() => {
|
|
1535
1593
|
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]];
|
|
1594
|
+
deviceCurrentResolve$1[device.id] = resolve;
|
|
1595
|
+
deviceCurrentReject$1[device.id] = reject;
|
|
1596
|
+
const isKeepAlive = payload[3] === commandIds$1.keepAlive;
|
|
1597
|
+
deviceResponseIdentifier$1[device.id] = [isKeepAlive ? 126 : 0, payload[4]];
|
|
1540
1598
|
const signedData = bridgeSecurity.getSignedCommand(device, payload);
|
|
1541
1599
|
if (!toolsSvc.canCommunicateWith(device.id)) return reject(new Error("Bridge not connected"));
|
|
1542
1600
|
if (signedData.length > 110) {
|
|
@@ -1562,21 +1620,21 @@ const promiseQueue = {
|
|
|
1562
1620
|
);
|
|
1563
1621
|
}
|
|
1564
1622
|
});
|
|
1565
|
-
return withTimeout(promise, 5e3, `Command timed out ${deviceResponseIdentifier[device.id]}, ${device.id}`);
|
|
1623
|
+
return withTimeout(promise, 5e3, `Command timed out ${deviceResponseIdentifier$1[device.id]}, ${device.id}`);
|
|
1566
1624
|
});
|
|
1567
|
-
return devicePromiseQueue[device.id];
|
|
1625
|
+
return devicePromiseQueue$1[device.id];
|
|
1568
1626
|
},
|
|
1569
1627
|
async processMessage(deviceId, payload) {
|
|
1570
1628
|
const numberArray = Array.from(new Uint8Array(payload));
|
|
1571
1629
|
if (numberArray[3] === 127) {
|
|
1572
1630
|
console.error(numberArray);
|
|
1573
|
-
return deviceCurrentReject[deviceId](new Error(`Command not succesful: ${numberArray[4]}`));
|
|
1631
|
+
return deviceCurrentReject$1[deviceId](new Error(`Command not succesful: ${numberArray[4]}`));
|
|
1574
1632
|
}
|
|
1575
1633
|
if ([226, 81].includes(numberArray[3]) && numberArray[4] && toolsSvc.canCommunicateWith(deviceId)) {
|
|
1576
1634
|
store.bridgeRebootRequired[deviceId] = true;
|
|
1577
1635
|
}
|
|
1578
|
-
if ((!deviceResponseIdentifier[deviceId][0] || numberArray[3] === deviceResponseIdentifier[deviceId][0]) && (!deviceResponseIdentifier[deviceId][1] || numberArray[4] === deviceResponseIdentifier[deviceId][1])) {
|
|
1579
|
-
return deviceCurrentResolve[deviceId](numberArray);
|
|
1636
|
+
if ((!deviceResponseIdentifier$1[deviceId][0] || numberArray[3] === deviceResponseIdentifier$1[deviceId][0]) && (!deviceResponseIdentifier$1[deviceId][1] || numberArray[4] === deviceResponseIdentifier$1[deviceId][1])) {
|
|
1637
|
+
return deviceCurrentResolve$1[deviceId](numberArray);
|
|
1580
1638
|
}
|
|
1581
1639
|
console.warn("message from the device not belonging to the pending promise: ", numberArray);
|
|
1582
1640
|
}
|
|
@@ -1593,7 +1651,7 @@ const messageTypeIds = {
|
|
|
1593
1651
|
command: 0,
|
|
1594
1652
|
response: 1
|
|
1595
1653
|
};
|
|
1596
|
-
const commandIds = {
|
|
1654
|
+
const commandIds$1 = {
|
|
1597
1655
|
readData: 34,
|
|
1598
1656
|
writeData: 46,
|
|
1599
1657
|
keepAlive: 62,
|
|
@@ -1642,7 +1700,7 @@ const subCommandIds = {
|
|
|
1642
1700
|
autolearnIdStatus: 176,
|
|
1643
1701
|
autolearnUnknownSensors: 192
|
|
1644
1702
|
};
|
|
1645
|
-
_.invert(commandIds);
|
|
1703
|
+
_.invert(commandIds$1);
|
|
1646
1704
|
_.invert(subCommandIds);
|
|
1647
1705
|
const keepAliveTimer = {};
|
|
1648
1706
|
const bridgeCommands = {
|
|
@@ -1653,7 +1711,7 @@ const bridgeCommands = {
|
|
|
1653
1711
|
},
|
|
1654
1712
|
async setAxlesPressure(deviceId, data) {
|
|
1655
1713
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
1656
|
-
await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.pressurePerAxle, data);
|
|
1714
|
+
await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.pressurePerAxle, data);
|
|
1657
1715
|
},
|
|
1658
1716
|
async setVehicleLayout(deviceId, structurizedPayload) {
|
|
1659
1717
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
@@ -1662,7 +1720,7 @@ const bridgeCommands = {
|
|
|
1662
1720
|
structurizedPayload,
|
|
1663
1721
|
deviceData.advertisingData.fwVersion
|
|
1664
1722
|
);
|
|
1665
|
-
await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.vehicleLayout, payload);
|
|
1723
|
+
await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.vehicleLayout, payload);
|
|
1666
1724
|
},
|
|
1667
1725
|
async getCustomerCANSettings(deviceId) {
|
|
1668
1726
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
@@ -1715,18 +1773,18 @@ const bridgeCommands = {
|
|
|
1715
1773
|
return { ...structurized, isFactory: result.isFactory };
|
|
1716
1774
|
},
|
|
1717
1775
|
async sendKeepAliveCommand(device) {
|
|
1718
|
-
return this.promisify(device, [...this.getCommandHeader(device), 2, commandIds.keepAlive, 0]);
|
|
1776
|
+
return this.promisify(device, [...this.getCommandHeader(device), 2, commandIds$1.keepAlive, 0]);
|
|
1719
1777
|
},
|
|
1720
1778
|
async sendOtaRequest(deviceId) {
|
|
1721
1779
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
1722
|
-
const command = [commandIds.otaRequest, 0];
|
|
1780
|
+
const command = [commandIds$1.otaRequest, 0];
|
|
1723
1781
|
const result = await this.promisify(deviceData, [...this.getCommandHeader(deviceData), command.length, ...command]);
|
|
1724
1782
|
return result;
|
|
1725
1783
|
},
|
|
1726
1784
|
async sendPinCommand(deviceId) {
|
|
1727
1785
|
const deviceData = await bridgeTools.getBridgeFromStore(deviceId);
|
|
1728
1786
|
const pin = await bridgeSecurity.getPin(deviceId);
|
|
1729
|
-
return this.promisify(deviceData, [...this.getCommandHeader(deviceData), 18, commandIds.pin, 0, ...pin]);
|
|
1787
|
+
return this.promisify(deviceData, [...this.getCommandHeader(deviceData), 18, commandIds$1.pin, 0, ...pin]);
|
|
1730
1788
|
},
|
|
1731
1789
|
async setBridgeToRestart(deviceId) {
|
|
1732
1790
|
if (store.bridgeRebootRequired[deviceId]) return;
|
|
@@ -1735,7 +1793,7 @@ const bridgeCommands = {
|
|
|
1735
1793
|
await this.promisify(deviceData, [
|
|
1736
1794
|
...this.getCommandHeader(deviceData),
|
|
1737
1795
|
2,
|
|
1738
|
-
useNewCommand ? commandIds.ecuReset : commandIds.reboot,
|
|
1796
|
+
useNewCommand ? commandIds$1.ecuReset : commandIds$1.reboot,
|
|
1739
1797
|
useNewCommand ? subCommandIds.ecuResetSubCommand : subCommandIds.rebootSubCommand
|
|
1740
1798
|
]);
|
|
1741
1799
|
},
|
|
@@ -1746,7 +1804,7 @@ const bridgeCommands = {
|
|
|
1746
1804
|
structurizedPayload,
|
|
1747
1805
|
deviceData.advertisingData.fwVersion
|
|
1748
1806
|
);
|
|
1749
|
-
return await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.customerCanSettings, payload);
|
|
1807
|
+
return await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.customerCanSettings, payload);
|
|
1750
1808
|
},
|
|
1751
1809
|
async setWorkshopCANSettings(deviceId, structurizedPayload) {
|
|
1752
1810
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
@@ -1755,7 +1813,7 @@ const bridgeCommands = {
|
|
|
1755
1813
|
structurizedPayload,
|
|
1756
1814
|
deviceData.advertisingData.fwVersion
|
|
1757
1815
|
);
|
|
1758
|
-
return await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.workshopCanSettings, payload);
|
|
1816
|
+
return await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.workshopCanSettings, payload);
|
|
1759
1817
|
},
|
|
1760
1818
|
async setCustomerPressureThresholds(deviceId, structurizedPayload) {
|
|
1761
1819
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
@@ -1764,7 +1822,7 @@ const bridgeCommands = {
|
|
|
1764
1822
|
structurizedPayload,
|
|
1765
1823
|
deviceData.advertisingData.fwVersion
|
|
1766
1824
|
);
|
|
1767
|
-
return await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.customerPressureThresholds, payload);
|
|
1825
|
+
return await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.customerPressureThresholds, payload);
|
|
1768
1826
|
},
|
|
1769
1827
|
async setCustomerTemperatureThresholds(deviceId, structurizedPayload) {
|
|
1770
1828
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
@@ -1775,7 +1833,7 @@ const bridgeCommands = {
|
|
|
1775
1833
|
);
|
|
1776
1834
|
return await this.writeCommand(
|
|
1777
1835
|
deviceData,
|
|
1778
|
-
commandIds.writeData,
|
|
1836
|
+
commandIds$1.writeData,
|
|
1779
1837
|
subCommandIds.customerTemperatureThresholds,
|
|
1780
1838
|
payload
|
|
1781
1839
|
);
|
|
@@ -1787,7 +1845,7 @@ const bridgeCommands = {
|
|
|
1787
1845
|
structurizedPayload,
|
|
1788
1846
|
deviceData.advertisingData.fwVersion
|
|
1789
1847
|
);
|
|
1790
|
-
return await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.customerImbalanceThresholds, payload);
|
|
1848
|
+
return await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.customerImbalanceThresholds, payload);
|
|
1791
1849
|
},
|
|
1792
1850
|
async getAutolearnSettings(deviceId) {
|
|
1793
1851
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
@@ -1816,7 +1874,7 @@ const bridgeCommands = {
|
|
|
1816
1874
|
structurizedPayload,
|
|
1817
1875
|
deviceData.advertisingData.fwVersion
|
|
1818
1876
|
);
|
|
1819
|
-
return await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.autolearnSettings, payload);
|
|
1877
|
+
return await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.autolearnSettings, payload);
|
|
1820
1878
|
},
|
|
1821
1879
|
async setAutolearnIdStatus(deviceId, structurizedPayload) {
|
|
1822
1880
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
@@ -1825,7 +1883,7 @@ const bridgeCommands = {
|
|
|
1825
1883
|
structurizedPayload,
|
|
1826
1884
|
deviceData.advertisingData.fwVersion
|
|
1827
1885
|
);
|
|
1828
|
-
return await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.autolearnIdStatus, payload);
|
|
1886
|
+
return await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.autolearnIdStatus, payload);
|
|
1829
1887
|
},
|
|
1830
1888
|
async getAutolearnUnknownSensors(device) {
|
|
1831
1889
|
const result = await this.readCommand(device, subCommandIds.autolearnUnknownSensors);
|
|
@@ -1846,7 +1904,7 @@ const bridgeCommands = {
|
|
|
1846
1904
|
// move logic to bridge svc
|
|
1847
1905
|
async setAxleInfo(deviceId, axleIndex, data) {
|
|
1848
1906
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
1849
|
-
await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.idsPerWheel(axleIndex), data);
|
|
1907
|
+
await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.idsPerWheel(axleIndex), data);
|
|
1850
1908
|
},
|
|
1851
1909
|
async getAxlesPressure(deviceId) {
|
|
1852
1910
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
@@ -1870,7 +1928,7 @@ const bridgeCommands = {
|
|
|
1870
1928
|
structurizedPayload,
|
|
1871
1929
|
deviceData.advertisingData.fwVersion
|
|
1872
1930
|
);
|
|
1873
|
-
return await this.writeCommand(deviceData, commandIds.writeData, subCommandIds.pressurePerAxle, payload);
|
|
1931
|
+
return await this.writeCommand(deviceData, commandIds$1.writeData, subCommandIds.pressurePerAxle, payload);
|
|
1874
1932
|
},
|
|
1875
1933
|
// // async setPressureThresholds(device: BleBridge, rules: any) {
|
|
1876
1934
|
// // // https://tirecheck.atlassian.net/wiki/spaces/HWPRG/pages/6547767302/Technical+Design+Document+BLE+CAN+Bridge+Krone#Example.1
|
|
@@ -1913,7 +1971,7 @@ const bridgeCommands = {
|
|
|
1913
1971
|
}
|
|
1914
1972
|
const result = await this.writeCommand(
|
|
1915
1973
|
deviceData,
|
|
1916
|
-
commandIds.sensorMeasurement,
|
|
1974
|
+
commandIds$1.sensorMeasurement,
|
|
1917
1975
|
subCommandIds.sensorMeasurementPerWheel(axlePosition, tyrePosition, isTwinTyre, isSpare),
|
|
1918
1976
|
[]
|
|
1919
1977
|
);
|
|
@@ -1924,7 +1982,7 @@ const bridgeCommands = {
|
|
|
1924
1982
|
const result = await this.promisify(device, [
|
|
1925
1983
|
...this.getCommandHeader(device),
|
|
1926
1984
|
commandLength,
|
|
1927
|
-
commandIds.readData,
|
|
1985
|
+
commandIds$1.readData,
|
|
1928
1986
|
subCommandId
|
|
1929
1987
|
]);
|
|
1930
1988
|
const data = result.slice(19, result.length - 8);
|
|
@@ -2889,6 +2947,342 @@ const pressureStick = {
|
|
|
2889
2947
|
onPressure: pressureStickService.onPressure
|
|
2890
2948
|
};
|
|
2891
2949
|
|
|
2950
|
+
const devicePromiseQueue = {};
|
|
2951
|
+
const deviceCurrentResolve = {};
|
|
2952
|
+
const deviceCurrentReject = {};
|
|
2953
|
+
const deviceResponseIdentifier = {};
|
|
2954
|
+
const deviceCurrentPartialMessage = {};
|
|
2955
|
+
const torqueWrenchPromiseQueue = {
|
|
2956
|
+
clearQueue(deviceId, message) {
|
|
2957
|
+
if (deviceCurrentReject[deviceId]) {
|
|
2958
|
+
deviceCurrentReject[deviceId](new Error(message ?? "Stopped sending commands"));
|
|
2959
|
+
}
|
|
2960
|
+
devicePromiseQueue[deviceId] = Promise.resolve();
|
|
2961
|
+
deviceResponseIdentifier[deviceId] = void 0;
|
|
2962
|
+
},
|
|
2963
|
+
async enqueue(deviceId, communication, payload, responseIdentifier, mtu = 20) {
|
|
2964
|
+
if (devicePromiseQueue[deviceId] === void 0) devicePromiseQueue[deviceId] = Promise.resolve();
|
|
2965
|
+
devicePromiseQueue[deviceId] = devicePromiseQueue[deviceId].then(() => {
|
|
2966
|
+
const promise = new Promise((resolve, reject) => {
|
|
2967
|
+
deviceCurrentResolve[deviceId] = resolve;
|
|
2968
|
+
deviceCurrentReject[deviceId] = reject;
|
|
2969
|
+
deviceResponseIdentifier[deviceId] = responseIdentifier;
|
|
2970
|
+
deviceCurrentPartialMessage[deviceId] = [];
|
|
2971
|
+
if (!toolsSvc.canCommunicateWith(deviceId)) return reject(new Error("Torque wrench not connected"));
|
|
2972
|
+
const chunks = [];
|
|
2973
|
+
for (let i = 0; i < payload.length; i += mtu) {
|
|
2974
|
+
chunks.push(payload.slice(i, i + mtu));
|
|
2975
|
+
}
|
|
2976
|
+
for (const chunk of chunks) {
|
|
2977
|
+
const convertedChunk = new Uint8Array(chunk).buffer;
|
|
2978
|
+
bluetooth.write(deviceId, communication.serviceId, communication.characteristicId, convertedChunk);
|
|
2979
|
+
}
|
|
2980
|
+
});
|
|
2981
|
+
return withTimeout(promise, 5e3, `Command timed out ${deviceResponseIdentifier[deviceId]}, ${deviceId}`);
|
|
2982
|
+
});
|
|
2983
|
+
return devicePromiseQueue[deviceId];
|
|
2984
|
+
},
|
|
2985
|
+
async processMessage(deviceId, payload, getIdentifier, isComplete, isError) {
|
|
2986
|
+
const numberArray = Array.from(new Uint8Array(payload));
|
|
2987
|
+
if (!deviceCurrentPartialMessage[deviceId]) deviceCurrentPartialMessage[deviceId] = [];
|
|
2988
|
+
deviceCurrentPartialMessage[deviceId] = _.concat(deviceCurrentPartialMessage[deviceId], numberArray);
|
|
2989
|
+
if (!isComplete(deviceCurrentPartialMessage[deviceId])) {
|
|
2990
|
+
return;
|
|
2991
|
+
}
|
|
2992
|
+
if (isError(deviceCurrentPartialMessage[deviceId])) {
|
|
2993
|
+
return deviceCurrentReject[deviceId](
|
|
2994
|
+
new Error("Error response", { cause: deviceCurrentPartialMessage[deviceId] })
|
|
2995
|
+
);
|
|
2996
|
+
}
|
|
2997
|
+
const identifier = getIdentifier(deviceCurrentPartialMessage[deviceId]);
|
|
2998
|
+
if (deviceResponseIdentifier[deviceId] === identifier) {
|
|
2999
|
+
deviceCurrentResolve[deviceId](deviceCurrentPartialMessage[deviceId]);
|
|
3000
|
+
}
|
|
3001
|
+
}
|
|
3002
|
+
};
|
|
3003
|
+
|
|
3004
|
+
const commandStart = "$9";
|
|
3005
|
+
const commandEnd = "*";
|
|
3006
|
+
const commandIds = {
|
|
3007
|
+
error: "004",
|
|
3008
|
+
acknowledge: "005",
|
|
3009
|
+
commTest: "100",
|
|
3010
|
+
getProperties: "120",
|
|
3011
|
+
startJob: "204",
|
|
3012
|
+
stopJob: "206",
|
|
3013
|
+
getNumberOfReadings: "224",
|
|
3014
|
+
getReading: "200",
|
|
3015
|
+
// Can only be called once for each reading.
|
|
3016
|
+
getReadingAgain: "202",
|
|
3017
|
+
getBattery: "150",
|
|
3018
|
+
getTime: "209",
|
|
3019
|
+
setTime: "208"
|
|
3020
|
+
};
|
|
3021
|
+
const errors = {
|
|
3022
|
+
"01": "Bad string",
|
|
3023
|
+
"02": "Bad checksum",
|
|
3024
|
+
"03": "Unknown command",
|
|
3025
|
+
"04": "No device present for command to act on",
|
|
3026
|
+
"05": "Invalid sample speed",
|
|
3027
|
+
"06": "Torque module offset difference bigger than 25%",
|
|
3028
|
+
"07": "Torque module gain outside 0.9 to 1.1",
|
|
3029
|
+
"08": "No RF properties",
|
|
3030
|
+
"09": "No reply from RF",
|
|
3031
|
+
"0A": "RF device already paired on this device",
|
|
3032
|
+
"0C": "Invalid frequency",
|
|
3033
|
+
"0D": "Invalid LED selection",
|
|
3034
|
+
"0F": "Transducer preloaded",
|
|
3035
|
+
"10": "No more readings",
|
|
3036
|
+
"11": "Job already loaded",
|
|
3037
|
+
"12": "No trace stored",
|
|
3038
|
+
"13": "Wrong transducers selected for Multi Start Mode",
|
|
3039
|
+
"14": "No short trace stored",
|
|
3040
|
+
"15": "Job finished",
|
|
3041
|
+
"16": "Missing time and date",
|
|
3042
|
+
"17": "Bad units for wrench type",
|
|
3043
|
+
"18": "Battery low"
|
|
3044
|
+
};
|
|
3045
|
+
const twMeta = deviceMeta.torqueWrench;
|
|
3046
|
+
const torqueWrenchCommands = {
|
|
3047
|
+
async sendCommand(deviceId, command, params) {
|
|
3048
|
+
const commandId = commandIds[command];
|
|
3049
|
+
let message = `${commandStart}${commandId}`;
|
|
3050
|
+
if (params?.length) {
|
|
3051
|
+
message += `,${params.join(",")}`;
|
|
3052
|
+
}
|
|
3053
|
+
message += commandEnd;
|
|
3054
|
+
const crc = getChecksum(message);
|
|
3055
|
+
message += `${crc}\r`;
|
|
3056
|
+
const array = new Uint8Array(message.length);
|
|
3057
|
+
for (let i = 0, l = message.length; i < l; i++) {
|
|
3058
|
+
array[i] = message.charCodeAt(i);
|
|
3059
|
+
}
|
|
3060
|
+
const decimalArray = Array.from(array);
|
|
3061
|
+
let result;
|
|
3062
|
+
try {
|
|
3063
|
+
result = await torqueWrenchPromiseQueue.enqueue(deviceId, twMeta.communication, decimalArray, commandIds[command]);
|
|
3064
|
+
} catch (error) {
|
|
3065
|
+
const formattedError = formatError(error);
|
|
3066
|
+
throw new Error(formattedError);
|
|
3067
|
+
}
|
|
3068
|
+
return result.map((num) => String.fromCharCode(num)).join("");
|
|
3069
|
+
},
|
|
3070
|
+
processMessage(deviceId, payload) {
|
|
3071
|
+
torqueWrenchPromiseQueue.processMessage(deviceId, payload, getIdentifier, isComplete, isError);
|
|
3072
|
+
}
|
|
3073
|
+
};
|
|
3074
|
+
function isComplete(message) {
|
|
3075
|
+
const completeReading = message[0] === 123 && message.at(-1) === 13;
|
|
3076
|
+
const completeCommand = message[0] === 36 && message.at(-1) === 13;
|
|
3077
|
+
return completeReading || completeCommand;
|
|
3078
|
+
}
|
|
3079
|
+
function isError(message) {
|
|
3080
|
+
return message[4] === 52;
|
|
3081
|
+
}
|
|
3082
|
+
function getIdentifier(message) {
|
|
3083
|
+
if (message[0] === 123) return "200";
|
|
3084
|
+
return message.slice(6, 9).map((num) => String.fromCharCode(num)).join("");
|
|
3085
|
+
}
|
|
3086
|
+
function getChecksum(message) {
|
|
3087
|
+
let checksum = 0;
|
|
3088
|
+
for (const ch of message) {
|
|
3089
|
+
checksum ^= ch.charCodeAt(0);
|
|
3090
|
+
}
|
|
3091
|
+
return decimalToHex(checksum).toUpperCase();
|
|
3092
|
+
}
|
|
3093
|
+
function formatError(error) {
|
|
3094
|
+
if (!error.cause) throw new Error(error);
|
|
3095
|
+
const message = error.cause.slice(6, 8);
|
|
3096
|
+
const errorId = message.map((num) => String.fromCharCode(num)).join("");
|
|
3097
|
+
return errors[errorId] || "Unknown error";
|
|
3098
|
+
}
|
|
3099
|
+
|
|
3100
|
+
let jobInterval = null;
|
|
3101
|
+
const torqueWrenchService = {
|
|
3102
|
+
onReading(callback) {
|
|
3103
|
+
simulatorSvc.registerEvent("tw:reading", callback);
|
|
3104
|
+
},
|
|
3105
|
+
async getProperties(deviceId) {
|
|
3106
|
+
const result = {
|
|
3107
|
+
serialNumber: "",
|
|
3108
|
+
span: 0,
|
|
3109
|
+
calibrationDate: "",
|
|
3110
|
+
ppr: 0,
|
|
3111
|
+
units: "Nm",
|
|
3112
|
+
threshold: 10
|
|
3113
|
+
};
|
|
3114
|
+
const message = await torqueWrenchCommands.sendCommand(deviceId, "getProperties");
|
|
3115
|
+
const params = getMessageParams(message);
|
|
3116
|
+
if (params[4] === "3") result.units = "Nm";
|
|
3117
|
+
else if (params[4] === "7") result.units = "lb-ft";
|
|
3118
|
+
result.serialNumber = params[0];
|
|
3119
|
+
result.span = Number.parseInt(params[1]);
|
|
3120
|
+
if (result.units === "lb-ft") result.span = Math.floor(result.span * 0.738);
|
|
3121
|
+
result.calibrationDate = params[2];
|
|
3122
|
+
result.ppr = Number.parseInt(params[3]);
|
|
3123
|
+
return result;
|
|
3124
|
+
},
|
|
3125
|
+
async startJob(deviceId, params) {
|
|
3126
|
+
await this.stopJob(deviceId);
|
|
3127
|
+
const { units, span, ppr, threshold } = store.torqueWrenchProperties[deviceId];
|
|
3128
|
+
const { torqueMin, torqueMax, angleMin, angleMax, direction, jobTimeout } = params;
|
|
3129
|
+
const msgParams = {
|
|
3130
|
+
id: "01",
|
|
3131
|
+
nuts: decimalToHex(params.nuts),
|
|
3132
|
+
mode: units === "lb-ft" ? "20" : "1",
|
|
3133
|
+
// Peak measurement mode
|
|
3134
|
+
cycle: "7",
|
|
3135
|
+
// 10 seconds cycle (probably for measurements - not sure what it does exactly, not specified in docs)
|
|
3136
|
+
control: torqueMin != null || torqueMax != null ? "0" : "1",
|
|
3137
|
+
direction: direction === "counter-clockwise" ? "1" : "0",
|
|
3138
|
+
minTorqueThreshold: torqueToAdcParam(threshold, span, units),
|
|
3139
|
+
torqueMin: torqueToAdcParam(torqueMin ?? 0, span, units),
|
|
3140
|
+
torqueMax: torqueToAdcParam(torqueMax ?? -1, span, units),
|
|
3141
|
+
clickThreshold: torqueToAdcParam(threshold, span, units),
|
|
3142
|
+
// Probably not used in our case (for this specified mode).
|
|
3143
|
+
angleMin: angleToPulsesParam(angleMin ?? 0, ppr),
|
|
3144
|
+
angleMax: angleToPulsesParam(angleMax ?? -1, ppr),
|
|
3145
|
+
frequency: "0542"
|
|
3146
|
+
// No idea
|
|
3147
|
+
};
|
|
3148
|
+
const paramsString = Object.values(msgParams);
|
|
3149
|
+
await torqueWrenchCommands.sendCommand(deviceId, "startJob", paramsString);
|
|
3150
|
+
jobInterval = setInterval(async () => {
|
|
3151
|
+
const numberOfReading = await this.getNumberOfReadings(deviceId);
|
|
3152
|
+
if (numberOfReading.count > 0) this.getReading(deviceId);
|
|
3153
|
+
}, 2e3);
|
|
3154
|
+
if (jobTimeout) {
|
|
3155
|
+
await new Promise(
|
|
3156
|
+
(resolve) => setTimeout(() => {
|
|
3157
|
+
this.stopJob(deviceId);
|
|
3158
|
+
resolve("");
|
|
3159
|
+
}, jobTimeout * 1e3)
|
|
3160
|
+
);
|
|
3161
|
+
}
|
|
3162
|
+
},
|
|
3163
|
+
async stopJob(deviceId) {
|
|
3164
|
+
clearInterval(jobInterval);
|
|
3165
|
+
return torqueWrenchCommands.sendCommand(deviceId, "stopJob");
|
|
3166
|
+
},
|
|
3167
|
+
async getNumberOfReadings(deviceId) {
|
|
3168
|
+
const message = await torqueWrenchCommands.sendCommand(deviceId, "getNumberOfReadings");
|
|
3169
|
+
const params = getMessageParams(message);
|
|
3170
|
+
return { count: Number(params[0]), jobId: params[1] };
|
|
3171
|
+
},
|
|
3172
|
+
async getReading(deviceId) {
|
|
3173
|
+
const reading = await torqueWrenchCommands.sendCommand(deviceId, "getReading");
|
|
3174
|
+
const properties = {
|
|
3175
|
+
jobId: reading.slice(2, 4),
|
|
3176
|
+
nut: reading.slice(4, 6),
|
|
3177
|
+
torqueAdc: reading.slice(6, 10),
|
|
3178
|
+
anglePulses: reading.slice(10, 14),
|
|
3179
|
+
duration: reading.slice(14, 18)
|
|
3180
|
+
};
|
|
3181
|
+
const torque = adcToTorque(
|
|
3182
|
+
properties.torqueAdc,
|
|
3183
|
+
store.torqueWrenchProperties[deviceId].span,
|
|
3184
|
+
store.torqueWrenchProperties[deviceId].units
|
|
3185
|
+
);
|
|
3186
|
+
const angle = pulsesToAngle(properties.anglePulses, store.torqueWrenchProperties[deviceId].ppr);
|
|
3187
|
+
const formattedReading = {
|
|
3188
|
+
jobId: Number.parseInt(properties.jobId, 16),
|
|
3189
|
+
nut: Number.parseInt(properties.nut, 16),
|
|
3190
|
+
torque,
|
|
3191
|
+
angle,
|
|
3192
|
+
duration: Number.parseInt(properties.duration, 16) / 1e3
|
|
3193
|
+
};
|
|
3194
|
+
simulatorSvc.triggerEvent("tw:reading", deviceId, formattedReading);
|
|
3195
|
+
},
|
|
3196
|
+
// getReadingAgain(deviceId: string) {
|
|
3197
|
+
// return torqueWrenchCommands.sendCommand(deviceId, 'getNumberOfReadings')
|
|
3198
|
+
// },
|
|
3199
|
+
async getBattery(deviceId) {
|
|
3200
|
+
const message = await torqueWrenchCommands.sendCommand(deviceId, "getBattery");
|
|
3201
|
+
const params = getMessageParams(message);
|
|
3202
|
+
return Number(params[0]);
|
|
3203
|
+
},
|
|
3204
|
+
async getTime(deviceId) {
|
|
3205
|
+
const message = await torqueWrenchCommands.sendCommand(deviceId, "getTime");
|
|
3206
|
+
const match = message.match(/209,([^*]*)\*/);
|
|
3207
|
+
console.log("\u{1F680} ~ getTime ~ match:", match);
|
|
3208
|
+
if (!match[1]) throw new Error("Invalid time response");
|
|
3209
|
+
const hh = match[1].substring(0, 2);
|
|
3210
|
+
const mm = match[1].substring(2, 4);
|
|
3211
|
+
const ss = match[1].substring(4, 6);
|
|
3212
|
+
const dd = match[1].substring(6, 8);
|
|
3213
|
+
const MM = match[1].substring(8, 10);
|
|
3214
|
+
const yy = match[1].substring(10, 12);
|
|
3215
|
+
const fullYear = `20${yy}`;
|
|
3216
|
+
return /* @__PURE__ */ new Date(`${fullYear}-${MM}-${dd}T${hh}:${mm}:${ss}Z`);
|
|
3217
|
+
},
|
|
3218
|
+
setTime(deviceId, date) {
|
|
3219
|
+
const hours = String(date.getHours()).padStart(2, "0");
|
|
3220
|
+
const minutes = String(date.getMinutes()).padStart(2, "0");
|
|
3221
|
+
const seconds = String(date.getSeconds()).padStart(2, "0");
|
|
3222
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
3223
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
3224
|
+
const year = String(date.getFullYear()).slice(-2);
|
|
3225
|
+
const params = [hours, minutes, seconds, day, month, year];
|
|
3226
|
+
return torqueWrenchCommands.sendCommand(deviceId, "setTime", params);
|
|
3227
|
+
}
|
|
3228
|
+
};
|
|
3229
|
+
function torqueToAdcParam(value, span, deviceUnits) {
|
|
3230
|
+
if (value < 0) return "FFFF";
|
|
3231
|
+
if (deviceUnits !== "Nm") value = value * 0.738;
|
|
3232
|
+
const adc = Math.round(value / span * 16384);
|
|
3233
|
+
return decimalToHex(adc, 4).toUpperCase();
|
|
3234
|
+
}
|
|
3235
|
+
function angleToPulsesParam(value, ppr) {
|
|
3236
|
+
if (value < 0) return "FFFF";
|
|
3237
|
+
const pulses = Math.round(value * ppr / 90);
|
|
3238
|
+
return decimalToHex(pulses, 4).toUpperCase();
|
|
3239
|
+
}
|
|
3240
|
+
function getMessageParams(message) {
|
|
3241
|
+
return message.match(/^\$[^,]+,[^,]+,(.*)\*/)?.[1].split(",") || [];
|
|
3242
|
+
}
|
|
3243
|
+
function adcToTorque(value, span, units) {
|
|
3244
|
+
const torque = Number.parseInt(value, 16) * span / 16384;
|
|
3245
|
+
if (units !== "Nm") return torque / 0.738;
|
|
3246
|
+
return torque;
|
|
3247
|
+
}
|
|
3248
|
+
function pulsesToAngle(value, ppr) {
|
|
3249
|
+
return Number.parseInt(value, 16) * 90 / ppr;
|
|
3250
|
+
}
|
|
3251
|
+
|
|
3252
|
+
const torqueWrench = {
|
|
3253
|
+
async connect(deviceId) {
|
|
3254
|
+
const twMeta = deviceMeta.torqueWrench;
|
|
3255
|
+
await bluetooth.connect(deviceId, this.disconnect);
|
|
3256
|
+
await ble.startNotification(
|
|
3257
|
+
deviceId,
|
|
3258
|
+
twMeta.communication.serviceId,
|
|
3259
|
+
twMeta.communication.characteristicId,
|
|
3260
|
+
(notification) => {
|
|
3261
|
+
torqueWrenchCommands.processMessage(deviceId, notification);
|
|
3262
|
+
},
|
|
3263
|
+
(error) => console.warn("ble.startNotification error", error)
|
|
3264
|
+
);
|
|
3265
|
+
const properties = await torqueWrenchService.getProperties(deviceId);
|
|
3266
|
+
store.torqueWrenchProperties[deviceId] = properties;
|
|
3267
|
+
store.setState(deviceId, "paired");
|
|
3268
|
+
},
|
|
3269
|
+
async disconnect(deviceId, reason) {
|
|
3270
|
+
store.setState(deviceId, "disconnecting");
|
|
3271
|
+
await torqueWrenchService.stopJob(deviceId);
|
|
3272
|
+
await bluetooth.disconnect(deviceId);
|
|
3273
|
+
store.setState(deviceId, void 0, reason ?? "manualDisconnection");
|
|
3274
|
+
},
|
|
3275
|
+
getProperties: torqueWrenchService.getProperties,
|
|
3276
|
+
setTime: torqueWrenchService.setTime,
|
|
3277
|
+
startJob: torqueWrenchService.startJob,
|
|
3278
|
+
stopJob: torqueWrenchService.stopJob,
|
|
3279
|
+
getNumberOfReadings: torqueWrenchService.getNumberOfReadings,
|
|
3280
|
+
getReading: torqueWrenchService.getReading,
|
|
3281
|
+
getBattery: torqueWrenchService.getBattery,
|
|
3282
|
+
getTime: torqueWrenchService.getTime,
|
|
3283
|
+
onReading: torqueWrenchService.onReading
|
|
3284
|
+
};
|
|
3285
|
+
|
|
2892
3286
|
const bridgeSimulator = {
|
|
2893
3287
|
isRebootRequired(deviceId) {
|
|
2894
3288
|
return store.bridgeRebootRequired[deviceId];
|
|
@@ -3489,10 +3883,14 @@ function createTirecheckDeviceSdk(platform, bleImplementation, securityKeys) {
|
|
|
3489
3883
|
bridgeOta,
|
|
3490
3884
|
/** Methods for working with Tirecheck TPMS FlexiGauge */
|
|
3491
3885
|
flexiGaugeTpms,
|
|
3886
|
+
// flexiGauge,
|
|
3492
3887
|
/** Methods for working with Tirecheck Pressure Stick */
|
|
3493
3888
|
pressureStick,
|
|
3889
|
+
// ateq,
|
|
3494
3890
|
/** Allows simulating devices without actually using bluetooth */
|
|
3495
|
-
simulator
|
|
3891
|
+
simulator,
|
|
3892
|
+
/** Methods for working with Tirecheck Torque Wrench */
|
|
3893
|
+
torqueWrench
|
|
3496
3894
|
};
|
|
3497
3895
|
}
|
|
3498
3896
|
|