react-native-ble-nitro 1.1.0 → 1.3.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 +87 -20
- package/android/CMakeLists.txt +32 -0
- package/android/build.gradle +140 -0
- package/android/fix-prefab.gradle +51 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/cpp/cpp-adapter.cpp +6 -0
- package/android/src/main/java/com/margelo/nitro/co/zyke/ble/BleNitroBleManager.kt +899 -0
- package/android/src/main/java/com/margelo/nitro/co/zyke/ble/BleNitroPackage.kt +38 -0
- package/ios/BleNitroBleManager.swift +56 -17
- package/ios/BlePeripheralDelegate.swift +36 -8
- package/lib/commonjs/index.d.ts +22 -9
- package/lib/commonjs/index.d.ts.map +1 -1
- package/lib/commonjs/index.js +63 -12
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/specs/NativeBleNitro.nitro.d.ts +14 -5
- package/lib/commonjs/specs/NativeBleNitro.nitro.d.ts.map +1 -1
- package/lib/commonjs/specs/NativeBleNitro.nitro.js +8 -1
- package/lib/commonjs/specs/NativeBleNitro.nitro.js.map +1 -1
- package/lib/index.d.ts +22 -9
- package/lib/index.js +61 -10
- package/lib/specs/NativeBleNitro.nitro.d.ts +14 -5
- package/lib/specs/NativeBleNitro.nitro.js +7 -0
- package/nitrogen/generated/android/BleNitroOnLoad.cpp +6 -6
- package/nitrogen/generated/android/c++/JAndroidScanMode.hpp +65 -0
- package/nitrogen/generated/android/c++/JBLEDevice.hpp +3 -0
- package/nitrogen/generated/android/c++/JFunc_void_bool_std__shared_ptr_ArrayBuffer__std__string.hpp +78 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__optional_BLEDevice__std__optional_std__string_.hpp +86 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__string_std__shared_ptr_ArrayBuffer_.hpp +78 -0
- package/nitrogen/generated/android/c++/JHybridNativeBleNitroSpec.cpp +29 -20
- package/nitrogen/generated/android/c++/JHybridNativeBleNitroSpec.hpp +5 -4
- package/nitrogen/generated/android/c++/JManufacturerData.hpp +3 -0
- package/nitrogen/generated/android/c++/JManufacturerDataEntry.hpp +7 -15
- package/nitrogen/generated/android/c++/JScanFilter.hpp +8 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/co/zyke/ble/AndroidScanMode.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/co/zyke/ble/{Func_void_bool_std__vector_double__std__string.kt → Func_void_bool_std__shared_ptr_ArrayBuffer__std__string.kt} +12 -12
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/co/zyke/ble/{Func_void_BLEDevice.kt → Func_void_std__optional_BLEDevice__std__optional_std__string_.kt} +14 -14
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/co/zyke/ble/{Func_void_std__string_std__vector_double_.kt → Func_void_std__string_std__shared_ptr_ArrayBuffer_.kt} +12 -12
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/co/zyke/ble/HybridNativeBleNitroSpec.kt +12 -8
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/co/zyke/ble/ManufacturerDataEntry.kt +1 -1
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/co/zyke/ble/ScanFilter.kt +4 -1
- package/nitrogen/generated/ios/BleNitro-Swift-Cxx-Bridge.cpp +15 -15
- package/nitrogen/generated/ios/BleNitro-Swift-Cxx-Bridge.hpp +69 -56
- package/nitrogen/generated/ios/BleNitro-Swift-Cxx-Umbrella.hpp +6 -0
- package/nitrogen/generated/ios/c++/HybridNativeBleNitroSpecSwift.hpp +23 -6
- package/nitrogen/generated/ios/swift/AndroidScanMode.swift +48 -0
- package/nitrogen/generated/ios/swift/{Func_void_bool_std__vector_double__std__string.swift → Func_void_bool_std__shared_ptr_ArrayBuffer__std__string.swift} +11 -11
- package/nitrogen/generated/ios/swift/Func_void_std__optional_BLEDevice__std__optional_std__string_.swift +59 -0
- package/nitrogen/generated/ios/swift/{Func_void_std__string_std__vector_double_.swift → Func_void_std__string_std__shared_ptr_ArrayBuffer_.swift} +11 -11
- package/nitrogen/generated/ios/swift/HybridNativeBleNitroSpec.swift +5 -4
- package/nitrogen/generated/ios/swift/HybridNativeBleNitroSpec_cxx.swift +41 -29
- package/nitrogen/generated/ios/swift/ManufacturerDataEntry.swift +5 -17
- package/nitrogen/generated/ios/swift/ScanFilter.swift +13 -2
- package/nitrogen/generated/shared/c++/AndroidScanMode.hpp +64 -0
- package/nitrogen/generated/shared/c++/HybridNativeBleNitroSpec.cpp +1 -0
- package/nitrogen/generated/shared/c++/HybridNativeBleNitroSpec.hpp +10 -6
- package/nitrogen/generated/shared/c++/ManufacturerDataEntry.hpp +8 -7
- package/nitrogen/generated/shared/c++/ScanFilter.hpp +9 -3
- package/package.json +1 -1
- package/plugin/build/index.d.ts +2 -0
- package/plugin/build/index.js +2 -0
- package/plugin/build/withBleNitro.d.ts +5 -1
- package/plugin/build/withBleNitro.js +18 -7
- package/react-native.config.js +10 -2
- package/src/__tests__/index.test.ts +48 -13
- package/src/index.ts +74 -16
- package/src/specs/NativeBleNitro.nitro.ts +17 -5
- package/nitrogen/generated/android/c++/JFunc_void_BLEDevice.hpp +0 -82
- package/nitrogen/generated/android/c++/JFunc_void_bool_std__vector_double__std__string.hpp +0 -86
- package/nitrogen/generated/android/c++/JFunc_void_std__string_std__vector_double_.hpp +0 -86
- package/nitrogen/generated/ios/swift/Func_void_BLEDevice.swift +0 -47
|
@@ -8,6 +8,7 @@ jest.mock('../specs/NativeBleNitro', () => ({
|
|
|
8
8
|
connect: jest.fn(),
|
|
9
9
|
disconnect: jest.fn(),
|
|
10
10
|
isConnected: jest.fn(),
|
|
11
|
+
requestMTU: jest.fn(),
|
|
11
12
|
discoverServices: jest.fn(),
|
|
12
13
|
getServices: jest.fn(),
|
|
13
14
|
getCharacteristics: jest.fn(),
|
|
@@ -15,12 +16,27 @@ jest.mock('../specs/NativeBleNitro', () => ({
|
|
|
15
16
|
writeCharacteristic: jest.fn(),
|
|
16
17
|
subscribeToCharacteristic: jest.fn(),
|
|
17
18
|
unsubscribeFromCharacteristic: jest.fn(),
|
|
18
|
-
|
|
19
|
+
getConnectedDevices: jest.fn(),
|
|
19
20
|
requestBluetoothEnable: jest.fn(),
|
|
20
21
|
state: jest.fn(),
|
|
21
22
|
subscribeToStateChange: jest.fn(),
|
|
23
|
+
unsubscribeFromStateChange: jest.fn(),
|
|
24
|
+
openSettings: jest.fn(),
|
|
25
|
+
},
|
|
26
|
+
BLEState: {
|
|
27
|
+
Unknown: 0,
|
|
28
|
+
Resetting: 1,
|
|
29
|
+
Unsupported: 2,
|
|
30
|
+
Unauthorized: 3,
|
|
31
|
+
PoweredOff: 4,
|
|
32
|
+
PoweredOn: 5
|
|
33
|
+
},
|
|
34
|
+
AndroidScanMode: {
|
|
35
|
+
LowLatency: 0,
|
|
36
|
+
Balanced: 1,
|
|
37
|
+
LowPower: 2,
|
|
38
|
+
Opportunistic: 3
|
|
22
39
|
},
|
|
23
|
-
BLEState: { PoweredOn: 5, PoweredOff: 4 },
|
|
24
40
|
}));
|
|
25
41
|
|
|
26
42
|
import { ble as BleNitro } from '../index';
|
|
@@ -46,15 +62,23 @@ describe('BleNitro', () => {
|
|
|
46
62
|
serviceUUIDs: ['test'],
|
|
47
63
|
rssiThreshold: -100,
|
|
48
64
|
allowDuplicates: false,
|
|
65
|
+
androidScanMode: 1, // AndroidScanMode.Balanced (default)
|
|
49
66
|
},
|
|
50
67
|
expect.any(Function)
|
|
51
68
|
);
|
|
52
69
|
});
|
|
53
70
|
|
|
54
|
-
test('stopScan calls native and resolves', () => {
|
|
55
|
-
|
|
56
|
-
|
|
71
|
+
test('stopScan calls native and resolves', async () => {
|
|
72
|
+
// First start a scan to set _isScanning to true
|
|
73
|
+
mockNative.startScan.mockImplementation((filter, callback) => { // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
74
|
+
// Just start scanning
|
|
57
75
|
});
|
|
76
|
+
|
|
77
|
+
const scanCallback = jest.fn();
|
|
78
|
+
await BleNitro.startScan({ serviceUUIDs: ['test'] }, scanCallback);
|
|
79
|
+
|
|
80
|
+
// Now stop the scan
|
|
81
|
+
mockNative.stopScan.mockImplementation(() => true);
|
|
58
82
|
|
|
59
83
|
BleNitro.stopScan();
|
|
60
84
|
|
|
@@ -91,8 +115,9 @@ describe('BleNitro', () => {
|
|
|
91
115
|
});
|
|
92
116
|
|
|
93
117
|
test('writeCharacteristic requires connected device', async () => {
|
|
118
|
+
const data = new Uint8Array([1, 2, 3]);
|
|
94
119
|
await expect(
|
|
95
|
-
BleNitro.writeCharacteristic('device', 'service', 'char',
|
|
120
|
+
BleNitro.writeCharacteristic('device', 'service', 'char', data.buffer)
|
|
96
121
|
).rejects.toThrow('Device not connected');
|
|
97
122
|
});
|
|
98
123
|
|
|
@@ -104,8 +129,9 @@ describe('BleNitro', () => {
|
|
|
104
129
|
await BleNitro.connect('device');
|
|
105
130
|
|
|
106
131
|
// Then read
|
|
107
|
-
mockNative.readCharacteristic.mockImplementation((_device: string, _service: string, _char: string, callback: (success: boolean, data:
|
|
108
|
-
|
|
132
|
+
mockNative.readCharacteristic.mockImplementation((_device: string, _service: string, _char: string, callback: (success: boolean, data: ArrayBuffer, error: string) => void) => {
|
|
133
|
+
const testData = new Uint8Array([85]);
|
|
134
|
+
callback(true, testData.buffer, ''); // Battery level 85%
|
|
109
135
|
});
|
|
110
136
|
|
|
111
137
|
const result = await BleNitro.readCharacteristic('device', 'service', 'char');
|
|
@@ -117,7 +143,11 @@ describe('BleNitro', () => {
|
|
|
117
143
|
'0000char-0000-1000-8000-00805f9b34fb', // 'char' padded to 8 chars
|
|
118
144
|
expect.any(Function)
|
|
119
145
|
);
|
|
120
|
-
|
|
146
|
+
|
|
147
|
+
// Result should be ArrayBuffer
|
|
148
|
+
expect(result).toBeInstanceOf(ArrayBuffer);
|
|
149
|
+
const resultArray = new Uint8Array(result);
|
|
150
|
+
expect(resultArray[0]).toBe(85);
|
|
121
151
|
});
|
|
122
152
|
|
|
123
153
|
test('disconnect calls native', async () => {
|
|
@@ -146,17 +176,22 @@ describe('BleNitro', () => {
|
|
|
146
176
|
await BleNitro.connect('device');
|
|
147
177
|
|
|
148
178
|
// Mock subscription
|
|
149
|
-
mockNative.subscribeToCharacteristic.mockImplementation((_device: string, _service: string, _char: string, updateCallback: (charId: string, data:
|
|
179
|
+
mockNative.subscribeToCharacteristic.mockImplementation((_device: string, _service: string, _char: string, updateCallback: (charId: string, data: ArrayBuffer) => void, resultCallback: (success: boolean, error: string) => void) => {
|
|
150
180
|
resultCallback(true, '');
|
|
151
181
|
// Simulate notification
|
|
152
|
-
|
|
182
|
+
const testData = new Uint8Array([1, 2, 3]);
|
|
183
|
+
updateCallback('char-id', testData.buffer);
|
|
153
184
|
});
|
|
154
185
|
|
|
155
186
|
const notificationCallback = jest.fn();
|
|
156
|
-
BleNitro.subscribeToCharacteristic('device', 'service', 'char', notificationCallback);
|
|
187
|
+
const subscription = BleNitro.subscribeToCharacteristic('device', 'service', 'char', notificationCallback);
|
|
157
188
|
|
|
158
189
|
expect(mockNative.subscribeToCharacteristic).toHaveBeenCalled();
|
|
159
|
-
expect(notificationCallback).toHaveBeenCalledWith('char-id',
|
|
190
|
+
expect(notificationCallback).toHaveBeenCalledWith('char-id', expect.any(ArrayBuffer));
|
|
191
|
+
|
|
192
|
+
// Verify subscription object
|
|
193
|
+
expect(subscription).toHaveProperty('remove');
|
|
194
|
+
expect(typeof subscription.remove).toBe('function');
|
|
160
195
|
});
|
|
161
196
|
|
|
162
197
|
test('connect with disconnect event callback', async () => {
|
package/src/index.ts
CHANGED
|
@@ -3,17 +3,21 @@ import {
|
|
|
3
3
|
ScanFilter as NativeScanFilter,
|
|
4
4
|
BLEDevice as NativeBLEDevice,
|
|
5
5
|
BLEState as NativeBLEState,
|
|
6
|
+
ScanCallback as NativeScanCallback,
|
|
7
|
+
AndroidScanMode as NativeAndroidScanMode,
|
|
6
8
|
} from './specs/NativeBleNitro';
|
|
7
9
|
|
|
10
|
+
|
|
8
11
|
export interface ScanFilter {
|
|
9
12
|
serviceUUIDs?: string[];
|
|
10
13
|
rssiThreshold?: number;
|
|
11
14
|
allowDuplicates?: boolean;
|
|
15
|
+
androidScanMode?: AndroidScanMode;
|
|
12
16
|
}
|
|
13
17
|
|
|
14
18
|
export interface ManufacturerDataEntry {
|
|
15
19
|
id: string;
|
|
16
|
-
data:
|
|
20
|
+
data: ArrayBuffer;
|
|
17
21
|
}
|
|
18
22
|
|
|
19
23
|
export interface ManufacturerData {
|
|
@@ -43,7 +47,7 @@ export type DisconnectEventCallback = (
|
|
|
43
47
|
export type OperationCallback = (success: boolean, error: string) => void;
|
|
44
48
|
export type CharacteristicUpdateCallback = (
|
|
45
49
|
characteristicId: string,
|
|
46
|
-
data:
|
|
50
|
+
data: ArrayBuffer
|
|
47
51
|
) => void;
|
|
48
52
|
|
|
49
53
|
export type Subscription = {
|
|
@@ -59,6 +63,13 @@ export enum BLEState {
|
|
|
59
63
|
PoweredOn = 'PoweredOn',
|
|
60
64
|
};
|
|
61
65
|
|
|
66
|
+
export enum AndroidScanMode {
|
|
67
|
+
LowLatency = 'LowLatency',
|
|
68
|
+
Balanced = 'Balanced',
|
|
69
|
+
LowPower = 'LowPower',
|
|
70
|
+
Opportunistic = 'Opportunistic',
|
|
71
|
+
}
|
|
72
|
+
|
|
62
73
|
function mapNativeBLEStateToBLEState(nativeState: NativeBLEState): BLEState {
|
|
63
74
|
const map = {
|
|
64
75
|
0: BLEState.Unknown,
|
|
@@ -71,6 +82,17 @@ function mapNativeBLEStateToBLEState(nativeState: NativeBLEState): BLEState {
|
|
|
71
82
|
return map[nativeState];
|
|
72
83
|
}
|
|
73
84
|
|
|
85
|
+
function mapAndroidScanModeToNativeAndroidScanMode(scanMode: AndroidScanMode): NativeAndroidScanMode {
|
|
86
|
+
const map = {
|
|
87
|
+
LowLatency: NativeAndroidScanMode.LowLatency,
|
|
88
|
+
Balanced: NativeAndroidScanMode.Balanced,
|
|
89
|
+
LowPower: NativeAndroidScanMode.LowPower,
|
|
90
|
+
Opportunistic: NativeAndroidScanMode.Opportunistic,
|
|
91
|
+
}
|
|
92
|
+
return map[scanMode];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
|
|
74
96
|
let _instance: BleNitro;
|
|
75
97
|
|
|
76
98
|
export class BleNitro {
|
|
@@ -116,7 +138,8 @@ export class BleNitro {
|
|
|
116
138
|
*/
|
|
117
139
|
public startScan(
|
|
118
140
|
filter: ScanFilter = {},
|
|
119
|
-
callback: ScanCallback
|
|
141
|
+
callback: ScanCallback,
|
|
142
|
+
onError?: (error: string) => void,
|
|
120
143
|
): void {
|
|
121
144
|
if (this._isScanning) {
|
|
122
145
|
return;
|
|
@@ -127,12 +150,29 @@ export class BleNitro {
|
|
|
127
150
|
serviceUUIDs: filter.serviceUUIDs || [],
|
|
128
151
|
rssiThreshold: filter.rssiThreshold ?? -100,
|
|
129
152
|
allowDuplicates: filter.allowDuplicates ?? false,
|
|
153
|
+
androidScanMode: mapAndroidScanModeToNativeAndroidScanMode(filter.androidScanMode ?? AndroidScanMode.Balanced),
|
|
130
154
|
};
|
|
131
155
|
|
|
132
156
|
// Create callback wrapper
|
|
133
|
-
const scanCallback = (device: NativeBLEDevice) => {
|
|
134
|
-
|
|
135
|
-
|
|
157
|
+
const scanCallback: NativeScanCallback = (device: NativeBLEDevice | null, error: string | null) => {
|
|
158
|
+
if (error && !device) {
|
|
159
|
+
this._isScanning = false;
|
|
160
|
+
onError?.(error);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
device = device!; // eslint-disable-line @typescript-eslint/no-non-null-assertion
|
|
164
|
+
// Convert manufacturer data to Uint8Arrays
|
|
165
|
+
const convertedDevice: BLEDevice = {
|
|
166
|
+
...device,
|
|
167
|
+
serviceUUIDs: BleNitro.normalizeGattUUIDs(device.serviceUUIDs),
|
|
168
|
+
manufacturerData: {
|
|
169
|
+
companyIdentifiers: device.manufacturerData.companyIdentifiers.map(entry => ({
|
|
170
|
+
id: entry.id,
|
|
171
|
+
data: entry.data
|
|
172
|
+
}))
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
callback(convertedDevice);
|
|
136
176
|
};
|
|
137
177
|
|
|
138
178
|
// Start scan
|
|
@@ -150,6 +190,7 @@ export class BleNitro {
|
|
|
150
190
|
}
|
|
151
191
|
|
|
152
192
|
BleNitroNative.stopScan();
|
|
193
|
+
this._isScanning = false;
|
|
153
194
|
}
|
|
154
195
|
|
|
155
196
|
/**
|
|
@@ -168,10 +209,16 @@ export class BleNitro {
|
|
|
168
209
|
*/
|
|
169
210
|
public getConnectedDevices(services?: string[]): BLEDevice[] {
|
|
170
211
|
const devices = BleNitroNative.getConnectedDevices(services || []);
|
|
171
|
-
// Normalize service UUIDs
|
|
212
|
+
// Normalize service UUIDs - manufacturer data already comes as ArrayBuffers
|
|
172
213
|
return devices.map(device => ({
|
|
173
214
|
...device,
|
|
174
|
-
serviceUUIDs: BleNitro.normalizeGattUUIDs(device.serviceUUIDs)
|
|
215
|
+
serviceUUIDs: BleNitro.normalizeGattUUIDs(device.serviceUUIDs),
|
|
216
|
+
manufacturerData: {
|
|
217
|
+
companyIdentifiers: device.manufacturerData.companyIdentifiers.map(entry => ({
|
|
218
|
+
id: entry.id,
|
|
219
|
+
data: entry.data
|
|
220
|
+
}))
|
|
221
|
+
}
|
|
175
222
|
}));
|
|
176
223
|
}
|
|
177
224
|
|
|
@@ -247,6 +294,18 @@ export class BleNitro {
|
|
|
247
294
|
return BleNitroNative.isConnected(deviceId);
|
|
248
295
|
}
|
|
249
296
|
|
|
297
|
+
/**
|
|
298
|
+
* Request a new MTU size
|
|
299
|
+
* @param deviceId ID of the device
|
|
300
|
+
* @param mtu New MTU size, min is 23, max is 517
|
|
301
|
+
* @returns On Android: new MTU size; on iOS: current MTU size as it is handled by iOS itself; on error: -1
|
|
302
|
+
*/
|
|
303
|
+
public requestMTU(deviceId: string, mtu: number): number {
|
|
304
|
+
mtu = parseInt(mtu.toString(), 10);
|
|
305
|
+
const deviceMtu = BleNitroNative.requestMTU(deviceId, mtu);
|
|
306
|
+
return deviceMtu;
|
|
307
|
+
}
|
|
308
|
+
|
|
250
309
|
/**
|
|
251
310
|
* Discover services for a connected device
|
|
252
311
|
* @param deviceId ID of the device
|
|
@@ -322,13 +381,13 @@ export class BleNitro {
|
|
|
322
381
|
* @param deviceId ID of the device
|
|
323
382
|
* @param serviceId ID of the service
|
|
324
383
|
* @param characteristicId ID of the characteristic
|
|
325
|
-
* @returns Promise resolving to the characteristic data as
|
|
384
|
+
* @returns Promise resolving to the characteristic data as ArrayBuffer
|
|
326
385
|
*/
|
|
327
386
|
public readCharacteristic(
|
|
328
387
|
deviceId: string,
|
|
329
388
|
serviceId: string,
|
|
330
389
|
characteristicId: string
|
|
331
|
-
): Promise<
|
|
390
|
+
): Promise<ArrayBuffer> {
|
|
332
391
|
return new Promise((resolve, reject) => {
|
|
333
392
|
// Check if connected first
|
|
334
393
|
if (!this._connectedDevices[deviceId]) {
|
|
@@ -340,7 +399,7 @@ export class BleNitro {
|
|
|
340
399
|
deviceId,
|
|
341
400
|
BleNitro.normalizeGattUUID(serviceId),
|
|
342
401
|
BleNitro.normalizeGattUUID(characteristicId),
|
|
343
|
-
(success: boolean, data:
|
|
402
|
+
(success: boolean, data: ArrayBuffer, error: string) => {
|
|
344
403
|
if (success) {
|
|
345
404
|
resolve(data);
|
|
346
405
|
} else {
|
|
@@ -356,7 +415,7 @@ export class BleNitro {
|
|
|
356
415
|
* @param deviceId ID of the device
|
|
357
416
|
* @param serviceId ID of the service
|
|
358
417
|
* @param characteristicId ID of the characteristic
|
|
359
|
-
* @param data Data to write as
|
|
418
|
+
* @param data Data to write as ArrayBuffer
|
|
360
419
|
* @param withResponse Whether to wait for response
|
|
361
420
|
* @returns Promise resolving when write is complete
|
|
362
421
|
*/
|
|
@@ -364,7 +423,7 @@ export class BleNitro {
|
|
|
364
423
|
deviceId: string,
|
|
365
424
|
serviceId: string,
|
|
366
425
|
characteristicId: string,
|
|
367
|
-
data:
|
|
426
|
+
data: ArrayBuffer,
|
|
368
427
|
withResponse: boolean = true
|
|
369
428
|
): Promise<boolean> {
|
|
370
429
|
return new Promise((resolve, reject) => {
|
|
@@ -416,7 +475,7 @@ export class BleNitro {
|
|
|
416
475
|
deviceId,
|
|
417
476
|
BleNitro.normalizeGattUUID(serviceId),
|
|
418
477
|
BleNitro.normalizeGattUUID(characteristicId),
|
|
419
|
-
(charId: string, data:
|
|
478
|
+
(charId: string, data: ArrayBuffer) => {
|
|
420
479
|
callback(charId, data);
|
|
421
480
|
},
|
|
422
481
|
(success, error) => {
|
|
@@ -484,8 +543,7 @@ export class BleNitro {
|
|
|
484
543
|
}
|
|
485
544
|
|
|
486
545
|
/**
|
|
487
|
-
* Request to enable Bluetooth
|
|
488
|
-
* Only works on Android
|
|
546
|
+
* Request to enable Bluetooth (Android only)
|
|
489
547
|
* @returns Promise resolving when Bluetooth is enabled
|
|
490
548
|
*/
|
|
491
549
|
public requestBluetoothEnable(): Promise<boolean> {
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { HybridObject } from 'react-native-nitro-modules';
|
|
2
2
|
|
|
3
|
+
// Type alias for BLE data - ArrayBuffers for efficient binary data handling
|
|
4
|
+
export type BLEValue = ArrayBuffer;
|
|
5
|
+
|
|
3
6
|
// Nitro constraint: Use numeric enums instead of string unions
|
|
4
7
|
export enum BLEState {
|
|
5
8
|
Unknown = 0,
|
|
@@ -12,7 +15,7 @@ export enum BLEState {
|
|
|
12
15
|
|
|
13
16
|
export interface ManufacturerDataEntry {
|
|
14
17
|
id: string;
|
|
15
|
-
data:
|
|
18
|
+
data: BLEValue;
|
|
16
19
|
}
|
|
17
20
|
|
|
18
21
|
export interface ManufacturerData {
|
|
@@ -28,22 +31,30 @@ export interface BLEDevice {
|
|
|
28
31
|
isConnectable: boolean;
|
|
29
32
|
}
|
|
30
33
|
|
|
34
|
+
export enum AndroidScanMode {
|
|
35
|
+
LowLatency = 0,
|
|
36
|
+
Balanced = 1,
|
|
37
|
+
LowPower = 2,
|
|
38
|
+
Opportunistic = 3,
|
|
39
|
+
}
|
|
40
|
+
|
|
31
41
|
export interface ScanFilter {
|
|
32
42
|
serviceUUIDs: string[];
|
|
33
43
|
rssiThreshold: number;
|
|
34
44
|
allowDuplicates: boolean;
|
|
45
|
+
androidScanMode: AndroidScanMode;
|
|
35
46
|
}
|
|
36
47
|
|
|
37
|
-
export type ScanCallback = (device: BLEDevice) => void;
|
|
48
|
+
export type ScanCallback = (device: BLEDevice | null, error: string | null) => void;
|
|
38
49
|
export type DevicesCallback = (devices: BLEDevice[]) => void;
|
|
39
50
|
export type ConnectionCallback = (success: boolean, deviceId: string, error: string) => void;
|
|
40
51
|
export type DisconnectionEventCallback = (deviceId: string, interrupted: boolean, error: string) => void;
|
|
41
52
|
export type OperationCallback = (success: boolean, error: string) => void;
|
|
42
|
-
export type CharacteristicCallback = (characteristicId: string, data:
|
|
53
|
+
export type CharacteristicCallback = (characteristicId: string, data: BLEValue) => void;
|
|
43
54
|
export type StateCallback = (state: BLEState) => void;
|
|
44
55
|
export type BooleanCallback = (result: boolean) => void;
|
|
45
56
|
export type StringArrayCallback = (result: string[]) => void;
|
|
46
|
-
export type ReadCharacteristicCallback = (success: boolean, data:
|
|
57
|
+
export type ReadCharacteristicCallback = (success: boolean, data: BLEValue, error: string) => void;
|
|
47
58
|
|
|
48
59
|
export type OperationResult = {
|
|
49
60
|
success: boolean;
|
|
@@ -67,6 +78,7 @@ export interface NativeBleNitro extends HybridObject<{ ios: 'swift'; android: 'k
|
|
|
67
78
|
connect(deviceId: string, callback: ConnectionCallback, disconnectCallback?: DisconnectionEventCallback): void;
|
|
68
79
|
disconnect(deviceId: string, callback: OperationCallback): void;
|
|
69
80
|
isConnected(deviceId: string): boolean;
|
|
81
|
+
requestMTU(deviceId: string, mtu: number): number;
|
|
70
82
|
|
|
71
83
|
// Service discovery
|
|
72
84
|
discoverServices(deviceId: string, callback: OperationCallback): void;
|
|
@@ -75,7 +87,7 @@ export interface NativeBleNitro extends HybridObject<{ ios: 'swift'; android: 'k
|
|
|
75
87
|
|
|
76
88
|
// Characteristic operations
|
|
77
89
|
readCharacteristic(deviceId: string, serviceId: string, characteristicId: string, callback: ReadCharacteristicCallback): void;
|
|
78
|
-
writeCharacteristic(deviceId: string, serviceId: string, characteristicId: string, data:
|
|
90
|
+
writeCharacteristic(deviceId: string, serviceId: string, characteristicId: string, data: BLEValue, withResponse: boolean, callback: OperationCallback): void;
|
|
79
91
|
subscribeToCharacteristic(deviceId: string, serviceId: string, characteristicId: string, updateCallback: CharacteristicCallback, resultCallback: OperationCallback): void;
|
|
80
92
|
unsubscribeFromCharacteristic(deviceId: string, serviceId: string, characteristicId: string, callback: OperationCallback): void;
|
|
81
93
|
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
///
|
|
2
|
-
/// JFunc_void_BLEDevice.hpp
|
|
3
|
-
/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
|
|
4
|
-
/// https://github.com/mrousavy/nitro
|
|
5
|
-
/// Copyright © 2025 Marc Rousavy @ Margelo
|
|
6
|
-
///
|
|
7
|
-
|
|
8
|
-
#pragma once
|
|
9
|
-
|
|
10
|
-
#include <fbjni/fbjni.h>
|
|
11
|
-
#include <functional>
|
|
12
|
-
|
|
13
|
-
#include "BLEDevice.hpp"
|
|
14
|
-
#include <functional>
|
|
15
|
-
#include "JBLEDevice.hpp"
|
|
16
|
-
#include <string>
|
|
17
|
-
#include "ManufacturerData.hpp"
|
|
18
|
-
#include "JManufacturerData.hpp"
|
|
19
|
-
#include "ManufacturerDataEntry.hpp"
|
|
20
|
-
#include <vector>
|
|
21
|
-
#include "JManufacturerDataEntry.hpp"
|
|
22
|
-
|
|
23
|
-
namespace margelo::nitro::co::zyke::ble {
|
|
24
|
-
|
|
25
|
-
using namespace facebook;
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Represents the Java/Kotlin callback `(device: BLEDevice) -> Unit`.
|
|
29
|
-
* This can be passed around between C++ and Java/Kotlin.
|
|
30
|
-
*/
|
|
31
|
-
struct JFunc_void_BLEDevice: public jni::JavaClass<JFunc_void_BLEDevice> {
|
|
32
|
-
public:
|
|
33
|
-
static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/co/zyke/ble/Func_void_BLEDevice;";
|
|
34
|
-
|
|
35
|
-
public:
|
|
36
|
-
/**
|
|
37
|
-
* Invokes the function this `JFunc_void_BLEDevice` instance holds through JNI.
|
|
38
|
-
*/
|
|
39
|
-
void invoke(const BLEDevice& device) const {
|
|
40
|
-
static const auto method = javaClassStatic()->getMethod<void(jni::alias_ref<JBLEDevice> /* device */)>("invoke");
|
|
41
|
-
method(self(), JBLEDevice::fromCpp(device));
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* An implementation of Func_void_BLEDevice that is backed by a C++ implementation (using `std::function<...>`)
|
|
47
|
-
*/
|
|
48
|
-
struct JFunc_void_BLEDevice_cxx final: public jni::HybridClass<JFunc_void_BLEDevice_cxx, JFunc_void_BLEDevice> {
|
|
49
|
-
public:
|
|
50
|
-
static jni::local_ref<JFunc_void_BLEDevice::javaobject> fromCpp(const std::function<void(const BLEDevice& /* device */)>& func) {
|
|
51
|
-
return JFunc_void_BLEDevice_cxx::newObjectCxxArgs(func);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
public:
|
|
55
|
-
/**
|
|
56
|
-
* Invokes the C++ `std::function<...>` this `JFunc_void_BLEDevice_cxx` instance holds.
|
|
57
|
-
*/
|
|
58
|
-
void invoke_cxx(jni::alias_ref<JBLEDevice> device) {
|
|
59
|
-
_func(device->toCpp());
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
public:
|
|
63
|
-
[[nodiscard]]
|
|
64
|
-
inline const std::function<void(const BLEDevice& /* device */)>& getFunction() const {
|
|
65
|
-
return _func;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
public:
|
|
69
|
-
static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/co/zyke/ble/Func_void_BLEDevice_cxx;";
|
|
70
|
-
static void registerNatives() {
|
|
71
|
-
registerHybrid({makeNativeMethod("invoke_cxx", JFunc_void_BLEDevice_cxx::invoke_cxx)});
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
private:
|
|
75
|
-
explicit JFunc_void_BLEDevice_cxx(const std::function<void(const BLEDevice& /* device */)>& func): _func(func) { }
|
|
76
|
-
|
|
77
|
-
private:
|
|
78
|
-
friend HybridBase;
|
|
79
|
-
std::function<void(const BLEDevice& /* device */)> _func;
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
} // namespace margelo::nitro::co::zyke::ble
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
///
|
|
2
|
-
/// JFunc_void_bool_std__vector_double__std__string.hpp
|
|
3
|
-
/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
|
|
4
|
-
/// https://github.com/mrousavy/nitro
|
|
5
|
-
/// Copyright © 2025 Marc Rousavy @ Margelo
|
|
6
|
-
///
|
|
7
|
-
|
|
8
|
-
#pragma once
|
|
9
|
-
|
|
10
|
-
#include <fbjni/fbjni.h>
|
|
11
|
-
#include <functional>
|
|
12
|
-
|
|
13
|
-
#include <vector>
|
|
14
|
-
#include <string>
|
|
15
|
-
#include <functional>
|
|
16
|
-
|
|
17
|
-
namespace margelo::nitro::co::zyke::ble {
|
|
18
|
-
|
|
19
|
-
using namespace facebook;
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Represents the Java/Kotlin callback `(success: Boolean, data: DoubleArray, error: String) -> Unit`.
|
|
23
|
-
* This can be passed around between C++ and Java/Kotlin.
|
|
24
|
-
*/
|
|
25
|
-
struct JFunc_void_bool_std__vector_double__std__string: public jni::JavaClass<JFunc_void_bool_std__vector_double__std__string> {
|
|
26
|
-
public:
|
|
27
|
-
static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/co/zyke/ble/Func_void_bool_std__vector_double__std__string;";
|
|
28
|
-
|
|
29
|
-
public:
|
|
30
|
-
/**
|
|
31
|
-
* Invokes the function this `JFunc_void_bool_std__vector_double__std__string` instance holds through JNI.
|
|
32
|
-
*/
|
|
33
|
-
void invoke(bool success, const std::vector<double>& data, const std::string& error) const {
|
|
34
|
-
static const auto method = javaClassStatic()->getMethod<void(jboolean /* success */, jni::alias_ref<jni::JArrayDouble> /* data */, jni::alias_ref<jni::JString> /* error */)>("invoke");
|
|
35
|
-
method(self(), success, [&]() {
|
|
36
|
-
size_t __size = data.size();
|
|
37
|
-
jni::local_ref<jni::JArrayDouble> __array = jni::JArrayDouble::newArray(__size);
|
|
38
|
-
__array->setRegion(0, __size, data.data());
|
|
39
|
-
return __array;
|
|
40
|
-
}(), jni::make_jstring(error));
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* An implementation of Func_void_bool_std__vector_double__std__string that is backed by a C++ implementation (using `std::function<...>`)
|
|
46
|
-
*/
|
|
47
|
-
struct JFunc_void_bool_std__vector_double__std__string_cxx final: public jni::HybridClass<JFunc_void_bool_std__vector_double__std__string_cxx, JFunc_void_bool_std__vector_double__std__string> {
|
|
48
|
-
public:
|
|
49
|
-
static jni::local_ref<JFunc_void_bool_std__vector_double__std__string::javaobject> fromCpp(const std::function<void(bool /* success */, const std::vector<double>& /* data */, const std::string& /* error */)>& func) {
|
|
50
|
-
return JFunc_void_bool_std__vector_double__std__string_cxx::newObjectCxxArgs(func);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
public:
|
|
54
|
-
/**
|
|
55
|
-
* Invokes the C++ `std::function<...>` this `JFunc_void_bool_std__vector_double__std__string_cxx` instance holds.
|
|
56
|
-
*/
|
|
57
|
-
void invoke_cxx(jboolean success, jni::alias_ref<jni::JArrayDouble> data, jni::alias_ref<jni::JString> error) {
|
|
58
|
-
_func(static_cast<bool>(success), [&]() {
|
|
59
|
-
size_t __size = data->size();
|
|
60
|
-
std::vector<double> __vector(__size);
|
|
61
|
-
data->getRegion(0, __size, __vector.data());
|
|
62
|
-
return __vector;
|
|
63
|
-
}(), error->toStdString());
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
public:
|
|
67
|
-
[[nodiscard]]
|
|
68
|
-
inline const std::function<void(bool /* success */, const std::vector<double>& /* data */, const std::string& /* error */)>& getFunction() const {
|
|
69
|
-
return _func;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
public:
|
|
73
|
-
static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/co/zyke/ble/Func_void_bool_std__vector_double__std__string_cxx;";
|
|
74
|
-
static void registerNatives() {
|
|
75
|
-
registerHybrid({makeNativeMethod("invoke_cxx", JFunc_void_bool_std__vector_double__std__string_cxx::invoke_cxx)});
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
private:
|
|
79
|
-
explicit JFunc_void_bool_std__vector_double__std__string_cxx(const std::function<void(bool /* success */, const std::vector<double>& /* data */, const std::string& /* error */)>& func): _func(func) { }
|
|
80
|
-
|
|
81
|
-
private:
|
|
82
|
-
friend HybridBase;
|
|
83
|
-
std::function<void(bool /* success */, const std::vector<double>& /* data */, const std::string& /* error */)> _func;
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
} // namespace margelo::nitro::co::zyke::ble
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
///
|
|
2
|
-
/// JFunc_void_std__string_std__vector_double_.hpp
|
|
3
|
-
/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
|
|
4
|
-
/// https://github.com/mrousavy/nitro
|
|
5
|
-
/// Copyright © 2025 Marc Rousavy @ Margelo
|
|
6
|
-
///
|
|
7
|
-
|
|
8
|
-
#pragma once
|
|
9
|
-
|
|
10
|
-
#include <fbjni/fbjni.h>
|
|
11
|
-
#include <functional>
|
|
12
|
-
|
|
13
|
-
#include <string>
|
|
14
|
-
#include <vector>
|
|
15
|
-
#include <functional>
|
|
16
|
-
|
|
17
|
-
namespace margelo::nitro::co::zyke::ble {
|
|
18
|
-
|
|
19
|
-
using namespace facebook;
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Represents the Java/Kotlin callback `(characteristicId: String, data: DoubleArray) -> Unit`.
|
|
23
|
-
* This can be passed around between C++ and Java/Kotlin.
|
|
24
|
-
*/
|
|
25
|
-
struct JFunc_void_std__string_std__vector_double_: public jni::JavaClass<JFunc_void_std__string_std__vector_double_> {
|
|
26
|
-
public:
|
|
27
|
-
static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/co/zyke/ble/Func_void_std__string_std__vector_double_;";
|
|
28
|
-
|
|
29
|
-
public:
|
|
30
|
-
/**
|
|
31
|
-
* Invokes the function this `JFunc_void_std__string_std__vector_double_` instance holds through JNI.
|
|
32
|
-
*/
|
|
33
|
-
void invoke(const std::string& characteristicId, const std::vector<double>& data) const {
|
|
34
|
-
static const auto method = javaClassStatic()->getMethod<void(jni::alias_ref<jni::JString> /* characteristicId */, jni::alias_ref<jni::JArrayDouble> /* data */)>("invoke");
|
|
35
|
-
method(self(), jni::make_jstring(characteristicId), [&]() {
|
|
36
|
-
size_t __size = data.size();
|
|
37
|
-
jni::local_ref<jni::JArrayDouble> __array = jni::JArrayDouble::newArray(__size);
|
|
38
|
-
__array->setRegion(0, __size, data.data());
|
|
39
|
-
return __array;
|
|
40
|
-
}());
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* An implementation of Func_void_std__string_std__vector_double_ that is backed by a C++ implementation (using `std::function<...>`)
|
|
46
|
-
*/
|
|
47
|
-
struct JFunc_void_std__string_std__vector_double__cxx final: public jni::HybridClass<JFunc_void_std__string_std__vector_double__cxx, JFunc_void_std__string_std__vector_double_> {
|
|
48
|
-
public:
|
|
49
|
-
static jni::local_ref<JFunc_void_std__string_std__vector_double_::javaobject> fromCpp(const std::function<void(const std::string& /* characteristicId */, const std::vector<double>& /* data */)>& func) {
|
|
50
|
-
return JFunc_void_std__string_std__vector_double__cxx::newObjectCxxArgs(func);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
public:
|
|
54
|
-
/**
|
|
55
|
-
* Invokes the C++ `std::function<...>` this `JFunc_void_std__string_std__vector_double__cxx` instance holds.
|
|
56
|
-
*/
|
|
57
|
-
void invoke_cxx(jni::alias_ref<jni::JString> characteristicId, jni::alias_ref<jni::JArrayDouble> data) {
|
|
58
|
-
_func(characteristicId->toStdString(), [&]() {
|
|
59
|
-
size_t __size = data->size();
|
|
60
|
-
std::vector<double> __vector(__size);
|
|
61
|
-
data->getRegion(0, __size, __vector.data());
|
|
62
|
-
return __vector;
|
|
63
|
-
}());
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
public:
|
|
67
|
-
[[nodiscard]]
|
|
68
|
-
inline const std::function<void(const std::string& /* characteristicId */, const std::vector<double>& /* data */)>& getFunction() const {
|
|
69
|
-
return _func;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
public:
|
|
73
|
-
static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/co/zyke/ble/Func_void_std__string_std__vector_double__cxx;";
|
|
74
|
-
static void registerNatives() {
|
|
75
|
-
registerHybrid({makeNativeMethod("invoke_cxx", JFunc_void_std__string_std__vector_double__cxx::invoke_cxx)});
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
private:
|
|
79
|
-
explicit JFunc_void_std__string_std__vector_double__cxx(const std::function<void(const std::string& /* characteristicId */, const std::vector<double>& /* data */)>& func): _func(func) { }
|
|
80
|
-
|
|
81
|
-
private:
|
|
82
|
-
friend HybridBase;
|
|
83
|
-
std::function<void(const std::string& /* characteristicId */, const std::vector<double>& /* data */)> _func;
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
} // namespace margelo::nitro::co::zyke::ble
|