react-native-ble-nitro 1.3.0 → 1.4.0

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.
Files changed (37) hide show
  1. package/README.md +32 -10
  2. package/android/src/main/java/com/margelo/nitro/co/zyke/ble/BleNitroBleManager.kt +6 -0
  3. package/ios/BleNitroBleManager.swift +84 -2
  4. package/lib/commonjs/index.d.ts +4 -188
  5. package/lib/commonjs/index.d.ts.map +1 -1
  6. package/lib/commonjs/index.js +6 -441
  7. package/lib/commonjs/index.js.map +1 -1
  8. package/lib/commonjs/manager.d.ts +204 -0
  9. package/lib/commonjs/manager.d.ts.map +1 -0
  10. package/lib/commonjs/manager.js +469 -0
  11. package/lib/commonjs/manager.js.map +1 -0
  12. package/lib/commonjs/specs/NativeBleNitro.nitro.d.ts +2 -0
  13. package/lib/commonjs/specs/NativeBleNitro.nitro.d.ts.map +1 -1
  14. package/lib/index.d.ts +4 -188
  15. package/lib/index.js +3 -436
  16. package/lib/manager.d.ts +203 -0
  17. package/lib/manager.js +455 -0
  18. package/lib/specs/NativeBleNitro.nitro.d.ts +2 -0
  19. package/nitrogen/generated/android/BleNitroOnLoad.cpp +2 -0
  20. package/nitrogen/generated/android/c++/JFunc_void_std__vector_BLEDevice_.hpp +102 -0
  21. package/nitrogen/generated/android/c++/JHybridNativeBleNitroSpec.cpp +6 -1
  22. package/nitrogen/generated/android/c++/JHybridNativeBleNitroSpec.hpp +1 -0
  23. package/nitrogen/generated/android/kotlin/com/margelo/nitro/co/zyke/ble/Func_void_std__vector_BLEDevice_.kt +81 -0
  24. package/nitrogen/generated/android/kotlin/com/margelo/nitro/co/zyke/ble/HybridNativeBleNitroSpec.kt +9 -0
  25. package/nitrogen/generated/ios/BleNitro-Swift-Cxx-Bridge.cpp +8 -0
  26. package/nitrogen/generated/ios/BleNitro-Swift-Cxx-Bridge.hpp +38 -16
  27. package/nitrogen/generated/ios/c++/HybridNativeBleNitroSpecSwift.hpp +15 -9
  28. package/nitrogen/generated/ios/swift/Func_void_std__vector_BLEDevice_.swift +47 -0
  29. package/nitrogen/generated/ios/swift/HybridNativeBleNitroSpec.swift +1 -0
  30. package/nitrogen/generated/ios/swift/HybridNativeBleNitroSpec_cxx.swift +22 -0
  31. package/nitrogen/generated/shared/c++/HybridNativeBleNitroSpec.cpp +1 -0
  32. package/nitrogen/generated/shared/c++/HybridNativeBleNitroSpec.hpp +6 -5
  33. package/package.json +9 -1
  34. package/src/__tests__/index.test.ts +24 -21
  35. package/src/index.ts +24 -600
  36. package/src/manager.ts +627 -0
  37. package/src/specs/NativeBleNitro.nitro.ts +4 -0
