tirecheck-device-sdk 0.1.94 → 0.1.96
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 +214 -154
- package/dist/index.d.cts +23 -5
- package/dist/index.d.mts +23 -5
- package/dist/index.d.ts +23 -5
- package/dist/index.mjs +214 -154
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -502,7 +502,7 @@ const deviceMeta = {
|
|
|
502
502
|
getDeviceInfoFromAdvertising: bridgeOtaAdvertisingParser.getDeviceInfoFromAdvertising
|
|
503
503
|
},
|
|
504
504
|
flexiGaugeTpms: {
|
|
505
|
-
nameRegex:
|
|
505
|
+
nameRegex: /^Flexi.*/,
|
|
506
506
|
communication: {
|
|
507
507
|
serviceId: "4880c12c-fdcb-4077-8920-a450d7f9b907",
|
|
508
508
|
characteristicId: "fec26ec4-6d71-4442-9f81-55bc21d658d6"
|
|
@@ -520,28 +520,21 @@ const deviceMeta = {
|
|
|
520
520
|
},
|
|
521
521
|
reconnect: true
|
|
522
522
|
// Do we need it here?
|
|
523
|
+
},
|
|
524
|
+
pressureStick: {
|
|
525
|
+
nameRegex: /Pressure Stick.*/,
|
|
526
|
+
communication: {
|
|
527
|
+
serviceId: "4880c12c-fdcb-4077-8920-a450d7f9b907",
|
|
528
|
+
characteristicId: "fec26ec4-6d71-4442-9f81-55bc21d658d6"
|
|
529
|
+
},
|
|
530
|
+
getDeviceInfoFromAdvertising: (device) => {
|
|
531
|
+
const bleDevice = {
|
|
532
|
+
...device,
|
|
533
|
+
type: "pressureStick"
|
|
534
|
+
};
|
|
535
|
+
return bleDevice;
|
|
536
|
+
}
|
|
523
537
|
}
|
|
524
|
-
// pressureStick: {
|
|
525
|
-
// nameRegex: /Pressure Stick.*/,
|
|
526
|
-
// characteristic: {
|
|
527
|
-
// serviceId: '4880c12c-fdcb-4077-8920-a450d7f9b907',
|
|
528
|
-
// characteristicId: 'fec26ec4-6d71-4442-9f81-55bc21d658d6',
|
|
529
|
-
// },
|
|
530
|
-
// getDeviceInfoFromAdvertising: () => {},
|
|
531
|
-
// capabilities: [
|
|
532
|
-
// {
|
|
533
|
-
// id: 'pressure',
|
|
534
|
-
// // processFn: processPressure,
|
|
535
|
-
// regex: /P([0-9.]+)mBar/,
|
|
536
|
-
// },
|
|
537
|
-
// // only pressure is needed for initial implementation, uncomment tpms functionality when needed
|
|
538
|
-
// // {
|
|
539
|
-
// // id: 'tpms',
|
|
540
|
-
// // processFn: processTpms,
|
|
541
|
-
// // regex: /^\*TPMS/,
|
|
542
|
-
// // },
|
|
543
|
-
// ],
|
|
544
|
-
// },
|
|
545
538
|
};
|
|
546
539
|
|
|
547
540
|
const checkUnreachableDevicesTimeouts = {};
|
|
@@ -565,7 +558,7 @@ const bluetooth = {
|
|
|
565
558
|
stopScan() {
|
|
566
559
|
ble.stopScan();
|
|
567
560
|
},
|
|
568
|
-
connect,
|
|
561
|
+
connect: connect$1,
|
|
569
562
|
disconnect: disconnect$1,
|
|
570
563
|
write,
|
|
571
564
|
read
|
|
@@ -592,7 +585,7 @@ async function scanDevices(services = [], duration) {
|
|
|
592
585
|
(e) => console.error("ble.startScanWithOptions error:", e)
|
|
593
586
|
);
|
|
594
587
|
}
|
|
595
|
-
async function connect(deviceId, disconnectCallback) {
|
|
588
|
+
async function connect$1(deviceId, disconnectCallback) {
|
|
596
589
|
if (toolsSvc.canCommunicateWith(deviceId)) return console.warn("Connect Warn: Already connected to device");
|
|
597
590
|
store.setState(deviceId, "connecting");
|
|
598
591
|
let connectedDevice;
|
|
@@ -713,6 +706,78 @@ function getDeviceNameFromAdvertising(advertising) {
|
|
|
713
706
|
return deviceName;
|
|
714
707
|
}
|
|
715
708
|
|
|
709
|
+
const otaServiceUuid = "1d14d6ee-fd63-4fa1-bfa4-8f47b42119f0";
|
|
710
|
+
const otaControlCharacteristicUuid = "f7bf3564-fb6d-4e53-88a4-5e37e0326063";
|
|
711
|
+
const otaDataCharacteristicUuid = "984227f3-34fc-4045-a5d0-2c581f81a153";
|
|
712
|
+
const bridgeOtaCommands = {
|
|
713
|
+
async beginOta(deviceId) {
|
|
714
|
+
await bluetooth.write(deviceId, otaServiceUuid, otaControlCharacteristicUuid, new Uint8Array([0]).buffer, true);
|
|
715
|
+
},
|
|
716
|
+
async uploadOtaChunk(deviceId, data) {
|
|
717
|
+
await bluetooth.write(deviceId, otaServiceUuid, otaDataCharacteristicUuid, data, true);
|
|
718
|
+
},
|
|
719
|
+
async endOta(deviceId) {
|
|
720
|
+
await bluetooth.write(deviceId, otaServiceUuid, otaControlCharacteristicUuid, new Uint8Array([3]).buffer, true);
|
|
721
|
+
}
|
|
722
|
+
};
|
|
723
|
+
|
|
724
|
+
const bridgeOtaService = {
|
|
725
|
+
async updateFirmware(deviceId, bootloader, firmware, progressCallback) {
|
|
726
|
+
await delay(2e3);
|
|
727
|
+
progressCallback("Connecting to the bridge...", 0.1);
|
|
728
|
+
await bridgeOta.connect(deviceId);
|
|
729
|
+
progressCallback("Uploading bootloader...", 0.12);
|
|
730
|
+
await bridgeOtaCommands.beginOta(deviceId);
|
|
731
|
+
await uploadOta(deviceId, bootloader, (str, percents) => progressCallback(str, 0.12 + percents * 0.2));
|
|
732
|
+
await bridgeOtaCommands.endOta(deviceId);
|
|
733
|
+
progressCallback("Uploading application...", 0.32);
|
|
734
|
+
await bridgeOtaCommands.beginOta(deviceId);
|
|
735
|
+
await uploadOta(deviceId, firmware, (str, percents) => progressCallback(str, 0.32 + percents * 0.5));
|
|
736
|
+
await bridgeOtaCommands.endOta(deviceId);
|
|
737
|
+
progressCallback("Upload completed, disconnecting...", 0.81);
|
|
738
|
+
await bridgeOta.disconnect(deviceId);
|
|
739
|
+
progressCallback("Disconnected...", 1);
|
|
740
|
+
}
|
|
741
|
+
};
|
|
742
|
+
async function uploadOta(deviceId, firmwareBinary, reportStatus) {
|
|
743
|
+
let uploadedBytes = 0;
|
|
744
|
+
let chunkIndex = 0;
|
|
745
|
+
const mtu = store.platform === "android" ? 512 : deviceMeta.bridgeOta.mtu;
|
|
746
|
+
while (uploadedBytes < firmwareBinary.byteLength) {
|
|
747
|
+
if (chunkIndex % 100 === 0)
|
|
748
|
+
reportStatus(
|
|
749
|
+
`Uploading new firmware... (${___default.round(uploadedBytes / 1e3)} / ${___default.round(
|
|
750
|
+
firmwareBinary.byteLength / 1e3
|
|
751
|
+
)} KB)`,
|
|
752
|
+
uploadedBytes / firmwareBinary.byteLength
|
|
753
|
+
);
|
|
754
|
+
const chunkSize = Math.min(mtu - 3, firmwareBinary.byteLength - uploadedBytes);
|
|
755
|
+
const chunk = firmwareBinary.slice(uploadedBytes, uploadedBytes + chunkSize);
|
|
756
|
+
await bridgeOtaCommands.uploadOtaChunk(deviceId, chunk);
|
|
757
|
+
uploadedBytes += chunkSize;
|
|
758
|
+
chunkIndex++;
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
const bridgeOta = {
|
|
763
|
+
async connect(deviceId) {
|
|
764
|
+
await bluetooth.connect(deviceId, this.disconnect);
|
|
765
|
+
const _deviceId = store.deviceIdMapingTable[deviceId] ?? deviceId;
|
|
766
|
+
if (store.platform !== "ios") {
|
|
767
|
+
await ble.requestMtu(_deviceId, 512);
|
|
768
|
+
}
|
|
769
|
+
store.setState(deviceId, "paired");
|
|
770
|
+
},
|
|
771
|
+
async disconnect(deviceId, reason) {
|
|
772
|
+
store.setState(deviceId, "disconnecting");
|
|
773
|
+
await bluetooth.disconnect(deviceId);
|
|
774
|
+
store.setState(deviceId, void 0, reason ?? "manualDisconnection");
|
|
775
|
+
},
|
|
776
|
+
async updateFirmware(deviceId, bootloader, firmware, progressCallback) {
|
|
777
|
+
return bridgeOtaService.updateFirmware(deviceId, bootloader, firmware, progressCallback);
|
|
778
|
+
}
|
|
779
|
+
};
|
|
780
|
+
|
|
716
781
|
const bridgeCommandStructures = {
|
|
717
782
|
workshopCanSettings: {
|
|
718
783
|
id: [98, 96],
|
|
@@ -1530,25 +1595,26 @@ const bridgeSecurity = {
|
|
|
1530
1595
|
};
|
|
1531
1596
|
|
|
1532
1597
|
const bridgeMeta = deviceMeta.bridge;
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
};
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1598
|
+
const devicePromiseQueue = {};
|
|
1599
|
+
const deviceCurrentResolve = {};
|
|
1600
|
+
const deviceCurrentReject = {};
|
|
1601
|
+
const deviceResponseIdentifier = {};
|
|
1602
|
+
const promiseQueue = {
|
|
1603
|
+
clearQueue(deviceId, message) {
|
|
1604
|
+
if (deviceCurrentReject[deviceId]) {
|
|
1605
|
+
deviceCurrentReject[deviceId](new Error(message ?? "Stopped sending commands"));
|
|
1606
|
+
}
|
|
1607
|
+
devicePromiseQueue[deviceId] = Promise.resolve();
|
|
1608
|
+
deviceResponseIdentifier[deviceId] = [];
|
|
1544
1609
|
},
|
|
1545
1610
|
async enqueue(device, payload) {
|
|
1546
|
-
|
|
1611
|
+
if (devicePromiseQueue[device.id] === void 0) devicePromiseQueue[device.id] = Promise.resolve();
|
|
1612
|
+
devicePromiseQueue[device.id] = devicePromiseQueue[device.id].then(() => {
|
|
1547
1613
|
const promise = new Promise((resolve, reject) => {
|
|
1548
|
-
|
|
1549
|
-
|
|
1614
|
+
deviceCurrentResolve[device.id] = resolve;
|
|
1615
|
+
deviceCurrentReject[device.id] = reject;
|
|
1550
1616
|
const isKeepAlive = payload[3] === commandIds.keepAlive;
|
|
1551
|
-
|
|
1617
|
+
deviceResponseIdentifier[device.id] = [isKeepAlive ? 126 : 0, payload[4]];
|
|
1552
1618
|
const signedData = bridgeSecurity.getSignedCommand(device, payload);
|
|
1553
1619
|
if (!toolsSvc.canCommunicateWith(device.id)) return reject(new Error("Bridge not connected"));
|
|
1554
1620
|
if (signedData.length > 110) {
|
|
@@ -1574,21 +1640,21 @@ const promiseQueue$1 = {
|
|
|
1574
1640
|
);
|
|
1575
1641
|
}
|
|
1576
1642
|
});
|
|
1577
|
-
return withTimeout(promise, 5e3, `Command timed out ${
|
|
1643
|
+
return withTimeout(promise, 5e3, `Command timed out ${deviceResponseIdentifier[device.id]}, ${device.id}`);
|
|
1578
1644
|
});
|
|
1579
|
-
return
|
|
1645
|
+
return devicePromiseQueue[device.id];
|
|
1580
1646
|
},
|
|
1581
1647
|
async processMessage(deviceId, payload) {
|
|
1582
1648
|
const numberArray = Array.from(new Uint8Array(payload));
|
|
1583
1649
|
if (numberArray[3] === 127) {
|
|
1584
1650
|
console.error(numberArray);
|
|
1585
|
-
return
|
|
1651
|
+
return deviceCurrentReject[deviceId](new Error(`Command not succesful: ${numberArray[4]}`));
|
|
1586
1652
|
}
|
|
1587
1653
|
if ([226, 81].includes(numberArray[3]) && numberArray[4] && toolsSvc.canCommunicateWith(deviceId)) {
|
|
1588
1654
|
store.bridgeRebootRequired[deviceId] = true;
|
|
1589
1655
|
}
|
|
1590
|
-
if ((!
|
|
1591
|
-
return
|
|
1656
|
+
if ((!deviceResponseIdentifier[deviceId][0] || numberArray[3] === deviceResponseIdentifier[deviceId][0]) && (!deviceResponseIdentifier[deviceId][1] || numberArray[4] === deviceResponseIdentifier[deviceId][1])) {
|
|
1657
|
+
return deviceCurrentResolve[deviceId](numberArray);
|
|
1592
1658
|
}
|
|
1593
1659
|
console.warn("message from the device not belonging to the pending promise: ", numberArray);
|
|
1594
1660
|
}
|
|
@@ -1975,79 +2041,7 @@ const bridgeCommands = {
|
|
|
1975
2041
|
}
|
|
1976
2042
|
this.sendKeepAliveCommand(device);
|
|
1977
2043
|
}, 1e4);
|
|
1978
|
-
return promiseQueue
|
|
1979
|
-
}
|
|
1980
|
-
};
|
|
1981
|
-
|
|
1982
|
-
const otaServiceUuid = "1d14d6ee-fd63-4fa1-bfa4-8f47b42119f0";
|
|
1983
|
-
const otaControlCharacteristicUuid = "f7bf3564-fb6d-4e53-88a4-5e37e0326063";
|
|
1984
|
-
const otaDataCharacteristicUuid = "984227f3-34fc-4045-a5d0-2c581f81a153";
|
|
1985
|
-
const bridgeOtaCommands = {
|
|
1986
|
-
async beginOta(deviceId) {
|
|
1987
|
-
await bluetooth.write(deviceId, otaServiceUuid, otaControlCharacteristicUuid, new Uint8Array([0]).buffer, true);
|
|
1988
|
-
},
|
|
1989
|
-
async uploadOtaChunk(deviceId, data) {
|
|
1990
|
-
await bluetooth.write(deviceId, otaServiceUuid, otaDataCharacteristicUuid, data, true);
|
|
1991
|
-
},
|
|
1992
|
-
async endOta(deviceId) {
|
|
1993
|
-
await bluetooth.write(deviceId, otaServiceUuid, otaControlCharacteristicUuid, new Uint8Array([3]).buffer, true);
|
|
1994
|
-
}
|
|
1995
|
-
};
|
|
1996
|
-
|
|
1997
|
-
const bridgeOtaService = {
|
|
1998
|
-
async updateFirmware(deviceId, bootloader, firmware, progressCallback) {
|
|
1999
|
-
await delay(2e3);
|
|
2000
|
-
progressCallback("Connecting to the bridge...", 0.1);
|
|
2001
|
-
await bridgeOta.connect(deviceId);
|
|
2002
|
-
progressCallback("Uploading bootloader...", 0.12);
|
|
2003
|
-
await bridgeOtaCommands.beginOta(deviceId);
|
|
2004
|
-
await uploadOta(deviceId, bootloader, (str, percents) => progressCallback(str, 0.12 + percents * 0.2));
|
|
2005
|
-
await bridgeOtaCommands.endOta(deviceId);
|
|
2006
|
-
progressCallback("Uploading application...", 0.32);
|
|
2007
|
-
await bridgeOtaCommands.beginOta(deviceId);
|
|
2008
|
-
await uploadOta(deviceId, firmware, (str, percents) => progressCallback(str, 0.32 + percents * 0.5));
|
|
2009
|
-
await bridgeOtaCommands.endOta(deviceId);
|
|
2010
|
-
progressCallback("Upload completed, disconnecting...", 0.81);
|
|
2011
|
-
await bridgeOta.disconnect(deviceId);
|
|
2012
|
-
progressCallback("Disconnected...", 1);
|
|
2013
|
-
}
|
|
2014
|
-
};
|
|
2015
|
-
async function uploadOta(deviceId, firmwareBinary, reportStatus) {
|
|
2016
|
-
let uploadedBytes = 0;
|
|
2017
|
-
let chunkIndex = 0;
|
|
2018
|
-
const mtu = store.platform === "android" ? 512 : deviceMeta.bridgeOta.mtu;
|
|
2019
|
-
while (uploadedBytes < firmwareBinary.byteLength) {
|
|
2020
|
-
if (chunkIndex % 100 === 0)
|
|
2021
|
-
reportStatus(
|
|
2022
|
-
`Uploading new firmware... (${___default.round(uploadedBytes / 1e3)} / ${___default.round(
|
|
2023
|
-
firmwareBinary.byteLength / 1e3
|
|
2024
|
-
)} KB)`,
|
|
2025
|
-
uploadedBytes / firmwareBinary.byteLength
|
|
2026
|
-
);
|
|
2027
|
-
const chunkSize = Math.min(mtu - 3, firmwareBinary.byteLength - uploadedBytes);
|
|
2028
|
-
const chunk = firmwareBinary.slice(uploadedBytes, uploadedBytes + chunkSize);
|
|
2029
|
-
await bridgeOtaCommands.uploadOtaChunk(deviceId, chunk);
|
|
2030
|
-
uploadedBytes += chunkSize;
|
|
2031
|
-
chunkIndex++;
|
|
2032
|
-
}
|
|
2033
|
-
}
|
|
2034
|
-
|
|
2035
|
-
const bridgeOta = {
|
|
2036
|
-
async connect(deviceId) {
|
|
2037
|
-
await bluetooth.connect(deviceId, this.disconnect);
|
|
2038
|
-
const _deviceId = store.deviceIdMapingTable[deviceId] ?? deviceId;
|
|
2039
|
-
if (store.platform !== "ios") {
|
|
2040
|
-
await ble.requestMtu(_deviceId, 512);
|
|
2041
|
-
}
|
|
2042
|
-
store.setState(deviceId, "paired");
|
|
2043
|
-
},
|
|
2044
|
-
async disconnect(deviceId, reason) {
|
|
2045
|
-
store.setState(deviceId, "disconnecting");
|
|
2046
|
-
await bluetooth.disconnect(deviceId);
|
|
2047
|
-
store.setState(deviceId, void 0, reason ?? "manualDisconnection");
|
|
2048
|
-
},
|
|
2049
|
-
async updateFirmware(deviceId, bootloader, firmware, progressCallback) {
|
|
2050
|
-
return bridgeOtaService.updateFirmware(deviceId, bootloader, firmware, progressCallback);
|
|
2044
|
+
return promiseQueue.enqueue(device, writeCommand);
|
|
2051
2045
|
}
|
|
2052
2046
|
};
|
|
2053
2047
|
|
|
@@ -2069,8 +2063,13 @@ const bridgeService = {
|
|
|
2069
2063
|
getVehicleReadings,
|
|
2070
2064
|
resetAutolearnStatuses,
|
|
2071
2065
|
getAutolearnStatuses,
|
|
2072
|
-
isRebootRequired
|
|
2066
|
+
isRebootRequired,
|
|
2067
|
+
sendPinCommand
|
|
2073
2068
|
};
|
|
2069
|
+
async function sendPinCommand(deviceId) {
|
|
2070
|
+
if (!canCommunicateWith(deviceId)) throw new Error("Bridge not connected");
|
|
2071
|
+
await bridgeCommands.sendPinCommand(deviceId);
|
|
2072
|
+
}
|
|
2074
2073
|
async function updateFirmware(deviceId, bootloader, firmware, reportStatus) {
|
|
2075
2074
|
reportStatus("Sending OTA Request...", 0.02);
|
|
2076
2075
|
await bridgeCommands.sendOtaRequest(deviceId);
|
|
@@ -2392,7 +2391,7 @@ async function getVehicleReadings(deviceId, tcVehicle) {
|
|
|
2392
2391
|
try {
|
|
2393
2392
|
for (const vehicleTyre of tcVehicle.tcTyres) {
|
|
2394
2393
|
if (vehicleTyre.tcTpmsSensor && vehicleTyre.mountedOn?.positionId) {
|
|
2395
|
-
if (!canCommunicateWith(deviceId))
|
|
2394
|
+
if (!canCommunicateWith(deviceId)) break;
|
|
2396
2395
|
const reading = await getSensorReading(deviceId, vehicleTyre.mountedOn.positionId);
|
|
2397
2396
|
readings.push(reading);
|
|
2398
2397
|
}
|
|
@@ -2690,12 +2689,28 @@ function isRebootRequired(deviceId) {
|
|
|
2690
2689
|
|
|
2691
2690
|
const bridge = {
|
|
2692
2691
|
disconnect,
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2692
|
+
connect,
|
|
2693
|
+
getVehicle: bridgeService.getVehicle,
|
|
2694
|
+
setVehicle: bridgeService.setVehicle,
|
|
2695
|
+
getConfiguration: bridgeService.getConfiguration,
|
|
2696
|
+
setConfiguration: bridgeService.setConfiguration,
|
|
2697
|
+
getSensorReading: bridgeService.getSensorReading,
|
|
2698
|
+
getVehicleReadings: bridgeService.getVehicleReadings,
|
|
2699
|
+
getAutolearnStatuses: bridgeService.getAutolearnStatuses,
|
|
2700
|
+
resetAutolearnStatuses: bridgeService.resetAutolearnStatuses,
|
|
2701
|
+
updateFirmware: bridgeService.updateFirmware,
|
|
2702
|
+
isRebootRequired: bridgeService.isRebootRequired
|
|
2703
|
+
};
|
|
2704
|
+
async function connect(deviceId, accessLevel) {
|
|
2705
|
+
if (canCommunicateWith(deviceId)) return;
|
|
2706
|
+
await promiseQueue.clearQueue(deviceId, "Previous pending commands aborted");
|
|
2707
|
+
const bridgeMeta = deviceMeta.bridge;
|
|
2708
|
+
await bluetooth.connect(deviceId, disconnect);
|
|
2709
|
+
if (store.deviceState[deviceId] === "paired") {
|
|
2710
|
+
return console.warn("Connect Warn: Already connected");
|
|
2711
|
+
}
|
|
2712
|
+
const _deviceId = store.deviceIdMapingTable[deviceId] ?? deviceId;
|
|
2713
|
+
try {
|
|
2699
2714
|
if (store.platform !== "ios") {
|
|
2700
2715
|
await ble.requestMtu(_deviceId, deviceMeta.bridge.mtu);
|
|
2701
2716
|
}
|
|
@@ -2703,28 +2718,22 @@ const bridge = {
|
|
|
2703
2718
|
_deviceId,
|
|
2704
2719
|
bridgeMeta.communication.serviceId,
|
|
2705
2720
|
bridgeMeta.communication.characteristicId,
|
|
2706
|
-
(notification) => promiseQueue
|
|
2721
|
+
(notification) => promiseQueue.processMessage(deviceId, notification),
|
|
2707
2722
|
(error) => console.error("startNotification Error", error)
|
|
2708
2723
|
);
|
|
2709
2724
|
store.deviceAccessLevel[deviceId] = accessLevel ?? "driver";
|
|
2710
2725
|
store.bridgeRebootRequired[deviceId] = false;
|
|
2711
|
-
await
|
|
2726
|
+
await bridgeService.sendPinCommand(deviceId);
|
|
2712
2727
|
store.setState(deviceId, "paired");
|
|
2713
|
-
}
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
getSensorReading: bridgeService.getSensorReading,
|
|
2719
|
-
getVehicleReadings: bridgeService.getVehicleReadings,
|
|
2720
|
-
getAutolearnStatuses: bridgeService.getAutolearnStatuses,
|
|
2721
|
-
resetAutolearnStatuses: bridgeService.resetAutolearnStatuses,
|
|
2722
|
-
updateFirmware: bridgeService.updateFirmware,
|
|
2723
|
-
isRebootRequired: bridgeService.isRebootRequired
|
|
2724
|
-
};
|
|
2728
|
+
} catch (e) {
|
|
2729
|
+
disconnect(deviceId);
|
|
2730
|
+
throw new Error(`Pairing unsuccessful ${e}`);
|
|
2731
|
+
}
|
|
2732
|
+
}
|
|
2725
2733
|
async function disconnect(deviceId, reason) {
|
|
2734
|
+
await waitUntil(() => store.deviceState[deviceId] === "paired" || store.deviceState[deviceId] === void 0);
|
|
2726
2735
|
store.setState(deviceId, "disconnecting");
|
|
2727
|
-
promiseQueue
|
|
2736
|
+
promiseQueue.clearQueue(deviceId, "Previous pending commands aborted");
|
|
2728
2737
|
await bluetooth.disconnect(deviceId);
|
|
2729
2738
|
delete store.devices[deviceId];
|
|
2730
2739
|
deviceUnreachableCallback?.(deviceId);
|
|
@@ -2736,11 +2745,13 @@ const simulatorSvc = {
|
|
|
2736
2745
|
registerEvent(eventName, callback) {
|
|
2737
2746
|
callbacks[eventName] = callback;
|
|
2738
2747
|
},
|
|
2739
|
-
triggerEvent(eventName, deviceId) {
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2748
|
+
triggerEvent(eventName, deviceId, payload) {
|
|
2749
|
+
if (payload === void 0) {
|
|
2750
|
+
const simulatedDevice = store.simulatedDevices[deviceId];
|
|
2751
|
+
if (!simulatedDevice) throw new Error(`Device not found`);
|
|
2752
|
+
payload = simulatedDevice.simulatorData?.events?.[eventName];
|
|
2753
|
+
if (!payload) throw new Error(`Event not found`);
|
|
2754
|
+
}
|
|
2744
2755
|
const callback = callbacks[eventName];
|
|
2745
2756
|
if (!callback) {
|
|
2746
2757
|
console.warn(`Event ${eventName} not registered`);
|
|
@@ -2779,10 +2790,7 @@ async function getBattery(deviceId) {
|
|
|
2779
2790
|
}
|
|
2780
2791
|
|
|
2781
2792
|
let sensorReadings = [];
|
|
2782
|
-
|
|
2783
|
-
let buttonCallback;
|
|
2784
|
-
let tpmsCallback;
|
|
2785
|
-
const capabilities = [
|
|
2793
|
+
const capabilities$1 = [
|
|
2786
2794
|
{
|
|
2787
2795
|
id: "td",
|
|
2788
2796
|
processFn: processTreadDepth,
|
|
@@ -2819,7 +2827,7 @@ const flexiGaugeTpmsService = {
|
|
|
2819
2827
|
processMessage(deviceId, message) {
|
|
2820
2828
|
const numberArray = Array.from(new Uint8Array(message));
|
|
2821
2829
|
const stringFromBytes = String.fromCharCode.apply(null, numberArray).replace("\r\n", "");
|
|
2822
|
-
for (const capability of capabilities) {
|
|
2830
|
+
for (const capability of capabilities$1) {
|
|
2823
2831
|
if (capability.regex.test(stringFromBytes)) {
|
|
2824
2832
|
return capability.processFn(deviceId, stringFromBytes);
|
|
2825
2833
|
}
|
|
@@ -2829,12 +2837,12 @@ const flexiGaugeTpmsService = {
|
|
|
2829
2837
|
function processTreadDepth(deviceId, value) {
|
|
2830
2838
|
const treadDepth = value.match(/\d+/)?.[0];
|
|
2831
2839
|
const convertedValue = Number(treadDepth) / 1e3;
|
|
2832
|
-
|
|
2840
|
+
simulatorSvc.triggerEvent("fg:treadDepth", deviceId, convertedValue);
|
|
2833
2841
|
}
|
|
2834
2842
|
function processButtonPress(deviceId, value) {
|
|
2835
2843
|
const buttonName = value.match(/\*(.)/);
|
|
2836
2844
|
if (!buttonName || !buttonName[1]) throw new Error("Unrecognized button");
|
|
2837
|
-
|
|
2845
|
+
simulatorSvc.triggerEvent("fg:button", deviceId, buttonName[1]);
|
|
2838
2846
|
}
|
|
2839
2847
|
function processTpms(deviceId, value) {
|
|
2840
2848
|
const groupedValue = value.split(" ");
|
|
@@ -2854,12 +2862,13 @@ function processTpms(deviceId, value) {
|
|
|
2854
2862
|
}
|
|
2855
2863
|
if (type === "ENDSCANNING") {
|
|
2856
2864
|
if (!sensorReadings.length) {
|
|
2857
|
-
|
|
2865
|
+
simulatorSvc.triggerEvent("fg:tpms", deviceId, null);
|
|
2866
|
+
return;
|
|
2858
2867
|
}
|
|
2859
2868
|
const strongestReading = sensorReadings.reduce((accumulator, currentReading) => {
|
|
2860
2869
|
return Number(currentReading.Rssi) > Number(accumulator.Rssi) ? currentReading : accumulator;
|
|
2861
2870
|
}, sensorReadings[0]);
|
|
2862
|
-
|
|
2871
|
+
simulatorSvc.triggerEvent("fg:tpms", deviceId, strongestReading);
|
|
2863
2872
|
}
|
|
2864
2873
|
}
|
|
2865
2874
|
|
|
@@ -2888,6 +2897,55 @@ const flexiGaugeTpms = {
|
|
|
2888
2897
|
startTpmsScan: flexiGaugeTpmsService.startTpmsScan
|
|
2889
2898
|
};
|
|
2890
2899
|
|
|
2900
|
+
const capabilities = [
|
|
2901
|
+
{
|
|
2902
|
+
id: "pressure",
|
|
2903
|
+
processFn: processPressure,
|
|
2904
|
+
regex: /P([0-9.]+)mBar/
|
|
2905
|
+
}
|
|
2906
|
+
];
|
|
2907
|
+
const pressureStickService = {
|
|
2908
|
+
onPressure(callback) {
|
|
2909
|
+
simulatorSvc.registerEvent("ps:pressure", callback);
|
|
2910
|
+
},
|
|
2911
|
+
processMessage(deviceId, message) {
|
|
2912
|
+
const numberArray = Array.from(new Uint8Array(message));
|
|
2913
|
+
const stringFromBytes = String.fromCharCode.apply(null, numberArray).replace("\r\n", "");
|
|
2914
|
+
for (const capability of capabilities) {
|
|
2915
|
+
if (capability.regex.test(stringFromBytes)) {
|
|
2916
|
+
return capability.processFn(deviceId, stringFromBytes);
|
|
2917
|
+
}
|
|
2918
|
+
}
|
|
2919
|
+
}
|
|
2920
|
+
};
|
|
2921
|
+
function processPressure(deviceId, msg) {
|
|
2922
|
+
const match = /P([0-9.]+)mBar/i.exec(msg);
|
|
2923
|
+
if (!match) throw new Error("Incorrect pressure message");
|
|
2924
|
+
const pressure = Number(match[1]) / 1e3;
|
|
2925
|
+
simulatorSvc.triggerEvent("ps:pressure", deviceId, pressure);
|
|
2926
|
+
}
|
|
2927
|
+
|
|
2928
|
+
const pressureStick = {
|
|
2929
|
+
async connect(deviceId) {
|
|
2930
|
+
const psMeta = deviceMeta.pressureStick;
|
|
2931
|
+
await bluetooth.connect(deviceId, this.disconnect);
|
|
2932
|
+
await ble.startNotification(
|
|
2933
|
+
deviceId,
|
|
2934
|
+
psMeta.communication.serviceId,
|
|
2935
|
+
psMeta.communication.characteristicId,
|
|
2936
|
+
(notification) => pressureStickService.processMessage(deviceId, notification),
|
|
2937
|
+
(error) => console.warn("ble.startNotification error", error)
|
|
2938
|
+
);
|
|
2939
|
+
store.setState(deviceId, "paired");
|
|
2940
|
+
},
|
|
2941
|
+
async disconnect(deviceId, reason) {
|
|
2942
|
+
store.setState(deviceId, "disconnecting");
|
|
2943
|
+
await bluetooth.disconnect(deviceId);
|
|
2944
|
+
store.setState(deviceId, void 0, reason ?? "manualDisconnection");
|
|
2945
|
+
},
|
|
2946
|
+
onPressure: pressureStickService.onPressure
|
|
2947
|
+
};
|
|
2948
|
+
|
|
2891
2949
|
const bridgeSimulator = {
|
|
2892
2950
|
isRebootRequired(deviceId) {
|
|
2893
2951
|
return store.bridgeRebootRequired[deviceId];
|
|
@@ -3261,6 +3319,8 @@ function createTirecheckDeviceSdk(platform, bleImplementation) {
|
|
|
3261
3319
|
bridgeOta,
|
|
3262
3320
|
/** Methods for working with Tirecheck TPMS FlexiGauge */
|
|
3263
3321
|
flexiGaugeTpms,
|
|
3322
|
+
/** Methods for working with Tirecheck Pressure Stick */
|
|
3323
|
+
pressureStick,
|
|
3264
3324
|
/** Allows simulating devices without actually using bluetooth */
|
|
3265
3325
|
simulator
|
|
3266
3326
|
};
|
package/dist/index.d.cts
CHANGED
|
@@ -83,6 +83,14 @@ declare const _default$1: {
|
|
|
83
83
|
getDeviceInfoFromAdvertising: (device: PeripheralData) => BleFlexiGaugeTpms;
|
|
84
84
|
reconnect: boolean;
|
|
85
85
|
};
|
|
86
|
+
pressureStick: {
|
|
87
|
+
nameRegex: RegExp;
|
|
88
|
+
communication: {
|
|
89
|
+
serviceId: string;
|
|
90
|
+
characteristicId: string;
|
|
91
|
+
};
|
|
92
|
+
getDeviceInfoFromAdvertising: (device: PeripheralData) => BlePressureStick;
|
|
93
|
+
};
|
|
86
94
|
};
|
|
87
95
|
|
|
88
96
|
declare const _default: {
|
|
@@ -734,7 +742,7 @@ type BridgeCommandStructurized<T extends BridgeCommandStructureProperties> = {
|
|
|
734
742
|
};
|
|
735
743
|
type BleDeviceType = keyof typeof _default$1;
|
|
736
744
|
/** distinguish by type, e.g. `if (device.type === 'bridge')`, to access furhter fields */
|
|
737
|
-
type BleDevice = BleBridge | BleBridgeOta | BleFlexiGaugeTpms;
|
|
745
|
+
type BleDevice = BleBridge | BleBridgeOta | BleFlexiGaugeTpms | BlePressureStick;
|
|
738
746
|
type BleDeviceSimulated = BleBridgeSimulated | BleFlexiGaugeTpmsSimulated;
|
|
739
747
|
type BleDeviceStatus = 'connected' | 'connecting' | 'disconnecting' | undefined;
|
|
740
748
|
interface BleDeviceBase {
|
|
@@ -764,6 +772,9 @@ interface BleBridgeOta extends BleDeviceBase {
|
|
|
764
772
|
};
|
|
765
773
|
type: 'bridgeOta';
|
|
766
774
|
}
|
|
775
|
+
interface BlePressureStick extends BleDeviceBase {
|
|
776
|
+
type: 'pressureStick';
|
|
777
|
+
}
|
|
767
778
|
interface BleBridgeSimulated extends BleBridge {
|
|
768
779
|
isDisabled?: boolean;
|
|
769
780
|
simulatorData: {
|
|
@@ -809,11 +820,12 @@ type Wrapper<T extends Record<string, (...args: any) => any>> = {
|
|
|
809
820
|
};
|
|
810
821
|
type ReportStatusFn = (status: string, completionPercentage: number) => void;
|
|
811
822
|
type DeviceState = 'connected' | 'connecting' | 'disconnecting' | 'paired' | undefined;
|
|
812
|
-
type StateReason = 'lostConnection' | 'manualDisconnection' | 'failedConnection' | 'failedDisconnection' | 'firmwareUpdate';
|
|
823
|
+
type StateReason = 'lostConnection' | 'manualDisconnection' | 'failedConnection' | 'failedDisconnection' | 'firmwareUpdate' | string;
|
|
813
824
|
interface EventHandlers {
|
|
814
825
|
'fg:treadDepth'?: (deviceId: string, value: number) => void;
|
|
815
826
|
'fg:button'?: (deviceId: string, value: string) => void;
|
|
816
827
|
'fg:tpms'?: (deviceId: string, value: FgSensorReading | undefined) => void;
|
|
828
|
+
'ps:pressure'?: (deviceId: string, value: number) => void;
|
|
817
829
|
}
|
|
818
830
|
type EventName = keyof EventHandlers;
|
|
819
831
|
|
|
@@ -836,7 +848,7 @@ declare function createTirecheckDeviceSdk(platform: DevicePlatform, bleImplement
|
|
|
836
848
|
/** Methods for working with Tirecheck CAN Bridge */
|
|
837
849
|
bridge: {
|
|
838
850
|
disconnect: (deviceId: string, reason?: StateReason) => Promise<void>;
|
|
839
|
-
connect(deviceId: string, accessLevel: BridgeAccessLevel)
|
|
851
|
+
connect: (deviceId: string, accessLevel: BridgeAccessLevel) => Promise<void>;
|
|
840
852
|
getVehicle: (deviceId: string) => Promise<BridgeTcVehicle>;
|
|
841
853
|
setVehicle: (deviceId: string, tcVehicle: BridgeTcVehicle) => Promise<void>;
|
|
842
854
|
getConfiguration: (deviceId: string) => Promise<BridgeConfiguration>;
|
|
@@ -864,14 +876,20 @@ declare function createTirecheckDeviceSdk(platform: DevicePlatform, bleImplement
|
|
|
864
876
|
getBattery: (deviceId: string) => Promise<number>;
|
|
865
877
|
startTpmsScan: (deviceId: string) => void;
|
|
866
878
|
};
|
|
879
|
+
/** Methods for working with Tirecheck Pressure Stick */
|
|
880
|
+
pressureStick: {
|
|
881
|
+
connect(deviceId: string): Promise<void>;
|
|
882
|
+
disconnect(deviceId: string, reason?: StateReason): Promise<void>;
|
|
883
|
+
onPressure: (callback: (deviceId: string, value: number) => void) => void;
|
|
884
|
+
};
|
|
867
885
|
/** Allows simulating devices without actually using bluetooth */
|
|
868
886
|
simulator: {
|
|
869
887
|
putSimulatedDevices(devices: Record<string, DeepPartial<BleDeviceSimulated>>): Record<string, BleDeviceSimulated>;
|
|
870
888
|
putSimulatedDevice(device: DeepPartial<BleDeviceSimulated>): BleBridgeSimulated | BleFlexiGaugeTpmsSimulated;
|
|
871
889
|
deleteSimulatedDevice(deviceId: string): void;
|
|
872
890
|
getSimulatedDevices(): Record<string, BleDeviceSimulated>;
|
|
873
|
-
triggerEvent: (eventName: EventName, deviceId: string) => void;
|
|
891
|
+
triggerEvent: (eventName: EventName, deviceId: string, payload?: any) => void;
|
|
874
892
|
};
|
|
875
893
|
};
|
|
876
894
|
|
|
877
|
-
export { type BleBridge, type BleBridgeAdvertisingData, type BleBridgeOta, type BleBridgeSimulated, type BleDevice, type BleDeviceBase, type BleDeviceSimulated, type BleDeviceStatus, type BleDeviceType, type BleFlexiGaugeTpms, type BleFlexiGaugeTpmsSimulated, 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 };
|
|
895
|
+
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 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
|
@@ -83,6 +83,14 @@ declare const _default$1: {
|
|
|
83
83
|
getDeviceInfoFromAdvertising: (device: PeripheralData) => BleFlexiGaugeTpms;
|
|
84
84
|
reconnect: boolean;
|
|
85
85
|
};
|
|
86
|
+
pressureStick: {
|
|
87
|
+
nameRegex: RegExp;
|
|
88
|
+
communication: {
|
|
89
|
+
serviceId: string;
|
|
90
|
+
characteristicId: string;
|
|
91
|
+
};
|
|
92
|
+
getDeviceInfoFromAdvertising: (device: PeripheralData) => BlePressureStick;
|
|
93
|
+
};
|
|
86
94
|
};
|
|
87
95
|
|
|
88
96
|
declare const _default: {
|
|
@@ -734,7 +742,7 @@ type BridgeCommandStructurized<T extends BridgeCommandStructureProperties> = {
|
|
|
734
742
|
};
|
|
735
743
|
type BleDeviceType = keyof typeof _default$1;
|
|
736
744
|
/** distinguish by type, e.g. `if (device.type === 'bridge')`, to access furhter fields */
|
|
737
|
-
type BleDevice = BleBridge | BleBridgeOta | BleFlexiGaugeTpms;
|
|
745
|
+
type BleDevice = BleBridge | BleBridgeOta | BleFlexiGaugeTpms | BlePressureStick;
|
|
738
746
|
type BleDeviceSimulated = BleBridgeSimulated | BleFlexiGaugeTpmsSimulated;
|
|
739
747
|
type BleDeviceStatus = 'connected' | 'connecting' | 'disconnecting' | undefined;
|
|
740
748
|
interface BleDeviceBase {
|
|
@@ -764,6 +772,9 @@ interface BleBridgeOta extends BleDeviceBase {
|
|
|
764
772
|
};
|
|
765
773
|
type: 'bridgeOta';
|
|
766
774
|
}
|
|
775
|
+
interface BlePressureStick extends BleDeviceBase {
|
|
776
|
+
type: 'pressureStick';
|
|
777
|
+
}
|
|
767
778
|
interface BleBridgeSimulated extends BleBridge {
|
|
768
779
|
isDisabled?: boolean;
|
|
769
780
|
simulatorData: {
|
|
@@ -809,11 +820,12 @@ type Wrapper<T extends Record<string, (...args: any) => any>> = {
|
|
|
809
820
|
};
|
|
810
821
|
type ReportStatusFn = (status: string, completionPercentage: number) => void;
|
|
811
822
|
type DeviceState = 'connected' | 'connecting' | 'disconnecting' | 'paired' | undefined;
|
|
812
|
-
type StateReason = 'lostConnection' | 'manualDisconnection' | 'failedConnection' | 'failedDisconnection' | 'firmwareUpdate';
|
|
823
|
+
type StateReason = 'lostConnection' | 'manualDisconnection' | 'failedConnection' | 'failedDisconnection' | 'firmwareUpdate' | string;
|
|
813
824
|
interface EventHandlers {
|
|
814
825
|
'fg:treadDepth'?: (deviceId: string, value: number) => void;
|
|
815
826
|
'fg:button'?: (deviceId: string, value: string) => void;
|
|
816
827
|
'fg:tpms'?: (deviceId: string, value: FgSensorReading | undefined) => void;
|
|
828
|
+
'ps:pressure'?: (deviceId: string, value: number) => void;
|
|
817
829
|
}
|
|
818
830
|
type EventName = keyof EventHandlers;
|
|
819
831
|
|
|
@@ -836,7 +848,7 @@ declare function createTirecheckDeviceSdk(platform: DevicePlatform, bleImplement
|
|
|
836
848
|
/** Methods for working with Tirecheck CAN Bridge */
|
|
837
849
|
bridge: {
|
|
838
850
|
disconnect: (deviceId: string, reason?: StateReason) => Promise<void>;
|
|
839
|
-
connect(deviceId: string, accessLevel: BridgeAccessLevel)
|
|
851
|
+
connect: (deviceId: string, accessLevel: BridgeAccessLevel) => Promise<void>;
|
|
840
852
|
getVehicle: (deviceId: string) => Promise<BridgeTcVehicle>;
|
|
841
853
|
setVehicle: (deviceId: string, tcVehicle: BridgeTcVehicle) => Promise<void>;
|
|
842
854
|
getConfiguration: (deviceId: string) => Promise<BridgeConfiguration>;
|
|
@@ -864,14 +876,20 @@ declare function createTirecheckDeviceSdk(platform: DevicePlatform, bleImplement
|
|
|
864
876
|
getBattery: (deviceId: string) => Promise<number>;
|
|
865
877
|
startTpmsScan: (deviceId: string) => void;
|
|
866
878
|
};
|
|
879
|
+
/** Methods for working with Tirecheck Pressure Stick */
|
|
880
|
+
pressureStick: {
|
|
881
|
+
connect(deviceId: string): Promise<void>;
|
|
882
|
+
disconnect(deviceId: string, reason?: StateReason): Promise<void>;
|
|
883
|
+
onPressure: (callback: (deviceId: string, value: number) => void) => void;
|
|
884
|
+
};
|
|
867
885
|
/** Allows simulating devices without actually using bluetooth */
|
|
868
886
|
simulator: {
|
|
869
887
|
putSimulatedDevices(devices: Record<string, DeepPartial<BleDeviceSimulated>>): Record<string, BleDeviceSimulated>;
|
|
870
888
|
putSimulatedDevice(device: DeepPartial<BleDeviceSimulated>): BleBridgeSimulated | BleFlexiGaugeTpmsSimulated;
|
|
871
889
|
deleteSimulatedDevice(deviceId: string): void;
|
|
872
890
|
getSimulatedDevices(): Record<string, BleDeviceSimulated>;
|
|
873
|
-
triggerEvent: (eventName: EventName, deviceId: string) => void;
|
|
891
|
+
triggerEvent: (eventName: EventName, deviceId: string, payload?: any) => void;
|
|
874
892
|
};
|
|
875
893
|
};
|
|
876
894
|
|
|
877
|
-
export { type BleBridge, type BleBridgeAdvertisingData, type BleBridgeOta, type BleBridgeSimulated, type BleDevice, type BleDeviceBase, type BleDeviceSimulated, type BleDeviceStatus, type BleDeviceType, type BleFlexiGaugeTpms, type BleFlexiGaugeTpmsSimulated, 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 };
|
|
895
|
+
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 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
|
@@ -83,6 +83,14 @@ declare const _default$1: {
|
|
|
83
83
|
getDeviceInfoFromAdvertising: (device: PeripheralData) => BleFlexiGaugeTpms;
|
|
84
84
|
reconnect: boolean;
|
|
85
85
|
};
|
|
86
|
+
pressureStick: {
|
|
87
|
+
nameRegex: RegExp;
|
|
88
|
+
communication: {
|
|
89
|
+
serviceId: string;
|
|
90
|
+
characteristicId: string;
|
|
91
|
+
};
|
|
92
|
+
getDeviceInfoFromAdvertising: (device: PeripheralData) => BlePressureStick;
|
|
93
|
+
};
|
|
86
94
|
};
|
|
87
95
|
|
|
88
96
|
declare const _default: {
|
|
@@ -734,7 +742,7 @@ type BridgeCommandStructurized<T extends BridgeCommandStructureProperties> = {
|
|
|
734
742
|
};
|
|
735
743
|
type BleDeviceType = keyof typeof _default$1;
|
|
736
744
|
/** distinguish by type, e.g. `if (device.type === 'bridge')`, to access furhter fields */
|
|
737
|
-
type BleDevice = BleBridge | BleBridgeOta | BleFlexiGaugeTpms;
|
|
745
|
+
type BleDevice = BleBridge | BleBridgeOta | BleFlexiGaugeTpms | BlePressureStick;
|
|
738
746
|
type BleDeviceSimulated = BleBridgeSimulated | BleFlexiGaugeTpmsSimulated;
|
|
739
747
|
type BleDeviceStatus = 'connected' | 'connecting' | 'disconnecting' | undefined;
|
|
740
748
|
interface BleDeviceBase {
|
|
@@ -764,6 +772,9 @@ interface BleBridgeOta extends BleDeviceBase {
|
|
|
764
772
|
};
|
|
765
773
|
type: 'bridgeOta';
|
|
766
774
|
}
|
|
775
|
+
interface BlePressureStick extends BleDeviceBase {
|
|
776
|
+
type: 'pressureStick';
|
|
777
|
+
}
|
|
767
778
|
interface BleBridgeSimulated extends BleBridge {
|
|
768
779
|
isDisabled?: boolean;
|
|
769
780
|
simulatorData: {
|
|
@@ -809,11 +820,12 @@ type Wrapper<T extends Record<string, (...args: any) => any>> = {
|
|
|
809
820
|
};
|
|
810
821
|
type ReportStatusFn = (status: string, completionPercentage: number) => void;
|
|
811
822
|
type DeviceState = 'connected' | 'connecting' | 'disconnecting' | 'paired' | undefined;
|
|
812
|
-
type StateReason = 'lostConnection' | 'manualDisconnection' | 'failedConnection' | 'failedDisconnection' | 'firmwareUpdate';
|
|
823
|
+
type StateReason = 'lostConnection' | 'manualDisconnection' | 'failedConnection' | 'failedDisconnection' | 'firmwareUpdate' | string;
|
|
813
824
|
interface EventHandlers {
|
|
814
825
|
'fg:treadDepth'?: (deviceId: string, value: number) => void;
|
|
815
826
|
'fg:button'?: (deviceId: string, value: string) => void;
|
|
816
827
|
'fg:tpms'?: (deviceId: string, value: FgSensorReading | undefined) => void;
|
|
828
|
+
'ps:pressure'?: (deviceId: string, value: number) => void;
|
|
817
829
|
}
|
|
818
830
|
type EventName = keyof EventHandlers;
|
|
819
831
|
|
|
@@ -836,7 +848,7 @@ declare function createTirecheckDeviceSdk(platform: DevicePlatform, bleImplement
|
|
|
836
848
|
/** Methods for working with Tirecheck CAN Bridge */
|
|
837
849
|
bridge: {
|
|
838
850
|
disconnect: (deviceId: string, reason?: StateReason) => Promise<void>;
|
|
839
|
-
connect(deviceId: string, accessLevel: BridgeAccessLevel)
|
|
851
|
+
connect: (deviceId: string, accessLevel: BridgeAccessLevel) => Promise<void>;
|
|
840
852
|
getVehicle: (deviceId: string) => Promise<BridgeTcVehicle>;
|
|
841
853
|
setVehicle: (deviceId: string, tcVehicle: BridgeTcVehicle) => Promise<void>;
|
|
842
854
|
getConfiguration: (deviceId: string) => Promise<BridgeConfiguration>;
|
|
@@ -864,14 +876,20 @@ declare function createTirecheckDeviceSdk(platform: DevicePlatform, bleImplement
|
|
|
864
876
|
getBattery: (deviceId: string) => Promise<number>;
|
|
865
877
|
startTpmsScan: (deviceId: string) => void;
|
|
866
878
|
};
|
|
879
|
+
/** Methods for working with Tirecheck Pressure Stick */
|
|
880
|
+
pressureStick: {
|
|
881
|
+
connect(deviceId: string): Promise<void>;
|
|
882
|
+
disconnect(deviceId: string, reason?: StateReason): Promise<void>;
|
|
883
|
+
onPressure: (callback: (deviceId: string, value: number) => void) => void;
|
|
884
|
+
};
|
|
867
885
|
/** Allows simulating devices without actually using bluetooth */
|
|
868
886
|
simulator: {
|
|
869
887
|
putSimulatedDevices(devices: Record<string, DeepPartial<BleDeviceSimulated>>): Record<string, BleDeviceSimulated>;
|
|
870
888
|
putSimulatedDevice(device: DeepPartial<BleDeviceSimulated>): BleBridgeSimulated | BleFlexiGaugeTpmsSimulated;
|
|
871
889
|
deleteSimulatedDevice(deviceId: string): void;
|
|
872
890
|
getSimulatedDevices(): Record<string, BleDeviceSimulated>;
|
|
873
|
-
triggerEvent: (eventName: EventName, deviceId: string) => void;
|
|
891
|
+
triggerEvent: (eventName: EventName, deviceId: string, payload?: any) => void;
|
|
874
892
|
};
|
|
875
893
|
};
|
|
876
894
|
|
|
877
|
-
export { type BleBridge, type BleBridgeAdvertisingData, type BleBridgeOta, type BleBridgeSimulated, type BleDevice, type BleDeviceBase, type BleDeviceSimulated, type BleDeviceStatus, type BleDeviceType, type BleFlexiGaugeTpms, type BleFlexiGaugeTpmsSimulated, 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 };
|
|
895
|
+
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 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
|
@@ -495,7 +495,7 @@ const deviceMeta = {
|
|
|
495
495
|
getDeviceInfoFromAdvertising: bridgeOtaAdvertisingParser.getDeviceInfoFromAdvertising
|
|
496
496
|
},
|
|
497
497
|
flexiGaugeTpms: {
|
|
498
|
-
nameRegex:
|
|
498
|
+
nameRegex: /^Flexi.*/,
|
|
499
499
|
communication: {
|
|
500
500
|
serviceId: "4880c12c-fdcb-4077-8920-a450d7f9b907",
|
|
501
501
|
characteristicId: "fec26ec4-6d71-4442-9f81-55bc21d658d6"
|
|
@@ -513,28 +513,21 @@ const deviceMeta = {
|
|
|
513
513
|
},
|
|
514
514
|
reconnect: true
|
|
515
515
|
// Do we need it here?
|
|
516
|
+
},
|
|
517
|
+
pressureStick: {
|
|
518
|
+
nameRegex: /Pressure Stick.*/,
|
|
519
|
+
communication: {
|
|
520
|
+
serviceId: "4880c12c-fdcb-4077-8920-a450d7f9b907",
|
|
521
|
+
characteristicId: "fec26ec4-6d71-4442-9f81-55bc21d658d6"
|
|
522
|
+
},
|
|
523
|
+
getDeviceInfoFromAdvertising: (device) => {
|
|
524
|
+
const bleDevice = {
|
|
525
|
+
...device,
|
|
526
|
+
type: "pressureStick"
|
|
527
|
+
};
|
|
528
|
+
return bleDevice;
|
|
529
|
+
}
|
|
516
530
|
}
|
|
517
|
-
// pressureStick: {
|
|
518
|
-
// nameRegex: /Pressure Stick.*/,
|
|
519
|
-
// characteristic: {
|
|
520
|
-
// serviceId: '4880c12c-fdcb-4077-8920-a450d7f9b907',
|
|
521
|
-
// characteristicId: 'fec26ec4-6d71-4442-9f81-55bc21d658d6',
|
|
522
|
-
// },
|
|
523
|
-
// getDeviceInfoFromAdvertising: () => {},
|
|
524
|
-
// capabilities: [
|
|
525
|
-
// {
|
|
526
|
-
// id: 'pressure',
|
|
527
|
-
// // processFn: processPressure,
|
|
528
|
-
// regex: /P([0-9.]+)mBar/,
|
|
529
|
-
// },
|
|
530
|
-
// // only pressure is needed for initial implementation, uncomment tpms functionality when needed
|
|
531
|
-
// // {
|
|
532
|
-
// // id: 'tpms',
|
|
533
|
-
// // processFn: processTpms,
|
|
534
|
-
// // regex: /^\*TPMS/,
|
|
535
|
-
// // },
|
|
536
|
-
// ],
|
|
537
|
-
// },
|
|
538
531
|
};
|
|
539
532
|
|
|
540
533
|
const checkUnreachableDevicesTimeouts = {};
|
|
@@ -558,7 +551,7 @@ const bluetooth = {
|
|
|
558
551
|
stopScan() {
|
|
559
552
|
ble.stopScan();
|
|
560
553
|
},
|
|
561
|
-
connect,
|
|
554
|
+
connect: connect$1,
|
|
562
555
|
disconnect: disconnect$1,
|
|
563
556
|
write,
|
|
564
557
|
read
|
|
@@ -585,7 +578,7 @@ async function scanDevices(services = [], duration) {
|
|
|
585
578
|
(e) => console.error("ble.startScanWithOptions error:", e)
|
|
586
579
|
);
|
|
587
580
|
}
|
|
588
|
-
async function connect(deviceId, disconnectCallback) {
|
|
581
|
+
async function connect$1(deviceId, disconnectCallback) {
|
|
589
582
|
if (toolsSvc.canCommunicateWith(deviceId)) return console.warn("Connect Warn: Already connected to device");
|
|
590
583
|
store.setState(deviceId, "connecting");
|
|
591
584
|
let connectedDevice;
|
|
@@ -706,6 +699,78 @@ function getDeviceNameFromAdvertising(advertising) {
|
|
|
706
699
|
return deviceName;
|
|
707
700
|
}
|
|
708
701
|
|
|
702
|
+
const otaServiceUuid = "1d14d6ee-fd63-4fa1-bfa4-8f47b42119f0";
|
|
703
|
+
const otaControlCharacteristicUuid = "f7bf3564-fb6d-4e53-88a4-5e37e0326063";
|
|
704
|
+
const otaDataCharacteristicUuid = "984227f3-34fc-4045-a5d0-2c581f81a153";
|
|
705
|
+
const bridgeOtaCommands = {
|
|
706
|
+
async beginOta(deviceId) {
|
|
707
|
+
await bluetooth.write(deviceId, otaServiceUuid, otaControlCharacteristicUuid, new Uint8Array([0]).buffer, true);
|
|
708
|
+
},
|
|
709
|
+
async uploadOtaChunk(deviceId, data) {
|
|
710
|
+
await bluetooth.write(deviceId, otaServiceUuid, otaDataCharacteristicUuid, data, true);
|
|
711
|
+
},
|
|
712
|
+
async endOta(deviceId) {
|
|
713
|
+
await bluetooth.write(deviceId, otaServiceUuid, otaControlCharacteristicUuid, new Uint8Array([3]).buffer, true);
|
|
714
|
+
}
|
|
715
|
+
};
|
|
716
|
+
|
|
717
|
+
const bridgeOtaService = {
|
|
718
|
+
async updateFirmware(deviceId, bootloader, firmware, progressCallback) {
|
|
719
|
+
await delay(2e3);
|
|
720
|
+
progressCallback("Connecting to the bridge...", 0.1);
|
|
721
|
+
await bridgeOta.connect(deviceId);
|
|
722
|
+
progressCallback("Uploading bootloader...", 0.12);
|
|
723
|
+
await bridgeOtaCommands.beginOta(deviceId);
|
|
724
|
+
await uploadOta(deviceId, bootloader, (str, percents) => progressCallback(str, 0.12 + percents * 0.2));
|
|
725
|
+
await bridgeOtaCommands.endOta(deviceId);
|
|
726
|
+
progressCallback("Uploading application...", 0.32);
|
|
727
|
+
await bridgeOtaCommands.beginOta(deviceId);
|
|
728
|
+
await uploadOta(deviceId, firmware, (str, percents) => progressCallback(str, 0.32 + percents * 0.5));
|
|
729
|
+
await bridgeOtaCommands.endOta(deviceId);
|
|
730
|
+
progressCallback("Upload completed, disconnecting...", 0.81);
|
|
731
|
+
await bridgeOta.disconnect(deviceId);
|
|
732
|
+
progressCallback("Disconnected...", 1);
|
|
733
|
+
}
|
|
734
|
+
};
|
|
735
|
+
async function uploadOta(deviceId, firmwareBinary, reportStatus) {
|
|
736
|
+
let uploadedBytes = 0;
|
|
737
|
+
let chunkIndex = 0;
|
|
738
|
+
const mtu = store.platform === "android" ? 512 : deviceMeta.bridgeOta.mtu;
|
|
739
|
+
while (uploadedBytes < firmwareBinary.byteLength) {
|
|
740
|
+
if (chunkIndex % 100 === 0)
|
|
741
|
+
reportStatus(
|
|
742
|
+
`Uploading new firmware... (${_.round(uploadedBytes / 1e3)} / ${_.round(
|
|
743
|
+
firmwareBinary.byteLength / 1e3
|
|
744
|
+
)} KB)`,
|
|
745
|
+
uploadedBytes / firmwareBinary.byteLength
|
|
746
|
+
);
|
|
747
|
+
const chunkSize = Math.min(mtu - 3, firmwareBinary.byteLength - uploadedBytes);
|
|
748
|
+
const chunk = firmwareBinary.slice(uploadedBytes, uploadedBytes + chunkSize);
|
|
749
|
+
await bridgeOtaCommands.uploadOtaChunk(deviceId, chunk);
|
|
750
|
+
uploadedBytes += chunkSize;
|
|
751
|
+
chunkIndex++;
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
const bridgeOta = {
|
|
756
|
+
async connect(deviceId) {
|
|
757
|
+
await bluetooth.connect(deviceId, this.disconnect);
|
|
758
|
+
const _deviceId = store.deviceIdMapingTable[deviceId] ?? deviceId;
|
|
759
|
+
if (store.platform !== "ios") {
|
|
760
|
+
await ble.requestMtu(_deviceId, 512);
|
|
761
|
+
}
|
|
762
|
+
store.setState(deviceId, "paired");
|
|
763
|
+
},
|
|
764
|
+
async disconnect(deviceId, reason) {
|
|
765
|
+
store.setState(deviceId, "disconnecting");
|
|
766
|
+
await bluetooth.disconnect(deviceId);
|
|
767
|
+
store.setState(deviceId, void 0, reason ?? "manualDisconnection");
|
|
768
|
+
},
|
|
769
|
+
async updateFirmware(deviceId, bootloader, firmware, progressCallback) {
|
|
770
|
+
return bridgeOtaService.updateFirmware(deviceId, bootloader, firmware, progressCallback);
|
|
771
|
+
}
|
|
772
|
+
};
|
|
773
|
+
|
|
709
774
|
const bridgeCommandStructures = {
|
|
710
775
|
workshopCanSettings: {
|
|
711
776
|
id: [98, 96],
|
|
@@ -1523,25 +1588,26 @@ const bridgeSecurity = {
|
|
|
1523
1588
|
};
|
|
1524
1589
|
|
|
1525
1590
|
const bridgeMeta = deviceMeta.bridge;
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
};
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1591
|
+
const devicePromiseQueue = {};
|
|
1592
|
+
const deviceCurrentResolve = {};
|
|
1593
|
+
const deviceCurrentReject = {};
|
|
1594
|
+
const deviceResponseIdentifier = {};
|
|
1595
|
+
const promiseQueue = {
|
|
1596
|
+
clearQueue(deviceId, message) {
|
|
1597
|
+
if (deviceCurrentReject[deviceId]) {
|
|
1598
|
+
deviceCurrentReject[deviceId](new Error(message ?? "Stopped sending commands"));
|
|
1599
|
+
}
|
|
1600
|
+
devicePromiseQueue[deviceId] = Promise.resolve();
|
|
1601
|
+
deviceResponseIdentifier[deviceId] = [];
|
|
1537
1602
|
},
|
|
1538
1603
|
async enqueue(device, payload) {
|
|
1539
|
-
|
|
1604
|
+
if (devicePromiseQueue[device.id] === void 0) devicePromiseQueue[device.id] = Promise.resolve();
|
|
1605
|
+
devicePromiseQueue[device.id] = devicePromiseQueue[device.id].then(() => {
|
|
1540
1606
|
const promise = new Promise((resolve, reject) => {
|
|
1541
|
-
|
|
1542
|
-
|
|
1607
|
+
deviceCurrentResolve[device.id] = resolve;
|
|
1608
|
+
deviceCurrentReject[device.id] = reject;
|
|
1543
1609
|
const isKeepAlive = payload[3] === commandIds.keepAlive;
|
|
1544
|
-
|
|
1610
|
+
deviceResponseIdentifier[device.id] = [isKeepAlive ? 126 : 0, payload[4]];
|
|
1545
1611
|
const signedData = bridgeSecurity.getSignedCommand(device, payload);
|
|
1546
1612
|
if (!toolsSvc.canCommunicateWith(device.id)) return reject(new Error("Bridge not connected"));
|
|
1547
1613
|
if (signedData.length > 110) {
|
|
@@ -1567,21 +1633,21 @@ const promiseQueue$1 = {
|
|
|
1567
1633
|
);
|
|
1568
1634
|
}
|
|
1569
1635
|
});
|
|
1570
|
-
return withTimeout(promise, 5e3, `Command timed out ${
|
|
1636
|
+
return withTimeout(promise, 5e3, `Command timed out ${deviceResponseIdentifier[device.id]}, ${device.id}`);
|
|
1571
1637
|
});
|
|
1572
|
-
return
|
|
1638
|
+
return devicePromiseQueue[device.id];
|
|
1573
1639
|
},
|
|
1574
1640
|
async processMessage(deviceId, payload) {
|
|
1575
1641
|
const numberArray = Array.from(new Uint8Array(payload));
|
|
1576
1642
|
if (numberArray[3] === 127) {
|
|
1577
1643
|
console.error(numberArray);
|
|
1578
|
-
return
|
|
1644
|
+
return deviceCurrentReject[deviceId](new Error(`Command not succesful: ${numberArray[4]}`));
|
|
1579
1645
|
}
|
|
1580
1646
|
if ([226, 81].includes(numberArray[3]) && numberArray[4] && toolsSvc.canCommunicateWith(deviceId)) {
|
|
1581
1647
|
store.bridgeRebootRequired[deviceId] = true;
|
|
1582
1648
|
}
|
|
1583
|
-
if ((!
|
|
1584
|
-
return
|
|
1649
|
+
if ((!deviceResponseIdentifier[deviceId][0] || numberArray[3] === deviceResponseIdentifier[deviceId][0]) && (!deviceResponseIdentifier[deviceId][1] || numberArray[4] === deviceResponseIdentifier[deviceId][1])) {
|
|
1650
|
+
return deviceCurrentResolve[deviceId](numberArray);
|
|
1585
1651
|
}
|
|
1586
1652
|
console.warn("message from the device not belonging to the pending promise: ", numberArray);
|
|
1587
1653
|
}
|
|
@@ -1968,79 +2034,7 @@ const bridgeCommands = {
|
|
|
1968
2034
|
}
|
|
1969
2035
|
this.sendKeepAliveCommand(device);
|
|
1970
2036
|
}, 1e4);
|
|
1971
|
-
return promiseQueue
|
|
1972
|
-
}
|
|
1973
|
-
};
|
|
1974
|
-
|
|
1975
|
-
const otaServiceUuid = "1d14d6ee-fd63-4fa1-bfa4-8f47b42119f0";
|
|
1976
|
-
const otaControlCharacteristicUuid = "f7bf3564-fb6d-4e53-88a4-5e37e0326063";
|
|
1977
|
-
const otaDataCharacteristicUuid = "984227f3-34fc-4045-a5d0-2c581f81a153";
|
|
1978
|
-
const bridgeOtaCommands = {
|
|
1979
|
-
async beginOta(deviceId) {
|
|
1980
|
-
await bluetooth.write(deviceId, otaServiceUuid, otaControlCharacteristicUuid, new Uint8Array([0]).buffer, true);
|
|
1981
|
-
},
|
|
1982
|
-
async uploadOtaChunk(deviceId, data) {
|
|
1983
|
-
await bluetooth.write(deviceId, otaServiceUuid, otaDataCharacteristicUuid, data, true);
|
|
1984
|
-
},
|
|
1985
|
-
async endOta(deviceId) {
|
|
1986
|
-
await bluetooth.write(deviceId, otaServiceUuid, otaControlCharacteristicUuid, new Uint8Array([3]).buffer, true);
|
|
1987
|
-
}
|
|
1988
|
-
};
|
|
1989
|
-
|
|
1990
|
-
const bridgeOtaService = {
|
|
1991
|
-
async updateFirmware(deviceId, bootloader, firmware, progressCallback) {
|
|
1992
|
-
await delay(2e3);
|
|
1993
|
-
progressCallback("Connecting to the bridge...", 0.1);
|
|
1994
|
-
await bridgeOta.connect(deviceId);
|
|
1995
|
-
progressCallback("Uploading bootloader...", 0.12);
|
|
1996
|
-
await bridgeOtaCommands.beginOta(deviceId);
|
|
1997
|
-
await uploadOta(deviceId, bootloader, (str, percents) => progressCallback(str, 0.12 + percents * 0.2));
|
|
1998
|
-
await bridgeOtaCommands.endOta(deviceId);
|
|
1999
|
-
progressCallback("Uploading application...", 0.32);
|
|
2000
|
-
await bridgeOtaCommands.beginOta(deviceId);
|
|
2001
|
-
await uploadOta(deviceId, firmware, (str, percents) => progressCallback(str, 0.32 + percents * 0.5));
|
|
2002
|
-
await bridgeOtaCommands.endOta(deviceId);
|
|
2003
|
-
progressCallback("Upload completed, disconnecting...", 0.81);
|
|
2004
|
-
await bridgeOta.disconnect(deviceId);
|
|
2005
|
-
progressCallback("Disconnected...", 1);
|
|
2006
|
-
}
|
|
2007
|
-
};
|
|
2008
|
-
async function uploadOta(deviceId, firmwareBinary, reportStatus) {
|
|
2009
|
-
let uploadedBytes = 0;
|
|
2010
|
-
let chunkIndex = 0;
|
|
2011
|
-
const mtu = store.platform === "android" ? 512 : deviceMeta.bridgeOta.mtu;
|
|
2012
|
-
while (uploadedBytes < firmwareBinary.byteLength) {
|
|
2013
|
-
if (chunkIndex % 100 === 0)
|
|
2014
|
-
reportStatus(
|
|
2015
|
-
`Uploading new firmware... (${_.round(uploadedBytes / 1e3)} / ${_.round(
|
|
2016
|
-
firmwareBinary.byteLength / 1e3
|
|
2017
|
-
)} KB)`,
|
|
2018
|
-
uploadedBytes / firmwareBinary.byteLength
|
|
2019
|
-
);
|
|
2020
|
-
const chunkSize = Math.min(mtu - 3, firmwareBinary.byteLength - uploadedBytes);
|
|
2021
|
-
const chunk = firmwareBinary.slice(uploadedBytes, uploadedBytes + chunkSize);
|
|
2022
|
-
await bridgeOtaCommands.uploadOtaChunk(deviceId, chunk);
|
|
2023
|
-
uploadedBytes += chunkSize;
|
|
2024
|
-
chunkIndex++;
|
|
2025
|
-
}
|
|
2026
|
-
}
|
|
2027
|
-
|
|
2028
|
-
const bridgeOta = {
|
|
2029
|
-
async connect(deviceId) {
|
|
2030
|
-
await bluetooth.connect(deviceId, this.disconnect);
|
|
2031
|
-
const _deviceId = store.deviceIdMapingTable[deviceId] ?? deviceId;
|
|
2032
|
-
if (store.platform !== "ios") {
|
|
2033
|
-
await ble.requestMtu(_deviceId, 512);
|
|
2034
|
-
}
|
|
2035
|
-
store.setState(deviceId, "paired");
|
|
2036
|
-
},
|
|
2037
|
-
async disconnect(deviceId, reason) {
|
|
2038
|
-
store.setState(deviceId, "disconnecting");
|
|
2039
|
-
await bluetooth.disconnect(deviceId);
|
|
2040
|
-
store.setState(deviceId, void 0, reason ?? "manualDisconnection");
|
|
2041
|
-
},
|
|
2042
|
-
async updateFirmware(deviceId, bootloader, firmware, progressCallback) {
|
|
2043
|
-
return bridgeOtaService.updateFirmware(deviceId, bootloader, firmware, progressCallback);
|
|
2037
|
+
return promiseQueue.enqueue(device, writeCommand);
|
|
2044
2038
|
}
|
|
2045
2039
|
};
|
|
2046
2040
|
|
|
@@ -2062,8 +2056,13 @@ const bridgeService = {
|
|
|
2062
2056
|
getVehicleReadings,
|
|
2063
2057
|
resetAutolearnStatuses,
|
|
2064
2058
|
getAutolearnStatuses,
|
|
2065
|
-
isRebootRequired
|
|
2059
|
+
isRebootRequired,
|
|
2060
|
+
sendPinCommand
|
|
2066
2061
|
};
|
|
2062
|
+
async function sendPinCommand(deviceId) {
|
|
2063
|
+
if (!canCommunicateWith(deviceId)) throw new Error("Bridge not connected");
|
|
2064
|
+
await bridgeCommands.sendPinCommand(deviceId);
|
|
2065
|
+
}
|
|
2067
2066
|
async function updateFirmware(deviceId, bootloader, firmware, reportStatus) {
|
|
2068
2067
|
reportStatus("Sending OTA Request...", 0.02);
|
|
2069
2068
|
await bridgeCommands.sendOtaRequest(deviceId);
|
|
@@ -2385,7 +2384,7 @@ async function getVehicleReadings(deviceId, tcVehicle) {
|
|
|
2385
2384
|
try {
|
|
2386
2385
|
for (const vehicleTyre of tcVehicle.tcTyres) {
|
|
2387
2386
|
if (vehicleTyre.tcTpmsSensor && vehicleTyre.mountedOn?.positionId) {
|
|
2388
|
-
if (!canCommunicateWith(deviceId))
|
|
2387
|
+
if (!canCommunicateWith(deviceId)) break;
|
|
2389
2388
|
const reading = await getSensorReading(deviceId, vehicleTyre.mountedOn.positionId);
|
|
2390
2389
|
readings.push(reading);
|
|
2391
2390
|
}
|
|
@@ -2683,12 +2682,28 @@ function isRebootRequired(deviceId) {
|
|
|
2683
2682
|
|
|
2684
2683
|
const bridge = {
|
|
2685
2684
|
disconnect,
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2685
|
+
connect,
|
|
2686
|
+
getVehicle: bridgeService.getVehicle,
|
|
2687
|
+
setVehicle: bridgeService.setVehicle,
|
|
2688
|
+
getConfiguration: bridgeService.getConfiguration,
|
|
2689
|
+
setConfiguration: bridgeService.setConfiguration,
|
|
2690
|
+
getSensorReading: bridgeService.getSensorReading,
|
|
2691
|
+
getVehicleReadings: bridgeService.getVehicleReadings,
|
|
2692
|
+
getAutolearnStatuses: bridgeService.getAutolearnStatuses,
|
|
2693
|
+
resetAutolearnStatuses: bridgeService.resetAutolearnStatuses,
|
|
2694
|
+
updateFirmware: bridgeService.updateFirmware,
|
|
2695
|
+
isRebootRequired: bridgeService.isRebootRequired
|
|
2696
|
+
};
|
|
2697
|
+
async function connect(deviceId, accessLevel) {
|
|
2698
|
+
if (canCommunicateWith(deviceId)) return;
|
|
2699
|
+
await promiseQueue.clearQueue(deviceId, "Previous pending commands aborted");
|
|
2700
|
+
const bridgeMeta = deviceMeta.bridge;
|
|
2701
|
+
await bluetooth.connect(deviceId, disconnect);
|
|
2702
|
+
if (store.deviceState[deviceId] === "paired") {
|
|
2703
|
+
return console.warn("Connect Warn: Already connected");
|
|
2704
|
+
}
|
|
2705
|
+
const _deviceId = store.deviceIdMapingTable[deviceId] ?? deviceId;
|
|
2706
|
+
try {
|
|
2692
2707
|
if (store.platform !== "ios") {
|
|
2693
2708
|
await ble.requestMtu(_deviceId, deviceMeta.bridge.mtu);
|
|
2694
2709
|
}
|
|
@@ -2696,28 +2711,22 @@ const bridge = {
|
|
|
2696
2711
|
_deviceId,
|
|
2697
2712
|
bridgeMeta.communication.serviceId,
|
|
2698
2713
|
bridgeMeta.communication.characteristicId,
|
|
2699
|
-
(notification) => promiseQueue
|
|
2714
|
+
(notification) => promiseQueue.processMessage(deviceId, notification),
|
|
2700
2715
|
(error) => console.error("startNotification Error", error)
|
|
2701
2716
|
);
|
|
2702
2717
|
store.deviceAccessLevel[deviceId] = accessLevel ?? "driver";
|
|
2703
2718
|
store.bridgeRebootRequired[deviceId] = false;
|
|
2704
|
-
await
|
|
2719
|
+
await bridgeService.sendPinCommand(deviceId);
|
|
2705
2720
|
store.setState(deviceId, "paired");
|
|
2706
|
-
}
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
getSensorReading: bridgeService.getSensorReading,
|
|
2712
|
-
getVehicleReadings: bridgeService.getVehicleReadings,
|
|
2713
|
-
getAutolearnStatuses: bridgeService.getAutolearnStatuses,
|
|
2714
|
-
resetAutolearnStatuses: bridgeService.resetAutolearnStatuses,
|
|
2715
|
-
updateFirmware: bridgeService.updateFirmware,
|
|
2716
|
-
isRebootRequired: bridgeService.isRebootRequired
|
|
2717
|
-
};
|
|
2721
|
+
} catch (e) {
|
|
2722
|
+
disconnect(deviceId);
|
|
2723
|
+
throw new Error(`Pairing unsuccessful ${e}`);
|
|
2724
|
+
}
|
|
2725
|
+
}
|
|
2718
2726
|
async function disconnect(deviceId, reason) {
|
|
2727
|
+
await waitUntil(() => store.deviceState[deviceId] === "paired" || store.deviceState[deviceId] === void 0);
|
|
2719
2728
|
store.setState(deviceId, "disconnecting");
|
|
2720
|
-
promiseQueue
|
|
2729
|
+
promiseQueue.clearQueue(deviceId, "Previous pending commands aborted");
|
|
2721
2730
|
await bluetooth.disconnect(deviceId);
|
|
2722
2731
|
delete store.devices[deviceId];
|
|
2723
2732
|
deviceUnreachableCallback?.(deviceId);
|
|
@@ -2729,11 +2738,13 @@ const simulatorSvc = {
|
|
|
2729
2738
|
registerEvent(eventName, callback) {
|
|
2730
2739
|
callbacks[eventName] = callback;
|
|
2731
2740
|
},
|
|
2732
|
-
triggerEvent(eventName, deviceId) {
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2741
|
+
triggerEvent(eventName, deviceId, payload) {
|
|
2742
|
+
if (payload === void 0) {
|
|
2743
|
+
const simulatedDevice = store.simulatedDevices[deviceId];
|
|
2744
|
+
if (!simulatedDevice) throw new Error(`Device not found`);
|
|
2745
|
+
payload = simulatedDevice.simulatorData?.events?.[eventName];
|
|
2746
|
+
if (!payload) throw new Error(`Event not found`);
|
|
2747
|
+
}
|
|
2737
2748
|
const callback = callbacks[eventName];
|
|
2738
2749
|
if (!callback) {
|
|
2739
2750
|
console.warn(`Event ${eventName} not registered`);
|
|
@@ -2772,10 +2783,7 @@ async function getBattery(deviceId) {
|
|
|
2772
2783
|
}
|
|
2773
2784
|
|
|
2774
2785
|
let sensorReadings = [];
|
|
2775
|
-
|
|
2776
|
-
let buttonCallback;
|
|
2777
|
-
let tpmsCallback;
|
|
2778
|
-
const capabilities = [
|
|
2786
|
+
const capabilities$1 = [
|
|
2779
2787
|
{
|
|
2780
2788
|
id: "td",
|
|
2781
2789
|
processFn: processTreadDepth,
|
|
@@ -2812,7 +2820,7 @@ const flexiGaugeTpmsService = {
|
|
|
2812
2820
|
processMessage(deviceId, message) {
|
|
2813
2821
|
const numberArray = Array.from(new Uint8Array(message));
|
|
2814
2822
|
const stringFromBytes = String.fromCharCode.apply(null, numberArray).replace("\r\n", "");
|
|
2815
|
-
for (const capability of capabilities) {
|
|
2823
|
+
for (const capability of capabilities$1) {
|
|
2816
2824
|
if (capability.regex.test(stringFromBytes)) {
|
|
2817
2825
|
return capability.processFn(deviceId, stringFromBytes);
|
|
2818
2826
|
}
|
|
@@ -2822,12 +2830,12 @@ const flexiGaugeTpmsService = {
|
|
|
2822
2830
|
function processTreadDepth(deviceId, value) {
|
|
2823
2831
|
const treadDepth = value.match(/\d+/)?.[0];
|
|
2824
2832
|
const convertedValue = Number(treadDepth) / 1e3;
|
|
2825
|
-
|
|
2833
|
+
simulatorSvc.triggerEvent("fg:treadDepth", deviceId, convertedValue);
|
|
2826
2834
|
}
|
|
2827
2835
|
function processButtonPress(deviceId, value) {
|
|
2828
2836
|
const buttonName = value.match(/\*(.)/);
|
|
2829
2837
|
if (!buttonName || !buttonName[1]) throw new Error("Unrecognized button");
|
|
2830
|
-
|
|
2838
|
+
simulatorSvc.triggerEvent("fg:button", deviceId, buttonName[1]);
|
|
2831
2839
|
}
|
|
2832
2840
|
function processTpms(deviceId, value) {
|
|
2833
2841
|
const groupedValue = value.split(" ");
|
|
@@ -2847,12 +2855,13 @@ function processTpms(deviceId, value) {
|
|
|
2847
2855
|
}
|
|
2848
2856
|
if (type === "ENDSCANNING") {
|
|
2849
2857
|
if (!sensorReadings.length) {
|
|
2850
|
-
|
|
2858
|
+
simulatorSvc.triggerEvent("fg:tpms", deviceId, null);
|
|
2859
|
+
return;
|
|
2851
2860
|
}
|
|
2852
2861
|
const strongestReading = sensorReadings.reduce((accumulator, currentReading) => {
|
|
2853
2862
|
return Number(currentReading.Rssi) > Number(accumulator.Rssi) ? currentReading : accumulator;
|
|
2854
2863
|
}, sensorReadings[0]);
|
|
2855
|
-
|
|
2864
|
+
simulatorSvc.triggerEvent("fg:tpms", deviceId, strongestReading);
|
|
2856
2865
|
}
|
|
2857
2866
|
}
|
|
2858
2867
|
|
|
@@ -2881,6 +2890,55 @@ const flexiGaugeTpms = {
|
|
|
2881
2890
|
startTpmsScan: flexiGaugeTpmsService.startTpmsScan
|
|
2882
2891
|
};
|
|
2883
2892
|
|
|
2893
|
+
const capabilities = [
|
|
2894
|
+
{
|
|
2895
|
+
id: "pressure",
|
|
2896
|
+
processFn: processPressure,
|
|
2897
|
+
regex: /P([0-9.]+)mBar/
|
|
2898
|
+
}
|
|
2899
|
+
];
|
|
2900
|
+
const pressureStickService = {
|
|
2901
|
+
onPressure(callback) {
|
|
2902
|
+
simulatorSvc.registerEvent("ps:pressure", callback);
|
|
2903
|
+
},
|
|
2904
|
+
processMessage(deviceId, message) {
|
|
2905
|
+
const numberArray = Array.from(new Uint8Array(message));
|
|
2906
|
+
const stringFromBytes = String.fromCharCode.apply(null, numberArray).replace("\r\n", "");
|
|
2907
|
+
for (const capability of capabilities) {
|
|
2908
|
+
if (capability.regex.test(stringFromBytes)) {
|
|
2909
|
+
return capability.processFn(deviceId, stringFromBytes);
|
|
2910
|
+
}
|
|
2911
|
+
}
|
|
2912
|
+
}
|
|
2913
|
+
};
|
|
2914
|
+
function processPressure(deviceId, msg) {
|
|
2915
|
+
const match = /P([0-9.]+)mBar/i.exec(msg);
|
|
2916
|
+
if (!match) throw new Error("Incorrect pressure message");
|
|
2917
|
+
const pressure = Number(match[1]) / 1e3;
|
|
2918
|
+
simulatorSvc.triggerEvent("ps:pressure", deviceId, pressure);
|
|
2919
|
+
}
|
|
2920
|
+
|
|
2921
|
+
const pressureStick = {
|
|
2922
|
+
async connect(deviceId) {
|
|
2923
|
+
const psMeta = deviceMeta.pressureStick;
|
|
2924
|
+
await bluetooth.connect(deviceId, this.disconnect);
|
|
2925
|
+
await ble.startNotification(
|
|
2926
|
+
deviceId,
|
|
2927
|
+
psMeta.communication.serviceId,
|
|
2928
|
+
psMeta.communication.characteristicId,
|
|
2929
|
+
(notification) => pressureStickService.processMessage(deviceId, notification),
|
|
2930
|
+
(error) => console.warn("ble.startNotification error", error)
|
|
2931
|
+
);
|
|
2932
|
+
store.setState(deviceId, "paired");
|
|
2933
|
+
},
|
|
2934
|
+
async disconnect(deviceId, reason) {
|
|
2935
|
+
store.setState(deviceId, "disconnecting");
|
|
2936
|
+
await bluetooth.disconnect(deviceId);
|
|
2937
|
+
store.setState(deviceId, void 0, reason ?? "manualDisconnection");
|
|
2938
|
+
},
|
|
2939
|
+
onPressure: pressureStickService.onPressure
|
|
2940
|
+
};
|
|
2941
|
+
|
|
2884
2942
|
const bridgeSimulator = {
|
|
2885
2943
|
isRebootRequired(deviceId) {
|
|
2886
2944
|
return store.bridgeRebootRequired[deviceId];
|
|
@@ -3254,6 +3312,8 @@ function createTirecheckDeviceSdk(platform, bleImplementation) {
|
|
|
3254
3312
|
bridgeOta,
|
|
3255
3313
|
/** Methods for working with Tirecheck TPMS FlexiGauge */
|
|
3256
3314
|
flexiGaugeTpms,
|
|
3315
|
+
/** Methods for working with Tirecheck Pressure Stick */
|
|
3316
|
+
pressureStick,
|
|
3257
3317
|
/** Allows simulating devices without actually using bluetooth */
|
|
3258
3318
|
simulator
|
|
3259
3319
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tirecheck-device-sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.96",
|
|
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",
|