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