tirecheck-device-sdk 0.2.70 → 0.2.72
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 +400 -25
- package/dist/index.d.cts +222 -7
- package/dist/index.d.mts +222 -7
- package/dist/index.d.ts +222 -7
- package/dist/index.mjs +400 -25
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -127,6 +127,19 @@ function normalizeError(error) {
|
|
|
127
127
|
return error;
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
+
const emptyBluetoothClassicSerialImplementation = {
|
|
131
|
+
list: async () => [],
|
|
132
|
+
discoverUnpaired: async () => [],
|
|
133
|
+
setDeviceDiscoveredListener: () => {
|
|
134
|
+
},
|
|
135
|
+
clearDeviceDiscoveredListener: () => {
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
let bluetoothClassicSerial = emptyBluetoothClassicSerialImplementation;
|
|
139
|
+
function setBluetoothClassicSerialImplementation(bluetoothClassicSerialImplementation) {
|
|
140
|
+
bluetoothClassicSerial = bluetoothClassicSerialImplementation ?? emptyBluetoothClassicSerialImplementation;
|
|
141
|
+
}
|
|
142
|
+
|
|
130
143
|
const tyreLabels = getDefaultTyreLabels();
|
|
131
144
|
const bridgeTools = {
|
|
132
145
|
getBridgeFromStore,
|
|
@@ -159,7 +172,7 @@ const bridgeTools = {
|
|
|
159
172
|
);
|
|
160
173
|
const result = [];
|
|
161
174
|
for (const key of keys) {
|
|
162
|
-
if (
|
|
175
|
+
if (structurizedObj[key] == null) throw new Error(`Missing key ${key} in the structure`);
|
|
163
176
|
const encoded = this.encodeData(structurizedObj[key], objStructure[key].display);
|
|
164
177
|
if (encoded.length < objStructure[key].size) {
|
|
165
178
|
const _padArray = Array.from({ length: objStructure[key].size - encoded.length }, () => 0);
|
|
@@ -199,7 +212,8 @@ const bridgeTools = {
|
|
|
199
212
|
return this.asciiToDecimalArray(_data);
|
|
200
213
|
}
|
|
201
214
|
if (displayUnits === "decimal") {
|
|
202
|
-
|
|
215
|
+
const hex = decimalToHex(_data);
|
|
216
|
+
return this.hexToDecimalArray(hex.length % 2 ? `0${hex}` : hex).reverse();
|
|
203
217
|
}
|
|
204
218
|
if (displayUnits === "reverseHex") {
|
|
205
219
|
const byteArray = _data.match(/.{1,2}/g) || [];
|
|
@@ -650,6 +664,17 @@ const deviceMeta = {
|
|
|
650
664
|
};
|
|
651
665
|
return bleDevice;
|
|
652
666
|
}
|
|
667
|
+
},
|
|
668
|
+
unitechRfid: {
|
|
669
|
+
nameRegex: /^RP902/i,
|
|
670
|
+
transport: "serial",
|
|
671
|
+
getDeviceInfoFromAdvertising: (device) => {
|
|
672
|
+
const bleDevice = {
|
|
673
|
+
...device,
|
|
674
|
+
type: "unitechRfid"
|
|
675
|
+
};
|
|
676
|
+
return bleDevice;
|
|
677
|
+
}
|
|
653
678
|
}
|
|
654
679
|
};
|
|
655
680
|
|
|
@@ -686,6 +711,8 @@ const bluetooth = {
|
|
|
686
711
|
deviceStateChangeCallback = callback;
|
|
687
712
|
},
|
|
688
713
|
scanDevices,
|
|
714
|
+
scanSerialDevicesPaired,
|
|
715
|
+
scanSerialDevicesUnpaired,
|
|
689
716
|
stopScan() {
|
|
690
717
|
ble.stopScan();
|
|
691
718
|
},
|
|
@@ -716,6 +743,47 @@ async function scanDevices(services = [], duration) {
|
|
|
716
743
|
(e) => console.error("ble.startScanWithOptions error:", e)
|
|
717
744
|
);
|
|
718
745
|
}
|
|
746
|
+
async function scanSerialDevicesPaired() {
|
|
747
|
+
try {
|
|
748
|
+
const pairedDevices = await bluetoothClassicSerial.list();
|
|
749
|
+
for (const device of pairedDevices ?? []) handleSerialDevice(device);
|
|
750
|
+
} catch (e) {
|
|
751
|
+
console.error("scanPairedSerialDevices error:", e);
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
async function scanSerialDevicesUnpaired() {
|
|
755
|
+
bluetoothClassicSerial.setDeviceDiscoveredListener?.((device) => handleSerialDevice(device));
|
|
756
|
+
try {
|
|
757
|
+
const unpairedDevices = await bluetoothClassicSerial.discoverUnpaired();
|
|
758
|
+
for (const device of unpairedDevices ?? []) handleSerialDevice(device);
|
|
759
|
+
} catch (e) {
|
|
760
|
+
const message = (typeof e === "string" ? e : e?.message ?? "").toLowerCase();
|
|
761
|
+
const pickerDismissed = store.platform === "ios" && ["cancel", "alreadyconnected", "already connected", "notfound", "not found"].some((m) => message.includes(m));
|
|
762
|
+
if (pickerDismissed) {
|
|
763
|
+
console.log("discoverSerialDevices: accessory picker returned no unpaired device -", message);
|
|
764
|
+
} else {
|
|
765
|
+
console.error("discoverSerialDevices error:", e);
|
|
766
|
+
}
|
|
767
|
+
} finally {
|
|
768
|
+
bluetoothClassicSerial.clearDeviceDiscoveredListener?.();
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
function handleSerialDevice(device) {
|
|
772
|
+
const rawId = device.id ?? device.address;
|
|
773
|
+
const id = rawId != null ? String(rawId) : void 0;
|
|
774
|
+
if (!id) {
|
|
775
|
+
console.warn("handleSerialDevice: skipped, no id/address", device);
|
|
776
|
+
return;
|
|
777
|
+
}
|
|
778
|
+
const peripheral = { id, name: device.name, rssi: device.rssi ?? 0, advertising: {} };
|
|
779
|
+
const processedDevice = processDevice(peripheral);
|
|
780
|
+
if (!processedDevice) {
|
|
781
|
+
console.warn("handleSerialDevice: processDevice returned null (filtered out)", id, device.name);
|
|
782
|
+
return;
|
|
783
|
+
}
|
|
784
|
+
store.devices[processedDevice.id] = processedDevice;
|
|
785
|
+
deviceAdvertisingCallback?.(processedDevice);
|
|
786
|
+
}
|
|
719
787
|
async function connect$1(deviceId, disconnectCallback) {
|
|
720
788
|
if (toolsSvc.canCommunicateWith(deviceId)) return console.warn("Connect Warn: Already connected to device");
|
|
721
789
|
store.setState(deviceId, "connecting");
|
|
@@ -804,7 +872,8 @@ function processDevice(device) {
|
|
|
804
872
|
console.warn("Error processing advertising", e);
|
|
805
873
|
return;
|
|
806
874
|
}
|
|
807
|
-
|
|
875
|
+
const isSerial = deviceMeta[deviceType].transport === "serial";
|
|
876
|
+
if (!isSerial) unreachableSvc.refresh(processedDevice.id, deviceUnreachableCallback);
|
|
808
877
|
return processedDevice;
|
|
809
878
|
}
|
|
810
879
|
function getDeviceTypeFromName(name) {
|
|
@@ -1777,6 +1846,109 @@ const bridgeCommandStructures = {
|
|
|
1777
1846
|
description: "Bluetooth chip FW version: major.minor.patch + release type (e.g. 1.2.0 Release)"
|
|
1778
1847
|
}
|
|
1779
1848
|
}
|
|
1849
|
+
},
|
|
1850
|
+
bridgeConfiguration: {
|
|
1851
|
+
id: [98, 1],
|
|
1852
|
+
name: "bridgeConfiguration",
|
|
1853
|
+
structure: {
|
|
1854
|
+
configVersion: {
|
|
1855
|
+
size: 4,
|
|
1856
|
+
description: "Application configuration version details",
|
|
1857
|
+
display: "decimal"
|
|
1858
|
+
},
|
|
1859
|
+
bleTxPower: {
|
|
1860
|
+
size: 2,
|
|
1861
|
+
description: "Used BLE Tx power (16 bit signed value; LSB = 0.1)",
|
|
1862
|
+
display: "decimal"
|
|
1863
|
+
},
|
|
1864
|
+
bleTxChannels: {
|
|
1865
|
+
size: 1,
|
|
1866
|
+
description: "BLE channel configuration (0x07 = all channels)"
|
|
1867
|
+
},
|
|
1868
|
+
bleConnectableAdvPeriod: {
|
|
1869
|
+
size: 2,
|
|
1870
|
+
description: "BLE Connectable Advertisement Period [LSB = 0.625 ms]",
|
|
1871
|
+
display: "decimal"
|
|
1872
|
+
},
|
|
1873
|
+
configurationFlags: {
|
|
1874
|
+
size: 1,
|
|
1875
|
+
description: "Configuration flags (1 = Enable inactivity timeout; 4 = Disable time lockout on false PINs)"
|
|
1876
|
+
},
|
|
1877
|
+
wrongPinsUntilLockout: {
|
|
1878
|
+
size: 1,
|
|
1879
|
+
description: "Minimal number of wrong pins allowed before the lockout activates",
|
|
1880
|
+
display: "decimal"
|
|
1881
|
+
},
|
|
1882
|
+
maxLockoutPeriodIncreases: {
|
|
1883
|
+
size: 1,
|
|
1884
|
+
description: "How many times the lockout period may be doubled",
|
|
1885
|
+
display: "decimal"
|
|
1886
|
+
},
|
|
1887
|
+
wrongPinInitialLockoutTime: {
|
|
1888
|
+
size: 1,
|
|
1889
|
+
description: "Initial lockout time duration after too many wrong PINs",
|
|
1890
|
+
display: "decimal"
|
|
1891
|
+
},
|
|
1892
|
+
securityConfiguration: {
|
|
1893
|
+
size: 1,
|
|
1894
|
+
description: "Bluetooth security configuration (0x03 - legacy pairing enabled; 0x07 - disabled)"
|
|
1895
|
+
},
|
|
1896
|
+
canEnabled: {
|
|
1897
|
+
size: 1,
|
|
1898
|
+
description: "CAN enabled state",
|
|
1899
|
+
display: "decimal"
|
|
1900
|
+
},
|
|
1901
|
+
bleEnabled: {
|
|
1902
|
+
size: 1,
|
|
1903
|
+
description: "BLE Advertisement enabled state",
|
|
1904
|
+
display: "decimal"
|
|
1905
|
+
},
|
|
1906
|
+
canBitrate: {
|
|
1907
|
+
size: 2,
|
|
1908
|
+
description: "CAN Bitrate [kbps]",
|
|
1909
|
+
display: "decimal"
|
|
1910
|
+
},
|
|
1911
|
+
movementDetectionLimit: {
|
|
1912
|
+
size: 2,
|
|
1913
|
+
description: "Movement detection limit [1/256 kmph per bit]",
|
|
1914
|
+
display: "decimal"
|
|
1915
|
+
},
|
|
1916
|
+
sensorInactivityTimeout: {
|
|
1917
|
+
size: 2,
|
|
1918
|
+
description: "Timeout [s] after which an inactive sensor is marked erroneous (max. 512 s)",
|
|
1919
|
+
display: "decimal"
|
|
1920
|
+
},
|
|
1921
|
+
manufacturerCode: {
|
|
1922
|
+
size: 4,
|
|
1923
|
+
description: "Manufacturer Code as per SAE J1939",
|
|
1924
|
+
display: "decimal"
|
|
1925
|
+
},
|
|
1926
|
+
identityNumber: {
|
|
1927
|
+
size: 4,
|
|
1928
|
+
description: "Identity number for ECU (max. 22 bits = 0x1FFFFF)",
|
|
1929
|
+
display: "decimal"
|
|
1930
|
+
},
|
|
1931
|
+
manufacturerName: {
|
|
1932
|
+
size: 20,
|
|
1933
|
+
description: "Manufacturer Name (SPN 4304, max. 20 bytes)",
|
|
1934
|
+
display: "ascii"
|
|
1935
|
+
},
|
|
1936
|
+
ecuPartNumber: {
|
|
1937
|
+
size: 20,
|
|
1938
|
+
description: "ECU Part Number (SPN 2901, max. 20 bytes)",
|
|
1939
|
+
display: "ascii"
|
|
1940
|
+
},
|
|
1941
|
+
softwareVersion: {
|
|
1942
|
+
size: 20,
|
|
1943
|
+
description: "Software Version (SPN 234, max. 20 bytes)",
|
|
1944
|
+
display: "ascii"
|
|
1945
|
+
},
|
|
1946
|
+
reservedConfiguration: {
|
|
1947
|
+
size: 4,
|
|
1948
|
+
description: "Reserved configuration",
|
|
1949
|
+
display: "decimal"
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1780
1952
|
}
|
|
1781
1953
|
};
|
|
1782
1954
|
|
|
@@ -1875,6 +2047,18 @@ const bridgeSecurity = {
|
|
|
1875
2047
|
}
|
|
1876
2048
|
return crc >>> 0;
|
|
1877
2049
|
},
|
|
2050
|
+
/** CRC-16/CCITT-FALSE (poly 0x1021, init 0xFFFF). Used for the RxSWIN (0xF18F) E010/E141 checksums. */
|
|
2051
|
+
crc16Ccitt(msg) {
|
|
2052
|
+
let crc = 65535;
|
|
2053
|
+
const polynomial = 4129;
|
|
2054
|
+
for (const byte of msg) {
|
|
2055
|
+
crc ^= (byte & 255) << 8;
|
|
2056
|
+
for (let j = 0; j < 8; j++) {
|
|
2057
|
+
crc = crc & 32768 ? (crc << 1 ^ polynomial) & 65535 : crc << 1 & 65535;
|
|
2058
|
+
}
|
|
2059
|
+
}
|
|
2060
|
+
return crc & 65535;
|
|
2061
|
+
},
|
|
1878
2062
|
getCrcArray(msg) {
|
|
1879
2063
|
const crc = this.crc32mpeg2(msg);
|
|
1880
2064
|
const crcHex = decimalToHex(crc).padStart(8, "0");
|
|
@@ -2280,6 +2464,21 @@ const bridgeCommands = {
|
|
|
2280
2464
|
deviceData.advertisingData.fwVersion
|
|
2281
2465
|
);
|
|
2282
2466
|
},
|
|
2467
|
+
async getBridgeConfiguration(deviceId) {
|
|
2468
|
+
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
2469
|
+
const result = await this.readCommand(deviceData, subCommandIds.bridgeConfiguration);
|
|
2470
|
+
const structurized = bridgeTools.convertBytesToStructure(
|
|
2471
|
+
bridgeCommandStructures.bridgeConfiguration.structure,
|
|
2472
|
+
result.data,
|
|
2473
|
+
deviceData.advertisingData.fwVersion
|
|
2474
|
+
);
|
|
2475
|
+
console.log(
|
|
2476
|
+
`[getBridgeConfiguration] raw payload (${result.data.length}B):`,
|
|
2477
|
+
result.data.map((b) => decimalToHex(b)).join(" ")
|
|
2478
|
+
);
|
|
2479
|
+
console.log("[getBridgeConfiguration] decoded structure:", structurized, `(isFactory: ${result.isFactory})`);
|
|
2480
|
+
return { ...structurized, isFactory: result.isFactory };
|
|
2481
|
+
},
|
|
2283
2482
|
async getErrorHistoryCounter(deviceId) {
|
|
2284
2483
|
const deviceData = bridgeTools.getBridgeFromStore(deviceId);
|
|
2285
2484
|
const result = await this.readCommand(deviceData, subCommandIds.errorHistoryCounter, {
|
|
@@ -2391,6 +2590,7 @@ const bridgeService = {
|
|
|
2391
2590
|
setVehicle,
|
|
2392
2591
|
getConfiguration,
|
|
2393
2592
|
setConfiguration,
|
|
2593
|
+
getRxSWIN,
|
|
2394
2594
|
getSensorReading,
|
|
2395
2595
|
getVehicleReadings,
|
|
2396
2596
|
resetAutolearnStatuses,
|
|
@@ -2462,7 +2662,7 @@ async function setVehicleLayout(deviceId, tcVehicle) {
|
|
|
2462
2662
|
}
|
|
2463
2663
|
await bridgeCommands.setVehicleLayout(deviceId, result);
|
|
2464
2664
|
}
|
|
2465
|
-
async function getConfiguration(deviceId
|
|
2665
|
+
async function getConfiguration(deviceId) {
|
|
2466
2666
|
const customerCANSettings = await bridgeCommands.getCustomerCANSettings(deviceId);
|
|
2467
2667
|
const workshopCANSettings = await bridgeCommands.getWorkshopCANSettings(deviceId);
|
|
2468
2668
|
const customerPressureThresholds = await bridgeCommands.getCustomerPressureThresholds(deviceId);
|
|
@@ -2470,16 +2670,23 @@ async function getConfiguration(deviceId, includeVehicleData = false) {
|
|
|
2470
2670
|
const customerImbalanceThresholds = await bridgeCommands.getCustomerImbalanceThresholds(deviceId);
|
|
2471
2671
|
const pressuresPerAxle = await bridgeCommands.getPressuresPerAxle(deviceId);
|
|
2472
2672
|
let autolearnSettings;
|
|
2673
|
+
let autolearnIdStatus;
|
|
2674
|
+
let autolearnUnknownSensors;
|
|
2473
2675
|
let errorHistoryCounter;
|
|
2474
2676
|
let eolStatus;
|
|
2677
|
+
let firmwareVersion;
|
|
2475
2678
|
if (bridgeTools.isVersionGreaterThan(deviceId, "0.9.7")) {
|
|
2476
2679
|
autolearnSettings = await bridgeCommands.getAutolearnSettings(deviceId);
|
|
2680
|
+
autolearnIdStatus = await bridgeCommands.getAutolearnIdStatus(deviceId);
|
|
2681
|
+
autolearnUnknownSensors = await bridgeCommands.getAutolearnUnknownSensors(deviceId);
|
|
2477
2682
|
}
|
|
2478
2683
|
if (bridgeTools.isVersionGreaterThan(deviceId, "1.1.F")) {
|
|
2479
2684
|
errorHistoryCounter = await bridgeCommands.getErrorHistoryCounter(deviceId);
|
|
2480
2685
|
eolStatus = await bridgeCommands.getEolStatus(deviceId);
|
|
2686
|
+
firmwareVersion = await bridgeCommands.getFirmwareVersion(deviceId);
|
|
2481
2687
|
}
|
|
2482
|
-
const
|
|
2688
|
+
const rxswin = await getRxSWIN(deviceId, { customerPressureThresholds, customerCANSettings });
|
|
2689
|
+
return {
|
|
2483
2690
|
customerCANSettings,
|
|
2484
2691
|
workshopCANSettings,
|
|
2485
2692
|
customerPressureThresholds,
|
|
@@ -2487,27 +2694,75 @@ async function getConfiguration(deviceId, includeVehicleData = false) {
|
|
|
2487
2694
|
customerImbalanceThresholds,
|
|
2488
2695
|
pressuresPerAxle,
|
|
2489
2696
|
autolearnSettings,
|
|
2697
|
+
autolearnIdStatus,
|
|
2698
|
+
autolearnUnknownSensors,
|
|
2490
2699
|
errorHistoryCounter,
|
|
2491
|
-
eolStatus
|
|
2700
|
+
eolStatus,
|
|
2701
|
+
firmwareVersion,
|
|
2702
|
+
rxswin
|
|
2492
2703
|
};
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2704
|
+
}
|
|
2705
|
+
async function getRxSWIN(deviceId, configuration) {
|
|
2706
|
+
if (!canCommunicateWith(deviceId)) throw new Error("Bridge not connected");
|
|
2707
|
+
const bridgeConfiguration = bridgeTools.isVersionGreaterThan(deviceId, "1.1.F") ? await bridgeCommands.getBridgeConfiguration(deviceId) : {
|
|
2708
|
+
canEnabled: 1,
|
|
2709
|
+
movementDetectionLimit: 1280,
|
|
2710
|
+
// Firmware default provided as 0x01FA for pre-1.2.0 bridges where record 0x01 is unavailable.
|
|
2711
|
+
sensorInactivityTimeout: 506,
|
|
2712
|
+
bleTxPower: 60,
|
|
2713
|
+
bleTxChannels: "07"
|
|
2714
|
+
};
|
|
2715
|
+
const customerPressureThresholds = configuration?.customerPressureThresholds ?? await bridgeCommands.getCustomerPressureThresholds(deviceId);
|
|
2716
|
+
const customerCANSettings = configuration?.customerCANSettings ?? await bridgeCommands.getCustomerCANSettings(deviceId);
|
|
2717
|
+
const fwVersion = bridgeTools.getBridgeFromStore(deviceId).advertisingData.fwVersion;
|
|
2718
|
+
const bleTxChannels = bridgeTools.hexToDecimalArray(bridgeConfiguration.bleTxChannels ?? "").reverse();
|
|
2719
|
+
const axle01PressureThresholds = bridgeTools.hexToDecimalArray(customerPressureThresholds.axle01 ?? "");
|
|
2720
|
+
const canProtocol = bridgeTools.hexToDecimalArray(customerCANSettings.canProtocol ?? "").reverse();
|
|
2721
|
+
const transparentFilteredMode = bridgeTools.hexToDecimalArray(customerCANSettings.transparentFilteredMode ?? "").reverse();
|
|
2722
|
+
const fwMajor = (fwVersion || "0").split(".")[0].charCodeAt(0) & 255;
|
|
2723
|
+
const bleTxPower = bridgeTools.intToBytes(bridgeConfiguration.bleTxPower ?? 0, 2);
|
|
2724
|
+
const canEnabled = bridgeTools.intToBytes(bridgeConfiguration.canEnabled ?? 0, 1);
|
|
2725
|
+
const movementDetectionLimit = bridgeTools.intToBytes(bridgeConfiguration.movementDetectionLimit ?? 0, 2);
|
|
2726
|
+
const sensorInactivityTimeout = bridgeTools.intToBytes(bridgeConfiguration.sensorInactivityTimeout ?? 0, 2);
|
|
2727
|
+
const e010Input = [bleTxPower[0] ?? 0, bleTxPower[1] ?? 0, bleTxChannels[0] ?? 0];
|
|
2728
|
+
const e141Input = [
|
|
2729
|
+
canEnabled[0] ?? 0,
|
|
2730
|
+
movementDetectionLimit[0] ?? 0,
|
|
2731
|
+
movementDetectionLimit[1] ?? 0,
|
|
2732
|
+
sensorInactivityTimeout[0] ?? 0,
|
|
2733
|
+
sensorInactivityTimeout[1] ?? 0,
|
|
2734
|
+
axle01PressureThresholds[0] ?? 0,
|
|
2735
|
+
canProtocol[0] ?? 0,
|
|
2736
|
+
transparentFilteredMode[0] ?? 0,
|
|
2737
|
+
fwMajor
|
|
2738
|
+
];
|
|
2739
|
+
console.log(`[getRxSWIN] e010: ${e010Input}`);
|
|
2740
|
+
console.log(`[getRxSWIN] e141: ${e141Input}`);
|
|
2741
|
+
const result = {
|
|
2742
|
+
R10SWIN: decimalToHex(bridgeSecurity.crc16Ccitt(e010Input), 4),
|
|
2743
|
+
R141SWIN: decimalToHex(bridgeSecurity.crc16Ccitt(e141Input), 4)
|
|
2744
|
+
};
|
|
2745
|
+
const item1Content = [
|
|
2746
|
+
...bridgeTools.asciiToDecimalArray("R010"),
|
|
2747
|
+
32,
|
|
2748
|
+
...bridgeTools.asciiToDecimalArray(result.R10SWIN)
|
|
2749
|
+
];
|
|
2750
|
+
const item2Content = [
|
|
2751
|
+
...bridgeTools.asciiToDecimalArray("R141"),
|
|
2752
|
+
32,
|
|
2753
|
+
...bridgeTools.asciiToDecimalArray(result.R141SWIN)
|
|
2754
|
+
];
|
|
2755
|
+
const item1 = [item1Content.length, ...item1Content];
|
|
2756
|
+
const item2 = [item2Content.length, ...item2Content];
|
|
2757
|
+
const payload = [...item1, ...item2];
|
|
2758
|
+
console.log(
|
|
2759
|
+
`[getRxSWIN] R010 item: "${String.fromCharCode(...item1.slice(1))}" (${item1.map((b) => decimalToHex(b)).join(" ")})`
|
|
2760
|
+
);
|
|
2761
|
+
console.log(
|
|
2762
|
+
`[getRxSWIN] R141 item: "${String.fromCharCode(...item2.slice(1))}" (${item2.map((b) => decimalToHex(b)).join(" ")})`
|
|
2763
|
+
);
|
|
2764
|
+
console.log(`[getRxSWIN] final payload (${payload.length}B): ${payload.map((b) => decimalToHex(b)).join(" ")}`);
|
|
2765
|
+
return result;
|
|
2511
2766
|
}
|
|
2512
2767
|
function bridgeVehiclesDifference(original, change) {
|
|
2513
2768
|
const differences = [];
|
|
@@ -3086,6 +3341,7 @@ const bridge = {
|
|
|
3086
3341
|
setVehicle: bridgeService.setVehicle,
|
|
3087
3342
|
getConfiguration: bridgeService.getConfiguration,
|
|
3088
3343
|
setConfiguration: bridgeService.setConfiguration,
|
|
3344
|
+
getRxSWIN: bridgeService.getRxSWIN,
|
|
3089
3345
|
getSensorReading: bridgeService.getSensorReading,
|
|
3090
3346
|
getVehicleReadings: bridgeService.getVehicleReadings,
|
|
3091
3347
|
getAutolearnStatuses: bridgeService.getAutolearnStatuses,
|
|
@@ -4153,6 +4409,95 @@ const torqueWrench = {
|
|
|
4153
4409
|
onReading: torqueWrenchService.onReading
|
|
4154
4410
|
};
|
|
4155
4411
|
|
|
4412
|
+
let unitech;
|
|
4413
|
+
function setUnitechRfidImplementation(unitechRfidImplementation) {
|
|
4414
|
+
if (!unitechRfidImplementation)
|
|
4415
|
+
return console.warn("Unitech RFID implementation is not provided, Unitech RFID functionality will not work");
|
|
4416
|
+
unitech = unitechRfidImplementation;
|
|
4417
|
+
}
|
|
4418
|
+
|
|
4419
|
+
const unitechRfidService = {
|
|
4420
|
+
subscribeListeners(deviceId) {
|
|
4421
|
+
unitech.addListener("readerState", (event) => {
|
|
4422
|
+
simulatorSvc.triggerEvent("unitech:readerState", deviceId, event);
|
|
4423
|
+
simulatorSvc.triggerEvent("unitech:readerStateConnect", deviceId, event);
|
|
4424
|
+
});
|
|
4425
|
+
unitech.addListener("actionState", (event) => simulatorSvc.triggerEvent("unitech:actionState", deviceId, event));
|
|
4426
|
+
unitech.addListener("trigger", (event) => simulatorSvc.triggerEvent("unitech:trigger", deviceId, event));
|
|
4427
|
+
unitech.addListener("tagRead", (event) => simulatorSvc.triggerEvent("unitech:tag", deviceId, event));
|
|
4428
|
+
unitech.addListener("battery", (event) => simulatorSvc.triggerEvent("unitech:battery", deviceId, event));
|
|
4429
|
+
unitech.addListener("temperature", (event) => simulatorSvc.triggerEvent("unitech:temperature", deviceId, event));
|
|
4430
|
+
},
|
|
4431
|
+
onReaderState(callback) {
|
|
4432
|
+
simulatorSvc.registerEvent("unitech:readerState", callback);
|
|
4433
|
+
},
|
|
4434
|
+
onActionState(callback) {
|
|
4435
|
+
simulatorSvc.registerEvent("unitech:actionState", callback);
|
|
4436
|
+
},
|
|
4437
|
+
onTrigger(callback) {
|
|
4438
|
+
simulatorSvc.registerEvent("unitech:trigger", callback);
|
|
4439
|
+
},
|
|
4440
|
+
onTagRead(callback) {
|
|
4441
|
+
simulatorSvc.registerEvent("unitech:tag", callback);
|
|
4442
|
+
},
|
|
4443
|
+
onBattery(callback) {
|
|
4444
|
+
simulatorSvc.registerEvent("unitech:battery", callback);
|
|
4445
|
+
},
|
|
4446
|
+
onTemperature(callback) {
|
|
4447
|
+
simulatorSvc.registerEvent("unitech:temperature", callback);
|
|
4448
|
+
}
|
|
4449
|
+
};
|
|
4450
|
+
|
|
4451
|
+
const unitechRfid = {
|
|
4452
|
+
async connect(deviceId) {
|
|
4453
|
+
const unitechDevices = Object.values(store.devices).filter((d) => d.type === "unitechRfid");
|
|
4454
|
+
for (const device2 of unitechDevices) {
|
|
4455
|
+
if (device2.id !== deviceId && store.deviceState[device2.id] === "paired") {
|
|
4456
|
+
await this.disconnect(device2.id, "manualDisconnection");
|
|
4457
|
+
}
|
|
4458
|
+
}
|
|
4459
|
+
store.setState(deviceId, "connecting");
|
|
4460
|
+
await unitech.removeAllListeners();
|
|
4461
|
+
const device = store.devices[deviceId];
|
|
4462
|
+
if (store.platform === "ios") {
|
|
4463
|
+
await unitech.startDetect({ deviceName: device.name });
|
|
4464
|
+
await toolsSvc.delay(500);
|
|
4465
|
+
await unitech.stopDetect();
|
|
4466
|
+
}
|
|
4467
|
+
const { connected } = await unitech.connect({ bluetoothAddress: device.id });
|
|
4468
|
+
if (!connected) throw new Error("UnitechRfid Error: Unable to connect to the device.");
|
|
4469
|
+
await unitechRfidService.subscribeListeners(deviceId);
|
|
4470
|
+
await withTimeout(
|
|
4471
|
+
new Promise((resolve) => {
|
|
4472
|
+
simulatorSvc.registerEvent("unitech:readerStateConnect", (_deviceId, event) => {
|
|
4473
|
+
if (event.state?.toLowerCase() === "connected") resolve();
|
|
4474
|
+
});
|
|
4475
|
+
}),
|
|
4476
|
+
15e3
|
|
4477
|
+
);
|
|
4478
|
+
await unitech.initDeviceSettings();
|
|
4479
|
+
store.setState(deviceId, "paired");
|
|
4480
|
+
},
|
|
4481
|
+
async disconnect(deviceId, reason) {
|
|
4482
|
+
store.setState(deviceId, "disconnecting");
|
|
4483
|
+
await unitech.removeAllListeners();
|
|
4484
|
+
await unitech.disconnect();
|
|
4485
|
+
store.setState(deviceId, void 0, reason ?? "manualDisconnection");
|
|
4486
|
+
},
|
|
4487
|
+
async startReading() {
|
|
4488
|
+
await unitech.startInventory();
|
|
4489
|
+
},
|
|
4490
|
+
async stopReading() {
|
|
4491
|
+
await unitech.stopInventory();
|
|
4492
|
+
},
|
|
4493
|
+
onReaderState: unitechRfidService.onReaderState,
|
|
4494
|
+
onActionState: unitechRfidService.onActionState,
|
|
4495
|
+
onTrigger: unitechRfidService.onTrigger,
|
|
4496
|
+
onTagRead: unitechRfidService.onTagRead,
|
|
4497
|
+
onBattery: unitechRfidService.onBattery,
|
|
4498
|
+
onTemperature: unitechRfidService.onTemperature
|
|
4499
|
+
};
|
|
4500
|
+
|
|
4156
4501
|
const bridgeSimulator = {
|
|
4157
4502
|
isRebootRequired(deviceId) {
|
|
4158
4503
|
return store.bridgeRebootRequired[deviceId];
|
|
@@ -4190,6 +4535,32 @@ const bridgeSimulator = {
|
|
|
4190
4535
|
const bridge = getSimulatedBridge(deviceId);
|
|
4191
4536
|
bridge.simulatorData.configuration = _.cloneDeep(config);
|
|
4192
4537
|
},
|
|
4538
|
+
async getRxSWIN(deviceId) {
|
|
4539
|
+
const bridge = getSimulatedBridge(deviceId);
|
|
4540
|
+
const config = bridge.simulatorData.configuration;
|
|
4541
|
+
const axle01PressureThresholds = bridgeTools.hexToDecimalArray(config.customerPressureThresholds?.axle01 ?? "");
|
|
4542
|
+
const canProtocol = bridgeTools.hexToDecimalArray(config.customerCANSettings?.canProtocol ?? "");
|
|
4543
|
+
const transparentFilteredMode = bridgeTools.hexToDecimalArray(
|
|
4544
|
+
config.customerCANSettings?.transparentFilteredMode ?? ""
|
|
4545
|
+
);
|
|
4546
|
+
const fwMajor = (bridge.advertisingData.fwVersion || "0").split(".")[0].charCodeAt(0) & 255;
|
|
4547
|
+
const e010Input = [0, 0, 0];
|
|
4548
|
+
const e141Input = [
|
|
4549
|
+
0,
|
|
4550
|
+
0,
|
|
4551
|
+
0,
|
|
4552
|
+
0,
|
|
4553
|
+
0,
|
|
4554
|
+
axle01PressureThresholds[0] ?? 0,
|
|
4555
|
+
canProtocol[0] ?? 0,
|
|
4556
|
+
transparentFilteredMode[0] ?? 0,
|
|
4557
|
+
fwMajor
|
|
4558
|
+
];
|
|
4559
|
+
return {
|
|
4560
|
+
R10SWIN: decimalToHex(bridgeSecurity.crc16Ccitt(e010Input), 4),
|
|
4561
|
+
R141SWIN: decimalToHex(bridgeSecurity.crc16Ccitt(e141Input), 4)
|
|
4562
|
+
};
|
|
4563
|
+
},
|
|
4193
4564
|
async getSensorReading(deviceId, positionId) {
|
|
4194
4565
|
const bridge = getSimulatedBridge(deviceId);
|
|
4195
4566
|
return bridge.simulatorData.sensors[positionId];
|
|
@@ -4794,11 +5165,13 @@ class BridgeTcVehicleAxle {
|
|
|
4794
5165
|
minTargetPressure;
|
|
4795
5166
|
}
|
|
4796
5167
|
|
|
4797
|
-
function createTirecheckDeviceSdk(platform, bleImplementation, securityKeys) {
|
|
5168
|
+
function createTirecheckDeviceSdk(platform, bleImplementation, securityKeys, unitechRfidImplementation, bluetoothClassicSerialImplementation) {
|
|
4798
5169
|
store.platform = platform;
|
|
4799
5170
|
bleImplementation = bleImplementation || emptyBleImplementation;
|
|
4800
5171
|
store.securityKeys = securityKeys || {};
|
|
4801
5172
|
setBleImplementation(bleImplementation);
|
|
5173
|
+
setUnitechRfidImplementation(unitechRfidImplementation);
|
|
5174
|
+
setBluetoothClassicSerialImplementation(bluetoothClassicSerialImplementation);
|
|
4802
5175
|
return {
|
|
4803
5176
|
/** Generic methods common for all devices */
|
|
4804
5177
|
bluetooth,
|
|
@@ -4816,6 +5189,8 @@ function createTirecheckDeviceSdk(platform, bleImplementation, securityKeys) {
|
|
|
4816
5189
|
simulator,
|
|
4817
5190
|
/** Methods for working with Tirecheck Torque Wrench */
|
|
4818
5191
|
torqueWrench,
|
|
5192
|
+
/** Methods for working with Unitech RFID reader */
|
|
5193
|
+
unitechRfid,
|
|
4819
5194
|
utils: {
|
|
4820
5195
|
bridge: {
|
|
4821
5196
|
convertBarToKpaByte: bridgeTools.convertBarToKpaByte,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tirecheck-device-sdk",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.72",
|
|
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",
|