@onekeyfe/hwk-desktop-noble-ble 1.2.8-alpha.13 → 1.2.8-alpha.52
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.d.mts +29 -2
- package/dist/index.d.ts +29 -2
- package/dist/index.js +84 -21
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +83 -21
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ElectronBleConnectOptions, ElectronBleScanOptions } from '@onekeyfe/hwk-adapter-core';
|
|
2
2
|
export { THIRD_PARTY_BLE_CHANNELS, THIRD_PARTY_BLE_DEVICE_TTL_MS, THIRD_PARTY_BLE_POWER_ON_TIMEOUT_MS, THIRD_PARTY_BLE_SCAN_DURATION_MS, THIRD_PARTY_BLE_SCAN_IDLE_STOP_MS, ThirdPartyBleChannel } from './constants.mjs';
|
|
3
3
|
|
|
4
4
|
type BleDebugLogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
@@ -12,6 +12,26 @@ type BleDebugLogger = (entry: BleDebugLogEntry) => void;
|
|
|
12
12
|
/** Replace sensitive values at any depth; everything else is forwarded verbatim. */
|
|
13
13
|
declare function redactBleDebugLogData(data?: Record<string, unknown>): Record<string, unknown> | undefined;
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Main-process allowlist entry for one vendor key. The renderer only names the vendor; which
|
|
17
|
+
* peripherals it may see and which GATT profile and framing it may use are decided here, so an
|
|
18
|
+
* IPC caller cannot turn the service into a generic BLE proxy. UUID arguments may arrive in any
|
|
19
|
+
* case, with or without dashes.
|
|
20
|
+
*/
|
|
21
|
+
interface ThirdPartyBleVendorProfile {
|
|
22
|
+
/** Whether an advertised service UUID belongs to this vendor. */
|
|
23
|
+
isServiceUuid(uuid: string): boolean;
|
|
24
|
+
/** Whether a local name belongs to this vendor; the handler passes a length-capped name. */
|
|
25
|
+
isName?(name: string): boolean;
|
|
26
|
+
/** Whether this GATT profile and write framing is one the vendor's firmware uses. */
|
|
27
|
+
acceptsConnect(options: ElectronBleConnectOptions): boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Vendors the desktop BLE service serves by default, keyed by the vendor string the connectors
|
|
31
|
+
* send. A host passing `vendors` replaces this map, so spread it to add a vendor.
|
|
32
|
+
*/
|
|
33
|
+
declare const DEFAULT_THIRD_PARTY_BLE_VENDORS: Readonly<Record<string, ThirdPartyBleVendorProfile>>;
|
|
34
|
+
|
|
15
35
|
/** Device info the main process returns to the renderer over IPC. */
|
|
16
36
|
interface ThirdPartyBleDeviceInfo {
|
|
17
37
|
/** Stable id (noble peripheral.id) used as connectId. */
|
|
@@ -139,6 +159,11 @@ interface NobleBleHandlerOptions {
|
|
|
139
159
|
/** Override the overall connect timeout (tests only; defaults to 31s). */
|
|
140
160
|
connectTimeoutMs?: number;
|
|
141
161
|
logger?: BleDebugLogger;
|
|
162
|
+
/**
|
|
163
|
+
* Vendors served over IPC, keyed by the `vendor` the renderer sends. Replaces the default map
|
|
164
|
+
* (spread `DEFAULT_THIRD_PARTY_BLE_VENDORS` to add one); unknown vendors are rejected.
|
|
165
|
+
*/
|
|
166
|
+
vendors?: Record<string, ThirdPartyBleVendorProfile>;
|
|
142
167
|
}
|
|
143
168
|
/** Noble BLE logic decoupled from Electron IPC, so tests can use a fake noble. */
|
|
144
169
|
declare class NobleBleHandler {
|
|
@@ -146,6 +171,7 @@ declare class NobleBleHandler {
|
|
|
146
171
|
private readonly _factory;
|
|
147
172
|
private readonly _connectTimeoutMs;
|
|
148
173
|
private readonly _logger?;
|
|
174
|
+
private readonly _vendors;
|
|
149
175
|
private readonly _discovered;
|
|
150
176
|
private readonly _lastSeen;
|
|
151
177
|
private readonly _connected;
|
|
@@ -167,6 +193,7 @@ declare class NobleBleHandler {
|
|
|
167
193
|
private _nativeReleased;
|
|
168
194
|
private _lastNobleRecoverAt?;
|
|
169
195
|
constructor(options?: NobleBleHandlerOptions);
|
|
196
|
+
private _resolveVendor;
|
|
170
197
|
setNotificationListener(handler: (id: string, hexData: string) => void): void;
|
|
171
198
|
setDisconnectedListener(handler: (id: string) => void): void;
|
|
172
199
|
init(): Promise<void>;
|
|
@@ -274,4 +301,4 @@ interface ThirdPartyBleSupportHandle {
|
|
|
274
301
|
*/
|
|
275
302
|
declare function initThirdPartyBleSupport(webContents: WebContentsLike, options?: InitThirdPartyBleSupportOptions): ThirdPartyBleSupportHandle;
|
|
276
303
|
|
|
277
|
-
export { type BleDebugLogEntry, type BleDebugLogLevel, type BleDebugLogger, type InitThirdPartyBleSupportOptions, type IpcMainLike, NobleBleHandler, type NobleBleHandlerOptions, type ThirdPartyBleApi, type ThirdPartyBleAvailability, type ThirdPartyBleDeviceInfo, type ThirdPartyBleSupportHandle, initThirdPartyBleSupport, redactBleDebugLogData };
|
|
304
|
+
export { type BleDebugLogEntry, type BleDebugLogLevel, type BleDebugLogger, DEFAULT_THIRD_PARTY_BLE_VENDORS, type InitThirdPartyBleSupportOptions, type IpcMainLike, NobleBleHandler, type NobleBleHandlerOptions, type ThirdPartyBleApi, type ThirdPartyBleAvailability, type ThirdPartyBleDeviceInfo, type ThirdPartyBleSupportHandle, type ThirdPartyBleVendorProfile, initThirdPartyBleSupport, redactBleDebugLogData };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ElectronBleConnectOptions, ElectronBleScanOptions } from '@onekeyfe/hwk-adapter-core';
|
|
2
2
|
export { THIRD_PARTY_BLE_CHANNELS, THIRD_PARTY_BLE_DEVICE_TTL_MS, THIRD_PARTY_BLE_POWER_ON_TIMEOUT_MS, THIRD_PARTY_BLE_SCAN_DURATION_MS, THIRD_PARTY_BLE_SCAN_IDLE_STOP_MS, ThirdPartyBleChannel } from './constants.js';
|
|
3
3
|
|
|
4
4
|
type BleDebugLogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
@@ -12,6 +12,26 @@ type BleDebugLogger = (entry: BleDebugLogEntry) => void;
|
|
|
12
12
|
/** Replace sensitive values at any depth; everything else is forwarded verbatim. */
|
|
13
13
|
declare function redactBleDebugLogData(data?: Record<string, unknown>): Record<string, unknown> | undefined;
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Main-process allowlist entry for one vendor key. The renderer only names the vendor; which
|
|
17
|
+
* peripherals it may see and which GATT profile and framing it may use are decided here, so an
|
|
18
|
+
* IPC caller cannot turn the service into a generic BLE proxy. UUID arguments may arrive in any
|
|
19
|
+
* case, with or without dashes.
|
|
20
|
+
*/
|
|
21
|
+
interface ThirdPartyBleVendorProfile {
|
|
22
|
+
/** Whether an advertised service UUID belongs to this vendor. */
|
|
23
|
+
isServiceUuid(uuid: string): boolean;
|
|
24
|
+
/** Whether a local name belongs to this vendor; the handler passes a length-capped name. */
|
|
25
|
+
isName?(name: string): boolean;
|
|
26
|
+
/** Whether this GATT profile and write framing is one the vendor's firmware uses. */
|
|
27
|
+
acceptsConnect(options: ElectronBleConnectOptions): boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Vendors the desktop BLE service serves by default, keyed by the vendor string the connectors
|
|
31
|
+
* send. A host passing `vendors` replaces this map, so spread it to add a vendor.
|
|
32
|
+
*/
|
|
33
|
+
declare const DEFAULT_THIRD_PARTY_BLE_VENDORS: Readonly<Record<string, ThirdPartyBleVendorProfile>>;
|
|
34
|
+
|
|
15
35
|
/** Device info the main process returns to the renderer over IPC. */
|
|
16
36
|
interface ThirdPartyBleDeviceInfo {
|
|
17
37
|
/** Stable id (noble peripheral.id) used as connectId. */
|
|
@@ -139,6 +159,11 @@ interface NobleBleHandlerOptions {
|
|
|
139
159
|
/** Override the overall connect timeout (tests only; defaults to 31s). */
|
|
140
160
|
connectTimeoutMs?: number;
|
|
141
161
|
logger?: BleDebugLogger;
|
|
162
|
+
/**
|
|
163
|
+
* Vendors served over IPC, keyed by the `vendor` the renderer sends. Replaces the default map
|
|
164
|
+
* (spread `DEFAULT_THIRD_PARTY_BLE_VENDORS` to add one); unknown vendors are rejected.
|
|
165
|
+
*/
|
|
166
|
+
vendors?: Record<string, ThirdPartyBleVendorProfile>;
|
|
142
167
|
}
|
|
143
168
|
/** Noble BLE logic decoupled from Electron IPC, so tests can use a fake noble. */
|
|
144
169
|
declare class NobleBleHandler {
|
|
@@ -146,6 +171,7 @@ declare class NobleBleHandler {
|
|
|
146
171
|
private readonly _factory;
|
|
147
172
|
private readonly _connectTimeoutMs;
|
|
148
173
|
private readonly _logger?;
|
|
174
|
+
private readonly _vendors;
|
|
149
175
|
private readonly _discovered;
|
|
150
176
|
private readonly _lastSeen;
|
|
151
177
|
private readonly _connected;
|
|
@@ -167,6 +193,7 @@ declare class NobleBleHandler {
|
|
|
167
193
|
private _nativeReleased;
|
|
168
194
|
private _lastNobleRecoverAt?;
|
|
169
195
|
constructor(options?: NobleBleHandlerOptions);
|
|
196
|
+
private _resolveVendor;
|
|
170
197
|
setNotificationListener(handler: (id: string, hexData: string) => void): void;
|
|
171
198
|
setDisconnectedListener(handler: (id: string) => void): void;
|
|
172
199
|
init(): Promise<void>;
|
|
@@ -274,4 +301,4 @@ interface ThirdPartyBleSupportHandle {
|
|
|
274
301
|
*/
|
|
275
302
|
declare function initThirdPartyBleSupport(webContents: WebContentsLike, options?: InitThirdPartyBleSupportOptions): ThirdPartyBleSupportHandle;
|
|
276
303
|
|
|
277
|
-
export { type BleDebugLogEntry, type BleDebugLogLevel, type BleDebugLogger, type InitThirdPartyBleSupportOptions, type IpcMainLike, NobleBleHandler, type NobleBleHandlerOptions, type ThirdPartyBleApi, type ThirdPartyBleAvailability, type ThirdPartyBleDeviceInfo, type ThirdPartyBleSupportHandle, initThirdPartyBleSupport, redactBleDebugLogData };
|
|
304
|
+
export { type BleDebugLogEntry, type BleDebugLogLevel, type BleDebugLogger, DEFAULT_THIRD_PARTY_BLE_VENDORS, type InitThirdPartyBleSupportOptions, type IpcMainLike, NobleBleHandler, type NobleBleHandlerOptions, type ThirdPartyBleApi, type ThirdPartyBleAvailability, type ThirdPartyBleDeviceInfo, type ThirdPartyBleSupportHandle, type ThirdPartyBleVendorProfile, initThirdPartyBleSupport, redactBleDebugLogData };
|
package/dist/index.js
CHANGED
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
DEFAULT_THIRD_PARTY_BLE_VENDORS: () => DEFAULT_THIRD_PARTY_BLE_VENDORS,
|
|
23
24
|
NobleBleHandler: () => NobleBleHandler,
|
|
24
25
|
THIRD_PARTY_BLE_CHANNELS: () => THIRD_PARTY_BLE_CHANNELS,
|
|
25
26
|
THIRD_PARTY_BLE_DEVICE_TTL_MS: () => THIRD_PARTY_BLE_DEVICE_TTL_MS,
|
|
@@ -114,24 +115,74 @@ var THIRD_PARTY_BLE_SCAN_IDLE_STOP_MS = 1e4;
|
|
|
114
115
|
var THIRD_PARTY_BLE_DEVICE_TTL_MS = 5e3;
|
|
115
116
|
var THIRD_PARTY_BLE_POWER_ON_TIMEOUT_MS = 1e4;
|
|
116
117
|
|
|
118
|
+
// src/vendorProfiles.ts
|
|
119
|
+
var normalizeBleUuid = (uuid) => uuid.replace(/-/g, "").toLowerCase();
|
|
120
|
+
var isUuidString = (value) => typeof value === "string";
|
|
121
|
+
var isIntegerInRange = (value, min, max) => typeof value === "number" && Number.isInteger(value) && value >= min && value <= max;
|
|
122
|
+
var TREZOR_SERVICE_UUID = normalizeBleUuid("8c000001-a59b-4d58-a9ad-073df69fa1b1");
|
|
123
|
+
var TREZOR_WRITE_UUID = normalizeBleUuid("8c000002-a59b-4d58-a9ad-073df69fa1b1");
|
|
124
|
+
var TREZOR_NOTIFY_UUID = normalizeBleUuid("8c000003-a59b-4d58-a9ad-073df69fa1b1");
|
|
125
|
+
var TREZOR_PACKET_SIZE = 244;
|
|
126
|
+
var TREZOR_MAX_CHUNK_DELAY_MS = 50;
|
|
127
|
+
var TREZOR_NAME_BRAND = /\bTrezor\b/i;
|
|
128
|
+
var TREZOR_NAME_MODEL = /\bSafe\s*7\b|\bT3W1\b/i;
|
|
129
|
+
var trezorProfile = {
|
|
130
|
+
isServiceUuid: (uuid) => isUuidString(uuid) && normalizeBleUuid(uuid) === TREZOR_SERVICE_UUID,
|
|
131
|
+
isName: (name) => TREZOR_NAME_BRAND.test(name) && TREZOR_NAME_MODEL.test(name),
|
|
132
|
+
acceptsConnect: (options) => {
|
|
133
|
+
const { write } = options;
|
|
134
|
+
return isUuidString(options.serviceUuid) && isUuidString(options.writeUuid) && isUuidString(options.notifyUuid) && normalizeBleUuid(options.serviceUuid) === TREZOR_SERVICE_UUID && normalizeBleUuid(options.writeUuid) === TREZOR_WRITE_UUID && normalizeBleUuid(options.notifyUuid) === TREZOR_NOTIFY_UUID && typeof write === "object" && write !== null && write.mode === "padded" && write.chunkSize === TREZOR_PACKET_SIZE && (write.chunkDelayMs === void 0 || isIntegerInRange(write.chunkDelayMs, 0, TREZOR_MAX_CHUNK_DELAY_MS)) && write.maxLength === void 0;
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
var LEDGER_UUID = /^13d634002c97([0-9a-f]{4})000([0-3])4c6564676572$/;
|
|
138
|
+
var LEDGER_ROLE_SERVICE = "0";
|
|
139
|
+
var LEDGER_ROLE_NOTIFY = "1";
|
|
140
|
+
var LEDGER_ROLE_WRITE = "2";
|
|
141
|
+
var LEDGER_ROLE_WRITE_CMD = "3";
|
|
142
|
+
var LEDGER_MAX_FRAME_SIZE = 255;
|
|
143
|
+
var parseLedgerUuid = (uuid) => {
|
|
144
|
+
if (!isUuidString(uuid)) return void 0;
|
|
145
|
+
const parsed = LEDGER_UUID.exec(normalizeBleUuid(uuid));
|
|
146
|
+
return parsed ? { model: parsed[1], role: parsed[2] } : void 0;
|
|
147
|
+
};
|
|
148
|
+
var ledgerProfile = {
|
|
149
|
+
isServiceUuid: (uuid) => parseLedgerUuid(uuid)?.role === LEDGER_ROLE_SERVICE,
|
|
150
|
+
acceptsConnect: (options) => {
|
|
151
|
+
const service = parseLedgerUuid(options.serviceUuid);
|
|
152
|
+
const notify = parseLedgerUuid(options.notifyUuid);
|
|
153
|
+
const write = parseLedgerUuid(options.writeUuid);
|
|
154
|
+
const framing = options.write;
|
|
155
|
+
return service?.role === LEDGER_ROLE_SERVICE && notify?.role === LEDGER_ROLE_NOTIFY && (write?.role === LEDGER_ROLE_WRITE || write?.role === LEDGER_ROLE_WRITE_CMD) && notify.model === service.model && write.model === service.model && typeof framing === "object" && framing !== null && framing.mode === "raw" && isIntegerInRange(framing.maxLength, 1, LEDGER_MAX_FRAME_SIZE) && framing.chunkSize === void 0 && framing.chunkDelayMs === void 0;
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
var DEFAULT_THIRD_PARTY_BLE_VENDORS = Object.freeze({
|
|
159
|
+
ledger: ledgerProfile,
|
|
160
|
+
trezor: trezorProfile
|
|
161
|
+
});
|
|
162
|
+
|
|
117
163
|
// src/NobleBleHandler.ts
|
|
118
164
|
var DEFAULT_NOBLE_FACTORY = () => {
|
|
119
165
|
const noble = require("@stoprocent/noble");
|
|
120
166
|
return noble;
|
|
121
167
|
};
|
|
122
|
-
var
|
|
123
|
-
var matchesPeripheral = (p,
|
|
124
|
-
if (!match) return false;
|
|
168
|
+
var BLE_NAME_MATCH_MAX_LENGTH = 64;
|
|
169
|
+
var matchesPeripheral = (p, profile, narrowTo) => {
|
|
125
170
|
const adv = p.advertisement ?? {};
|
|
126
171
|
const advertised = adv.serviceUuids ?? [];
|
|
127
|
-
if (
|
|
128
|
-
(uuid) =>
|
|
172
|
+
if (advertised.some(
|
|
173
|
+
(uuid) => typeof uuid === "string" && profile.isServiceUuid(uuid) && (!narrowTo || narrowTo.has(normalizeBleUuid(uuid)))
|
|
129
174
|
)) {
|
|
130
175
|
return true;
|
|
131
176
|
}
|
|
132
177
|
const name = adv.localName;
|
|
133
|
-
if (!
|
|
134
|
-
return
|
|
178
|
+
if (!profile.isName || typeof name !== "string" || !name) return false;
|
|
179
|
+
return profile.isName(name.slice(0, BLE_NAME_MATCH_MAX_LENGTH));
|
|
180
|
+
};
|
|
181
|
+
var requestedServiceUuids = (options) => {
|
|
182
|
+
const requested = options?.match ? options.match.serviceUuids : options?.serviceUuids;
|
|
183
|
+
if (!Array.isArray(requested)) return void 0;
|
|
184
|
+
const uuids = requested.filter((uuid) => typeof uuid === "string");
|
|
185
|
+
return uuids.length ? new Set(uuids.map(normalizeBleUuid)) : void 0;
|
|
135
186
|
};
|
|
136
187
|
var peripheralToInfo = (p) => {
|
|
137
188
|
const adv = p.advertisement ?? {};
|
|
@@ -193,6 +244,12 @@ var NobleBleHandler = class {
|
|
|
193
244
|
this._factory = options.nobleFactory ?? DEFAULT_NOBLE_FACTORY;
|
|
194
245
|
this._connectTimeoutMs = options.connectTimeoutMs ?? BLE_CONNECT_TIMEOUT_MS;
|
|
195
246
|
this._logger = options.logger;
|
|
247
|
+
this._vendors = new Map(Object.entries(options.vendors ?? DEFAULT_THIRD_PARTY_BLE_VENDORS));
|
|
248
|
+
}
|
|
249
|
+
_resolveVendor(vendor) {
|
|
250
|
+
const profile = typeof vendor === "string" ? this._vendors.get(vendor) : void 0;
|
|
251
|
+
if (typeof vendor !== "string" || !profile) throw new Error("Unsupported BLE vendor");
|
|
252
|
+
return { vendor, profile };
|
|
196
253
|
}
|
|
197
254
|
setNotificationListener(handler) {
|
|
198
255
|
this._onNotification = handler;
|
|
@@ -245,14 +302,15 @@ var NobleBleHandler = class {
|
|
|
245
302
|
* packet, and a Safe 7 ADV carries only its name (UUID is in the scan response).
|
|
246
303
|
*/
|
|
247
304
|
async scan(options) {
|
|
248
|
-
this.
|
|
305
|
+
const { vendor, profile } = this._resolveVendor(options?.vendor);
|
|
306
|
+
this._scanOwners.add(vendor);
|
|
249
307
|
try {
|
|
250
308
|
await this.init();
|
|
251
309
|
} catch (error) {
|
|
252
|
-
this._scanOwners.delete(
|
|
310
|
+
this._scanOwners.delete(vendor);
|
|
253
311
|
throw error;
|
|
254
312
|
}
|
|
255
|
-
if (!this._scanOwners.has(
|
|
313
|
+
if (!this._scanOwners.has(vendor)) return [];
|
|
256
314
|
try {
|
|
257
315
|
await this._setScanning(true);
|
|
258
316
|
} catch (error) {
|
|
@@ -261,7 +319,7 @@ var NobleBleHandler = class {
|
|
|
261
319
|
}
|
|
262
320
|
this._assertActive();
|
|
263
321
|
this._armIdleStop();
|
|
264
|
-
const devices = this._snapshot(options);
|
|
322
|
+
const devices = this._snapshot(vendor, profile, requestedServiceUuids(options));
|
|
265
323
|
if (devices.length === 0) {
|
|
266
324
|
this._log("warn", "scan.empty", {
|
|
267
325
|
raw: this._discovered.size,
|
|
@@ -275,9 +333,8 @@ var NobleBleHandler = class {
|
|
|
275
333
|
* In-range devices matching the caller, minus TTL-expired ones. `_discovered`
|
|
276
334
|
* is only a cache; a missing device can still be reached by `_directConnect`.
|
|
277
335
|
*/
|
|
278
|
-
_snapshot(
|
|
336
|
+
_snapshot(vendor, profile, narrowTo) {
|
|
279
337
|
const now = Date.now();
|
|
280
|
-
const match = options?.match ?? { serviceUuids: options?.serviceUuids };
|
|
281
338
|
const result = [];
|
|
282
339
|
for (const [id, peripheral] of this._discovered) {
|
|
283
340
|
if (now - (this._lastSeen.get(id) ?? 0) > THIRD_PARTY_BLE_DEVICE_TTL_MS) {
|
|
@@ -285,11 +342,11 @@ var NobleBleHandler = class {
|
|
|
285
342
|
this._lastSeen.delete(id);
|
|
286
343
|
continue;
|
|
287
344
|
}
|
|
288
|
-
if (!matchesPeripheral(peripheral,
|
|
345
|
+
if (!matchesPeripheral(peripheral, profile, narrowTo)) continue;
|
|
289
346
|
result.push(peripheralToInfo(peripheral));
|
|
290
347
|
}
|
|
291
348
|
for (const [id, entry] of this._connected) {
|
|
292
|
-
if (entry.vendor !==
|
|
349
|
+
if (entry.vendor !== vendor) continue;
|
|
293
350
|
if (result.some((info) => info.id === id)) continue;
|
|
294
351
|
result.push(peripheralToInfo(entry.peripheral));
|
|
295
352
|
}
|
|
@@ -406,7 +463,9 @@ var NobleBleHandler = class {
|
|
|
406
463
|
*/
|
|
407
464
|
getDevice(id) {
|
|
408
465
|
const p = this._discovered.get(id);
|
|
409
|
-
if (!p)
|
|
466
|
+
if (!p || ![...this._vendors.values()].some((profile) => matchesPeripheral(p, profile))) {
|
|
467
|
+
return null;
|
|
468
|
+
}
|
|
410
469
|
return peripheralToInfo(p);
|
|
411
470
|
}
|
|
412
471
|
/** Live RSSI (dBm) of a connected peripheral, else the cached scan-time value. */
|
|
@@ -523,10 +582,13 @@ var NobleBleHandler = class {
|
|
|
523
582
|
// `timed out` (unreachable) and `connection failed` (stale bond) differently.
|
|
524
583
|
async connect(id, options) {
|
|
525
584
|
if (!options || !options.vendor || ![options.serviceUuid, options.writeUuid, options.notifyUuid].every(
|
|
526
|
-
(uuid) => typeof uuid === "string" && /^[0-9a-f]{32}$/i.test(
|
|
585
|
+
(uuid) => typeof uuid === "string" && /^[0-9a-f]{32}$/i.test(normalizeBleUuid(uuid))
|
|
527
586
|
)) {
|
|
528
587
|
throw new Error("Invalid BLE GATT profile");
|
|
529
588
|
}
|
|
589
|
+
if (!this._resolveVendor(options.vendor).profile.acceptsConnect(options)) {
|
|
590
|
+
throw new Error(`BLE GATT profile not allowed for ${options.vendor}`);
|
|
591
|
+
}
|
|
530
592
|
this._assertActive();
|
|
531
593
|
const claim = { abandoned: false };
|
|
532
594
|
let abandon;
|
|
@@ -634,10 +696,10 @@ var NobleBleHandler = class {
|
|
|
634
696
|
[options.serviceUuid],
|
|
635
697
|
[options.writeUuid, options.notifyUuid]
|
|
636
698
|
);
|
|
637
|
-
const writeUuid =
|
|
638
|
-
const notifyUuid =
|
|
639
|
-
const writeChar = characteristics.find((c) =>
|
|
640
|
-
const notifyChar = characteristics.find((c) =>
|
|
699
|
+
const writeUuid = normalizeBleUuid(options.writeUuid);
|
|
700
|
+
const notifyUuid = normalizeBleUuid(options.notifyUuid);
|
|
701
|
+
const writeChar = characteristics.find((c) => normalizeBleUuid(c.uuid) === writeUuid);
|
|
702
|
+
const notifyChar = characteristics.find((c) => normalizeBleUuid(c.uuid) === notifyUuid);
|
|
641
703
|
if (!writeChar || !notifyChar) {
|
|
642
704
|
throw new Error(`BLE characteristics not found on device ${id}`);
|
|
643
705
|
}
|
|
@@ -948,6 +1010,7 @@ function initThirdPartyBleSupport(webContents, options = {}) {
|
|
|
948
1010
|
}
|
|
949
1011
|
// Annotate the CommonJS export names for ESM import in node:
|
|
950
1012
|
0 && (module.exports = {
|
|
1013
|
+
DEFAULT_THIRD_PARTY_BLE_VENDORS,
|
|
951
1014
|
NobleBleHandler,
|
|
952
1015
|
THIRD_PARTY_BLE_CHANNELS,
|
|
953
1016
|
THIRD_PARTY_BLE_DEVICE_TTL_MS,
|