package/src/manager.ts ADDED
@@ -0,0 +1,627 @@
1
+ import BleNitroNative from './specs/NativeBleNitro';
2
+ import {
3
+ ScanFilter as NativeScanFilter,
4
+ BLEDevice as NativeBLEDevice,
5
+ BLEState as NativeBLEState,
6
+ ScanCallback as NativeScanCallback,
7
+ AndroidScanMode as NativeAndroidScanMode,
8
+ } from './specs/NativeBleNitro';
9
+
10
+ export type ByteArray = number[];
11
+
12
+ export interface ScanFilter {
13
+ serviceUUIDs?: string[];
14
+ rssiThreshold?: number;
15
+ allowDuplicates?: boolean;
16
+ androidScanMode?: AndroidScanMode;
17
+ }
18
+
19
+ export interface ManufacturerDataEntry {
20
+ id: string;
21
+ data: ByteArray;
22
+ }
23
+
24
+ export interface ManufacturerData {
25
+ companyIdentifiers: ManufacturerDataEntry[];
26
+ }
27
+
28
+ export interface BLEDevice {
29
+ id: string;
30
+ name: string;
31
+ rssi: number;
32
+ manufacturerData: ManufacturerData;
33
+ serviceUUIDs: string[];
34
+ isConnectable: boolean;
35
+ }
36
+
37
+ export type ScanCallback = (device: BLEDevice) => void;
38
+ export type RestoreStateCallback = (connectedPeripherals: BLEDevice[]) => void;
39
+ export type ConnectionCallback = (
40
+ success: boolean,
41
+ deviceId: string,
42
+ error: string
43
+ ) => void;
44
+ export type DisconnectEventCallback = (
45
+ deviceId: string,
46
+ interrupted: boolean,
47
+ error: string
48
+ ) => void;
49
+ export type OperationCallback = (success: boolean, error: string) => void;
50
+ export type CharacteristicUpdateCallback = (
51
+ characteristicId: string,
52
+ data: ByteArray
53
+ ) => void;
54
+
55
+ export type Subscription = {
56
+ remove: () => void;
57
+ };
58
+
59
+ export enum BLEState {
60
+ Unknown = 'Unknown',
61
+ Resetting = 'Resetting',
62
+ Unsupported = 'Unsupported',
63
+ Unauthorized = 'Unauthorized',
64
+ PoweredOff = 'PoweredOff',
65
+ PoweredOn = 'PoweredOn',
66
+ };
67
+
68
+ export enum AndroidScanMode {
69
+ LowLatency = 'LowLatency',
70
+ Balanced = 'Balanced',
71
+ LowPower = 'LowPower',
72
+ Opportunistic = 'Opportunistic',
73
+ }
74
+
75
+ export type BleNitroManagerOptions = {
76
+ onRestoreState?: RestoreStateCallback;
77
+ };
78
+
79
+ export function mapNativeBLEStateToBLEState(nativeState: NativeBLEState): BLEState {
80
+ const map = {
81
+ 0: BLEState.Unknown,
82
+ 1: BLEState.Resetting,
83
+ 2: BLEState.Unsupported,
84
+ 3: BLEState.Unauthorized,
85
+ 4: BLEState.PoweredOff,
86
+ 5: BLEState.PoweredOn,
87
+ };
88
+ return map[nativeState];
89
+ }
90
+
91
+ export function mapAndroidScanModeToNativeAndroidScanMode(scanMode: AndroidScanMode): NativeAndroidScanMode {
92
+ const map = {
93
+ LowLatency: NativeAndroidScanMode.LowLatency,
94
+ Balanced: NativeAndroidScanMode.Balanced,
95
+ LowPower: NativeAndroidScanMode.LowPower,
96
+ Opportunistic: NativeAndroidScanMode.Opportunistic,
97
+ }
98
+ return map[scanMode];
99
+ }
100
+
101
+ export function convertNativeBleDeviceToBleDevice(nativeBleDevice: NativeBLEDevice): BLEDevice {
102
+ return {
103
+ ...nativeBleDevice,
104
+ serviceUUIDs: BleNitroManager.normalizeGattUUIDs(nativeBleDevice.serviceUUIDs),
105
+ manufacturerData: {
106
+ companyIdentifiers: nativeBleDevice.manufacturerData.companyIdentifiers.map(entry => ({
107
+ id: entry.id,
108
+ data: arrayBufferToByteArray(entry.data)
109
+ }))
110
+ }
111
+ }
112
+ }
113
+
114
+ export function arrayBufferToByteArray(buffer: ArrayBuffer): ByteArray {
115
+ return Array.from(new Uint8Array(buffer));
116
+ }
117
+
118
+ export function byteArrayToArrayBuffer(data: ByteArray): ArrayBuffer {
119
+ return new Uint8Array(data).buffer;
120
+ }
121
+
122
+ export class BleNitroManager {
123
+ private _isScanning: boolean = false;
124
+ private _connectedDevices: { [deviceId: string]: boolean } = {};
125
+
126
+ private _restoreStateCallback: RestoreStateCallback | null = null;
127
+ private _restoredState: BLEDevice[] | null = null;
128
+
129
+ constructor(options?: BleNitroManagerOptions) {
130
+ this._restoreStateCallback = options?.onRestoreState || null;
131
+ BleNitroNative.setRestoreStateCallback((peripherals: NativeBLEDevice[]) => this.onNativeRestoreStateCallback(peripherals));
132
+ }
133
+
134
+ private onNativeRestoreStateCallback(peripherals: NativeBLEDevice[]) {
135
+ const bleDevices = peripherals.map((peripheral) => convertNativeBleDeviceToBleDevice(peripheral));
136
+ if (this._restoreStateCallback) {
137
+ this._restoreStateCallback(bleDevices);
138
+ } else {
139
+ this._restoredState = bleDevices;
140
+ }
141
+ }
142
+
143
+ public onRestoreState(callback: RestoreStateCallback) {
144
+ if (this._restoredState) {
145
+ callback(this._restoredState);
146
+ this._restoredState = null;
147
+ }
148
+ this._restoreStateCallback = callback;
149
+ }
150
+
151
+ /**
152
+ * Converts a 16- oder 32-Bit UUID to a 128-Bit UUID
153
+ *
154
+ * @param uuid 16-, 32- or 128-Bit UUID as string
155
+ * @returns Full 128-Bit UUID
156
+ */
157
+ public static normalizeGattUUID(uuid: string): string {
158
+ const cleanUuid = uuid.toLowerCase();
159
+
160
+ // 128-Bit UUID → normalisieren
161
+ if (cleanUuid.length === 36 && cleanUuid.includes("-")) {
162
+ return cleanUuid;
163
+ }
164
+
165
+ // GATT-Service UUIDs
166
+ // 16- oder 32-Bit UUID → 128-Bit UUID
167
+ const padded = cleanUuid.padStart(8, "0");
168
+ return `${padded}-0000-1000-8000-00805f9b34fb`;
169
+ }
170
+
171
+ public static normalizeGattUUIDs(uuids: string[]): string[] {
172
+ return uuids.map((uuid) => BleNitroManager.normalizeGattUUID(uuid));
173
+ }
174
+
175
+ /**
176
+ * Start scanning for Bluetooth devices
177
+ * @param filter Optional scan filter
178
+ * @param callback Callback function called when a device is found
179
+ * @returns Promise resolving to success state
180
+ */
181
+ public startScan(
182
+ filter: ScanFilter = {},
183
+ callback: ScanCallback,
184
+ onError?: (error: string) => void,
185
+ ): void {
186
+ if (this._isScanning) {
187
+ return;
188
+ }
189
+
190
+ // Create native scan filter with defaults
191
+ const nativeFilter: NativeScanFilter = {
192
+ serviceUUIDs: filter.serviceUUIDs || [],
193
+ rssiThreshold: filter.rssiThreshold ?? -100,
194
+ allowDuplicates: filter.allowDuplicates ?? false,
195
+ androidScanMode: mapAndroidScanModeToNativeAndroidScanMode(filter.androidScanMode ?? AndroidScanMode.Balanced),
196
+ };
197
+
198
+ // Create callback wrapper
199
+ const scanCallback: NativeScanCallback = (device: NativeBLEDevice | null, error: string | null) => {
200
+ if (error && !device) {
201
+ this._isScanning = false;
202
+ onError?.(error);
203
+ return;
204
+ }
205
+ device = device!; // eslint-disable-line @typescript-eslint/no-non-null-assertion
206
+ // Convert manufacturer data to Uint8Arrays
207
+ const convertedDevice: BLEDevice = convertNativeBleDeviceToBleDevice(device);
208
+ callback(convertedDevice);
209
+ };
210
+
211
+ // Start scan
212
+ BleNitroNative.startScan(nativeFilter, scanCallback);
213
+ this._isScanning = true;
214
+ }
215
+
216
+ /**
217
+ * Stop scanning for Bluetooth devices
218
+ * @returns Promise resolving to success state
219
+ */
220
+ public stopScan(): void {
221
+ if (!this._isScanning) {
222
+ return;
223
+ }
224
+
225
+ BleNitroNative.stopScan();
226
+ this._isScanning = false;
227
+ }
228
+
229
+ /**
230
+ * Check if currently scanning for devices
231
+ * @returns Promise resolving to scanning state
232
+ */
233
+ public isScanning(): boolean {
234
+ this._isScanning = BleNitroNative.isScanning();
235
+ return this._isScanning;
236
+ }
237
+
238
+ /**
239
+ * Get all currently connected devices
240
+ * @param services Optional list of service UUIDs to filter by
241
+ * @returns Array of connected devices
242
+ */
243
+ public getConnectedDevices(services?: string[]): BLEDevice[] {
244
+ const devices = BleNitroNative.getConnectedDevices(services || []);
245
+ // Normalize service UUIDs - manufacturer data already comes as ArrayBuffers
246
+ return devices.map(device => convertNativeBleDeviceToBleDevice(device));
247
+ }
248
+
249
+ /**
250
+ * Connect to a Bluetooth device
251
+ * @param deviceId ID of the device to connect to
252
+ * @param onDisconnect Optional callback for disconnect events
253
+ * @returns Promise resolving when connected
254
+ */
255
+ public connect(
256
+ deviceId: string,
257
+ onDisconnect?: DisconnectEventCallback
258
+ ): Promise<string> {
259
+ return new Promise((resolve, reject) => {
260
+ // Check if already connected
261
+ if (this._connectedDevices[deviceId]) {
262
+ resolve(deviceId);
263
+ return;
264
+ }
265
+
266
+ BleNitroNative.connect(
267
+ deviceId,
268
+ (success: boolean, connectedDeviceId: string, error: string) => {
269
+ if (success) {
270
+ this._connectedDevices[deviceId] = true;
271
+ resolve(connectedDeviceId);
272
+ } else {
273
+ reject(new Error(error));
274
+ }
275
+ },
276
+ onDisconnect ? (deviceId: string, interrupted: boolean, error: string) => {
277
+ // Remove from connected devices when disconnected
278
+ delete this._connectedDevices[deviceId];
279
+ onDisconnect(deviceId, interrupted, error);
280
+ } : undefined
281
+ );
282
+ });
283
+ }
284
+
285
+ /**
286
+ * Disconnect from a Bluetooth device
287
+ * @param deviceId ID of the device to disconnect from
288
+ * @returns Promise resolving when disconnected
289
+ */
290
+ public disconnect(deviceId: string): Promise<void> {
291
+ return new Promise((resolve, reject) => {
292
+ // Check if already disconnected
293
+ if (!this._connectedDevices[deviceId]) {
294
+ resolve();
295
+ return;
296
+ }
297
+
298
+ BleNitroNative.disconnect(
299
+ deviceId,
300
+ (success: boolean, error: string) => {
301
+ if (success) {
302
+ delete this._connectedDevices[deviceId];
303
+ resolve();
304
+ } else {
305
+ reject(new Error(error));
306
+ }
307
+ }
308
+ );
309
+ });
310
+ }
311
+
312
+ /**
313
+ * Check if connected to a device
314
+ * @param deviceId ID of the device to check
315
+ * @returns Promise resolving to connection state
316
+ */
317
+ public isConnected(deviceId: string): boolean {
318
+ return BleNitroNative.isConnected(deviceId);
319
+ }
320
+
321
+ /**
322
+ * Request a new MTU size
323
+ * @param deviceId ID of the device
324
+ * @param mtu New MTU size, min is 23, max is 517
325
+ * @returns On Android: new MTU size; on iOS: current MTU size as it is handled by iOS itself; on error: -1
326
+ */
327
+ public requestMTU(deviceId: string, mtu: number): number {
328
+ mtu = parseInt(mtu.toString(), 10);
329
+ const deviceMtu = BleNitroNative.requestMTU(deviceId, mtu);
330
+ return deviceMtu;
331
+ }
332
+
333
+ /**
334
+ * Discover services for a connected device
335
+ * @param deviceId ID of the device
336
+ * @returns Promise resolving when services are discovered
337
+ */
338
+ public discoverServices(deviceId: string): Promise<boolean> {
339
+ return new Promise((resolve, reject) => {
340
+ // Check if connected first
341
+ if (!this._connectedDevices[deviceId]) {
342
+ reject(new Error('Device not connected'));
343
+ return;
344
+ }
345
+
346
+ BleNitroNative.discoverServices(
347
+ deviceId,
348
+ (success: boolean, error: string) => {
349
+ if (success) {
350
+ resolve(true);
351
+ } else {
352
+ reject(new Error(error));
353
+ }
354
+ }
355
+ );
356
+ });
357
+ }
358
+
359
+ /**
360
+ * Get services for a connected device
361
+ * @param deviceId ID of the device
362
+ * @returns Promise resolving to array of service UUIDs
363
+ */
364
+ public getServices(deviceId: string): Promise<string[]> {
365
+ return new Promise(async (resolve, reject) => {
366
+ // Check if connected first
367
+ if (!this._connectedDevices[deviceId]) {
368
+ reject(new Error('Device not connected'));
369
+ return;
370
+ }
371
+
372
+ const success = await this.discoverServices(deviceId);
373
+ if (!success) {
374
+ reject(new Error('Failed to discover services'));
375
+ return;
376
+ }
377
+ const services = BleNitroNative.getServices(deviceId);
378
+ resolve(BleNitroManager.normalizeGattUUIDs(services));
379
+ });
380
+ }
381
+
382
+ /**
383
+ * Get characteristics for a service
384
+ * @param deviceId ID of the device
385
+ * @param serviceId ID of the service
386
+ * @returns Promise resolving to array of characteristic UUIDs
387
+ */
388
+ public getCharacteristics(
389
+ deviceId: string,
390
+ serviceId: string
391
+ ): string[] {
392
+ if (!this._connectedDevices[deviceId]) {
393
+ throw new Error('Device not connected');
394
+ }
395
+
396
+ const characteristics = BleNitroNative.getCharacteristics(
397
+ deviceId,
398
+ BleNitroManager.normalizeGattUUID(serviceId),
399
+ );
400
+ return BleNitroManager.normalizeGattUUIDs(characteristics);
401
+ }
402
+
403
+ /**
404
+ * Read a characteristic value
405
+ * @param deviceId ID of the device
406
+ * @param serviceId ID of the service
407
+ * @param characteristicId ID of the characteristic
408
+ * @returns Promise resolving to the characteristic data as ArrayBuffer
409
+ */
410
+ public readCharacteristic(
411
+ deviceId: string,
412
+ serviceId: string,
413
+ characteristicId: string
414
+ ): Promise<ByteArray> {
415
+ return new Promise((resolve, reject) => {
416
+ // Check if connected first
417
+ if (!this._connectedDevices[deviceId]) {
418
+ reject(new Error('Device not connected'));
419
+ return;
420
+ }
421
+
422
+ BleNitroNative.readCharacteristic(
423
+ deviceId,
424
+ BleNitroManager.normalizeGattUUID(serviceId),
425
+ BleNitroManager.normalizeGattUUID(characteristicId),
426
+ (success: boolean, data: ArrayBuffer, error: string) => {
427
+ if (success) {
428
+ resolve(arrayBufferToByteArray(data));
429
+ } else {
430
+ reject(new Error(error));
431
+ }
432
+ }
433
+ );
434
+ });
435
+ }
436
+
437
+ /**
438
+ * Write a value to a characteristic
439
+ * @param deviceId ID of the device
440
+ * @param serviceId ID of the service
441
+ * @param characteristicId ID of the characteristic
442
+ * @param data Data to write as ByteArray (number[])
443
+ * @param withResponse Whether to wait for response
444
+ * @returns Promise resolving when write is complete
445
+ */
446
+ public writeCharacteristic(
447
+ deviceId: string,
448
+ serviceId: string,
449
+ characteristicId: string,
450
+ data: ByteArray,
451
+ withResponse: boolean = true
452
+ ): Promise<boolean> {
453
+ return new Promise((resolve, reject) => {
454
+ // Check if connected first
455
+ if (!this._connectedDevices[deviceId]) {
456
+ reject(new Error('Device not connected'));
457
+ return;
458
+ }
459
+
460
+ BleNitroNative.writeCharacteristic(
461
+ deviceId,
462
+ BleNitroManager.normalizeGattUUID(serviceId),
463
+ BleNitroManager.normalizeGattUUID(characteristicId),
464
+ byteArrayToArrayBuffer(data),
465
+ withResponse,
466
+ (success: boolean, error: string) => {
467
+ if (success) {
468
+ resolve(true);
469
+ } else {
470
+ reject(new Error(error));
471
+ }
472
+ }
473
+ );
474
+ });
475
+ }
476
+
477
+ /**
478
+ * Subscribe to characteristic notifications
479
+ * @param deviceId ID of the device
480
+ * @param serviceId ID of the service
481
+ * @param characteristicId ID of the characteristic
482
+ * @param callback Callback function called when notification is received
483
+ * @returns Promise resolving when subscription is complete
484
+ */
485
+ public subscribeToCharacteristic(
486
+ deviceId: string,
487
+ serviceId: string,
488
+ characteristicId: string,
489
+ callback: CharacteristicUpdateCallback
490
+ ): Subscription {
491
+ // Check if connected first
492
+ if (!this._connectedDevices[deviceId]) {
493
+ throw new Error('Device not connected');
494
+ }
495
+
496
+ let _success = false;
497
+
498
+ BleNitroNative.subscribeToCharacteristic(
499
+ deviceId,
500
+ BleNitroManager.normalizeGattUUID(serviceId),
501
+ BleNitroManager.normalizeGattUUID(characteristicId),
502
+ (charId: string, data: ArrayBuffer) => {
503
+ callback(charId, arrayBufferToByteArray(data));
504
+ },
505
+ (success, error) => {
506
+ _success = success;
507
+ if (!success) {
508
+ throw new Error(error);
509
+ }
510
+ }
511
+ );
512
+
513
+ return {
514
+ remove: () => {
515
+ if (!_success) {
516
+ return;
517
+ }
518
+ this.unsubscribeFromCharacteristic(
519
+ deviceId,
520
+ serviceId,
521
+ characteristicId
522
+ ).catch(() => {});
523
+ }
524
+ };
525
+ }
526
+
527
+ /**
528
+ * Unsubscribe from characteristic notifications
529
+ * @param deviceId ID of the device
530
+ * @param serviceId ID of the service
531
+ * @param characteristicId ID of the characteristic
532
+ * @returns Promise resolving when unsubscription is complete
533
+ */
534
+ public unsubscribeFromCharacteristic(
535
+ deviceId: string,
536
+ serviceId: string,
537
+ characteristicId: string
538
+ ): Promise<void> {
539
+ return new Promise((resolve, reject) => {
540
+ // Check if connected first
541
+ if (!this._connectedDevices[deviceId]) {
542
+ reject(new Error('Device not connected'));
543
+ return;
544
+ }
545
+
546
+ BleNitroNative.unsubscribeFromCharacteristic(
547
+ deviceId,
548
+ BleNitroManager.normalizeGattUUID(serviceId),
549
+ BleNitroManager.normalizeGattUUID(characteristicId),
550
+ (success: boolean, error: string) => {
551
+ if (success) {
552
+ resolve();
553
+ } else {
554
+ reject(new Error(error));
555
+ }
556
+ }
557
+ );
558
+ });
559
+ }
560
+
561
+ /**
562
+ * Check if Bluetooth is enabled
563
+ * @returns Promise resolving to Bluetooth state
564
+ */
565
+ public isBluetoothEnabled(): boolean {
566
+ return this.state() === BLEState.PoweredOn;
567
+ }
568
+
569
+ /**
570
+ * Request to enable Bluetooth (Android only)
571
+ * @returns Promise resolving when Bluetooth is enabled
572
+ */
573
+ public requestBluetoothEnable(): Promise<boolean> {
574
+ return new Promise((resolve, reject) => {
575
+ BleNitroNative.requestBluetoothEnable(
576
+ (success: boolean, error: string) => {
577
+ if (success) {
578
+ resolve(true);
579
+ } else {
580
+ reject(new Error(error));
581
+ }
582
+ }
583
+ );
584
+ });
585
+ }
586
+
587
+ /**
588
+ * Get the current Bluetooth state
589
+ * @returns Promise resolving to Bluetooth state
590
+ * @see BLEState
591
+ */
592
+ public state(): BLEState {
593
+ return mapNativeBLEStateToBLEState(BleNitroNative.state());
594
+ }
595
+
596
+ /**
597
+ * Subscribe to Bluetooth state changes
598
+ * @param callback Callback function called when state changes
599
+ * @param emitInitial Whether to emit initial state callback
600
+ * @returns Promise resolving when subscription is complete
601
+ * @see BLEState
602
+ */
603
+ public subscribeToStateChange(callback: (state: BLEState) => void, emitInitial = false): Subscription {
604
+ if (emitInitial) {
605
+ const state = this.state();
606
+ callback(state);
607
+ }
608
+
609
+ BleNitroNative.subscribeToStateChange((nativeState: NativeBLEState) => {
610
+ callback(mapNativeBLEStateToBLEState(nativeState));
611
+ });
612
+
613
+ return {
614
+ remove: () => {
615
+ BleNitroNative.unsubscribeFromStateChange();
616
+ },
617
+ };
618
+ }
619
+
620
+ /**
621
+ * Open Bluetooth settings
622
+ * @returns Promise resolving when settings are opened
623
+ */
624
+ public openSettings(): Promise<void> {
625
+ return BleNitroNative.openSettings();
626
+ }
627
+ }
@@ -55,6 +55,7 @@ export type StateCallback = (state: BLEState) => void;
55
55
  export type BooleanCallback = (result: boolean) => void;
56
56
  export type StringArrayCallback = (result: string[]) => void;
57
57
  export type ReadCharacteristicCallback = (success: boolean, data: BLEValue, error: string) => void;
58
+ export type RestoreCallback = (restoredPeripherals: BLEDevice[]) => void;
58
59
 
59
60
  export type OperationResult = {
60
61
  success: boolean;
@@ -66,6 +67,9 @@ export type OperationResult = {
66
67
  * Defines the interface between TypeScript and native implementations
67
68
  */
68
69
  export interface NativeBleNitro extends HybridObject<{ ios: 'swift'; android: 'kotlin' }> {
70
+ // ios only
71
+ setRestoreStateCallback(callback: RestoreCallback): void;
72
+
69
73
  // Scanning operations
70
74
  startScan(filter: ScanFilter, callback: ScanCallback): void;
71
75
  stopScan(): boolean;