@onekeyfe/hd-transport-electron 1.1.2-alpha.1 → 1.1.2-alpha.2
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.
|
@@ -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-bf2b2a66.js'); });
|
|
36
36
|
setupNobleBleHandlers(webContents);
|
|
37
37
|
});
|
|
38
38
|
}
|
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-732ee055.js');
|
|
4
4
|
var hdShared = require('@onekeyfe/hd-shared');
|
|
5
5
|
var hdTransport = require('@onekeyfe/hd-transport');
|
|
6
6
|
|
|
@@ -26,7 +26,6 @@ const connectedDevices = new Map();
|
|
|
26
26
|
const deviceCharacteristics = new Map();
|
|
27
27
|
const notificationCallbacks = new Map();
|
|
28
28
|
const subscribedDevices = new Map();
|
|
29
|
-
const subscriptionOperations = new Map();
|
|
30
29
|
const devicePacketStates = new Map();
|
|
31
30
|
const recentWriteOperations = new Map();
|
|
32
31
|
const WRITE_DISCONNECT_THRESHOLD = 1000;
|
|
@@ -37,7 +36,7 @@ const BLUETOOTH_INIT_TIMEOUT = 10000;
|
|
|
37
36
|
const DEVICE_SCAN_TIMEOUT = 5000;
|
|
38
37
|
const FAST_SCAN_TIMEOUT = 1500;
|
|
39
38
|
const DEVICE_CHECK_INTERVAL = 500;
|
|
40
|
-
const CONNECTION_TIMEOUT =
|
|
39
|
+
const CONNECTION_TIMEOUT = 15000;
|
|
41
40
|
const CHUNK_WRITE_DELAY = 10;
|
|
42
41
|
const BLE_PACKET_SIZE = 192;
|
|
43
42
|
const MIN_HEADER_LENGTH = 9;
|
|
@@ -57,13 +56,7 @@ function processNotificationData(deviceId, data) {
|
|
|
57
56
|
packetState.buffer = [...data.subarray(3)];
|
|
58
57
|
packetState.packetCount = 1;
|
|
59
58
|
packetState.messageId = messageId;
|
|
60
|
-
if (packetState.bufferLength
|
|
61
|
-
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Invalid negative packet length detected:', {
|
|
62
|
-
length: packetState.bufferLength,
|
|
63
|
-
dataLength: data.length,
|
|
64
|
-
rawHeader: data.subarray(0, Math.min(16, data.length)).toString('hex'),
|
|
65
|
-
lengthBytes: data.subarray(5, 9).toString('hex'),
|
|
66
|
-
});
|
|
59
|
+
if (packetState.bufferLength <= 0) {
|
|
67
60
|
resetPacketState(packetState);
|
|
68
61
|
return { isComplete: false, error: 'Invalid packet length in header' };
|
|
69
62
|
}
|
|
@@ -212,19 +205,13 @@ function cleanupDeviceState(deviceId) {
|
|
|
212
205
|
devicePacketStates.delete(deviceId);
|
|
213
206
|
subscribedDevices.delete(deviceId);
|
|
214
207
|
recentWriteOperations.delete(deviceId);
|
|
215
|
-
subscriptionOperations.delete(deviceId);
|
|
216
208
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Device state cleaned up:', deviceId);
|
|
217
209
|
}
|
|
218
210
|
function handleDeviceDisconnect(deviceId, webContents) {
|
|
219
|
-
var _a
|
|
220
|
-
logger === null || logger === void 0 ? void 0 : logger.
|
|
221
|
-
deviceId,
|
|
222
|
-
hasPeripheral: connectedDevices.has(deviceId),
|
|
223
|
-
hasCharacteristics: deviceCharacteristics.has(deviceId),
|
|
224
|
-
stackTrace: (_a = new Error().stack) === null || _a === void 0 ? void 0 : _a.split('\n').slice(1, 5),
|
|
225
|
-
});
|
|
211
|
+
var _a;
|
|
212
|
+
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Device disconnected:', deviceId);
|
|
226
213
|
const peripheral = connectedDevices.get(deviceId);
|
|
227
|
-
const deviceName = ((
|
|
214
|
+
const deviceName = ((_a = peripheral === null || peripheral === void 0 ? void 0 : peripheral.advertisement) === null || _a === void 0 ? void 0 : _a.localName) || 'Unknown Device';
|
|
228
215
|
const recentWriteTime = recentWriteOperations.get(deviceId);
|
|
229
216
|
const now = Date.now();
|
|
230
217
|
const isPairingRejection = recentWriteTime && now - recentWriteTime < WRITE_DISCONNECT_THRESHOLD;
|
|
@@ -245,12 +232,17 @@ function setupDisconnectListener(peripheral, deviceId, webContents) {
|
|
|
245
232
|
});
|
|
246
233
|
}
|
|
247
234
|
function handleDeviceDiscovered(peripheral) {
|
|
248
|
-
var _a;
|
|
235
|
+
var _a, _b;
|
|
249
236
|
const deviceName = ((_a = peripheral.advertisement) === null || _a === void 0 ? void 0 : _a.localName) || 'Unknown Device';
|
|
250
237
|
if (!hdShared.isOnekeyDevice(deviceName)) {
|
|
251
238
|
return;
|
|
252
239
|
}
|
|
253
|
-
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Discovered OneKey device:',
|
|
240
|
+
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Discovered OneKey device:', {
|
|
241
|
+
id: peripheral.id,
|
|
242
|
+
name: deviceName,
|
|
243
|
+
rssi: peripheral.rssi,
|
|
244
|
+
serviceUuids: (_b = peripheral.advertisement) === null || _b === void 0 ? void 0 : _b.serviceUuids,
|
|
245
|
+
}, peripheral);
|
|
254
246
|
discoveredDevices.set(peripheral.id, peripheral);
|
|
255
247
|
}
|
|
256
248
|
function performTargetedScan(targetDeviceId) {
|
|
@@ -453,14 +445,6 @@ function discoverServicesAndCharacteristics(peripheral) {
|
|
|
453
445
|
}
|
|
454
446
|
function connectDevice(deviceId, webContents) {
|
|
455
447
|
return index.__awaiter(this, void 0, void 0, function* () {
|
|
456
|
-
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Connect device request:', {
|
|
457
|
-
deviceId,
|
|
458
|
-
hasDiscovered: discoveredDevices.has(deviceId),
|
|
459
|
-
hasConnected: connectedDevices.has(deviceId),
|
|
460
|
-
hasCharacteristics: deviceCharacteristics.has(deviceId),
|
|
461
|
-
totalDiscovered: discoveredDevices.size,
|
|
462
|
-
totalConnected: connectedDevices.size,
|
|
463
|
-
});
|
|
464
448
|
let peripheral = discoveredDevices.get(deviceId);
|
|
465
449
|
if (!peripheral) {
|
|
466
450
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Device not discovered, attempting targeted scan for:', deviceId);
|
|
@@ -494,26 +478,18 @@ function connectDevice(deviceId, webContents) {
|
|
|
494
478
|
}
|
|
495
479
|
if (deviceCharacteristics.has(deviceId)) {
|
|
496
480
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Device characteristics already available');
|
|
497
|
-
const
|
|
498
|
-
if (
|
|
499
|
-
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE]
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
return;
|
|
508
|
-
}
|
|
509
|
-
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Found orphaned characteristics without active subscription, cleaning up');
|
|
510
|
-
const existingCharacteristics = deviceCharacteristics.get(deviceId);
|
|
511
|
-
if (existingCharacteristics) {
|
|
512
|
-
existingCharacteristics.notify.removeAllListeners('data');
|
|
481
|
+
const existingCallback = notificationCallbacks.get(deviceId);
|
|
482
|
+
if (existingCallback) {
|
|
483
|
+
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Cleaning up existing notification state');
|
|
484
|
+
const existingCharacteristics = deviceCharacteristics.get(deviceId);
|
|
485
|
+
if (existingCharacteristics) {
|
|
486
|
+
existingCharacteristics.notify.removeAllListeners('data');
|
|
487
|
+
}
|
|
488
|
+
notificationCallbacks.delete(deviceId);
|
|
489
|
+
devicePacketStates.delete(deviceId);
|
|
490
|
+
subscribedDevices.delete(deviceId);
|
|
513
491
|
}
|
|
514
|
-
|
|
515
|
-
devicePacketStates.delete(deviceId);
|
|
516
|
-
subscribedDevices.delete(deviceId);
|
|
492
|
+
return;
|
|
517
493
|
}
|
|
518
494
|
try {
|
|
519
495
|
const characteristics = yield discoverServicesAndCharacteristics(peripheral);
|
|
@@ -649,7 +625,6 @@ function subscribeNotifications(deviceId, callback) {
|
|
|
649
625
|
}
|
|
650
626
|
const { notify: notifyCharacteristic } = characteristics;
|
|
651
627
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Subscribing to notifications for device:', deviceId);
|
|
652
|
-
subscriptionOperations.set(deviceId, 'subscribing');
|
|
653
628
|
if (subscribedDevices.get(deviceId)) {
|
|
654
629
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Device already subscribed to characteristic, updating callback only');
|
|
655
630
|
notificationCallbacks.set(deviceId, callback);
|
|
@@ -659,7 +634,6 @@ function subscribeNotifications(deviceId, callback) {
|
|
|
659
634
|
packetCount: 0,
|
|
660
635
|
messageId: undefined,
|
|
661
636
|
});
|
|
662
|
-
subscriptionOperations.set(deviceId, 'idle');
|
|
663
637
|
return Promise.resolve();
|
|
664
638
|
}
|
|
665
639
|
if (notificationCallbacks.has(deviceId)) {
|
|
@@ -674,17 +648,14 @@ function subscribeNotifications(deviceId, callback) {
|
|
|
674
648
|
messageId: undefined,
|
|
675
649
|
});
|
|
676
650
|
return new Promise((resolve, reject) => {
|
|
677
|
-
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] 🔄 Starting subscription process...', { deviceId });
|
|
678
651
|
notifyCharacteristic.subscribe((error) => {
|
|
679
652
|
if (error) {
|
|
680
|
-
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE]
|
|
681
|
-
subscriptionOperations.set(deviceId, 'idle');
|
|
653
|
+
logger === null || logger === void 0 ? void 0 : logger.error('[NobleBLE] Notification subscription failed:', error);
|
|
682
654
|
reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleCharacteristicNotifyError, error));
|
|
683
655
|
return;
|
|
684
656
|
}
|
|
685
|
-
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE]
|
|
657
|
+
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Notification subscription successful');
|
|
686
658
|
subscribedDevices.set(deviceId, true);
|
|
687
|
-
subscriptionOperations.set(deviceId, 'idle');
|
|
688
659
|
notifyCharacteristic.on('data', (data) => {
|
|
689
660
|
const result = processNotificationData(deviceId, data);
|
|
690
661
|
if (result.error) {
|
|
@@ -713,7 +684,6 @@ function unsubscribeNotifications(deviceId) {
|
|
|
713
684
|
}
|
|
714
685
|
const { notify: notifyCharacteristic } = characteristics;
|
|
715
686
|
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] Unsubscribing from notifications for device:', deviceId);
|
|
716
|
-
subscriptionOperations.set(deviceId, 'unsubscribing');
|
|
717
687
|
return new Promise(resolve => {
|
|
718
688
|
notifyCharacteristic.unsubscribe((error) => {
|
|
719
689
|
if (error) {
|
|
@@ -726,7 +696,6 @@ function unsubscribeNotifications(deviceId) {
|
|
|
726
696
|
notificationCallbacks.delete(deviceId);
|
|
727
697
|
devicePacketStates.delete(deviceId);
|
|
728
698
|
subscribedDevices.delete(deviceId);
|
|
729
|
-
subscriptionOperations.set(deviceId, 'idle');
|
|
730
699
|
resolve();
|
|
731
700
|
});
|
|
732
701
|
});
|
|
@@ -753,12 +722,6 @@ function setupNobleBleHandlers(webContents) {
|
|
|
753
722
|
}));
|
|
754
723
|
ipcMain.handle(hdShared.EOneKeyBleMessageKeys.NOBLE_BLE_GET_DEVICE, (_event, deviceId) => getDevice(deviceId));
|
|
755
724
|
ipcMain.handle(hdShared.EOneKeyBleMessageKeys.NOBLE_BLE_CONNECT, (_event, deviceId) => index.__awaiter(this, void 0, void 0, function* () {
|
|
756
|
-
logger === null || logger === void 0 ? void 0 : logger.info('[NobleBLE] IPC CONNECT request received:', {
|
|
757
|
-
deviceId,
|
|
758
|
-
hasPeripheral: connectedDevices.has(deviceId),
|
|
759
|
-
hasCharacteristics: deviceCharacteristics.has(deviceId),
|
|
760
|
-
totalConnectedDevices: connectedDevices.size,
|
|
761
|
-
});
|
|
762
725
|
yield connectDevice(deviceId, webContents);
|
|
763
726
|
}));
|
|
764
727
|
ipcMain.handle(hdShared.EOneKeyBleMessageKeys.NOBLE_BLE_DISCONNECT, (_event, deviceId) => index.__awaiter(this, void 0, void 0, function* () {
|
|
@@ -807,7 +770,6 @@ function setupNobleBleHandlers(webContents) {
|
|
|
807
770
|
notificationCallbacks.clear();
|
|
808
771
|
devicePacketStates.clear();
|
|
809
772
|
subscribedDevices.clear();
|
|
810
|
-
subscriptionOperations.clear();
|
|
811
773
|
});
|
|
812
774
|
safeLog(logger, 'info', 'Noble BLE IPC handlers setup completed');
|
|
813
775
|
}
|
|
@@ -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":"AAkBA,OAAO,KAAK,EAAE,WAAW,EAAsB,MAAM,UAAU,CAAC;AA88BhE,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI,CA8HpE"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/hd-transport-electron",
|
|
3
|
-
"version": "1.1.2-alpha.
|
|
3
|
+
"version": "1.1.2-alpha.2",
|
|
4
4
|
"author": "OneKey",
|
|
5
5
|
"homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
|
|
6
6
|
"license": "MIT",
|
|
@@ -26,12 +26,12 @@
|
|
|
26
26
|
"electron-log": ">=4.0.0"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@onekeyfe/hd-shared": "^1.1.2-alpha.
|
|
29
|
+
"@onekeyfe/hd-shared": "^1.1.2-alpha.2"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@types/web-bluetooth": "^0.0.17",
|
|
33
33
|
"electron": "^25.0.0",
|
|
34
34
|
"typescript": "^5.3.3"
|
|
35
35
|
},
|
|
36
|
-
"gitHead": "
|
|
36
|
+
"gitHead": "3d9a4eec5eddf20b1a01c41f5c80793446924c6e"
|
|
37
37
|
}
|
package/src/noble-ble-handler.ts
CHANGED
|
@@ -14,7 +14,6 @@ import {
|
|
|
14
14
|
isHeaderChunk,
|
|
15
15
|
ERRORS,
|
|
16
16
|
HardwareErrorCode,
|
|
17
|
-
wait,
|
|
18
17
|
} from '@onekeyfe/hd-shared';
|
|
19
18
|
import { COMMON_HEADER_SIZE } from '@onekeyfe/hd-transport';
|
|
20
19
|
import type { WebContents, IpcMainInvokeEvent } from 'electron';
|
|
@@ -47,9 +46,6 @@ const deviceCharacteristics = new Map<string, CharacteristicPair>();
|
|
|
47
46
|
const notificationCallbacks = new Map<string, (data: string) => void>();
|
|
48
47
|
const subscribedDevices = new Map<string, boolean>(); // Track subscription status
|
|
49
48
|
|
|
50
|
-
// 🔒 Add subscription operation state tracking to prevent race conditions
|
|
51
|
-
const subscriptionOperations = new Map<string, 'subscribing' | 'unsubscribing' | 'idle'>();
|
|
52
|
-
|
|
53
49
|
// Packet reassembly state for each device
|
|
54
50
|
interface PacketAssemblyState {
|
|
55
51
|
bufferLength: number;
|
|
@@ -75,7 +71,7 @@ const BLUETOOTH_INIT_TIMEOUT = 10000; // 10 seconds for Bluetooth initialization
|
|
|
75
71
|
const DEVICE_SCAN_TIMEOUT = 5000; // 5 seconds for device scanning
|
|
76
72
|
const FAST_SCAN_TIMEOUT = 1500; // 1.5 seconds for fast targeted scanning
|
|
77
73
|
const DEVICE_CHECK_INTERVAL = 500; // 500ms interval for periodic device checks
|
|
78
|
-
const CONNECTION_TIMEOUT =
|
|
74
|
+
const CONNECTION_TIMEOUT = 15000; // 15 seconds for device connection
|
|
79
75
|
const CHUNK_WRITE_DELAY = 10; // 10ms delay between chunk writes
|
|
80
76
|
|
|
81
77
|
// BLE packet size constants
|
|
@@ -116,14 +112,8 @@ function processNotificationData(deviceId: string, data: Buffer): PacketProcessR
|
|
|
116
112
|
packetState.packetCount = 1;
|
|
117
113
|
packetState.messageId = messageId;
|
|
118
114
|
|
|
119
|
-
//
|
|
120
|
-
if (packetState.bufferLength
|
|
121
|
-
logger?.error('[NobleBLE] Invalid negative packet length detected:', {
|
|
122
|
-
length: packetState.bufferLength,
|
|
123
|
-
dataLength: data.length,
|
|
124
|
-
rawHeader: data.subarray(0, Math.min(16, data.length)).toString('hex'),
|
|
125
|
-
lengthBytes: data.subarray(5, 9).toString('hex'),
|
|
126
|
-
});
|
|
115
|
+
// Validate expected length is reasonable
|
|
116
|
+
if (packetState.bufferLength <= 0) {
|
|
127
117
|
resetPacketState(packetState);
|
|
128
118
|
return { isComplete: false, error: 'Invalid packet length in header' };
|
|
129
119
|
}
|
|
@@ -309,19 +299,12 @@ function cleanupDeviceState(deviceId: string): void {
|
|
|
309
299
|
devicePacketStates.delete(deviceId);
|
|
310
300
|
subscribedDevices.delete(deviceId);
|
|
311
301
|
recentWriteOperations.delete(deviceId);
|
|
312
|
-
// 🔒 Clear operation state
|
|
313
|
-
subscriptionOperations.delete(deviceId);
|
|
314
302
|
logger?.info('[NobleBLE] Device state cleaned up:', deviceId);
|
|
315
303
|
}
|
|
316
304
|
|
|
317
305
|
// Handle device disconnection - unified handler for all disconnect scenarios
|
|
318
306
|
function handleDeviceDisconnect(deviceId: string, webContents: WebContents): void {
|
|
319
|
-
logger?.
|
|
320
|
-
deviceId,
|
|
321
|
-
hasPeripheral: connectedDevices.has(deviceId),
|
|
322
|
-
hasCharacteristics: deviceCharacteristics.has(deviceId),
|
|
323
|
-
stackTrace: new Error().stack?.split('\n').slice(1, 5),
|
|
324
|
-
});
|
|
307
|
+
logger?.info('[NobleBLE] Device disconnected:', deviceId);
|
|
325
308
|
|
|
326
309
|
// Get device info before cleanup
|
|
327
310
|
const peripheral = connectedDevices.get(deviceId);
|
|
@@ -372,7 +355,16 @@ function handleDeviceDiscovered(peripheral: Peripheral): void {
|
|
|
372
355
|
return;
|
|
373
356
|
}
|
|
374
357
|
|
|
375
|
-
logger?.info(
|
|
358
|
+
logger?.info(
|
|
359
|
+
'[NobleBLE] Discovered OneKey device:',
|
|
360
|
+
{
|
|
361
|
+
id: peripheral.id,
|
|
362
|
+
name: deviceName,
|
|
363
|
+
rssi: peripheral.rssi,
|
|
364
|
+
serviceUuids: peripheral.advertisement?.serviceUuids,
|
|
365
|
+
},
|
|
366
|
+
peripheral
|
|
367
|
+
);
|
|
376
368
|
|
|
377
369
|
// Cache the device in both maps
|
|
378
370
|
discoveredDevices.set(peripheral.id, peripheral);
|
|
@@ -644,15 +636,6 @@ async function discoverServicesAndCharacteristics(
|
|
|
644
636
|
|
|
645
637
|
// Connect to device - supports both discovered and direct connection modes
|
|
646
638
|
async function connectDevice(deviceId: string, webContents: WebContents): Promise<void> {
|
|
647
|
-
logger?.info('[NobleBLE] Connect device request:', {
|
|
648
|
-
deviceId,
|
|
649
|
-
hasDiscovered: discoveredDevices.has(deviceId),
|
|
650
|
-
hasConnected: connectedDevices.has(deviceId),
|
|
651
|
-
hasCharacteristics: deviceCharacteristics.has(deviceId),
|
|
652
|
-
totalDiscovered: discoveredDevices.size,
|
|
653
|
-
totalConnected: connectedDevices.size,
|
|
654
|
-
});
|
|
655
|
-
|
|
656
639
|
let peripheral = discoveredDevices.get(deviceId);
|
|
657
640
|
|
|
658
641
|
// If device not discovered, try a targeted scan for this specific device
|
|
@@ -705,45 +688,19 @@ async function connectDevice(deviceId: string, webContents: WebContents): Promis
|
|
|
705
688
|
// Check if we already have characteristics for this device
|
|
706
689
|
if (deviceCharacteristics.has(deviceId)) {
|
|
707
690
|
logger?.info('[NobleBLE] Device characteristics already available');
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
);
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
// Retry connection after waiting
|
|
720
|
-
return connectDevice(deviceId, webContents);
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
// Don't clean up notification state if device is already properly connected
|
|
724
|
-
// The existing notification subscription is still valid and working
|
|
725
|
-
const hasActiveSubscription = subscribedDevices.has(deviceId);
|
|
726
|
-
const hasCallback = notificationCallbacks.has(deviceId);
|
|
727
|
-
|
|
728
|
-
if (hasActiveSubscription && hasCallback) {
|
|
729
|
-
logger?.info(
|
|
730
|
-
'[NobleBLE] Device already has active notification subscription, reusing connection'
|
|
731
|
-
);
|
|
732
|
-
return;
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
// Only clean up if subscription is broken
|
|
736
|
-
logger?.info(
|
|
737
|
-
'[NobleBLE] Found orphaned characteristics without active subscription, cleaning up'
|
|
738
|
-
);
|
|
739
|
-
const existingCharacteristics = deviceCharacteristics.get(deviceId);
|
|
740
|
-
if (existingCharacteristics) {
|
|
741
|
-
existingCharacteristics.notify.removeAllListeners('data');
|
|
691
|
+
// Clean up existing notification state to avoid conflicts
|
|
692
|
+
const existingCallback = notificationCallbacks.get(deviceId);
|
|
693
|
+
if (existingCallback) {
|
|
694
|
+
logger?.info('[NobleBLE] Cleaning up existing notification state');
|
|
695
|
+
const existingCharacteristics = deviceCharacteristics.get(deviceId);
|
|
696
|
+
if (existingCharacteristics) {
|
|
697
|
+
existingCharacteristics.notify.removeAllListeners('data');
|
|
698
|
+
}
|
|
699
|
+
notificationCallbacks.delete(deviceId);
|
|
700
|
+
devicePacketStates.delete(deviceId);
|
|
701
|
+
subscribedDevices.delete(deviceId);
|
|
742
702
|
}
|
|
743
|
-
|
|
744
|
-
devicePacketStates.delete(deviceId);
|
|
745
|
-
subscribedDevices.delete(deviceId);
|
|
746
|
-
// Continue to re-setup the connection properly
|
|
703
|
+
return;
|
|
747
704
|
}
|
|
748
705
|
|
|
749
706
|
// Discover services and characteristics
|
|
@@ -931,9 +888,6 @@ async function subscribeNotifications(
|
|
|
931
888
|
|
|
932
889
|
logger?.info('[NobleBLE] Subscribing to notifications for device:', deviceId);
|
|
933
890
|
|
|
934
|
-
// 🔒 Set operation state to prevent race conditions
|
|
935
|
-
subscriptionOperations.set(deviceId, 'subscribing');
|
|
936
|
-
|
|
937
891
|
// Check if already subscribed at the characteristic level
|
|
938
892
|
if (subscribedDevices.get(deviceId)) {
|
|
939
893
|
logger?.info('[NobleBLE] Device already subscribed to characteristic, updating callback only');
|
|
@@ -949,8 +903,6 @@ async function subscribeNotifications(
|
|
|
949
903
|
messageId: undefined,
|
|
950
904
|
});
|
|
951
905
|
|
|
952
|
-
// 🔒 Clear operation state
|
|
953
|
-
subscriptionOperations.set(deviceId, 'idle');
|
|
954
906
|
return Promise.resolve();
|
|
955
907
|
}
|
|
956
908
|
|
|
@@ -973,23 +925,16 @@ async function subscribeNotifications(
|
|
|
973
925
|
|
|
974
926
|
return new Promise((resolve, reject) => {
|
|
975
927
|
// Subscribe to notifications only if not already subscribed
|
|
976
|
-
logger?.info('[NobleBLE] 🔄 Starting subscription process...', { deviceId });
|
|
977
|
-
|
|
978
928
|
notifyCharacteristic.subscribe((error: string) => {
|
|
979
929
|
if (error) {
|
|
980
|
-
logger?.error('[NobleBLE]
|
|
981
|
-
// 🔒 Clear operation state on error
|
|
982
|
-
subscriptionOperations.set(deviceId, 'idle');
|
|
930
|
+
logger?.error('[NobleBLE] Notification subscription failed:', error);
|
|
983
931
|
reject(ERRORS.TypedError(HardwareErrorCode.BleCharacteristicNotifyError, error));
|
|
984
932
|
return;
|
|
985
933
|
}
|
|
986
934
|
|
|
987
|
-
logger?.info('[NobleBLE]
|
|
935
|
+
logger?.info('[NobleBLE] Notification subscription successful');
|
|
988
936
|
subscribedDevices.set(deviceId, true);
|
|
989
937
|
|
|
990
|
-
// 🔒 Clear operation state on success
|
|
991
|
-
subscriptionOperations.set(deviceId, 'idle');
|
|
992
|
-
|
|
993
938
|
// Set up data handler with robust packet reassembly
|
|
994
939
|
notifyCharacteristic.on('data', (data: Buffer) => {
|
|
995
940
|
const result = processNotificationData(deviceId, data);
|
|
@@ -1026,9 +971,6 @@ async function unsubscribeNotifications(deviceId: string): Promise<void> {
|
|
|
1026
971
|
|
|
1027
972
|
logger?.info('[NobleBLE] Unsubscribing from notifications for device:', deviceId);
|
|
1028
973
|
|
|
1029
|
-
// 🔒 Set operation state to prevent race conditions
|
|
1030
|
-
subscriptionOperations.set(deviceId, 'unsubscribing');
|
|
1031
|
-
|
|
1032
974
|
return new Promise<void>(resolve => {
|
|
1033
975
|
notifyCharacteristic.unsubscribe((error: string) => {
|
|
1034
976
|
if (error) {
|
|
@@ -1042,9 +984,6 @@ async function unsubscribeNotifications(deviceId: string): Promise<void> {
|
|
|
1042
984
|
notificationCallbacks.delete(deviceId);
|
|
1043
985
|
devicePacketStates.delete(deviceId);
|
|
1044
986
|
subscribedDevices.delete(deviceId);
|
|
1045
|
-
|
|
1046
|
-
// 🔒 Clear operation state
|
|
1047
|
-
subscriptionOperations.set(deviceId, 'idle');
|
|
1048
987
|
resolve();
|
|
1049
988
|
});
|
|
1050
989
|
});
|
|
@@ -1089,12 +1028,6 @@ export function setupNobleBleHandlers(webContents: WebContents): void {
|
|
|
1089
1028
|
ipcMain.handle(
|
|
1090
1029
|
EOneKeyBleMessageKeys.NOBLE_BLE_CONNECT,
|
|
1091
1030
|
async (_event: IpcMainInvokeEvent, deviceId: string) => {
|
|
1092
|
-
logger?.info('[NobleBLE] IPC CONNECT request received:', {
|
|
1093
|
-
deviceId,
|
|
1094
|
-
hasPeripheral: connectedDevices.has(deviceId),
|
|
1095
|
-
hasCharacteristics: deviceCharacteristics.has(deviceId),
|
|
1096
|
-
totalConnectedDevices: connectedDevices.size,
|
|
1097
|
-
});
|
|
1098
1031
|
await connectDevice(deviceId, webContents);
|
|
1099
1032
|
}
|
|
1100
1033
|
);
|
|
@@ -1176,9 +1109,6 @@ export function setupNobleBleHandlers(webContents: WebContents): void {
|
|
|
1176
1109
|
notificationCallbacks.clear();
|
|
1177
1110
|
devicePacketStates.clear();
|
|
1178
1111
|
subscribedDevices.clear();
|
|
1179
|
-
|
|
1180
|
-
// Clear operation states
|
|
1181
|
-
subscriptionOperations.clear();
|
|
1182
1112
|
});
|
|
1183
1113
|
|
|
1184
1114
|
safeLog(logger, 'info', 'Noble BLE IPC handlers setup completed');
|