tirecheck-device-sdk 0.1.95 → 0.1.97

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 CHANGED
@@ -341,8 +341,9 @@ function getDefaultTyreLabels() {
341
341
  const bridgeAdvertisingParser = {
342
342
  getDeviceInfoFromAdvertising(device) {
343
343
  const adversitingType = getAdvertisingType(device);
344
- if (adversitingType !== "connectable") return void 0;
344
+ if (adversitingType !== "connectable") return;
345
345
  const advertisingData = getAdvertisingData({ advertising: device.advertising, deviceName: device.name });
346
+ if (!advertisingData) return;
346
347
  const macArray = advertisingData?.macAddress?.map((n) => bridgeTools.decimalToHex(n).toUpperCase()).reverse() || [];
347
348
  const bridgeId = macArray.join("");
348
349
  const vin = String.fromCharCode(...advertisingData?.vinNum || []).split("\0").join("");
@@ -378,7 +379,7 @@ function getAdvertisingData({ advertising, deviceName }) {
378
379
  const adv = Array.from(uint8);
379
380
  const advertisingData = advertising.kCBAdvDataIsConnectable ? processIosAdvertising(adv, isKrone) : processAndroidAdvertising(adv, isKrone);
380
381
  if (!advertisingData || !advertisingData.macAddress.length || !advertisingData.randomAdvNumber.length || !advertisingData.vinNum.length) {
381
- throw new Error("Device not recognized");
382
+ return;
382
383
  }
383
384
  return advertisingData;
384
385
  }
@@ -520,28 +521,21 @@ const deviceMeta = {
520
521
  },
521
522
  reconnect: true
522
523
  // Do we need it here?
524
+ },
525
+ pressureStick: {
526
+ nameRegex: /Pressure Stick.*/,
527
+ communication: {
528
+ serviceId: "4880c12c-fdcb-4077-8920-a450d7f9b907",
529
+ characteristicId: "fec26ec4-6d71-4442-9f81-55bc21d658d6"
530
+ },
531
+ getDeviceInfoFromAdvertising: (device) => {
532
+ const bleDevice = {
533
+ ...device,
534
+ type: "pressureStick"
535
+ };
536
+ return bleDevice;
537
+ }
523
538
  }
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
539
  };
546
540
 
547
541
  const checkUnreachableDevicesTimeouts = {};
@@ -596,12 +590,16 @@ async function connect$1(deviceId, disconnectCallback) {
596
590
  if (toolsSvc.canCommunicateWith(deviceId)) return console.warn("Connect Warn: Already connected to device");
597
591
  store.setState(deviceId, "connecting");
598
592
  let connectedDevice;
599
- for (let attempt = 0; attempt < 3; attempt++) {
593
+ for (let attempt = 1; attempt <= 3; attempt++) {
600
594
  try {
601
595
  connectedDevice = await withTimeout(connectInner(deviceId, disconnectCallback), 2e4);
602
596
  const _deviceId = store.deviceIdMapingTable[deviceId] ?? deviceId;
603
597
  const isConnected = await ble.isConnected(_deviceId);
604
- if (connectedDevice && isConnected) break;
598
+ if (connectedDevice || isConnected) {
599
+ break;
600
+ } else {
601
+ throw new Error("Connection incomplete");
602
+ }
605
603
  } catch (e) {
606
604
  console.warn(`${attempt} connect fail`, e);
607
605
  if (attempt === 3) {
@@ -1729,7 +1727,7 @@ const subCommandIds = {
1729
1727
  };
1730
1728
  ___default.invert(commandIds);
1731
1729
  ___default.invert(subCommandIds);
1732
- let keepAliveTimer;
1730
+ const keepAliveTimer = {};
1733
1731
  const bridgeCommands = {
1734
1732
  getCommandHeader(device) {
1735
1733
  const accessLevel = store.deviceAccessLevel[device.id];
@@ -2040,11 +2038,11 @@ const bridgeCommands = {
2040
2038
  throw new Error("Invalid command");
2041
2039
  }
2042
2040
  if (!canCommunicateWith(device.id)) throw new Error("Bridge not connected");
2043
- clearTimeout(keepAliveTimer);
2044
- keepAliveTimer = setTimeout(() => {
2041
+ clearTimeout(keepAliveTimer[device.id]);
2042
+ keepAliveTimer[device.id] = setTimeout(() => {
2045
2043
  if (store.deviceState[device.id] !== "paired" || store.devices[device.id]?.type !== "bridge") {
2046
2044
  console.warn("keep alive timer cleared");
2047
- return clearTimeout(keepAliveTimer);
2045
+ return clearTimeout(keepAliveTimer[device.id]);
2048
2046
  }
2049
2047
  this.sendKeepAliveCommand(device);
2050
2048
  }, 1e4);
@@ -2671,10 +2669,10 @@ async function assignTyres(deviceId, tcVehicle) {
2671
2669
  async function assignAxlePressureLimits(deviceId, tcVehicle, tcVehicleAxle, axleIndex, bridgeAxlesPressureData) {
2672
2670
  const axlesPressureData = bridgeAxlesPressureData ?? (await bridgeCommands.getAxlesPressure(deviceId)).data;
2673
2671
  if (axlesPressureData[axleIndex * 3]) {
2674
- tcVehicleAxle.maxTargetPressure = ___default.round(bridgeTools.kpaByteToBar(axlesPressureData[axleIndex * 3]), 1);
2672
+ tcVehicleAxle.maxTargetPressure = ___default.floor(bridgeTools.kpaByteToBar(axlesPressureData[axleIndex * 3]), 1);
2675
2673
  }
2676
2674
  if (axlesPressureData[axleIndex * 3 + 1]) {
2677
- tcVehicleAxle.minTargetPressure = ___default.round(bridgeTools.kpaByteToBar(axlesPressureData[axleIndex * 3 + 1]), 1);
2675
+ tcVehicleAxle.minTargetPressure = ___default.ceil(bridgeTools.kpaByteToBar(axlesPressureData[axleIndex * 3 + 1]), 1);
2678
2676
  }
2679
2677
  if (axlesPressureData[axleIndex * 3 + 2]) {
2680
2678
  tcVehicleAxle.targetPressure = ___default.round(
@@ -2733,12 +2731,11 @@ async function connect(deviceId, accessLevel) {
2733
2731
  await bridgeService.sendPinCommand(deviceId);
2734
2732
  store.setState(deviceId, "paired");
2735
2733
  } catch (e) {
2736
- disconnect(deviceId);
2734
+ disconnect(deviceId, "failedConnection");
2737
2735
  throw new Error(`Pairing unsuccessful ${e}`);
2738
2736
  }
2739
2737
  }
2740
2738
  async function disconnect(deviceId, reason) {
2741
- await waitUntil(() => store.deviceState[deviceId] === "paired" || store.deviceState[deviceId] === void 0);
2742
2739
  store.setState(deviceId, "disconnecting");
2743
2740
  promiseQueue.clearQueue(deviceId, "Previous pending commands aborted");
2744
2741
  await bluetooth.disconnect(deviceId);
@@ -2752,11 +2749,13 @@ const simulatorSvc = {
2752
2749
  registerEvent(eventName, callback) {
2753
2750
  callbacks[eventName] = callback;
2754
2751
  },
2755
- triggerEvent(eventName, deviceId) {
2756
- const simulatedDevice = store.simulatedDevices[deviceId];
2757
- if (!simulatedDevice) throw new Error(`Device not found`);
2758
- const payload = simulatedDevice.simulatorData?.events?.[eventName];
2759
- if (!payload) throw new Error(`Event not found`);
2752
+ triggerEvent(eventName, deviceId, payload) {
2753
+ if (payload === void 0) {
2754
+ const simulatedDevice = store.simulatedDevices[deviceId];
2755
+ if (!simulatedDevice) throw new Error(`Device not found`);
2756
+ payload = simulatedDevice.simulatorData?.events?.[eventName];
2757
+ if (!payload) throw new Error(`Event not found`);
2758
+ }
2760
2759
  const callback = callbacks[eventName];
2761
2760
  if (!callback) {
2762
2761
  console.warn(`Event ${eventName} not registered`);
@@ -2795,10 +2794,7 @@ async function getBattery(deviceId) {
2795
2794
  }
2796
2795
 
2797
2796
  let sensorReadings = [];
2798
- let treadDepthCallback;
2799
- let buttonCallback;
2800
- let tpmsCallback;
2801
- const capabilities = [
2797
+ const capabilities$1 = [
2802
2798
  {
2803
2799
  id: "td",
2804
2800
  processFn: processTreadDepth,
@@ -2835,7 +2831,7 @@ const flexiGaugeTpmsService = {
2835
2831
  processMessage(deviceId, message) {
2836
2832
  const numberArray = Array.from(new Uint8Array(message));
2837
2833
  const stringFromBytes = String.fromCharCode.apply(null, numberArray).replace("\r\n", "");
2838
- for (const capability of capabilities) {
2834
+ for (const capability of capabilities$1) {
2839
2835
  if (capability.regex.test(stringFromBytes)) {
2840
2836
  return capability.processFn(deviceId, stringFromBytes);
2841
2837
  }
@@ -2845,12 +2841,12 @@ const flexiGaugeTpmsService = {
2845
2841
  function processTreadDepth(deviceId, value) {
2846
2842
  const treadDepth = value.match(/\d+/)?.[0];
2847
2843
  const convertedValue = Number(treadDepth) / 1e3;
2848
- treadDepthCallback(deviceId, convertedValue);
2844
+ simulatorSvc.triggerEvent("fg:treadDepth", deviceId, convertedValue);
2849
2845
  }
2850
2846
  function processButtonPress(deviceId, value) {
2851
2847
  const buttonName = value.match(/\*(.)/);
2852
2848
  if (!buttonName || !buttonName[1]) throw new Error("Unrecognized button");
2853
- buttonCallback(deviceId, buttonName[1]);
2849
+ simulatorSvc.triggerEvent("fg:button", deviceId, buttonName[1]);
2854
2850
  }
2855
2851
  function processTpms(deviceId, value) {
2856
2852
  const groupedValue = value.split(" ");
@@ -2870,12 +2866,13 @@ function processTpms(deviceId, value) {
2870
2866
  }
2871
2867
  if (type === "ENDSCANNING") {
2872
2868
  if (!sensorReadings.length) {
2873
- tpmsCallback(deviceId, void 0);
2869
+ simulatorSvc.triggerEvent("fg:tpms", deviceId, null);
2870
+ return;
2874
2871
  }
2875
2872
  const strongestReading = sensorReadings.reduce((accumulator, currentReading) => {
2876
2873
  return Number(currentReading.Rssi) > Number(accumulator.Rssi) ? currentReading : accumulator;
2877
2874
  }, sensorReadings[0]);
2878
- tpmsCallback(deviceId, strongestReading);
2875
+ simulatorSvc.triggerEvent("fg:tpms", deviceId, strongestReading);
2879
2876
  }
2880
2877
  }
2881
2878
 
@@ -2904,6 +2901,55 @@ const flexiGaugeTpms = {
2904
2901
  startTpmsScan: flexiGaugeTpmsService.startTpmsScan
2905
2902
  };
2906
2903
 
2904
+ const capabilities = [
2905
+ {
2906
+ id: "pressure",
2907
+ processFn: processPressure,
2908
+ regex: /P([0-9.]+)mBar/
2909
+ }
2910
+ ];
2911
+ const pressureStickService = {
2912
+ onPressure(callback) {
2913
+ simulatorSvc.registerEvent("ps:pressure", callback);
2914
+ },
2915
+ processMessage(deviceId, message) {
2916
+ const numberArray = Array.from(new Uint8Array(message));
2917
+ const stringFromBytes = String.fromCharCode.apply(null, numberArray).replace("\r\n", "");
2918
+ for (const capability of capabilities) {
2919
+ if (capability.regex.test(stringFromBytes)) {
2920
+ return capability.processFn(deviceId, stringFromBytes);
2921
+ }
2922
+ }
2923
+ }
2924
+ };
2925
+ function processPressure(deviceId, msg) {
2926
+ const match = /P([0-9.]+)mBar/i.exec(msg);
2927
+ if (!match) throw new Error("Incorrect pressure message");
2928
+ const pressure = Number(match[1]) / 1e3;
2929
+ simulatorSvc.triggerEvent("ps:pressure", deviceId, pressure);
2930
+ }
2931
+
2932
+ const pressureStick = {
2933
+ async connect(deviceId) {
2934
+ const psMeta = deviceMeta.pressureStick;
2935
+ await bluetooth.connect(deviceId, this.disconnect);
2936
+ await ble.startNotification(
2937
+ deviceId,
2938
+ psMeta.communication.serviceId,
2939
+ psMeta.communication.characteristicId,
2940
+ (notification) => pressureStickService.processMessage(deviceId, notification),
2941
+ (error) => console.warn("ble.startNotification error", error)
2942
+ );
2943
+ store.setState(deviceId, "paired");
2944
+ },
2945
+ async disconnect(deviceId, reason) {
2946
+ store.setState(deviceId, "disconnecting");
2947
+ await bluetooth.disconnect(deviceId);
2948
+ store.setState(deviceId, void 0, reason ?? "manualDisconnection");
2949
+ },
2950
+ onPressure: pressureStickService.onPressure
2951
+ };
2952
+
2907
2953
  const bridgeSimulator = {
2908
2954
  isRebootRequired(deviceId) {
2909
2955
  return store.bridgeRebootRequired[deviceId];
@@ -3277,6 +3323,8 @@ function createTirecheckDeviceSdk(platform, bleImplementation) {
3277
3323
  bridgeOta,
3278
3324
  /** Methods for working with Tirecheck TPMS FlexiGauge */
3279
3325
  flexiGaugeTpms,
3326
+ /** Methods for working with Tirecheck Pressure Stick */
3327
+ pressureStick,
3280
3328
  /** Allows simulating devices without actually using bluetooth */
3281
3329
  simulator
3282
3330
  };
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: {
@@ -814,6 +825,7 @@ 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
 
@@ -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: {
@@ -814,6 +825,7 @@ 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
 
@@ -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: {
@@ -814,6 +825,7 @@ 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
 
@@ -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
@@ -334,8 +334,9 @@ function getDefaultTyreLabels() {
334
334
  const bridgeAdvertisingParser = {
335
335
  getDeviceInfoFromAdvertising(device) {
336
336
  const adversitingType = getAdvertisingType(device);
337
- if (adversitingType !== "connectable") return void 0;
337
+ if (adversitingType !== "connectable") return;
338
338
  const advertisingData = getAdvertisingData({ advertising: device.advertising, deviceName: device.name });
339
+ if (!advertisingData) return;
339
340
  const macArray = advertisingData?.macAddress?.map((n) => bridgeTools.decimalToHex(n).toUpperCase()).reverse() || [];
340
341
  const bridgeId = macArray.join("");
341
342
  const vin = String.fromCharCode(...advertisingData?.vinNum || []).split("\0").join("");
@@ -371,7 +372,7 @@ function getAdvertisingData({ advertising, deviceName }) {
371
372
  const adv = Array.from(uint8);
372
373
  const advertisingData = advertising.kCBAdvDataIsConnectable ? processIosAdvertising(adv, isKrone) : processAndroidAdvertising(adv, isKrone);
373
374
  if (!advertisingData || !advertisingData.macAddress.length || !advertisingData.randomAdvNumber.length || !advertisingData.vinNum.length) {
374
- throw new Error("Device not recognized");
375
+ return;
375
376
  }
376
377
  return advertisingData;
377
378
  }
@@ -513,28 +514,21 @@ const deviceMeta = {
513
514
  },
514
515
  reconnect: true
515
516
  // Do we need it here?
517
+ },
518
+ pressureStick: {
519
+ nameRegex: /Pressure Stick.*/,
520
+ communication: {
521
+ serviceId: "4880c12c-fdcb-4077-8920-a450d7f9b907",
522
+ characteristicId: "fec26ec4-6d71-4442-9f81-55bc21d658d6"
523
+ },
524
+ getDeviceInfoFromAdvertising: (device) => {
525
+ const bleDevice = {
526
+ ...device,
527
+ type: "pressureStick"
528
+ };
529
+ return bleDevice;
530
+ }
516
531
  }
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
532
  };
539
533
 
540
534
  const checkUnreachableDevicesTimeouts = {};
@@ -589,12 +583,16 @@ async function connect$1(deviceId, disconnectCallback) {
589
583
  if (toolsSvc.canCommunicateWith(deviceId)) return console.warn("Connect Warn: Already connected to device");
590
584
  store.setState(deviceId, "connecting");
591
585
  let connectedDevice;
592
- for (let attempt = 0; attempt < 3; attempt++) {
586
+ for (let attempt = 1; attempt <= 3; attempt++) {
593
587
  try {
594
588
  connectedDevice = await withTimeout(connectInner(deviceId, disconnectCallback), 2e4);
595
589
  const _deviceId = store.deviceIdMapingTable[deviceId] ?? deviceId;
596
590
  const isConnected = await ble.isConnected(_deviceId);
597
- if (connectedDevice && isConnected) break;
591
+ if (connectedDevice || isConnected) {
592
+ break;
593
+ } else {
594
+ throw new Error("Connection incomplete");
595
+ }
598
596
  } catch (e) {
599
597
  console.warn(`${attempt} connect fail`, e);
600
598
  if (attempt === 3) {
@@ -1722,7 +1720,7 @@ const subCommandIds = {
1722
1720
  };
1723
1721
  _.invert(commandIds);
1724
1722
  _.invert(subCommandIds);
1725
- let keepAliveTimer;
1723
+ const keepAliveTimer = {};
1726
1724
  const bridgeCommands = {
1727
1725
  getCommandHeader(device) {
1728
1726
  const accessLevel = store.deviceAccessLevel[device.id];
@@ -2033,11 +2031,11 @@ const bridgeCommands = {
2033
2031
  throw new Error("Invalid command");
2034
2032
  }
2035
2033
  if (!canCommunicateWith(device.id)) throw new Error("Bridge not connected");
2036
- clearTimeout(keepAliveTimer);
2037
- keepAliveTimer = setTimeout(() => {
2034
+ clearTimeout(keepAliveTimer[device.id]);
2035
+ keepAliveTimer[device.id] = setTimeout(() => {
2038
2036
  if (store.deviceState[device.id] !== "paired" || store.devices[device.id]?.type !== "bridge") {
2039
2037
  console.warn("keep alive timer cleared");
2040
- return clearTimeout(keepAliveTimer);
2038
+ return clearTimeout(keepAliveTimer[device.id]);
2041
2039
  }
2042
2040
  this.sendKeepAliveCommand(device);
2043
2041
  }, 1e4);
@@ -2664,10 +2662,10 @@ async function assignTyres(deviceId, tcVehicle) {
2664
2662
  async function assignAxlePressureLimits(deviceId, tcVehicle, tcVehicleAxle, axleIndex, bridgeAxlesPressureData) {
2665
2663
  const axlesPressureData = bridgeAxlesPressureData ?? (await bridgeCommands.getAxlesPressure(deviceId)).data;
2666
2664
  if (axlesPressureData[axleIndex * 3]) {
2667
- tcVehicleAxle.maxTargetPressure = _.round(bridgeTools.kpaByteToBar(axlesPressureData[axleIndex * 3]), 1);
2665
+ tcVehicleAxle.maxTargetPressure = _.floor(bridgeTools.kpaByteToBar(axlesPressureData[axleIndex * 3]), 1);
2668
2666
  }
2669
2667
  if (axlesPressureData[axleIndex * 3 + 1]) {
2670
- tcVehicleAxle.minTargetPressure = _.round(bridgeTools.kpaByteToBar(axlesPressureData[axleIndex * 3 + 1]), 1);
2668
+ tcVehicleAxle.minTargetPressure = _.ceil(bridgeTools.kpaByteToBar(axlesPressureData[axleIndex * 3 + 1]), 1);
2671
2669
  }
2672
2670
  if (axlesPressureData[axleIndex * 3 + 2]) {
2673
2671
  tcVehicleAxle.targetPressure = _.round(
@@ -2726,12 +2724,11 @@ async function connect(deviceId, accessLevel) {
2726
2724
  await bridgeService.sendPinCommand(deviceId);
2727
2725
  store.setState(deviceId, "paired");
2728
2726
  } catch (e) {
2729
- disconnect(deviceId);
2727
+ disconnect(deviceId, "failedConnection");
2730
2728
  throw new Error(`Pairing unsuccessful ${e}`);
2731
2729
  }
2732
2730
  }
2733
2731
  async function disconnect(deviceId, reason) {
2734
- await waitUntil(() => store.deviceState[deviceId] === "paired" || store.deviceState[deviceId] === void 0);
2735
2732
  store.setState(deviceId, "disconnecting");
2736
2733
  promiseQueue.clearQueue(deviceId, "Previous pending commands aborted");
2737
2734
  await bluetooth.disconnect(deviceId);
@@ -2745,11 +2742,13 @@ const simulatorSvc = {
2745
2742
  registerEvent(eventName, callback) {
2746
2743
  callbacks[eventName] = callback;
2747
2744
  },
2748
- triggerEvent(eventName, deviceId) {
2749
- const simulatedDevice = store.simulatedDevices[deviceId];
2750
- if (!simulatedDevice) throw new Error(`Device not found`);
2751
- const payload = simulatedDevice.simulatorData?.events?.[eventName];
2752
- if (!payload) throw new Error(`Event not found`);
2745
+ triggerEvent(eventName, deviceId, payload) {
2746
+ if (payload === void 0) {
2747
+ const simulatedDevice = store.simulatedDevices[deviceId];
2748
+ if (!simulatedDevice) throw new Error(`Device not found`);
2749
+ payload = simulatedDevice.simulatorData?.events?.[eventName];
2750
+ if (!payload) throw new Error(`Event not found`);
2751
+ }
2753
2752
  const callback = callbacks[eventName];
2754
2753
  if (!callback) {
2755
2754
  console.warn(`Event ${eventName} not registered`);
@@ -2788,10 +2787,7 @@ async function getBattery(deviceId) {
2788
2787
  }
2789
2788
 
2790
2789
  let sensorReadings = [];
2791
- let treadDepthCallback;
2792
- let buttonCallback;
2793
- let tpmsCallback;
2794
- const capabilities = [
2790
+ const capabilities$1 = [
2795
2791
  {
2796
2792
  id: "td",
2797
2793
  processFn: processTreadDepth,
@@ -2828,7 +2824,7 @@ const flexiGaugeTpmsService = {
2828
2824
  processMessage(deviceId, message) {
2829
2825
  const numberArray = Array.from(new Uint8Array(message));
2830
2826
  const stringFromBytes = String.fromCharCode.apply(null, numberArray).replace("\r\n", "");
2831
- for (const capability of capabilities) {
2827
+ for (const capability of capabilities$1) {
2832
2828
  if (capability.regex.test(stringFromBytes)) {
2833
2829
  return capability.processFn(deviceId, stringFromBytes);
2834
2830
  }
@@ -2838,12 +2834,12 @@ const flexiGaugeTpmsService = {
2838
2834
  function processTreadDepth(deviceId, value) {
2839
2835
  const treadDepth = value.match(/\d+/)?.[0];
2840
2836
  const convertedValue = Number(treadDepth) / 1e3;
2841
- treadDepthCallback(deviceId, convertedValue);
2837
+ simulatorSvc.triggerEvent("fg:treadDepth", deviceId, convertedValue);
2842
2838
  }
2843
2839
  function processButtonPress(deviceId, value) {
2844
2840
  const buttonName = value.match(/\*(.)/);
2845
2841
  if (!buttonName || !buttonName[1]) throw new Error("Unrecognized button");
2846
- buttonCallback(deviceId, buttonName[1]);
2842
+ simulatorSvc.triggerEvent("fg:button", deviceId, buttonName[1]);
2847
2843
  }
2848
2844
  function processTpms(deviceId, value) {
2849
2845
  const groupedValue = value.split(" ");
@@ -2863,12 +2859,13 @@ function processTpms(deviceId, value) {
2863
2859
  }
2864
2860
  if (type === "ENDSCANNING") {
2865
2861
  if (!sensorReadings.length) {
2866
- tpmsCallback(deviceId, void 0);
2862
+ simulatorSvc.triggerEvent("fg:tpms", deviceId, null);
2863
+ return;
2867
2864
  }
2868
2865
  const strongestReading = sensorReadings.reduce((accumulator, currentReading) => {
2869
2866
  return Number(currentReading.Rssi) > Number(accumulator.Rssi) ? currentReading : accumulator;
2870
2867
  }, sensorReadings[0]);
2871
- tpmsCallback(deviceId, strongestReading);
2868
+ simulatorSvc.triggerEvent("fg:tpms", deviceId, strongestReading);
2872
2869
  }
2873
2870
  }
2874
2871
 
@@ -2897,6 +2894,55 @@ const flexiGaugeTpms = {
2897
2894
  startTpmsScan: flexiGaugeTpmsService.startTpmsScan
2898
2895
  };
2899
2896
 
2897
+ const capabilities = [
2898
+ {
2899
+ id: "pressure",
2900
+ processFn: processPressure,
2901
+ regex: /P([0-9.]+)mBar/
2902
+ }
2903
+ ];
2904
+ const pressureStickService = {
2905
+ onPressure(callback) {
2906
+ simulatorSvc.registerEvent("ps:pressure", callback);
2907
+ },
2908
+ processMessage(deviceId, message) {
2909
+ const numberArray = Array.from(new Uint8Array(message));
2910
+ const stringFromBytes = String.fromCharCode.apply(null, numberArray).replace("\r\n", "");
2911
+ for (const capability of capabilities) {
2912
+ if (capability.regex.test(stringFromBytes)) {
2913
+ return capability.processFn(deviceId, stringFromBytes);
2914
+ }
2915
+ }
2916
+ }
2917
+ };
2918
+ function processPressure(deviceId, msg) {
2919
+ const match = /P([0-9.]+)mBar/i.exec(msg);
2920
+ if (!match) throw new Error("Incorrect pressure message");
2921
+ const pressure = Number(match[1]) / 1e3;
2922
+ simulatorSvc.triggerEvent("ps:pressure", deviceId, pressure);
2923
+ }
2924
+
2925
+ const pressureStick = {
2926
+ async connect(deviceId) {
2927
+ const psMeta = deviceMeta.pressureStick;
2928
+ await bluetooth.connect(deviceId, this.disconnect);
2929
+ await ble.startNotification(
2930
+ deviceId,
2931
+ psMeta.communication.serviceId,
2932
+ psMeta.communication.characteristicId,
2933
+ (notification) => pressureStickService.processMessage(deviceId, notification),
2934
+ (error) => console.warn("ble.startNotification error", error)
2935
+ );
2936
+ store.setState(deviceId, "paired");
2937
+ },
2938
+ async disconnect(deviceId, reason) {
2939
+ store.setState(deviceId, "disconnecting");
2940
+ await bluetooth.disconnect(deviceId);
2941
+ store.setState(deviceId, void 0, reason ?? "manualDisconnection");
2942
+ },
2943
+ onPressure: pressureStickService.onPressure
2944
+ };
2945
+
2900
2946
  const bridgeSimulator = {
2901
2947
  isRebootRequired(deviceId) {
2902
2948
  return store.bridgeRebootRequired[deviceId];
@@ -3270,6 +3316,8 @@ function createTirecheckDeviceSdk(platform, bleImplementation) {
3270
3316
  bridgeOta,
3271
3317
  /** Methods for working with Tirecheck TPMS FlexiGauge */
3272
3318
  flexiGaugeTpms,
3319
+ /** Methods for working with Tirecheck Pressure Stick */
3320
+ pressureStick,
3273
3321
  /** Allows simulating devices without actually using bluetooth */
3274
3322
  simulator
3275
3323
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tirecheck-device-sdk",
3
- "version": "0.1.95",
3
+ "version": "0.1.97",
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",