@ukeyfe/hardware-transport-electron 1.1.25 → 1.1.27
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-60176982.js → index-5c4c1f33.js} +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -1
- package/dist/{noble-ble-handler-37d3b074.js → noble-ble-handler-3c136b8c.js} +35 -18
- package/dist/noble-ble-handler.d.ts.map +1 -1
- package/dist/types/noble-extended.d.ts +3 -2
- package/dist/types/noble-extended.d.ts.map +1 -1
- package/package.json +6 -6
- package/src/noble-ble-handler.ts +55 -29
- package/src/types/noble-extended.ts +3 -2
|
@@ -32,7 +32,7 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
|
|
|
32
32
|
|
|
33
33
|
function initNobleBleSupport(webContents) {
|
|
34
34
|
return __awaiter(this, void 0, void 0, function* () {
|
|
35
|
-
const { setupNobleBleHandlers } = yield Promise.resolve().then(function () { return require('./noble-ble-handler-
|
|
35
|
+
const { setupNobleBleHandlers } = yield Promise.resolve().then(function () { return require('./noble-ble-handler-3c136b8c.js'); });
|
|
36
36
|
setupNobleBleHandlers(webContents);
|
|
37
37
|
});
|
|
38
38
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { WebContents } from 'electron';
|
|
2
2
|
import { Characteristic, Peripheral } from '@stoprocent/noble';
|
|
3
|
+
import { UKeyDeviceInfoBase } from '@ukeyfe/hardware-transport';
|
|
3
4
|
|
|
4
|
-
interface DeviceInfo {
|
|
5
|
+
interface DeviceInfo extends UKeyDeviceInfoBase {
|
|
5
6
|
id: string;
|
|
6
7
|
name: string;
|
|
7
8
|
state: string;
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index = require('./index-
|
|
3
|
+
var index = require('./index-5c4c1f33.js');
|
|
4
4
|
var hardwareShared = require('@ukeyfe/hardware-shared');
|
|
5
5
|
var hardwareTransport = require('@ukeyfe/hardware-transport');
|
|
6
6
|
var pRetry = require('p-retry');
|
|
@@ -614,6 +614,7 @@ function enumerateDevices() {
|
|
|
614
614
|
if (!existingDevice) {
|
|
615
615
|
const deviceName = ((_a = peripheral.advertisement) === null || _a === void 0 ? void 0 : _a.localName) || 'Unknown Device';
|
|
616
616
|
devices.push({
|
|
617
|
+
commType: 'electron-ble',
|
|
617
618
|
id,
|
|
618
619
|
name: deviceName,
|
|
619
620
|
state: peripheral.state || 'disconnected',
|
|
@@ -663,6 +664,7 @@ function getDevice(deviceId) {
|
|
|
663
664
|
if (peripheral) {
|
|
664
665
|
const deviceName = ((_a = peripheral.advertisement) === null || _a === void 0 ? void 0 : _a.localName) || 'Unknown Device';
|
|
665
666
|
return {
|
|
667
|
+
commType: 'electron-ble',
|
|
666
668
|
id: peripheral.id,
|
|
667
669
|
name: deviceName,
|
|
668
670
|
state: peripheral.state || 'disconnected',
|
|
@@ -672,12 +674,14 @@ function getDevice(deviceId) {
|
|
|
672
674
|
if (connectedPeripheral) {
|
|
673
675
|
const deviceName = ((_b = connectedPeripheral.advertisement) === null || _b === void 0 ? void 0 : _b.localName) || 'Unknown Device';
|
|
674
676
|
return {
|
|
677
|
+
commType: 'electron-ble',
|
|
675
678
|
id: connectedPeripheral.id,
|
|
676
679
|
name: deviceName,
|
|
677
680
|
state: connectedPeripheral.state || 'connected',
|
|
678
681
|
};
|
|
679
682
|
}
|
|
680
683
|
return {
|
|
684
|
+
commType: 'electron-ble',
|
|
681
685
|
id: deviceId,
|
|
682
686
|
name: 'UKey Device',
|
|
683
687
|
state: 'disconnected',
|
|
@@ -1001,22 +1005,27 @@ function unsubscribeNotifications(deviceId) {
|
|
|
1001
1005
|
const { notify: notifyCharacteristic } = characteristics;
|
|
1002
1006
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Unsubscribing from notifications for device:', deviceId);
|
|
1003
1007
|
subscriptionOperations.set(deviceId, 'unsubscribing');
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
subscriptionOperations.set(deviceId, 'idle');
|
|
1017
|
-
resolve();
|
|
1008
|
+
try {
|
|
1009
|
+
yield new Promise((resolve, reject) => {
|
|
1010
|
+
notifyCharacteristic.unsubscribe((error) => {
|
|
1011
|
+
if (error) {
|
|
1012
|
+
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Notification unsubscription failed:', error);
|
|
1013
|
+
reject(error);
|
|
1014
|
+
}
|
|
1015
|
+
else {
|
|
1016
|
+
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Notification unsubscription successful');
|
|
1017
|
+
resolve();
|
|
1018
|
+
}
|
|
1019
|
+
});
|
|
1018
1020
|
});
|
|
1019
|
-
|
|
1021
|
+
notifyCharacteristic.removeAllListeners('data');
|
|
1022
|
+
notificationCallbacks.delete(deviceId);
|
|
1023
|
+
devicePacketStates.delete(deviceId);
|
|
1024
|
+
subscribedDevices.delete(deviceId);
|
|
1025
|
+
}
|
|
1026
|
+
finally {
|
|
1027
|
+
subscriptionOperations.set(deviceId, 'idle');
|
|
1028
|
+
}
|
|
1020
1029
|
});
|
|
1021
1030
|
}
|
|
1022
1031
|
function subscribeNotifications(deviceId, callback) {
|
|
@@ -1028,17 +1037,25 @@ function subscribeNotifications(deviceId, callback) {
|
|
|
1028
1037
|
}
|
|
1029
1038
|
const { notify: notifyCharacteristic } = characteristics;
|
|
1030
1039
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Subscribing to notifications for device:', deviceId);
|
|
1040
|
+
const opState = subscriptionOperations.get(deviceId);
|
|
1031
1041
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Subscribe context', {
|
|
1032
1042
|
deviceId,
|
|
1033
|
-
opStateBefore:
|
|
1043
|
+
opStateBefore: opState || 'idle',
|
|
1034
1044
|
paired: false,
|
|
1035
1045
|
hasController: false,
|
|
1036
1046
|
});
|
|
1037
|
-
const opState = subscriptionOperations.get(deviceId);
|
|
1038
1047
|
if (opState === 'subscribing') {
|
|
1048
|
+
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Subscription already in progress, updating callback only');
|
|
1039
1049
|
notificationCallbacks.set(deviceId, callback);
|
|
1040
1050
|
return Promise.resolve();
|
|
1041
1051
|
}
|
|
1052
|
+
if (opState === 'unsubscribing') {
|
|
1053
|
+
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Cannot subscribe while unsubscribe is in progress', {
|
|
1054
|
+
deviceId,
|
|
1055
|
+
opState,
|
|
1056
|
+
});
|
|
1057
|
+
throw hardwareShared.ERRORS.TypedError(hardwareShared.HardwareErrorCode.DeviceBusy, `Device ${deviceId} is currently unsubscribing, please retry after reconnection`);
|
|
1058
|
+
}
|
|
1042
1059
|
subscriptionOperations.set(deviceId, 'subscribing');
|
|
1043
1060
|
if (subscribedDevices.get(deviceId)) {
|
|
1044
1061
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Device already subscribed to characteristic, updating callback only');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"noble-ble-handler.d.ts","sourceRoot":"","sources":["../src/noble-ble-handler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"noble-ble-handler.d.ts","sourceRoot":"","sources":["../src/noble-ble-handler.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAsB,WAAW,EAAE,MAAM,UAAU,CAAC;AA0+ChE,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI,CAsKpE"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
1
|
+
import type { Characteristic, Peripheral } from '@stoprocent/noble';
|
|
2
|
+
import type { UKeyDeviceInfoBase } from '@ukeyfe/hardware-transport';
|
|
3
|
+
export interface DeviceInfo extends UKeyDeviceInfoBase {
|
|
3
4
|
id: string;
|
|
4
5
|
name: string;
|
|
5
6
|
state: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"noble-extended.d.ts","sourceRoot":"","sources":["../../src/types/noble-extended.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"noble-extended.d.ts","sourceRoot":"","sources":["../../src/types/noble-extended.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAGrE,MAAM,WAAW,UAAW,SAAQ,kBAAkB;IACpD,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAGD,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,cAAc,CAAC;IACtB,MAAM,EAAE,cAAc,CAAC;CACxB;AAGD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,CACX,YAAY,EAAE,MAAM,EAAE,EACtB,eAAe,EAAE,OAAO,EACxB,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,IAAI,GACjC,IAAI,CAAC;IACR,YAAY,CAAC,QAAQ,CAAC,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IAC1C,EAAE,CAAC,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IAClE,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,GAAG,IAAI,CAAC;IACxE,cAAc,CAAC,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IAC9E,cAAc,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,GAAG,IAAI,CAAC;CACrF;AAGD,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAC5C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAC7C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;CAC9C;AAGD,wBAAgB,OAAO,CACrB,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,EACjC,OAAO,EAAE,MAAM,EACf,GAAG,IAAI,EAAE,GAAG,EAAE,GACb,IAAI,CAMN"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ukeyfe/hardware-transport-electron",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.27",
|
|
4
4
|
"author": "UKey",
|
|
5
5
|
"homepage": "https://github.com/UKeyHQ/hardware-js-sdk#readme",
|
|
6
6
|
"license": "MIT",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
},
|
|
12
12
|
"repository": {
|
|
13
13
|
"type": "git",
|
|
14
|
-
"url": "git+https://github.com/
|
|
14
|
+
"url": "git+https://github.com/UKeyHQ/hardware-js-sdk.git"
|
|
15
15
|
},
|
|
16
16
|
"scripts": {
|
|
17
17
|
"dev": "rimraf dist && rollup -c ../../build/rollup.config.js -w",
|
|
@@ -26,9 +26,9 @@
|
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@stoprocent/noble": "2.3.4",
|
|
29
|
-
"@ukeyfe/hardware-core": "1.1.
|
|
30
|
-
"@ukeyfe/hardware-shared": "1.1.
|
|
31
|
-
"@ukeyfe/hardware-transport": "1.1.
|
|
29
|
+
"@ukeyfe/hardware-core": "1.1.27",
|
|
30
|
+
"@ukeyfe/hardware-shared": "1.1.27",
|
|
31
|
+
"@ukeyfe/hardware-transport": "1.1.27",
|
|
32
32
|
"p-retry": "^4.6.2"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
@@ -36,5 +36,5 @@
|
|
|
36
36
|
"electron": "^25.0.0",
|
|
37
37
|
"typescript": "^5.3.3"
|
|
38
38
|
},
|
|
39
|
-
"gitHead": "
|
|
39
|
+
"gitHead": "4ee8e8dcee0fd7e1a361d4f8935856c80e292805"
|
|
40
40
|
}
|
package/src/noble-ble-handler.ts
CHANGED
|
@@ -6,24 +6,26 @@
|
|
|
6
6
|
/* eslint-disable @typescript-eslint/no-var-requires, import/no-extraneous-dependencies */
|
|
7
7
|
|
|
8
8
|
import {
|
|
9
|
-
isUkeyDevice,
|
|
10
9
|
EUKeyBleMessageKeys,
|
|
10
|
+
ERRORS,
|
|
11
|
+
HardwareErrorCode,
|
|
12
|
+
UKEY_NOTIFY_CHARACTERISTIC_UUID,
|
|
11
13
|
UKEY_SERVICE_UUID,
|
|
12
14
|
UKEY_WRITE_CHARACTERISTIC_UUID,
|
|
13
|
-
UKEY_NOTIFY_CHARACTERISTIC_UUID,
|
|
14
15
|
isHeaderChunk,
|
|
15
|
-
|
|
16
|
-
HardwareErrorCode,
|
|
16
|
+
isUkeyDevice,
|
|
17
17
|
wait,
|
|
18
18
|
} from '@ukeyfe/hardware-shared';
|
|
19
19
|
import { COMMON_HEADER_SIZE } from '@ukeyfe/hardware-transport';
|
|
20
|
-
import type { WebContents, IpcMainInvokeEvent } from 'electron';
|
|
21
|
-
import type { Peripheral, Service, Characteristic } from '@stoprocent/noble';
|
|
22
20
|
import pRetry from 'p-retry';
|
|
23
|
-
|
|
21
|
+
|
|
24
22
|
import { safeLog } from './types/noble-extended';
|
|
25
23
|
import { softRefreshSubscription } from './ble-ops';
|
|
26
24
|
|
|
25
|
+
import type { IpcMainInvokeEvent, WebContents } from 'electron';
|
|
26
|
+
import type { Characteristic, Peripheral, Service } from '@stoprocent/noble';
|
|
27
|
+
import type { CharacteristicPair, DeviceInfo, Logger, NobleModule } from './types/noble-extended';
|
|
28
|
+
|
|
27
29
|
// Noble will be dynamically imported to avoid bundlinpissues
|
|
28
30
|
let noble: NobleModule | null = null;
|
|
29
31
|
let logger: Logger | null = null;
|
|
@@ -50,7 +52,7 @@ const deviceCharacteristics = new Map<string, CharacteristicPair>();
|
|
|
50
52
|
const notificationCallbacks = new Map<string, (data: string) => void>();
|
|
51
53
|
const subscribedDevices = new Map<string, boolean>(); // Track subscription status
|
|
52
54
|
|
|
53
|
-
// 🔒
|
|
55
|
+
// 🔒 Subscription operation state tracking to prevent race conditions
|
|
54
56
|
const subscriptionOperations = new Map<string, 'subscribing' | 'unsubscribing' | 'idle'>();
|
|
55
57
|
|
|
56
58
|
// Packet reassembly state for each device
|
|
@@ -824,6 +826,7 @@ async function enumerateDevices(): Promise<DeviceInfo[]> {
|
|
|
824
826
|
if (!existingDevice) {
|
|
825
827
|
const deviceName = peripheral.advertisement?.localName || 'Unknown Device';
|
|
826
828
|
devices.push({
|
|
829
|
+
commType: 'electron-ble',
|
|
827
830
|
id,
|
|
828
831
|
name: deviceName,
|
|
829
832
|
state: peripheral.state || 'disconnected',
|
|
@@ -882,6 +885,7 @@ function getDevice(deviceId: string): DeviceInfo | null {
|
|
|
882
885
|
if (peripheral) {
|
|
883
886
|
const deviceName = peripheral.advertisement?.localName || 'Unknown Device';
|
|
884
887
|
return {
|
|
888
|
+
commType: 'electron-ble',
|
|
885
889
|
id: peripheral.id,
|
|
886
890
|
name: deviceName,
|
|
887
891
|
state: peripheral.state || 'disconnected',
|
|
@@ -893,6 +897,7 @@ function getDevice(deviceId: string): DeviceInfo | null {
|
|
|
893
897
|
if (connectedPeripheral) {
|
|
894
898
|
const deviceName = connectedPeripheral.advertisement?.localName || 'Unknown Device';
|
|
895
899
|
return {
|
|
900
|
+
commType: 'electron-ble',
|
|
896
901
|
id: connectedPeripheral.id,
|
|
897
902
|
name: deviceName,
|
|
898
903
|
state: connectedPeripheral.state || 'connected',
|
|
@@ -902,6 +907,7 @@ function getDevice(deviceId: string): DeviceInfo | null {
|
|
|
902
907
|
// For direct connection mode, return a placeholder device info
|
|
903
908
|
// This allows the connection process to proceed without prior discovery
|
|
904
909
|
return {
|
|
910
|
+
commType: 'electron-ble',
|
|
905
911
|
id: deviceId,
|
|
906
912
|
name: 'UKey Device',
|
|
907
913
|
state: 'disconnected',
|
|
@@ -1367,25 +1373,28 @@ async function unsubscribeNotifications(deviceId: string): Promise<void> {
|
|
|
1367
1373
|
// 🔒 Set operation state to prevent race conditions
|
|
1368
1374
|
subscriptionOperations.set(deviceId, 'unsubscribing');
|
|
1369
1375
|
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
devicePacketStates.delete(deviceId);
|
|
1382
|
-
subscribedDevices.delete(deviceId);
|
|
1383
|
-
|
|
1384
|
-
// 🔒 Clear operation state
|
|
1385
|
-
subscriptionOperations.set(deviceId, 'idle');
|
|
1386
|
-
resolve();
|
|
1376
|
+
try {
|
|
1377
|
+
await new Promise<void>((resolve, reject) => {
|
|
1378
|
+
notifyCharacteristic.unsubscribe((error: Error | undefined) => {
|
|
1379
|
+
if (error) {
|
|
1380
|
+
logger?.error('[NobleBLE] Notification unsubscription failed:', error);
|
|
1381
|
+
reject(error);
|
|
1382
|
+
} else {
|
|
1383
|
+
logger?.info('[NobleBLE] Notification unsubscription successful');
|
|
1384
|
+
resolve();
|
|
1385
|
+
}
|
|
1386
|
+
});
|
|
1387
1387
|
});
|
|
1388
|
-
|
|
1388
|
+
|
|
1389
|
+
// Remove all listeners and clear subscription status
|
|
1390
|
+
notifyCharacteristic.removeAllListeners('data');
|
|
1391
|
+
notificationCallbacks.delete(deviceId);
|
|
1392
|
+
devicePacketStates.delete(deviceId);
|
|
1393
|
+
subscribedDevices.delete(deviceId);
|
|
1394
|
+
} finally {
|
|
1395
|
+
// 🔒 CRITICAL: Always clear operation state (even on error)
|
|
1396
|
+
subscriptionOperations.set(deviceId, 'idle');
|
|
1397
|
+
}
|
|
1389
1398
|
}
|
|
1390
1399
|
|
|
1391
1400
|
// Subscribe to notifications
|
|
@@ -1406,20 +1415,37 @@ async function subscribeNotifications(
|
|
|
1406
1415
|
const { notify: notifyCharacteristic } = characteristics;
|
|
1407
1416
|
|
|
1408
1417
|
logger?.info('[NobleBLE] Subscribing to notifications for device:', deviceId);
|
|
1418
|
+
|
|
1419
|
+
// 🔒 CRITICAL: Check operation state FIRST to prevent race conditions
|
|
1420
|
+
const opState = subscriptionOperations.get(deviceId);
|
|
1421
|
+
|
|
1409
1422
|
logger?.info('[NobleBLE] Subscribe context', {
|
|
1410
1423
|
deviceId,
|
|
1411
|
-
opStateBefore:
|
|
1424
|
+
opStateBefore: opState || 'idle',
|
|
1412
1425
|
paired: false,
|
|
1413
1426
|
hasController: false,
|
|
1414
1427
|
});
|
|
1428
|
+
|
|
1415
1429
|
// If a subscription is already in progress, dedupe
|
|
1416
|
-
const opState = subscriptionOperations.get(deviceId);
|
|
1417
1430
|
if (opState === 'subscribing') {
|
|
1418
|
-
|
|
1431
|
+
logger?.info('[NobleBLE] Subscription already in progress, updating callback only');
|
|
1419
1432
|
notificationCallbacks.set(deviceId, callback);
|
|
1420
1433
|
return Promise.resolve();
|
|
1421
1434
|
}
|
|
1422
1435
|
|
|
1436
|
+
// 🚨 CRITICAL: Reject subscribe if unsubscribe is in progress
|
|
1437
|
+
// Let upper layer handle retry after device reconnection
|
|
1438
|
+
if (opState === 'unsubscribing') {
|
|
1439
|
+
logger?.error('[NobleBLE] Cannot subscribe while unsubscribe is in progress', {
|
|
1440
|
+
deviceId,
|
|
1441
|
+
opState,
|
|
1442
|
+
});
|
|
1443
|
+
throw ERRORS.TypedError(
|
|
1444
|
+
HardwareErrorCode.DeviceBusy,
|
|
1445
|
+
`Device ${deviceId} is currently unsubscribing, please retry after reconnection`
|
|
1446
|
+
);
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1423
1449
|
// 🔒 Set operation state to prevent race conditions
|
|
1424
1450
|
subscriptionOperations.set(deviceId, 'subscribing');
|
|
1425
1451
|
|
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
* Supplements @types/noble with additional interfaces
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import type {
|
|
6
|
+
import type { Characteristic, Peripheral } from '@stoprocent/noble';
|
|
7
|
+
import type { UKeyDeviceInfoBase } from '@ukeyfe/hardware-transport';
|
|
7
8
|
|
|
8
9
|
// Device info interface for our API
|
|
9
|
-
export interface DeviceInfo {
|
|
10
|
+
export interface DeviceInfo extends UKeyDeviceInfoBase {
|
|
10
11
|
id: string;
|
|
11
12
|
name: string;
|
|
12
13
|
state: string;
|