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