react-native-ble-nitro 1.5.0 → 1.7.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 (86) hide show
  1. package/README.md +56 -12
  2. package/android/src/main/java/com/margelo/nitro/co/zyke/ble/BleNitroBleManager.kt +12 -5
  3. package/android/src/main/java/com/margelo/nitro/co/zyke/ble/BleNitroBleManagerFactory.kt +21 -0
  4. package/ios/BleNitroBleManager.swift +37 -24
  5. package/ios/BleNitroBleManagerFactory.swift +19 -0
  6. package/lib/commonjs/index.d.ts +2 -5
  7. package/lib/commonjs/index.d.ts.map +1 -1
  8. package/lib/commonjs/index.js +7 -15
  9. package/lib/commonjs/index.js.map +1 -1
  10. package/lib/commonjs/manager.d.ts +43 -12
  11. package/lib/commonjs/manager.d.ts.map +1 -1
  12. package/lib/commonjs/manager.js +107 -43
  13. package/lib/commonjs/manager.js.map +1 -1
  14. package/lib/commonjs/singleton.d.ts +10 -0
  15. package/lib/commonjs/singleton.d.ts.map +1 -0
  16. package/lib/commonjs/singleton.js +20 -0
  17. package/lib/commonjs/singleton.js.map +1 -0
  18. package/lib/commonjs/specs/NativeBleNitro.d.ts +1 -1
  19. package/lib/commonjs/specs/NativeBleNitro.d.ts.map +1 -1
  20. package/lib/commonjs/specs/NativeBleNitro.js +1 -0
  21. package/lib/commonjs/specs/NativeBleNitro.js.map +1 -1
  22. package/lib/commonjs/specs/NativeBleNitro.nitro.d.ts +3 -1
  23. package/lib/commonjs/specs/NativeBleNitro.nitro.d.ts.map +1 -1
  24. package/lib/commonjs/specs/NativeBleNitro.nitro.js.map +1 -1
  25. package/lib/commonjs/specs/NativeBleNitroFactory.d.ts +5 -0
  26. package/lib/commonjs/specs/NativeBleNitroFactory.d.ts.map +1 -0
  27. package/lib/commonjs/specs/NativeBleNitroFactory.js +23 -0
  28. package/lib/commonjs/specs/NativeBleNitroFactory.js.map +1 -0
  29. package/lib/commonjs/specs/NativeBleNitroFactory.nitro.d.ts +9 -0
  30. package/lib/commonjs/specs/NativeBleNitroFactory.nitro.d.ts.map +1 -0
  31. package/lib/commonjs/specs/NativeBleNitroFactory.nitro.js +3 -0
  32. package/lib/commonjs/specs/NativeBleNitroFactory.nitro.js.map +1 -0
  33. package/lib/index.d.ts +2 -5
  34. package/lib/index.js +2 -11
  35. package/lib/manager.d.ts +43 -12
  36. package/lib/manager.js +100 -38
  37. package/lib/singleton.d.ts +9 -0
  38. package/lib/singleton.js +15 -0
  39. package/lib/specs/NativeBleNitro.d.ts +1 -1
  40. package/lib/specs/NativeBleNitro.js +1 -0
  41. package/lib/specs/NativeBleNitro.nitro.d.ts +3 -1
  42. package/lib/specs/NativeBleNitroFactory.d.ts +4 -0
  43. package/lib/specs/NativeBleNitroFactory.js +6 -0
  44. package/lib/specs/NativeBleNitroFactory.nitro.d.ts +8 -0
  45. package/lib/specs/NativeBleNitroFactory.nitro.js +1 -0
  46. package/nitro.json +4 -0
  47. package/nitrogen/generated/android/BleNitro+autolinking.cmake +2 -0
  48. package/nitrogen/generated/android/BleNitroOnLoad.cpp +11 -0
  49. package/nitrogen/generated/android/c++/JBLEDevice.hpp +6 -2
  50. package/nitrogen/generated/android/c++/JFunc_void_std__vector_BLEDevice_.hpp +12 -12
  51. package/nitrogen/generated/android/c++/JHybridNativeBleNitroFactorySpec.cpp +71 -0
  52. package/nitrogen/generated/android/c++/JHybridNativeBleNitroFactorySpec.hpp +64 -0
  53. package/nitrogen/generated/android/c++/JHybridNativeBleNitroSpec.cpp +14 -6
  54. package/nitrogen/generated/android/c++/JHybridNativeBleNitroSpec.hpp +3 -2
  55. package/nitrogen/generated/android/kotlin/com/margelo/nitro/co/zyke/ble/BLEDevice.kt +4 -1
  56. package/nitrogen/generated/android/kotlin/com/margelo/nitro/co/zyke/ble/Func_void_std__vector_BLEDevice_.kt +9 -9
  57. package/nitrogen/generated/android/kotlin/com/margelo/nitro/co/zyke/ble/HybridNativeBleNitroFactorySpec.kt +57 -0
  58. package/nitrogen/generated/android/kotlin/com/margelo/nitro/co/zyke/ble/HybridNativeBleNitroSpec.kt +8 -4
  59. package/nitrogen/generated/ios/BleNitro-Swift-Cxx-Bridge.cpp +17 -0
  60. package/nitrogen/generated/ios/BleNitro-Swift-Cxx-Bridge.hpp +53 -9
  61. package/nitrogen/generated/ios/BleNitro-Swift-Cxx-Umbrella.hpp +5 -0
  62. package/nitrogen/generated/ios/BleNitroAutolinking.mm +8 -0
  63. package/nitrogen/generated/ios/BleNitroAutolinking.swift +15 -0
  64. package/nitrogen/generated/ios/c++/HybridNativeBleNitroFactorySpecSwift.cpp +11 -0
  65. package/nitrogen/generated/ios/c++/HybridNativeBleNitroFactorySpecSwift.hpp +94 -0
  66. package/nitrogen/generated/ios/c++/HybridNativeBleNitroSpecSwift.hpp +11 -5
  67. package/nitrogen/generated/ios/swift/BLEDevice.swift +13 -2
  68. package/nitrogen/generated/ios/swift/Func_void_std__vector_BLEDevice_.swift +5 -5
  69. package/nitrogen/generated/ios/swift/HybridNativeBleNitroFactorySpec.swift +49 -0
  70. package/nitrogen/generated/ios/swift/HybridNativeBleNitroFactorySpec_cxx.swift +149 -0
  71. package/nitrogen/generated/ios/swift/HybridNativeBleNitroSpec.swift +2 -2
  72. package/nitrogen/generated/ios/swift/HybridNativeBleNitroSpec_cxx.swift +24 -3
  73. package/nitrogen/generated/shared/c++/BLEDevice.hpp +6 -2
  74. package/nitrogen/generated/shared/c++/HybridNativeBleNitroFactorySpec.cpp +21 -0
  75. package/nitrogen/generated/shared/c++/HybridNativeBleNitroFactorySpec.hpp +71 -0
  76. package/nitrogen/generated/shared/c++/HybridNativeBleNitroSpec.cpp +2 -0
  77. package/nitrogen/generated/shared/c++/HybridNativeBleNitroSpec.hpp +5 -4
  78. package/package.json +9 -1
  79. package/src/__tests__/index.test.ts +53 -43
  80. package/src/index.ts +2 -13
  81. package/src/manager.ts +107 -38
  82. package/src/singleton.ts +17 -0
  83. package/src/specs/NativeBleNitro.nitro.ts +3 -1
  84. package/src/specs/NativeBleNitro.ts +2 -1
  85. package/src/specs/NativeBleNitroFactory.nitro.ts +6 -0
  86. package/src/specs/NativeBleNitroFactory.ts +9 -0
