react-native-ble-nitro 1.0.0-alpha.1
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/LICENSE +21 -0
- package/README.md +298 -0
- package/android/build.gradle +55 -0
- package/android/src/main/AndroidManifest.xml +23 -0
- package/android/src/main/kotlin/co/zyke/ble/BleNitroBleManager.kt +651 -0
- package/android/src/main/kotlin/co/zyke/ble/BleNitroPackage.kt +37 -0
- package/ios/BleNitro.podspec +37 -0
- package/ios/BleNitroBleManager.swift +509 -0
- package/ios/BleNitroModule.swift +31 -0
- package/lib/BleManagerCompatFactory.d.ts +53 -0
- package/lib/BleManagerCompatFactory.js +191 -0
- package/lib/BleManagerFactory.d.ts +12 -0
- package/lib/BleManagerFactory.js +22 -0
- package/lib/compatibility/constants.d.ts +49 -0
- package/lib/compatibility/constants.js +50 -0
- package/lib/compatibility/deviceWrapper.d.ts +99 -0
- package/lib/compatibility/deviceWrapper.js +259 -0
- package/lib/compatibility/enums.d.ts +43 -0
- package/lib/compatibility/enums.js +124 -0
- package/lib/compatibility/index.d.ts +11 -0
- package/lib/compatibility/index.js +12 -0
- package/lib/compatibility/serviceData.d.ts +51 -0
- package/lib/compatibility/serviceData.js +70 -0
- package/lib/errors/BleError.d.ts +59 -0
- package/lib/errors/BleError.js +120 -0
- package/lib/index.d.ts +7 -0
- package/lib/index.js +12 -0
- package/lib/specs/BleManager.nitro.d.ts +36 -0
- package/lib/specs/BleManager.nitro.js +1 -0
- package/lib/specs/Characteristic.nitro.d.ts +26 -0
- package/lib/specs/Characteristic.nitro.js +1 -0
- package/lib/specs/Descriptor.nitro.d.ts +17 -0
- package/lib/specs/Descriptor.nitro.js +1 -0
- package/lib/specs/Device.nitro.d.ts +37 -0
- package/lib/specs/Device.nitro.js +1 -0
- package/lib/specs/Service.nitro.d.ts +19 -0
- package/lib/specs/Service.nitro.js +1 -0
- package/lib/specs/types.d.ts +228 -0
- package/lib/specs/types.js +146 -0
- package/lib/utils/base64.d.ts +25 -0
- package/lib/utils/base64.js +80 -0
- package/lib/utils/index.d.ts +2 -0
- package/lib/utils/index.js +2 -0
- package/lib/utils/uuid.d.ts +9 -0
- package/lib/utils/uuid.js +37 -0
- package/nitro.json +15 -0
- package/package.json +102 -0
- package/plugin/build/index.d.ts +28 -0
- package/plugin/build/index.js +29 -0
- package/plugin/build/withBleNitro.d.ts +31 -0
- package/plugin/build/withBleNitro.js +87 -0
- package/react-native.config.js +13 -0
- package/src/BleManagerCompatFactory.ts +373 -0
- package/src/BleManagerFactory.ts +30 -0
- package/src/__tests__/BleManager.test.ts +327 -0
- package/src/__tests__/compatibility/deviceWrapper.test.ts +563 -0
- package/src/__tests__/compatibility/enums.test.ts +254 -0
- package/src/compatibility/constants.ts +71 -0
- package/src/compatibility/deviceWrapper.ts +427 -0
- package/src/compatibility/enums.ts +160 -0
- package/src/compatibility/index.ts +24 -0
- package/src/compatibility/serviceData.ts +85 -0
- package/src/errors/BleError.ts +193 -0
- package/src/index.ts +30 -0
- package/src/specs/BleManager.nitro.ts +152 -0
- package/src/specs/Characteristic.nitro.ts +61 -0
- package/src/specs/Descriptor.nitro.ts +28 -0
- package/src/specs/Device.nitro.ts +104 -0
- package/src/specs/Service.nitro.ts +64 -0
- package/src/specs/types.ts +259 -0
- package/src/utils/base64.ts +80 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/uuid.ts +45 -0
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Device wrapper for compatibility
|
|
3
|
+
*
|
|
4
|
+
* Wraps Nitro Device objects to provide the original react-native-ble-plx API
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { Device as NitroDevice } from '../specs/Device.nitro';
|
|
8
|
+
import type {
|
|
9
|
+
NativeDevice,
|
|
10
|
+
UUID,
|
|
11
|
+
Base64,
|
|
12
|
+
DeviceId,
|
|
13
|
+
TransactionId,
|
|
14
|
+
ConnectionPriority,
|
|
15
|
+
ConnectionOptions,
|
|
16
|
+
ServiceDataEntry,
|
|
17
|
+
NativeService,
|
|
18
|
+
NativeCharacteristic,
|
|
19
|
+
NativeDescriptor,
|
|
20
|
+
CharacteristicSubscriptionType,
|
|
21
|
+
Subscription
|
|
22
|
+
} from '../specs/types';
|
|
23
|
+
import { serviceDataArrayToMap } from './serviceData';
|
|
24
|
+
import {
|
|
25
|
+
normalizeCharacteristicSubscriptionType,
|
|
26
|
+
stateToString,
|
|
27
|
+
characteristicSubscriptionTypeToString
|
|
28
|
+
} from './enums';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Device wrapper that provides react-native-ble-plx compatibility
|
|
32
|
+
* Maps Nitro device properties to the expected API surface
|
|
33
|
+
*/
|
|
34
|
+
export class DeviceWrapper {
|
|
35
|
+
constructor(private nitroDevice: NitroDevice | any) {}
|
|
36
|
+
|
|
37
|
+
// Device identification
|
|
38
|
+
get id(): DeviceId {
|
|
39
|
+
return this.nitroDevice.id;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Map deviceName back to name for compatibility
|
|
43
|
+
get name(): string | null {
|
|
44
|
+
return this.nitroDevice.deviceName || null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
get rssi(): number | null {
|
|
48
|
+
return this.nitroDevice.rssi || null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
get mtu(): number {
|
|
52
|
+
return this.nitroDevice.mtu;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Advertisement data
|
|
56
|
+
get manufacturerData(): Base64 | null {
|
|
57
|
+
return this.nitroDevice.manufacturerData || null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
get rawScanRecord(): Base64 {
|
|
61
|
+
return this.nitroDevice.rawScanRecord;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Convert ServiceDataEntry[] back to { [uuid: string]: Base64 }
|
|
65
|
+
get serviceData(): { [uuid: string]: Base64 } | null {
|
|
66
|
+
return serviceDataArrayToMap(this.nitroDevice.serviceData || null);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
get serviceUUIDs(): UUID[] | null {
|
|
70
|
+
return this.nitroDevice.serviceUUIDs || null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
get localName(): string | null {
|
|
74
|
+
return this.nitroDevice.localName || null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
get txPowerLevel(): number | null {
|
|
78
|
+
return this.nitroDevice.txPowerLevel || null;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
get solicitedServiceUUIDs(): UUID[] | null {
|
|
82
|
+
return this.nitroDevice.solicitedServiceUUIDs || null;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
get isConnectable(): boolean | null {
|
|
86
|
+
return this.nitroDevice.isConnectable || null;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
get overflowServiceUUIDs(): UUID[] | null {
|
|
90
|
+
return this.nitroDevice.overflowServiceUUIDs || null;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Connection management methods
|
|
94
|
+
async requestConnectionPriority(
|
|
95
|
+
connectionPriority: ConnectionPriority,
|
|
96
|
+
transactionId?: TransactionId
|
|
97
|
+
): Promise<DeviceWrapper> {
|
|
98
|
+
const result = await this.nitroDevice.requestConnectionPriority(connectionPriority, transactionId);
|
|
99
|
+
return new DeviceWrapper(result);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async readRSSI(transactionId?: TransactionId): Promise<DeviceWrapper> {
|
|
103
|
+
const result = await this.nitroDevice.readRSSI(transactionId);
|
|
104
|
+
return new DeviceWrapper(result);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async requestMTU(mtu: number, transactionId?: TransactionId): Promise<DeviceWrapper> {
|
|
108
|
+
const result = await this.nitroDevice.requestMTU(mtu, transactionId);
|
|
109
|
+
return new DeviceWrapper(result);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async connect(options?: Partial<ConnectionOptions>): Promise<DeviceWrapper> {
|
|
113
|
+
// Provide defaults for required fields in Nitro interface
|
|
114
|
+
const connectionOptions: ConnectionOptions = {
|
|
115
|
+
autoConnect: options?.autoConnect ?? false,
|
|
116
|
+
requestMTU: options?.requestMTU ?? 23,
|
|
117
|
+
timeout: options?.timeout ?? 0,
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const result = await this.nitroDevice.connect(connectionOptions);
|
|
121
|
+
return new DeviceWrapper(result);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async cancelConnection(): Promise<DeviceWrapper> {
|
|
125
|
+
const result = await this.nitroDevice.cancelConnection();
|
|
126
|
+
return new DeviceWrapper(result);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async isConnected(): Promise<boolean> {
|
|
130
|
+
return await this.nitroDevice.isConnected();
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
onDisconnected(listener: (error: any | null, device: DeviceWrapper) => void): Subscription {
|
|
134
|
+
return this.nitroDevice.onDisconnected((error: any, device: any) => {
|
|
135
|
+
listener(error, new DeviceWrapper(device));
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Service discovery
|
|
140
|
+
async discoverAllServicesAndCharacteristics(transactionId?: TransactionId): Promise<DeviceWrapper> {
|
|
141
|
+
const result = await this.nitroDevice.discoverAllServicesAndCharacteristics(transactionId);
|
|
142
|
+
return new DeviceWrapper(result);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
async services(): Promise<ServiceWrapper[]> {
|
|
146
|
+
const services = await this.nitroDevice.services();
|
|
147
|
+
return services.map((service: any) => new ServiceWrapper(service, this.nitroDevice));
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Characteristic operations
|
|
151
|
+
async characteristicsForService(serviceUUID: UUID): Promise<CharacteristicWrapper[]> {
|
|
152
|
+
const characteristics = await this.nitroDevice.characteristicsForService(serviceUUID);
|
|
153
|
+
return characteristics.map((char: any) => new CharacteristicWrapper(char, this.nitroDevice));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
async readCharacteristicForService(
|
|
157
|
+
serviceUUID: UUID,
|
|
158
|
+
characteristicUUID: UUID,
|
|
159
|
+
transactionId?: TransactionId
|
|
160
|
+
): Promise<CharacteristicWrapper> {
|
|
161
|
+
const result = await this.nitroDevice.readCharacteristicForService(
|
|
162
|
+
serviceUUID,
|
|
163
|
+
characteristicUUID,
|
|
164
|
+
transactionId
|
|
165
|
+
);
|
|
166
|
+
return new CharacteristicWrapper(result, this.nitroDevice);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
async writeCharacteristicWithResponseForService(
|
|
170
|
+
serviceUUID: UUID,
|
|
171
|
+
characteristicUUID: UUID,
|
|
172
|
+
valueBase64: Base64,
|
|
173
|
+
transactionId?: TransactionId
|
|
174
|
+
): Promise<CharacteristicWrapper> {
|
|
175
|
+
const result = await this.nitroDevice.writeCharacteristicWithResponseForService(
|
|
176
|
+
serviceUUID,
|
|
177
|
+
characteristicUUID,
|
|
178
|
+
valueBase64,
|
|
179
|
+
transactionId
|
|
180
|
+
);
|
|
181
|
+
return new CharacteristicWrapper(result, this.nitroDevice);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
async writeCharacteristicWithoutResponseForService(
|
|
185
|
+
serviceUUID: UUID,
|
|
186
|
+
characteristicUUID: UUID,
|
|
187
|
+
valueBase64: Base64,
|
|
188
|
+
transactionId?: TransactionId
|
|
189
|
+
): Promise<CharacteristicWrapper> {
|
|
190
|
+
const result = await this.nitroDevice.writeCharacteristicWithoutResponseForService(
|
|
191
|
+
serviceUUID,
|
|
192
|
+
characteristicUUID,
|
|
193
|
+
valueBase64,
|
|
194
|
+
transactionId
|
|
195
|
+
);
|
|
196
|
+
return new CharacteristicWrapper(result, this.nitroDevice);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
monitorCharacteristicForService(
|
|
200
|
+
serviceUUID: UUID,
|
|
201
|
+
characteristicUUID: UUID,
|
|
202
|
+
listener: (error: any | null, characteristic: CharacteristicWrapper | null) => void,
|
|
203
|
+
transactionId?: TransactionId,
|
|
204
|
+
subscriptionType?: 'notification' | 'indication'
|
|
205
|
+
): Subscription {
|
|
206
|
+
const nitroSubscriptionType = subscriptionType
|
|
207
|
+
? normalizeCharacteristicSubscriptionType(subscriptionType)
|
|
208
|
+
: undefined;
|
|
209
|
+
|
|
210
|
+
return this.nitroDevice.monitorCharacteristicForService(
|
|
211
|
+
serviceUUID,
|
|
212
|
+
characteristicUUID,
|
|
213
|
+
(error: any, characteristic: any) => {
|
|
214
|
+
listener(
|
|
215
|
+
error,
|
|
216
|
+
characteristic ? new CharacteristicWrapper(characteristic, this.nitroDevice) : null
|
|
217
|
+
);
|
|
218
|
+
},
|
|
219
|
+
transactionId,
|
|
220
|
+
nitroSubscriptionType
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Descriptor operations
|
|
225
|
+
async descriptorsForService(
|
|
226
|
+
serviceUUID: UUID,
|
|
227
|
+
characteristicUUID: UUID
|
|
228
|
+
): Promise<DescriptorWrapper[]> {
|
|
229
|
+
const descriptors = await this.nitroDevice.descriptorsForService(serviceUUID, characteristicUUID);
|
|
230
|
+
return descriptors.map((desc: any) => new DescriptorWrapper(desc, this.nitroDevice));
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
async readDescriptorForService(
|
|
234
|
+
serviceUUID: UUID,
|
|
235
|
+
characteristicUUID: UUID,
|
|
236
|
+
descriptorUUID: UUID,
|
|
237
|
+
transactionId?: TransactionId
|
|
238
|
+
): Promise<DescriptorWrapper> {
|
|
239
|
+
const result = await this.nitroDevice.readDescriptorForService(
|
|
240
|
+
serviceUUID,
|
|
241
|
+
characteristicUUID,
|
|
242
|
+
descriptorUUID,
|
|
243
|
+
transactionId
|
|
244
|
+
);
|
|
245
|
+
return new DescriptorWrapper(result, this.nitroDevice);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
async writeDescriptorForService(
|
|
249
|
+
serviceUUID: UUID,
|
|
250
|
+
characteristicUUID: UUID,
|
|
251
|
+
descriptorUUID: UUID,
|
|
252
|
+
valueBase64: Base64,
|
|
253
|
+
transactionId?: TransactionId
|
|
254
|
+
): Promise<DescriptorWrapper> {
|
|
255
|
+
const result = await this.nitroDevice.writeDescriptorForService(
|
|
256
|
+
serviceUUID,
|
|
257
|
+
characteristicUUID,
|
|
258
|
+
descriptorUUID,
|
|
259
|
+
valueBase64,
|
|
260
|
+
transactionId
|
|
261
|
+
);
|
|
262
|
+
return new DescriptorWrapper(result, this.nitroDevice);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Service wrapper for compatibility
|
|
268
|
+
*/
|
|
269
|
+
export class ServiceWrapper {
|
|
270
|
+
constructor(
|
|
271
|
+
private nativeService: NativeService,
|
|
272
|
+
private nitroDevice: NitroDevice
|
|
273
|
+
) {}
|
|
274
|
+
|
|
275
|
+
get id(): number {
|
|
276
|
+
return this.nativeService.id;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
get uuid(): UUID {
|
|
280
|
+
return this.nativeService.uuid;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
get deviceID(): DeviceId {
|
|
284
|
+
return this.nativeService.deviceID;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
get isPrimary(): boolean {
|
|
288
|
+
return this.nativeService.isPrimary;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Delegate to device methods
|
|
292
|
+
async characteristics(): Promise<CharacteristicWrapper[]> {
|
|
293
|
+
const device = new DeviceWrapper(this.nitroDevice);
|
|
294
|
+
return await device.characteristicsForService(this.uuid);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
async readCharacteristic(
|
|
298
|
+
characteristicUUID: UUID,
|
|
299
|
+
transactionId?: TransactionId
|
|
300
|
+
): Promise<CharacteristicWrapper> {
|
|
301
|
+
const device = new DeviceWrapper(this.nitroDevice);
|
|
302
|
+
return await device.readCharacteristicForService(this.uuid, characteristicUUID, transactionId);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// ... other service methods would delegate similarly
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Characteristic wrapper for compatibility
|
|
310
|
+
*/
|
|
311
|
+
export class CharacteristicWrapper {
|
|
312
|
+
constructor(
|
|
313
|
+
private nativeCharacteristic: NativeCharacteristic,
|
|
314
|
+
private nitroDevice: NitroDevice
|
|
315
|
+
) {}
|
|
316
|
+
|
|
317
|
+
get id(): number {
|
|
318
|
+
return this.nativeCharacteristic.id;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
get uuid(): UUID {
|
|
322
|
+
return this.nativeCharacteristic.uuid;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
get serviceID(): number {
|
|
326
|
+
return this.nativeCharacteristic.serviceID;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
get serviceUUID(): UUID {
|
|
330
|
+
return this.nativeCharacteristic.serviceUUID;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
get deviceID(): DeviceId {
|
|
334
|
+
return this.nativeCharacteristic.deviceID;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
get isReadable(): boolean {
|
|
338
|
+
return this.nativeCharacteristic.isReadable;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
get isWritableWithResponse(): boolean {
|
|
342
|
+
return this.nativeCharacteristic.isWritableWithResponse;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
get isWritableWithoutResponse(): boolean {
|
|
346
|
+
return this.nativeCharacteristic.isWritableWithoutResponse;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
get isNotifiable(): boolean {
|
|
350
|
+
return this.nativeCharacteristic.isNotifiable;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
get isNotifying(): boolean {
|
|
354
|
+
return this.nativeCharacteristic.isNotifying;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
get isIndicatable(): boolean {
|
|
358
|
+
return this.nativeCharacteristic.isIndicatable;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
get value(): Base64 | null {
|
|
362
|
+
return this.nativeCharacteristic.value;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Delegate to device methods
|
|
366
|
+
async read(transactionId?: TransactionId): Promise<CharacteristicWrapper> {
|
|
367
|
+
const device = new DeviceWrapper(this.nitroDevice);
|
|
368
|
+
return await device.readCharacteristicForService(this.serviceUUID, this.uuid, transactionId);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// ... other characteristic methods would delegate similarly
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Descriptor wrapper for compatibility
|
|
376
|
+
*/
|
|
377
|
+
export class DescriptorWrapper {
|
|
378
|
+
constructor(
|
|
379
|
+
private nativeDescriptor: NativeDescriptor,
|
|
380
|
+
private nitroDevice: NitroDevice
|
|
381
|
+
) {}
|
|
382
|
+
|
|
383
|
+
get id(): number {
|
|
384
|
+
return this.nativeDescriptor.id;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
get uuid(): UUID {
|
|
388
|
+
return this.nativeDescriptor.uuid;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
get characteristicID(): number {
|
|
392
|
+
return this.nativeDescriptor.characteristicID;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
get characteristicUUID(): UUID {
|
|
396
|
+
return this.nativeDescriptor.characteristicUUID;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
get serviceID(): number {
|
|
400
|
+
return this.nativeDescriptor.serviceID;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
get serviceUUID(): UUID {
|
|
404
|
+
return this.nativeDescriptor.serviceUUID;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
get deviceID(): DeviceId {
|
|
408
|
+
return this.nativeDescriptor.deviceID;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
get value(): Base64 | null {
|
|
412
|
+
return this.nativeDescriptor.value;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// Delegate to device methods
|
|
416
|
+
async read(transactionId?: TransactionId): Promise<DescriptorWrapper> {
|
|
417
|
+
const device = new DeviceWrapper(this.nitroDevice);
|
|
418
|
+
return await device.readDescriptorForService(
|
|
419
|
+
this.serviceUUID,
|
|
420
|
+
this.characteristicUUID,
|
|
421
|
+
this.uuid,
|
|
422
|
+
transactionId
|
|
423
|
+
);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// ... other descriptor methods would delegate similarly
|
|
427
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enum compatibility layer
|
|
3
|
+
*
|
|
4
|
+
* Provides conversion between Nitro's numeric enums and the original
|
|
5
|
+
* string-based enums from react-native-ble-plx
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
State,
|
|
10
|
+
LogLevel,
|
|
11
|
+
CharacteristicSubscriptionType,
|
|
12
|
+
RefreshGattMoment,
|
|
13
|
+
} from '../specs/types';
|
|
14
|
+
|
|
15
|
+
// String mappings for backward compatibility
|
|
16
|
+
export const StateString = {
|
|
17
|
+
[State.Unknown]: 'Unknown',
|
|
18
|
+
[State.Resetting]: 'Resetting',
|
|
19
|
+
[State.Unsupported]: 'Unsupported',
|
|
20
|
+
[State.Unauthorized]: 'Unauthorized',
|
|
21
|
+
[State.PoweredOff]: 'PoweredOff',
|
|
22
|
+
[State.PoweredOn]: 'PoweredOn',
|
|
23
|
+
} as const;
|
|
24
|
+
|
|
25
|
+
export const LogLevelString = {
|
|
26
|
+
[LogLevel.None]: 'None',
|
|
27
|
+
[LogLevel.Verbose]: 'Verbose',
|
|
28
|
+
[LogLevel.Debug]: 'Debug',
|
|
29
|
+
[LogLevel.Info]: 'Info',
|
|
30
|
+
[LogLevel.Warning]: 'Warning',
|
|
31
|
+
[LogLevel.Error]: 'Error',
|
|
32
|
+
} as const;
|
|
33
|
+
|
|
34
|
+
export const CharacteristicSubscriptionTypeString = {
|
|
35
|
+
[CharacteristicSubscriptionType.Notification]: 'notification',
|
|
36
|
+
[CharacteristicSubscriptionType.Indication]: 'indication',
|
|
37
|
+
} as const;
|
|
38
|
+
|
|
39
|
+
export const RefreshGattMomentString = {
|
|
40
|
+
[RefreshGattMoment.OnConnected]: 'OnConnected',
|
|
41
|
+
} as const;
|
|
42
|
+
|
|
43
|
+
// Reverse mappings for converting strings back to numeric enums
|
|
44
|
+
const StringToState: { [key: string]: State } = {};
|
|
45
|
+
const StringToLogLevel: { [key: string]: LogLevel } = {};
|
|
46
|
+
const StringToCharacteristicSubscriptionType: { [key: string]: CharacteristicSubscriptionType } = {};
|
|
47
|
+
const StringToRefreshGattMoment: { [key: string]: RefreshGattMoment } = {};
|
|
48
|
+
|
|
49
|
+
// Build reverse mappings
|
|
50
|
+
Object.entries(StateString).forEach(([num, str]) => {
|
|
51
|
+
StringToState[str] = parseInt(num) as State;
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
Object.entries(LogLevelString).forEach(([num, str]) => {
|
|
55
|
+
StringToLogLevel[str] = parseInt(num) as LogLevel;
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
Object.entries(CharacteristicSubscriptionTypeString).forEach(([num, str]) => {
|
|
59
|
+
StringToCharacteristicSubscriptionType[str] = parseInt(num) as CharacteristicSubscriptionType;
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
Object.entries(RefreshGattMomentString).forEach(([num, str]) => {
|
|
63
|
+
StringToRefreshGattMoment[str] = parseInt(num) as RefreshGattMoment;
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Conversion functions
|
|
67
|
+
export function stateToString(state: State): string {
|
|
68
|
+
return StateString[state] ?? 'Unknown';
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function stringToState(stateString: string): State {
|
|
72
|
+
// Handle case insensitive lookup
|
|
73
|
+
const lowerString = stateString.toLowerCase();
|
|
74
|
+
for (const [key, value] of Object.entries(StringToState)) {
|
|
75
|
+
if (key.toLowerCase() === lowerString) {
|
|
76
|
+
return value;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return State.Unknown;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function logLevelToString(logLevel: LogLevel): string {
|
|
83
|
+
return LogLevelString[logLevel] ?? 'None';
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function stringToLogLevel(logLevelString: string): LogLevel {
|
|
87
|
+
// Handle case insensitive lookup
|
|
88
|
+
const lowerString = logLevelString.toLowerCase();
|
|
89
|
+
for (const [key, value] of Object.entries(StringToLogLevel)) {
|
|
90
|
+
if (key.toLowerCase() === lowerString) {
|
|
91
|
+
return value;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return LogLevel.None;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function characteristicSubscriptionTypeToString(
|
|
98
|
+
type: CharacteristicSubscriptionType
|
|
99
|
+
): string {
|
|
100
|
+
return CharacteristicSubscriptionTypeString[type] ?? 'notification';
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function stringToCharacteristicSubscriptionType(
|
|
104
|
+
typeString: string
|
|
105
|
+
): CharacteristicSubscriptionType {
|
|
106
|
+
// Handle case insensitive lookup
|
|
107
|
+
const lowerString = typeString.toLowerCase();
|
|
108
|
+
for (const [key, value] of Object.entries(StringToCharacteristicSubscriptionType)) {
|
|
109
|
+
if (key.toLowerCase() === lowerString) {
|
|
110
|
+
return value;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return CharacteristicSubscriptionType.Notification;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function refreshGattMomentToString(moment: RefreshGattMoment): 'OnConnected' {
|
|
117
|
+
return RefreshGattMomentString[moment] as 'OnConnected';
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function stringToRefreshGattMoment(momentString: 'OnConnected'): RefreshGattMoment {
|
|
121
|
+
return StringToRefreshGattMoment[momentString] ?? RefreshGattMoment.OnConnected;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Helper function to detect if a value is a string enum vs numeric enum
|
|
125
|
+
export function isStringEnumValue(value: any): boolean {
|
|
126
|
+
return typeof value === 'string';
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Generic converter that handles both string and numeric enum values
|
|
130
|
+
export function normalizeState(state: State | string): State {
|
|
131
|
+
if (typeof state === 'string') {
|
|
132
|
+
return stringToState(state);
|
|
133
|
+
}
|
|
134
|
+
return state;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function normalizeLogLevel(logLevel: LogLevel | string): LogLevel {
|
|
138
|
+
if (typeof logLevel === 'string') {
|
|
139
|
+
return stringToLogLevel(logLevel);
|
|
140
|
+
}
|
|
141
|
+
return logLevel;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function normalizeCharacteristicSubscriptionType(
|
|
145
|
+
type: CharacteristicSubscriptionType | 'notification' | 'indication'
|
|
146
|
+
): CharacteristicSubscriptionType {
|
|
147
|
+
if (typeof type === 'string') {
|
|
148
|
+
return stringToCharacteristicSubscriptionType(type);
|
|
149
|
+
}
|
|
150
|
+
return type;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export function normalizeRefreshGattMoment(
|
|
154
|
+
moment: RefreshGattMoment | 'OnConnected'
|
|
155
|
+
): RefreshGattMoment {
|
|
156
|
+
if (typeof moment === 'string') {
|
|
157
|
+
return stringToRefreshGattMoment(moment);
|
|
158
|
+
}
|
|
159
|
+
return moment;
|
|
160
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compatibility layer for react-native-ble-nitro
|
|
3
|
+
*
|
|
4
|
+
* This module provides compatibility shims and converters to maintain
|
|
5
|
+
* 100% API compatibility with react-native-ble-plx while working with
|
|
6
|
+
* Nitro's type system constraints.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export * from './serviceData';
|
|
10
|
+
export * from './deviceWrapper';
|
|
11
|
+
export * from './constants';
|
|
12
|
+
|
|
13
|
+
// Explicitly export enum utilities to avoid conflicts
|
|
14
|
+
export {
|
|
15
|
+
stateToString,
|
|
16
|
+
stringToState,
|
|
17
|
+
logLevelToString,
|
|
18
|
+
stringToLogLevel,
|
|
19
|
+
characteristicSubscriptionTypeToString,
|
|
20
|
+
stringToCharacteristicSubscriptionType,
|
|
21
|
+
normalizeState,
|
|
22
|
+
normalizeLogLevel,
|
|
23
|
+
normalizeCharacteristicSubscriptionType,
|
|
24
|
+
} from './enums';
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Service Data compatibility layer
|
|
3
|
+
*
|
|
4
|
+
* Provides conversion between Nitro's structured ServiceDataEntry[] format
|
|
5
|
+
* and the original { [uuid: string]: Base64 } format from react-native-ble-plx
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { ServiceDataEntry, UUID, Base64 } from '../specs/types';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Convert ServiceDataEntry array to the original index signature format
|
|
12
|
+
*/
|
|
13
|
+
export function serviceDataArrayToMap(entries: ServiceDataEntry[] | null): { [uuid: string]: Base64 } | null {
|
|
14
|
+
if (!entries || entries.length === 0) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const result: { [uuid: string]: Base64 } = {};
|
|
19
|
+
entries.forEach(entry => {
|
|
20
|
+
result[entry.uuid] = entry.data;
|
|
21
|
+
});
|
|
22
|
+
return result;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Convert the original index signature format to ServiceDataEntry array
|
|
27
|
+
*/
|
|
28
|
+
export function serviceDataMapToArray(map: { [uuid: string]: Base64 } | null): ServiceDataEntry[] | null {
|
|
29
|
+
if (!map || Object.keys(map).length === 0) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return Object.entries(map).map(([uuid, data]) => ({
|
|
34
|
+
uuid: uuid as UUID,
|
|
35
|
+
data,
|
|
36
|
+
}));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Merge two service data maps (used in device updates)
|
|
41
|
+
*/
|
|
42
|
+
export function mergeServiceDataMaps(
|
|
43
|
+
existing: { [uuid: string]: Base64 } | null,
|
|
44
|
+
updates: { [uuid: string]: Base64 } | null
|
|
45
|
+
): { [uuid: string]: Base64 } | null {
|
|
46
|
+
if (!existing && !updates) return null;
|
|
47
|
+
if (!existing) return updates;
|
|
48
|
+
if (!updates) return existing;
|
|
49
|
+
|
|
50
|
+
return { ...existing, ...updates };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Merge two service data arrays (used in native updates)
|
|
55
|
+
*/
|
|
56
|
+
export function mergeServiceDataArrays(
|
|
57
|
+
existing: ServiceDataEntry[] | null,
|
|
58
|
+
updates: ServiceDataEntry[] | null
|
|
59
|
+
): ServiceDataEntry[] | null {
|
|
60
|
+
const existingMap = serviceDataArrayToMap(existing);
|
|
61
|
+
const updatesMap = serviceDataArrayToMap(updates);
|
|
62
|
+
const mergedMap = mergeServiceDataMaps(existingMap, updatesMap);
|
|
63
|
+
return serviceDataMapToArray(mergedMap);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Check if service data contains a specific service UUID
|
|
68
|
+
*/
|
|
69
|
+
export function hasServiceUUID(serviceData: { [uuid: string]: Base64 } | null, uuid: UUID): boolean {
|
|
70
|
+
return serviceData ? uuid in serviceData : false;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Get service data for a specific UUID
|
|
75
|
+
*/
|
|
76
|
+
export function getServiceData(serviceData: { [uuid: string]: Base64 } | null, uuid: UUID): Base64 | null {
|
|
77
|
+
return serviceData?.[uuid] || null;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Get all service UUIDs from service data
|
|
82
|
+
*/
|
|
83
|
+
export function getServiceUUIDs(serviceData: { [uuid: string]: Base64 } | null): UUID[] {
|
|
84
|
+
return serviceData ? Object.keys(serviceData) as UUID[] : [];
|
|
85
|
+
}
|