@onekeyfe/hd-transport-web-device 1.2.2-alpha.101 → 1.2.2-alpha.102

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.
@@ -182,6 +182,40 @@ describe('ElectronBleTransport protocol detection', () => {
182
182
  jest.clearAllMocks();
183
183
  });
184
184
 
185
+ test('does not treat an error envelope from a legacy preload as a successful connect', async () => {
186
+ const device = { id: 'stale-bond-id', name: 'OneKey Pro 2' };
187
+ const nobleBle = createNobleBle(device);
188
+ nobleBle.connect.mockResolvedValue({
189
+ type: 'NobleBleIpcError',
190
+ success: false,
191
+ error: {
192
+ name: 'HardwareError',
193
+ message: 'Bluetooth pairing information is no longer valid',
194
+ errorCode: HardwareErrorCode.BleBondInvalid,
195
+ },
196
+ } as never);
197
+ const bleTransport = configureTransport(nobleBle);
198
+
199
+ await expect(
200
+ bleTransport.acquire({ uuid: device.id, expectedProtocol: 'V2' })
201
+ ).rejects.toMatchObject({
202
+ errorCode: HardwareErrorCode.BleBondInvalid,
203
+ });
204
+ expect(nobleBle.subscribe).not.toHaveBeenCalled();
205
+ expect(nobleBle.disconnect).toHaveBeenCalledWith(device.id);
206
+ });
207
+
208
+ test('sends a native disconnect even before acquire marks the device connected', async () => {
209
+ const device = { id: 'pending-connect-id', name: 'OneKey Pro 2' };
210
+ const nobleBle = createNobleBle(device);
211
+ const bleTransport = configureTransport(nobleBle) as any;
212
+
213
+ await bleTransport.releaseNative(device.id);
214
+
215
+ expect(nobleBle.unsubscribe).not.toHaveBeenCalled();
216
+ expect(nobleBle.disconnect).toHaveBeenCalledWith(device.id);
217
+ });
218
+
185
219
  test('keeps raw BLE lifecycle payloads off the public device event channel', async () => {
186
220
  const device = { id: 'lifecycle-pro2-id', name: 'OneKey Pro 2' };
187
221
  const nobleBle = createNobleBle(device);
@@ -1 +1 @@
1
- {"version":3,"file":"electron-ble-transport.d.ts","sourceRoot":"","sources":["../src/electron-ble-transport.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"electron-ble-transport.d.ts","sourceRoot":"","sources":["../src/electron-ble-transport.ts"],"names":[],"mappings":";AA0BA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAA4B,MAAM,iCAAiC,CAAC;AAC5F,OAAO,KAAK,EACV,gBAAgB,EAChB,YAAY,EAEZ,oBAAoB,EACrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,YAAY,MAAM,QAAQ,CAAC;AAIvC,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,UAAU,CAAC,EAAE,UAAU,CAAC;KACzB;CACF;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,gBAAgB,CAAC,EAAE,YAAY,CAAC;IAChC,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B,CAAC;AAiDF,MAAM,CAAC,OAAO,OAAO,oBAAoB;IACvC,OAAO,CAAC,SAAS,CAA0D;IAE3E,OAAO,CAAC,WAAW,CAA0D;IAE7E,OAAO,CAAC,6BAA6B,CAAqB;IAE1D,IAAI,SAA0B;IAE9B,UAAU,UAAS;IAEnB,UAAU,EAAE,QAAQ,CAAC,UAAU,GAAG,MAAM,CAAC,GAAG,IAAI,CAAQ;IAExD,OAAO,CAAC,kBAAkB,CAAuB;IAEjD,GAAG,CAAC,EAAE,GAAG,CAAC;IAEV,OAAO,CAAC,EAAE,YAAY,CAAC;IAEvB,OAAO,CAAC,gBAAgB,CAA0B;IAElD,OAAO,CAAC,cAAc,CAAwC;IAE9D,OAAO,CAAC,mBAAmB,CAAwC;IAGnE,OAAO,CAAC,mBAAmB,CAAqB;IAEhD,OAAO,CAAC,UAAU,CAAkC;IAEpD,OAAO,CAAC,sBAAsB,CAAkC;IAEhE,OAAO,CAAC,SAAS,CAAsE;IAEvF,OAAO,CAAC,YAAY,CAAoD;IAExE,OAAO,CAAC,aAAa,CAAwC;IAE7D,OAAO,CAAC,eAAe,CAAgD;IAEvE,OAAO,CAAC,eAAe,CAmBpB;IAGH,OAAO,CAAC,oBAAoB,CAAS;IAErC,OAAO,CAAC,oBAAoB,CAAsC;IAElE,OAAO,CAAC,WAAW,CAAsC;IAUzD,OAAO,CAAC,qBAAqB,CAAC,CAAa;IAE3C,OAAO,CAAC,kBAAkB,CAAkC;IAE5D,OAAO,CAAC,qBAAqB,CAAK;IAElC,OAAO,CAAC,uBAAuB;IAsC/B,OAAO,CAAC,oBAAoB;IAI5B,OAAO,CAAC,kBAAkB;IAiC1B,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,YAAY;IAqBxC,OAAO,CAAC,wBAAwB;IAgChC,SAAS,CAAC,UAAU,EAAE,GAAG;IAKzB,mBAAmB,CAAC,UAAU,EAAE,GAAG;IAgB7B,MAAM;IAIN,SAAS,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAiBxC,OAAO,CAAC,KAAK,EAAE,eAAe;;;;;;;;;;;IA4F9B,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,OAAO;IAY7D,UAAU,CAAC,EAAE,EAAE,MAAM;YAKb,aAAa;YAoBb,cAAc;IAwB5B,OAAO,CAAC,2BAA2B;IAUnC,OAAO,CAAC,4BAA4B;IAOpC,OAAO,CAAC,kBAAkB;YAMZ,cAAc;IA2D5B,OAAO,CAAC,8BAA8B;YAgBxB,iCAAiC;YAwBjC,eAAe;YAqBf,eAAe;YAyBf,SAAS;YAaT,wBAAwB;IAMtC,OAAO,CAAC,uBAAuB;IAc/B,OAAO,CAAC,qBAAqB;IAU7B,OAAO,CAAC,oBAAoB;IAqB5B,OAAO,CAAC,kBAAkB;IA+B1B,OAAO,CAAC,iCAAiC;IAazC,OAAO,CAAC,4BAA4B;IAkBpC,OAAO,CAAC,uBAAuB;IAS/B,OAAO,CAAC,sBAAsB;IAU9B,OAAO,CAAC,qBAAqB;IAI7B,OAAO,CAAC,sBAAsB;YAShB,mBAAmB;IAiBjC,OAAO,CAAC,4BAA4B;IAqB9B,IAAI,CACR,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,CAAC,EAAE,oBAAoB;IAuB1B,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;YAatD,cAAc;YAqFd,cAAc;IA0B5B,OAAO,CAAC,uBAAuB;IAyC/B,OAAO,CAAC,6BAA6B;IA4CrC,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;CAGxD"}
package/dist/index.js CHANGED
@@ -823,6 +823,19 @@ function resolveBlePacketCapacity(mtu, maximumPacketCapacity, fallbackPacketCapa
823
823
 
824
824
  const { parseConfigure, ProtocolV1, check } = transport__default["default"];
825
825
  const toBleDescriptor = (device, protocolType) => (Object.assign({ id: device.id, name: device.name, path: device.id, debug: false, commType: 'electron-ble' }, (protocolType ? { protocolType } : {})));
826
+ const invokeNobleBle = (request) => __awaiter(void 0, void 0, void 0, function* () {
827
+ const response = yield request;
828
+ if (response &&
829
+ typeof response === 'object' &&
830
+ 'type' in response &&
831
+ response.type === 'NobleBleIpcError' &&
832
+ 'success' in response &&
833
+ response.success === false &&
834
+ 'error' in response) {
835
+ return Promise.reject(response.error);
836
+ }
837
+ return response;
838
+ });
826
839
  const BLE_PACKET_SIZE_FALLBACK = 192;
827
840
  const BLE_PACKET_SIZE_MAXIMUM = 244;
828
841
  const BLE_WRITE_DELAY_MS = 5;
@@ -991,7 +1004,7 @@ class ElectronBleTransport {
991
1004
  if (!((_a = window.desktopApi) === null || _a === void 0 ? void 0 : _a.nobleBle)) {
992
1005
  throw new Error('Noble BLE API not available');
993
1006
  }
994
- const devices = yield window.desktopApi.nobleBle.enumerate();
1007
+ const devices = yield invokeNobleBle(window.desktopApi.nobleBle.enumerate());
995
1008
  (_b = this.Log) === null || _b === void 0 ? void 0 : _b.debug(`[Electron BLE] enumerate found ${devices.length} device(s):`);
996
1009
  for (const dev of devices) {
997
1010
  (_c = this.Log) === null || _c === void 0 ? void 0 : _c.debug(`[Electron BLE] id="${dev.id}" name="${dev.name}"`);
@@ -1024,7 +1037,7 @@ class ElectronBleTransport {
1024
1037
  if (!((_a = window.desktopApi) === null || _a === void 0 ? void 0 : _a.nobleBle)) {
1025
1038
  throw new Error('Noble BLE API not available');
1026
1039
  }
1027
- const device = yield window.desktopApi.nobleBle.getDevice(uuid);
1040
+ const device = yield invokeNobleBle(window.desktopApi.nobleBle.getDevice(uuid));
1028
1041
  if (!device) {
1029
1042
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceNotFound, `Device ${uuid} not found`);
1030
1043
  }
@@ -1035,7 +1048,7 @@ class ElectronBleTransport {
1035
1048
  this.deviceProtocolHints.set(uuid, protocolHint);
1036
1049
  }
1037
1050
  try {
1038
- yield window.desktopApi.nobleBle.connect(uuid);
1051
+ yield invokeNobleBle(window.desktopApi.nobleBle.connect(uuid));
1039
1052
  this.connectedDevices.add(uuid);
1040
1053
  }
1041
1054
  catch (error) {
@@ -1048,7 +1061,7 @@ class ElectronBleTransport {
1048
1061
  this.v1Buffers.set(uuid, { buffer: [], bufferLength: 0 });
1049
1062
  this.v2Assemblers.set(uuid, new transport.ProtocolV2FrameAssembler(transport.PROTOCOL_V2_BLE_FRAME_MAX_BYTES));
1050
1063
  try {
1051
- yield window.desktopApi.nobleBle.subscribe(uuid);
1064
+ yield invokeNobleBle(window.desktopApi.nobleBle.subscribe(uuid));
1052
1065
  }
1053
1066
  catch (error) {
1054
1067
  this.handleBluetoothError(error);
@@ -1069,9 +1082,15 @@ class ElectronBleTransport {
1069
1082
  catch (error) {
1070
1083
  (_e = this.Log) === null || _e === void 0 ? void 0 : _e.error('[Electron BLE] acquire failed:', error);
1071
1084
  try {
1072
- if (((_f = window.desktopApi) === null || _f === void 0 ? void 0 : _f.nobleBle) && this.connectedDevices.has(uuid)) {
1073
- yield window.desktopApi.nobleBle.unsubscribe(uuid);
1074
- yield window.desktopApi.nobleBle.disconnect(uuid);
1085
+ const nobleBle = (_f = window.desktopApi) === null || _f === void 0 ? void 0 : _f.nobleBle;
1086
+ if (nobleBle) {
1087
+ if (this.connectedDevices.has(uuid)) {
1088
+ yield invokeNobleBle(nobleBle.unsubscribe(uuid)).catch(cleanupError => {
1089
+ var _a;
1090
+ (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[Electron BLE] acquire unsubscribe failed:', cleanupError);
1091
+ });
1092
+ }
1093
+ yield invokeNobleBle(nobleBle.disconnect(uuid));
1075
1094
  }
1076
1095
  }
1077
1096
  catch (cleanupError) {
@@ -1104,13 +1123,17 @@ class ElectronBleTransport {
1104
1123
  var _a, _b;
1105
1124
  return __awaiter(this, void 0, void 0, function* () {
1106
1125
  try {
1107
- if (this.connectedDevices.has(id)) {
1108
- if ((_a = window.desktopApi) === null || _a === void 0 ? void 0 : _a.nobleBle) {
1109
- yield window.desktopApi.nobleBle.unsubscribe(id);
1110
- yield window.desktopApi.nobleBle.disconnect(id);
1126
+ const nobleBle = (_a = window.desktopApi) === null || _a === void 0 ? void 0 : _a.nobleBle;
1127
+ if (nobleBle) {
1128
+ if (this.connectedDevices.has(id)) {
1129
+ yield invokeNobleBle(nobleBle.unsubscribe(id)).catch(error => {
1130
+ var _a;
1131
+ (_a = this.Log) === null || _a === void 0 ? void 0 : _a.debug('[Electron BLE] release unsubscribe failed:', error);
1132
+ });
1111
1133
  }
1112
- this.cleanupDeviceState(id);
1134
+ yield invokeNobleBle(nobleBle.disconnect(id));
1113
1135
  }
1136
+ this.cleanupDeviceState(id);
1114
1137
  }
1115
1138
  catch (error) {
1116
1139
  (_b = this.Log) === null || _b === void 0 ? void 0 : _b.error('[Electron BLE] release failed:', error);
@@ -1134,7 +1157,7 @@ class ElectronBleTransport {
1134
1157
  }
1135
1158
  return;
1136
1159
  }
1137
- yield release(id, keepSession);
1160
+ yield invokeNobleBle(release(id, keepSession));
1138
1161
  }
1139
1162
  catch (error) {
1140
1163
  (_d = this.Log) === null || _d === void 0 ? void 0 : _d.error('[Electron BLE] logical release failed:', error);
@@ -1279,7 +1302,7 @@ class ElectronBleTransport {
1279
1302
  throw new Error('Noble BLE API not available');
1280
1303
  }
1281
1304
  try {
1282
- yield nobleBle.write(uuid, hexData, { pacingDelayMs: 0 });
1305
+ yield invokeNobleBle(nobleBle.write(uuid, hexData, { pacingDelayMs: 0 }));
1283
1306
  }
1284
1307
  catch (error) {
1285
1308
  this.handleBluetoothError(error);
@@ -1287,9 +1310,10 @@ class ElectronBleTransport {
1287
1310
  });
1288
1311
  }
1289
1312
  refreshBlePacketCapacity(uuid) {
1290
- var _a, _b;
1313
+ var _a;
1291
1314
  return __awaiter(this, void 0, void 0, function* () {
1292
- const device = yield ((_b = (_a = window.desktopApi) === null || _a === void 0 ? void 0 : _a.nobleBle) === null || _b === void 0 ? void 0 : _b.getDevice(uuid));
1315
+ const nobleBle = (_a = window.desktopApi) === null || _a === void 0 ? void 0 : _a.nobleBle;
1316
+ const device = nobleBle ? yield invokeNobleBle(nobleBle.getDevice(uuid)) : undefined;
1293
1317
  this.updateBlePacketCapacity(uuid, device === null || device === void 0 ? void 0 : device.mtu);
1294
1318
  });
1295
1319
  }
@@ -1512,7 +1536,7 @@ class ElectronBleTransport {
1512
1536
  if (hexString.length === 0) {
1513
1537
  throw new Error(`Buffer ${i + 1} is empty`);
1514
1538
  }
1515
- yield window.desktopApi.nobleBle.write(uuid, hexString);
1539
+ yield invokeNobleBle(window.desktopApi.nobleBle.write(uuid, hexString));
1516
1540
  }
1517
1541
  const response = yield Promise.race([
1518
1542
  runPromise.promise,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hd-transport-web-device",
3
- "version": "1.2.2-alpha.101",
3
+ "version": "1.2.2-alpha.102",
4
4
  "author": "OneKey",
5
5
  "homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
6
6
  "license": "MIT",
@@ -21,13 +21,13 @@
21
21
  "lint:fix": "eslint . --fix"
22
22
  },
23
23
  "dependencies": {
24
- "@onekeyfe/hd-shared": "1.2.2-alpha.101",
25
- "@onekeyfe/hd-transport": "1.2.2-alpha.101"
24
+ "@onekeyfe/hd-shared": "1.2.2-alpha.102",
25
+ "@onekeyfe/hd-transport": "1.2.2-alpha.102"
26
26
  },
27
27
  "devDependencies": {
28
- "@onekeyfe/hd-transport-electron": "1.2.2-alpha.101",
28
+ "@onekeyfe/hd-transport-electron": "1.2.2-alpha.102",
29
29
  "@types/w3c-web-usb": "^1.0.6",
30
30
  "@types/web-bluetooth": "^0.0.17"
31
31
  },
32
- "gitHead": "b9a5ca0c73e5e2cc979c91c007ace476e442718c"
32
+ "gitHead": "abddc95e03d794d9c6fce7765d59de1f48a684d0"
33
33
  }
@@ -25,7 +25,7 @@ import {
25
25
  import { resolveBlePacketCapacity } from './ble-packet-capacity';
26
26
 
27
27
  import type { Deferred } from '@onekeyfe/hd-shared';
28
- import type { DesktopAPI } from '@onekeyfe/hd-transport-electron';
28
+ import type { DesktopAPI, NobleBleIpcErrorResponse } from '@onekeyfe/hd-transport-electron';
29
29
  import type {
30
30
  OneKeyDeviceInfo,
31
31
  ProtocolType,
@@ -68,6 +68,22 @@ const toBleDescriptor = (
68
68
  ...(protocolType ? { protocolType } : {}),
69
69
  } as OneKeyDeviceInfo);
70
70
 
71
+ const invokeNobleBle = async <T>(request: Promise<T>): Promise<T> => {
72
+ const response = await (request as Promise<T | NobleBleIpcErrorResponse>);
73
+ if (
74
+ response &&
75
+ typeof response === 'object' &&
76
+ 'type' in response &&
77
+ response.type === 'NobleBleIpcError' &&
78
+ 'success' in response &&
79
+ response.success === false &&
80
+ 'error' in response
81
+ ) {
82
+ return Promise.reject(response.error);
83
+ }
84
+ return response as T;
85
+ };
86
+
71
87
  const BLE_PACKET_SIZE_FALLBACK = 192;
72
88
  const BLE_PACKET_SIZE_MAXIMUM = 244;
73
89
  const BLE_WRITE_DELAY_MS = 5;
@@ -320,7 +336,7 @@ export default class ElectronBleTransport {
320
336
  if (!window.desktopApi?.nobleBle) {
321
337
  throw new Error('Noble BLE API not available');
322
338
  }
323
- const devices = await window.desktopApi.nobleBle.enumerate();
339
+ const devices = await invokeNobleBle(window.desktopApi.nobleBle.enumerate());
324
340
  this.Log?.debug(`[Electron BLE] enumerate found ${devices.length} device(s):`);
325
341
  for (const dev of devices) {
326
342
  this.Log?.debug(`[Electron BLE] id="${dev.id}" name="${dev.name}"`);
@@ -355,7 +371,7 @@ export default class ElectronBleTransport {
355
371
  throw new Error('Noble BLE API not available');
356
372
  }
357
373
 
358
- const device = await window.desktopApi.nobleBle.getDevice(uuid);
374
+ const device = await invokeNobleBle(window.desktopApi.nobleBle.getDevice(uuid));
359
375
  if (!device) {
360
376
  throw ERRORS.TypedError(HardwareErrorCode.DeviceNotFound, `Device ${uuid} not found`);
361
377
  }
@@ -367,7 +383,7 @@ export default class ElectronBleTransport {
367
383
  }
368
384
 
369
385
  try {
370
- await window.desktopApi.nobleBle.connect(uuid);
386
+ await invokeNobleBle(window.desktopApi.nobleBle.connect(uuid));
371
387
  this.connectedDevices.add(uuid);
372
388
  } catch (error) {
373
389
  this.handleBluetoothError(error);
@@ -382,7 +398,7 @@ export default class ElectronBleTransport {
382
398
  this.v2Assemblers.set(uuid, new ProtocolV2FrameAssembler(PROTOCOL_V2_BLE_FRAME_MAX_BYTES));
383
399
 
384
400
  try {
385
- await window.desktopApi.nobleBle.subscribe(uuid);
401
+ await invokeNobleBle(window.desktopApi.nobleBle.subscribe(uuid));
386
402
  } catch (error) {
387
403
  this.handleBluetoothError(error);
388
404
  }
@@ -407,9 +423,14 @@ export default class ElectronBleTransport {
407
423
  } catch (error) {
408
424
  this.Log?.error('[Electron BLE] acquire failed:', error);
409
425
  try {
410
- if (window.desktopApi?.nobleBle && this.connectedDevices.has(uuid)) {
411
- await window.desktopApi.nobleBle.unsubscribe(uuid);
412
- await window.desktopApi.nobleBle.disconnect(uuid);
426
+ const nobleBle = window.desktopApi?.nobleBle;
427
+ if (nobleBle) {
428
+ if (this.connectedDevices.has(uuid)) {
429
+ await invokeNobleBle(nobleBle.unsubscribe(uuid)).catch(cleanupError => {
430
+ this.Log?.debug('[Electron BLE] acquire unsubscribe failed:', cleanupError);
431
+ });
432
+ }
433
+ await invokeNobleBle(nobleBle.disconnect(uuid));
413
434
  }
414
435
  } catch (cleanupError) {
415
436
  this.Log?.debug('[Electron BLE] acquire cleanup failed:', cleanupError);
@@ -438,13 +459,16 @@ export default class ElectronBleTransport {
438
459
  // Hard teardown, error paths only: a link presumed dead must not be reused.
439
460
  private async releaseNative(id: string) {
440
461
  try {
441
- if (this.connectedDevices.has(id)) {
442
- if (window.desktopApi?.nobleBle) {
443
- await window.desktopApi.nobleBle.unsubscribe(id);
444
- await window.desktopApi.nobleBle.disconnect(id);
462
+ const nobleBle = window.desktopApi?.nobleBle;
463
+ if (nobleBle) {
464
+ if (this.connectedDevices.has(id)) {
465
+ await invokeNobleBle(nobleBle.unsubscribe(id)).catch(error => {
466
+ this.Log?.debug('[Electron BLE] release unsubscribe failed:', error);
467
+ });
445
468
  }
446
- this.cleanupDeviceState(id);
469
+ await invokeNobleBle(nobleBle.disconnect(id));
447
470
  }
471
+ this.cleanupDeviceState(id);
448
472
  } catch (error) {
449
473
  this.Log?.error('[Electron BLE] release failed:', error);
450
474
  this.cleanupDeviceState(id);
@@ -470,7 +494,7 @@ export default class ElectronBleTransport {
470
494
  }
471
495
  return;
472
496
  }
473
- await release(id, keepSession);
497
+ await invokeNobleBle(release(id, keepSession));
474
498
  } catch (error) {
475
499
  this.Log?.error('[Electron BLE] logical release failed:', error);
476
500
  this.cleanupDeviceState(id);
@@ -652,14 +676,15 @@ export default class ElectronBleTransport {
652
676
  }
653
677
 
654
678
  try {
655
- await nobleBle.write(uuid, hexData, { pacingDelayMs: 0 });
679
+ await invokeNobleBle(nobleBle.write(uuid, hexData, { pacingDelayMs: 0 }));
656
680
  } catch (error) {
657
681
  this.handleBluetoothError(error);
658
682
  }
659
683
  }
660
684
 
661
685
  private async refreshBlePacketCapacity(uuid: string): Promise<void> {
662
- const device = await window.desktopApi?.nobleBle?.getDevice(uuid);
686
+ const nobleBle = window.desktopApi?.nobleBle;
687
+ const device = nobleBle ? await invokeNobleBle(nobleBle.getDevice(uuid)) : undefined;
663
688
  this.updateBlePacketCapacity(uuid, device?.mtu);
664
689
  }
665
690
 
@@ -917,7 +942,7 @@ export default class ElectronBleTransport {
917
942
  if (hexString.length === 0) {
918
943
  throw new Error(`Buffer ${i + 1} is empty`);
919
944
  }
920
- await window.desktopApi.nobleBle.write(uuid, hexString);
945
+ await invokeNobleBle(window.desktopApi.nobleBle.write(uuid, hexString));
921
946
  }
922
947
 
923
948
  const response = await Promise.race([