package/lib/index.js CHANGED
@@ -1,11 +1,2 @@
1
- import { BleNitroManager } from "./manager";
2
- export { BLEState, AndroidScanMode, } from "./manager";
3
- let _instance;
4
- export class BleNitro extends BleNitroManager {
5
- static instance() {
6
- if (!_instance) {
7
- _instance = new BleNitro();
8
- }
9
- return _instance;
10
- }
11
- }
1
+ export { BLEState, AndroidScanMode, BleNitroManager, } from "./manager";
2
+ export { BleNitro } from './singleton';
package/lib/manager.d.ts CHANGED
@@ -20,6 +20,7 @@ export interface BLEDevice {
20
20
  manufacturerData: ManufacturerData;
21
21
  serviceUUIDs: string[];
22
22
  isConnectable: boolean;
23
+ isConnected: boolean;
23
24
  }
24
25
  export type ScanCallback = (device: BLEDevice) => void;
25
26
  export type RestoreStateCallback = (connectedPeripherals: BLEDevice[]) => void;
@@ -45,6 +46,7 @@ export declare enum AndroidScanMode {
45
46
  Opportunistic = "Opportunistic"
46
47
  }
47
48
  export type BleNitroManagerOptions = {
49
+ restoreIdentifier?: string;
48
50
  onRestoredState?: RestoreStateCallback;
49
51
  };
50
52
  export declare function mapNativeBLEStateToBLEState(nativeState: NativeBLEState): BLEState;
@@ -57,8 +59,15 @@ export declare class BleNitroManager {
57
59
  private _connectedDevices;
58
60
  private _restoredStateCallback;
59
61
  private _restoredState;
62
+ private _restoreStateIdentifier;
63
+ private Instance;
60
64
  constructor(options?: BleNitroManagerOptions);
61
65
  private onNativeRestoreStateCallback;
66
+ /**
67
+ *
68
+ * Registers callback and returns restored peripheral state in it. Not working from 1.7.x upwards for singleton implementation!
69
+ * @deprecated This method is deprecated and will be removed in 2.x, use onRestoredState option in BleNitroManageroptions instead!
70
+ */
62
71
  onRestoredState(callback: RestoreStateCallback): void;
63
72
  /**
64
73
  * Converts a 16- oder 32-Bit UUID to a 128-Bit UUID
@@ -72,17 +81,17 @@ export declare class BleNitroManager {
72
81
  * Start scanning for Bluetooth devices
73
82
  * @param filter Optional scan filter
74
83
  * @param callback Callback function called when a device is found
75
- * @returns Promise resolving to success state
84
+ * @returns void
76
85
  */
77
86
  startScan(filter: ScanFilter | undefined, callback: ScanCallback, onError?: (error: string) => void): void;
78
87
  /**
79
88
  * Stop scanning for Bluetooth devices
80
- * @returns Promise resolving to success state
89
+ * @returns void
81
90
  */
82
91
  stopScan(): void;
83
92
  /**
84
93
  * Check if currently scanning for devices
85
- * @returns Promise resolving to scanning state
94
+ * @returns Boolean indicating if currently scanning
86
95
  */
87
96
  isScanning(): boolean;
88
97
  /**
@@ -95,9 +104,20 @@ export declare class BleNitroManager {
95
104
  * Connect to a Bluetooth device
96
105
  * @param deviceId ID of the device to connect to
97
106
  * @param onDisconnect Optional callback for disconnect events
98
- * @returns Promise resolving when connected
107
+ * @returns Promise resolving deviceId when connected
99
108
  */
100
- connect(deviceId: string, onDisconnect?: DisconnectEventCallback): Promise<string>;
109
+ connect(deviceId: string, onDisconnect?: DisconnectEventCallback, autoConnectAndroid?: boolean): Promise<string>;
110
+ /**
111
+ * Scans for a device and connects to it
112
+ * @param deviceId ID of the device to connect to
113
+ * @param scanTimeout Optional timeout for the scan in milliseconds (default: 5000ms)
114
+ * @returns Promise resolving deviceId when connected
115
+ */
116
+ findAndConnect(deviceId: string, options?: {
117
+ scanTimeout?: number;
118
+ autoConnectAndroid?: boolean;
119
+ onDisconnect?: DisconnectEventCallback;
120
+ }): Promise<string>;
101
121
  /**
102
122
  * Disconnect from a Bluetooth device
103
123
  * @param deviceId ID of the device to disconnect from
@@ -107,7 +127,7 @@ export declare class BleNitroManager {
107
127
  /**
108
128
  * Check if connected to a device
109
129
  * @param deviceId ID of the device to check
110
- * @returns Promise resolving to connection state
130
+ * @returns Boolean indicating if device is connected
111
131
  */
112
132
  isConnected(deviceId: string): boolean;
113
133
  /**
@@ -139,15 +159,26 @@ export declare class BleNitroManager {
139
159
  * Get characteristics for a service
140
160
  * @param deviceId ID of the device
141
161
  * @param serviceId ID of the service
142
- * @returns Promise resolving to array of characteristic UUIDs
162
+ * @returns array of characteristic UUIDs
143
163
  */
144
164
  getCharacteristics(deviceId: string, serviceId: string): string[];
165
+ /**
166
+ * Get services and characteristics for a connected device
167
+ * @param deviceId ID of the device
168
+ * @returns Promise resolving to array of service and characteristic UUIDs
169
+ * @see getServices
170
+ * @see getCharacteristics
171
+ */
172
+ getServicesWithCharacteristics(deviceId: string): Promise<{
173
+ uuid: string;
174
+ characteristics: string[];
175
+ }[]>;
145
176
  /**
146
177
  * Read a characteristic value
147
178
  * @param deviceId ID of the device
148
179
  * @param serviceId ID of the service
149
180
  * @param characteristicId ID of the characteristic
150
- * @returns Promise resolving to the characteristic data as ArrayBuffer
181
+ * @returns Promise resolving to the characteristic data as ByteArray
151
182
  */
152
183
  readCharacteristic(deviceId: string, serviceId: string, characteristicId: string): Promise<ByteArray>;
153
184
  /**
@@ -166,7 +197,7 @@ export declare class BleNitroManager {
166
197
  * @param serviceId ID of the service
167
198
  * @param characteristicId ID of the characteristic
168
199
  * @param callback Callback function called when notification is received
169
- * @returns Promise resolving when subscription is complete
200
+ * @returns Subscription
170
201
  */
171
202
  subscribeToCharacteristic(deviceId: string, serviceId: string, characteristicId: string, callback: CharacteristicUpdateCallback): Subscription;
172
203
  /**
@@ -179,7 +210,7 @@ export declare class BleNitroManager {
179
210
  unsubscribeFromCharacteristic(deviceId: string, serviceId: string, characteristicId: string): Promise<void>;
180
211
  /**
181
212
  * Check if Bluetooth is enabled
182
- * @returns Promise resolving to Bluetooth state
213
+ * @returns returns Boolean according to Bluetooth state
183
214
  */
184
215
  isBluetoothEnabled(): boolean;
185
216
  /**
@@ -189,7 +220,7 @@ export declare class BleNitroManager {
189
220
  requestBluetoothEnable(): Promise<boolean>;
190
221
  /**
191
222
  * Get the current Bluetooth state
192
- * @returns Promise resolving to Bluetooth state
223
+ * @returns Bluetooth state
193
224
  * @see BLEState
194
225
  */
195
226
  state(): BLEState;
@@ -197,7 +228,7 @@ export declare class BleNitroManager {
197
228
  * Subscribe to Bluetooth state changes
198
229
  * @param callback Callback function called when state changes
199
230
  * @param emitInitial Whether to emit initial state callback
200
- * @returns Promise resolving when subscription is complete
231
+ * @returns Subscription
201
232
  * @see BLEState
202
233
  */
203
234
  subscribeToStateChange(callback: (state: BLEState) => void, emitInitial?: boolean): Subscription;
package/lib/manager.js CHANGED
@@ -1,4 +1,4 @@
1
- import BleNitroNative from './specs/NativeBleNitro';
1
+ import BleNitroNativeFactory from './specs/NativeBleNitroFactory';
2
2
  import { AndroidScanMode as NativeAndroidScanMode, } from './specs/NativeBleNitro';
3
3
  export var BLEState;
4
4
  (function (BLEState) {
@@ -59,13 +59,19 @@ export class BleNitroManager {
59
59
  constructor(options) {
60
60
  this._isScanning = false;
61
61
  this._connectedDevices = {};
62
- this._restoredStateCallback = null;
63
62
  this._restoredState = null;
64
- this._restoredStateCallback = options?.onRestoredState || null;
65
- BleNitroNative.setRestoreStateCallback((peripherals) => this.onNativeRestoreStateCallback(peripherals));
63
+ this._restoreStateIdentifier = null;
64
+ this._restoredStateCallback = options?.onRestoredState ?? null;
65
+ this._restoreStateIdentifier = options?.restoreIdentifier ?? null;
66
+ this.Instance = BleNitroNativeFactory.create(options?.restoreIdentifier, (peripherals) => this.onNativeRestoreStateCallback(peripherals));
66
67
  }
67
68
  onNativeRestoreStateCallback(peripherals) {
69
+ if (!this._restoreStateIdentifier)
70
+ return;
68
71
  const bleDevices = peripherals.map((peripheral) => convertNativeBleDeviceToBleDevice(peripheral));
72
+ bleDevices.forEach((device) => {
73
+ this._connectedDevices[device.id] = device.isConnected;
74
+ });
69
75
  if (this._restoredStateCallback) {
70
76
  this._restoredStateCallback(bleDevices);
71
77
  }
@@ -73,7 +79,14 @@ export class BleNitroManager {
73
79
  this._restoredState = bleDevices;
74
80
  }
75
81
  }
82
+ /**
83
+ *
84
+ * Registers callback and returns restored peripheral state in it. Not working from 1.7.x upwards for singleton implementation!
85
+ * @deprecated This method is deprecated and will be removed in 2.x, use onRestoredState option in BleNitroManageroptions instead!
86
+ */
76
87
  onRestoredState(callback) {
88
+ if (!this._restoreStateIdentifier)
89
+ return;
77
90
  if (this._restoredState) {
78
91
  callback(this._restoredState);
79
92
  this._restoredState = null;
@@ -104,7 +117,7 @@ export class BleNitroManager {
104
117
  * Start scanning for Bluetooth devices
105
118
  * @param filter Optional scan filter
106
119
  * @param callback Callback function called when a device is found
107
- * @returns Promise resolving to success state
120
+ * @returns void
108
121
  */
109
122
  startScan(filter = {}, callback, onError) {
110
123
  if (this._isScanning) {
@@ -130,26 +143,26 @@ export class BleNitroManager {
130
143
  callback(convertedDevice);
131
144
  };
132
145
  // Start scan
133
- BleNitroNative.startScan(nativeFilter, scanCallback);
146
+ this.Instance.startScan(nativeFilter, scanCallback);
134
147
  this._isScanning = true;
135
148
  }
136
149
  /**
137
150
  * Stop scanning for Bluetooth devices
138
- * @returns Promise resolving to success state
151
+ * @returns void
139
152
  */
140
153
  stopScan() {
141
154
  if (!this._isScanning) {
142
155
  return;
143
156
  }
144
- BleNitroNative.stopScan();
157
+ this.Instance.stopScan();
145
158
  this._isScanning = false;
146
159
  }
147
160
  /**
148
161
  * Check if currently scanning for devices
149
- * @returns Promise resolving to scanning state
162
+ * @returns Boolean indicating if currently scanning
150
163
  */
151
164
  isScanning() {
152
- this._isScanning = BleNitroNative.isScanning();
165
+ this._isScanning = this.Instance.isScanning();
153
166
  return this._isScanning;
154
167
  }
155
168
  /**
@@ -158,7 +171,7 @@ export class BleNitroManager {
158
171
  * @returns Array of connected devices
159
172
  */
160
173
  getConnectedDevices(services) {
161
- const devices = BleNitroNative.getConnectedDevices(services || []);
174
+ const devices = this.Instance.getConnectedDevices(services || []);
162
175
  // Normalize service UUIDs - manufacturer data already comes as ArrayBuffers
163
176
  return devices.map(device => convertNativeBleDeviceToBleDevice(device));
164
177
  }
@@ -166,16 +179,16 @@ export class BleNitroManager {
166
179
  * Connect to a Bluetooth device
167
180
  * @param deviceId ID of the device to connect to
168
181
  * @param onDisconnect Optional callback for disconnect events
169
- * @returns Promise resolving when connected
182
+ * @returns Promise resolving deviceId when connected
170
183
  */
171
- connect(deviceId, onDisconnect) {
184
+ connect(deviceId, onDisconnect, autoConnectAndroid) {
172
185
  return new Promise((resolve, reject) => {
173
186
  // Check if already connected
174
187
  if (this._connectedDevices[deviceId]) {
175
188
  resolve(deviceId);
176
189
  return;
177
190
  }
178
- BleNitroNative.connect(deviceId, (success, connectedDeviceId, error) => {
191
+ this.Instance.connect(deviceId, (success, connectedDeviceId, error) => {
179
192
  if (success) {
180
193
  this._connectedDevices[deviceId] = true;
181
194
  resolve(connectedDeviceId);
@@ -187,7 +200,39 @@ export class BleNitroManager {
187
200
  // Remove from connected devices when disconnected
188
201
  delete this._connectedDevices[deviceId];
189
202
  onDisconnect(deviceId, interrupted, error);
190
- } : undefined);
203
+ } : undefined, autoConnectAndroid ?? false);
204
+ });
205
+ }
206
+ /**
207
+ * Scans for a device and connects to it
208
+ * @param deviceId ID of the device to connect to
209
+ * @param scanTimeout Optional timeout for the scan in milliseconds (default: 5000ms)
210
+ * @returns Promise resolving deviceId when connected
211
+ */
212
+ findAndConnect(deviceId, options) {
213
+ const isConnected = this.isConnected(deviceId);
214
+ if (isConnected) {
215
+ return Promise.resolve(deviceId);
216
+ }
217
+ if (this._isScanning) {
218
+ this.stopScan();
219
+ }
220
+ return new Promise((resolve, reject) => {
221
+ const timeoutScan = setTimeout(() => {
222
+ this.stopScan();
223
+ reject(new Error('Scan timed out'));
224
+ }, options?.scanTimeout ?? 5000);
225
+ this.startScan(undefined, (device) => {
226
+ if (device.id === deviceId) {
227
+ this.stopScan();
228
+ clearTimeout(timeoutScan);
229
+ this.connect(deviceId, options?.onDisconnect, options?.autoConnectAndroid).then(async (connectedDeviceId) => {
230
+ resolve(connectedDeviceId);
231
+ }).catch((error) => {
232
+ reject(error);
233
+ });
234
+ }
235
+ });
191
236
  });
192
237
  }
193
238
  /**
@@ -202,7 +247,7 @@ export class BleNitroManager {
202
247
  resolve();
203
248
  return;
204
249
  }
205
- BleNitroNative.disconnect(deviceId, (success, error) => {
250
+ this.Instance.disconnect(deviceId, (success, error) => {
206
251
  if (success) {
207
252
  delete this._connectedDevices[deviceId];
208
253
  resolve();
@@ -216,10 +261,10 @@ export class BleNitroManager {
216
261
  /**
217
262
  * Check if connected to a device
218
263
  * @param deviceId ID of the device to check
219
- * @returns Promise resolving to connection state
264
+ * @returns Boolean indicating if device is connected
220
265
  */
221
266
  isConnected(deviceId) {
222
- return BleNitroNative.isConnected(deviceId);
267
+ return this.Instance.isConnected(deviceId);
223
268
  }
224
269
  /**
225
270
  * Request a new MTU size
@@ -229,7 +274,7 @@ export class BleNitroManager {
229
274
  */
230
275
  requestMTU(deviceId, mtu) {
231
276
  mtu = parseInt(mtu.toString(), 10);
232
- const deviceMtu = BleNitroNative.requestMTU(deviceId, mtu);
277
+ const deviceMtu = this.Instance.requestMTU(deviceId, mtu);
233
278
  return deviceMtu;
234
279
  }
235
280
  /**
@@ -244,7 +289,7 @@ export class BleNitroManager {
244
289
  reject(new Error('Device not connected'));
245
290
  return;
246
291
  }
247
- BleNitroNative.readRSSI(deviceId, (success, rssi, error) => {
292
+ this.Instance.readRSSI(deviceId, (success, rssi, error) => {
248
293
  if (success) {
249
294
  resolve(rssi);
250
295
  }
@@ -266,7 +311,7 @@ export class BleNitroManager {
266
311
  reject(new Error('Device not connected'));
267
312
  return;
268
313
  }
269
- BleNitroNative.discoverServices(deviceId, (success, error) => {
314
+ this.Instance.discoverServices(deviceId, (success, error) => {
270
315
  if (success) {
271
316
  resolve(true);
272
317
  }
@@ -293,7 +338,7 @@ export class BleNitroManager {
293
338
  reject(new Error('Failed to discover services'));
294
339
  return;
295
340
  }
296
- const services = BleNitroNative.getServices(deviceId);
341
+ const services = this.Instance.getServices(deviceId);
297
342
  resolve(BleNitroManager.normalizeGattUUIDs(services));
298
343
  });
299
344
  }
@@ -301,21 +346,38 @@ export class BleNitroManager {
301
346
  * Get characteristics for a service
302
347
  * @param deviceId ID of the device
303
348
  * @param serviceId ID of the service
304
- * @returns Promise resolving to array of characteristic UUIDs
349
+ * @returns array of characteristic UUIDs
305
350
  */
306
351
  getCharacteristics(deviceId, serviceId) {
307
352
  if (!this._connectedDevices[deviceId]) {
308
353
  throw new Error('Device not connected');
309
354
  }
310
- const characteristics = BleNitroNative.getCharacteristics(deviceId, BleNitroManager.normalizeGattUUID(serviceId));
355
+ const characteristics = this.Instance.getCharacteristics(deviceId, BleNitroManager.normalizeGattUUID(serviceId));
311
356
  return BleNitroManager.normalizeGattUUIDs(characteristics);
312
357
  }
358
+ /**
359
+ * Get services and characteristics for a connected device
360
+ * @param deviceId ID of the device
361
+ * @returns Promise resolving to array of service and characteristic UUIDs
362
+ * @see getServices
363
+ * @see getCharacteristics
364
+ */
365
+ async getServicesWithCharacteristics(deviceId) {
366
+ await this.discoverServices(deviceId);
367
+ const services = await this.getServices(deviceId);
368
+ return services.map((service) => {
369
+ return {
370
+ uuid: service,
371
+ characteristics: this.getCharacteristics(deviceId, service),
372
+ };
373
+ });
374
+ }
313
375
  /**
314
376
  * Read a characteristic value
315
377
  * @param deviceId ID of the device
316
378
  * @param serviceId ID of the service
317
379
  * @param characteristicId ID of the characteristic
318
- * @returns Promise resolving to the characteristic data as ArrayBuffer
380
+ * @returns Promise resolving to the characteristic data as ByteArray
319
381
  */
320
382
  readCharacteristic(deviceId, serviceId, characteristicId) {
321
383
  return new Promise((resolve, reject) => {
@@ -324,7 +386,7 @@ export class BleNitroManager {
324
386
  reject(new Error('Device not connected'));
325
387
  return;
326
388
  }
327
- BleNitroNative.readCharacteristic(deviceId, BleNitroManager.normalizeGattUUID(serviceId), BleNitroManager.normalizeGattUUID(characteristicId), (success, data, error) => {
389
+ this.Instance.readCharacteristic(deviceId, BleNitroManager.normalizeGattUUID(serviceId), BleNitroManager.normalizeGattUUID(characteristicId), (success, data, error) => {
328
390
  if (success) {
329
391
  resolve(arrayBufferToByteArray(data));
330
392
  }
@@ -350,7 +412,7 @@ export class BleNitroManager {
350
412
  reject(new Error('Device not connected'));
351
413
  return;
352
414
  }
353
- BleNitroNative.writeCharacteristic(deviceId, BleNitroManager.normalizeGattUUID(serviceId), BleNitroManager.normalizeGattUUID(characteristicId), byteArrayToArrayBuffer(data), withResponse, (success, responseData, error) => {
415
+ this.Instance.writeCharacteristic(deviceId, BleNitroManager.normalizeGattUUID(serviceId), BleNitroManager.normalizeGattUUID(characteristicId), byteArrayToArrayBuffer(data), withResponse, (success, responseData, error) => {
354
416
  if (success) {
355
417
  // Convert ArrayBuffer response to ByteArray
356
418
  const responseByteArray = arrayBufferToByteArray(responseData);
@@ -368,7 +430,7 @@ export class BleNitroManager {
368
430
  * @param serviceId ID of the service
369
431
  * @param characteristicId ID of the characteristic
370
432
  * @param callback Callback function called when notification is received
371
- * @returns Promise resolving when subscription is complete
433
+ * @returns Subscription
372
434
  */
373
435
  subscribeToCharacteristic(deviceId, serviceId, characteristicId, callback) {
374
436
  // Check if connected first
@@ -376,7 +438,7 @@ export class BleNitroManager {
376
438
  throw new Error('Device not connected');
377
439
  }
378
440
  let _success = false;
379
- BleNitroNative.subscribeToCharacteristic(deviceId, BleNitroManager.normalizeGattUUID(serviceId), BleNitroManager.normalizeGattUUID(characteristicId), (charId, data) => {
441
+ this.Instance.subscribeToCharacteristic(deviceId, BleNitroManager.normalizeGattUUID(serviceId), BleNitroManager.normalizeGattUUID(characteristicId), (charId, data) => {
380
442
  callback(charId, arrayBufferToByteArray(data));
381
443
  }, (success, error) => {
382
444
  _success = success;
@@ -407,7 +469,7 @@ export class BleNitroManager {
407
469
  reject(new Error('Device not connected'));
408
470
  return;
409
471
  }
410
- BleNitroNative.unsubscribeFromCharacteristic(deviceId, BleNitroManager.normalizeGattUUID(serviceId), BleNitroManager.normalizeGattUUID(characteristicId), (success, error) => {
472
+ this.Instance.unsubscribeFromCharacteristic(deviceId, BleNitroManager.normalizeGattUUID(serviceId), BleNitroManager.normalizeGattUUID(characteristicId), (success, error) => {
411
473
  if (success) {
412
474
  resolve();
413
475
  }
@@ -419,7 +481,7 @@ export class BleNitroManager {
419
481
  }
420
482
  /**
421
483
  * Check if Bluetooth is enabled
422
- * @returns Promise resolving to Bluetooth state
484
+ * @returns returns Boolean according to Bluetooth state
423
485
  */
424
486
  isBluetoothEnabled() {
425
487
  return this.state() === BLEState.PoweredOn;
@@ -430,7 +492,7 @@ export class BleNitroManager {
430
492
  */
431
493
  requestBluetoothEnable() {
432
494
  return new Promise((resolve, reject) => {
433
- BleNitroNative.requestBluetoothEnable((success, error) => {
495
+ this.Instance.requestBluetoothEnable((success, error) => {
434
496
  if (success) {
435
497
  resolve(true);
436
498
  }
@@ -442,17 +504,17 @@ export class BleNitroManager {
442
504
  }
443
505
  /**
444
506
  * Get the current Bluetooth state
445
- * @returns Promise resolving to Bluetooth state
507
+ * @returns Bluetooth state
446
508
  * @see BLEState
447
509
  */
448
510
  state() {
449
- return mapNativeBLEStateToBLEState(BleNitroNative.state());
511
+ return mapNativeBLEStateToBLEState(this.Instance.state());
450
512
  }
451
513
  /**
452
514
  * Subscribe to Bluetooth state changes
453
515
  * @param callback Callback function called when state changes
454
516
  * @param emitInitial Whether to emit initial state callback
455
- * @returns Promise resolving when subscription is complete
517
+ * @returns Subscription
456
518
  * @see BLEState
457
519
  */
458
520
  subscribeToStateChange(callback, emitInitial = false) {
@@ -460,12 +522,12 @@ export class BleNitroManager {
460
522
  const state = this.state();
461
523
  callback(state);
462
524
  }
463
- BleNitroNative.subscribeToStateChange((nativeState) => {
525
+ this.Instance.subscribeToStateChange((nativeState) => {
464
526
  callback(mapNativeBLEStateToBLEState(nativeState));
465
527
  });
466
528
  return {
467
529
  remove: () => {
468
- BleNitroNative.unsubscribeFromStateChange();
530
+ this.Instance.unsubscribeFromStateChange();
469
531
  },
470
532
  };
471
533
  }
@@ -474,6 +536,6 @@ export class BleNitroManager {
474
536
  * @returns Promise resolving when settings are opened
475
537
  */
476
538
  openSettings() {
477
- return BleNitroNative.openSettings();
539
+ return this.Instance.openSettings();
478
540
  }
479
541
  }
@@ -0,0 +1,9 @@
1
+ import { BleNitroManager } from "./manager";
2
+ export declare class BleNitro extends BleNitroManager {
3
+ /**
4
+ * Get a singleton instance of BleNitro, will create one if it does not exist.
5
+ * Singleton implementation does not allow to use state restoration on iOS!
6
+ * @returns {BleNitroManager} An instance of BleNitro
7
+ */
8
+ static instance(): BleNitroManager;
9
+ }
@@ -0,0 +1,15 @@
1
+ import { BleNitroManager } from "./manager";
2
+ let _instance;
3
+ export class BleNitro extends BleNitroManager {
4
+ /**
5
+ * Get a singleton instance of BleNitro, will create one if it does not exist.
6
+ * Singleton implementation does not allow to use state restoration on iOS!
7
+ * @returns {BleNitroManager} An instance of BleNitro
8
+ */
9
+ static instance() {
10
+ if (!_instance) {
11
+ _instance = new BleNitro();
12
+ }
13
+ return _instance;
14
+ }
15
+ }
@@ -1,4 +1,4 @@
1
- import type { NativeBleNitro } from './NativeBleNitro.nitro';
1
+ import { NativeBleNitro } from './NativeBleNitro.nitro';
2
2
  declare const NativeBleNitroImpl: NativeBleNitro;
3
3
  export default NativeBleNitroImpl;
4
4
  export * from './NativeBleNitro.nitro';
@@ -1,5 +1,6 @@
1
1
  import { NitroModules } from 'react-native-nitro-modules';
2
2
  // Export the native implementation
3
3
  const NativeBleNitroImpl = NitroModules.createHybridObject('NativeBleNitro');
4
+ // export default NativeBleNitroImpl;
4
5
  export default NativeBleNitroImpl;
5
6
  export * from './NativeBleNitro.nitro';
@@ -22,6 +22,7 @@ export interface BLEDevice {
22
22
  manufacturerData: ManufacturerData;
23
23
  serviceUUIDs: string[];
24
24
  isConnectable: boolean;
25
+ isConnected: boolean;
25
26
  }
26
27
  export declare enum AndroidScanMode {
27
28
  LowLatency = 0,
@@ -60,12 +61,13 @@ export interface NativeBleNitro extends HybridObject<{
60
61
  ios: 'swift';
61
62
  android: 'kotlin';
62
63
  }> {
64
+ restoreStateIdentifier?: string;
63
65
  setRestoreStateCallback(callback: RestoreCallback): void;
64
66
  startScan(filter: ScanFilter, callback: ScanCallback): void;
65
67
  stopScan(): boolean;
66
68
  isScanning(): boolean;
67
69
  getConnectedDevices(services: string[]): BLEDevice[];
68
- connect(deviceId: string, callback: ConnectionCallback, disconnectCallback?: DisconnectionEventCallback): void;
70
+ connect(deviceId: string, callback: ConnectionCallback, disconnectCallback?: DisconnectionEventCallback, autoConnectAndroid?: boolean): void;
69
71
  disconnect(deviceId: string, callback: OperationCallback): void;
70
72
  isConnected(deviceId: string): boolean;
71
73
  requestMTU(deviceId: string, mtu: number): number;
@@ -0,0 +1,4 @@
1
+ import { NativeBleNitroFactory } from './NativeBleNitroFactory.nitro';
2
+ declare const NativeBleNitroFactoryImpl: NativeBleNitroFactory;
3
+ export default NativeBleNitroFactoryImpl;
4
+ export * from './NativeBleNitro.nitro';
@@ -0,0 +1,6 @@
1
+ import { NitroModules } from 'react-native-nitro-modules';
2
+ // Export the native implementation
3
+ const NativeBleNitroFactoryImpl = NitroModules.createHybridObject('NativeBleNitroFactory');
4
+ // export default NativeBleNitroImpl;
5
+ export default NativeBleNitroFactoryImpl;
6
+ export * from './NativeBleNitro.nitro';
@@ -0,0 +1,8 @@
1
+ import { HybridObject } from "react-native-nitro-modules";
2
+ import { BLEDevice, NativeBleNitro } from "./NativeBleNitro.nitro";
3
+ export interface NativeBleNitroFactory extends HybridObject<{
4
+ ios: 'swift';
5
+ android: 'kotlin';
6
+ }> {
7
+ create(nativeRestoreStateIdentifier?: string, restoreStateCallback?: (peripherals: BLEDevice[]) => void): NativeBleNitro;
8
+ }
@@ -0,0 +1 @@
1
+ export {};
package/nitro.json CHANGED
@@ -12,6 +12,10 @@
12
12
  "NativeBleNitro": {
13
13
  "swift": "BleNitroBleManager",
14
14
  "kotlin": "BleNitroBleManager"
15
+ },
16
+ "NativeBleNitroFactory": {
17
+ "swift": "BleNitroBleManagerFactory",
18
+ "kotlin": "BleNitroBleManagerFactory"
15
19
  }
16
20
  },
17
21
  "ignorePaths": [
@@ -28,8 +28,10 @@ target_sources(
28
28
  ../nitrogen/generated/android/BleNitroOnLoad.cpp
29
29
  # Shared Nitrogen C++ sources
30
30
  ../nitrogen/generated/shared/c++/HybridNativeBleNitroSpec.cpp
31
+ ../nitrogen/generated/shared/c++/HybridNativeBleNitroFactorySpec.cpp
31
32
  # Android-specific Nitrogen C++ sources
32
33
  ../nitrogen/generated/android/c++/JHybridNativeBleNitroSpec.cpp
34
+ ../nitrogen/generated/android/c++/JHybridNativeBleNitroFactorySpec.cpp
33
35
  )
34
36
 
35
37
  # Define a flag to check if we are building properly
@@ -25,6 +25,7 @@
25
25
  #include "JFunc_void_bool_std__shared_ptr_ArrayBuffer__std__string.hpp"
26
26
  #include "JFunc_void_std__string_std__shared_ptr_ArrayBuffer_.hpp"
27
27
  #include "JFunc_void_BLEState.hpp"
28
+ #include "JHybridNativeBleNitroFactorySpec.hpp"
28
29
  #include <NitroModules/DefaultConstructableObject.hpp>
29
30
 
30
31
  namespace margelo::nitro::co::zyke::ble {
@@ -46,6 +47,7 @@ int initialize(JavaVM* vm) {
46
47
  margelo::nitro::co::zyke::ble::JFunc_void_bool_std__shared_ptr_ArrayBuffer__std__string_cxx::registerNatives();
47
48
  margelo::nitro::co::zyke::ble::JFunc_void_std__string_std__shared_ptr_ArrayBuffer__cxx::registerNatives();
48
49
  margelo::nitro::co::zyke::ble::JFunc_void_BLEState_cxx::registerNatives();
50
+ margelo::nitro::co::zyke::ble::JHybridNativeBleNitroFactorySpec::registerNatives();
49
51
 
50
52
  // Register Nitro Hybrid Objects
51
53
  HybridObjectRegistry::registerHybridObjectConstructor(
@@ -57,6 +59,15 @@ int initialize(JavaVM* vm) {
57
59
  return globalRef->cthis()->shared();
58
60
  }
59
61
  );
62
+ HybridObjectRegistry::registerHybridObjectConstructor(
63
+ "NativeBleNitroFactory",
64
+ []() -> std::shared_ptr<HybridObject> {
65
+ static DefaultConstructableObject<JHybridNativeBleNitroFactorySpec::javaobject> object("com/margelo/nitro/co/zyke/ble/BleNitroBleManagerFactory");
66
+ auto instance = object.create();
67
+ auto globalRef = jni::make_global(instance);
68
+ return globalRef->cthis()->shared();
69
+ }
70
+ );
60
71
  });
61
72
  }
62
73