@react-native-ohos/react-native-ble-plx 3.2.1-rc.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.
Files changed (65) hide show
  1. package/LICENSE +202 -0
  2. package/README.OpenSource +11 -0
  3. package/README.md +9 -0
  4. package/app.plugin.js +1 -0
  5. package/harmony/rn_bleplx/build-profile.json5 +8 -0
  6. package/harmony/rn_bleplx/hvigorfile.ts +2 -0
  7. package/harmony/rn_bleplx/index.ets +27 -0
  8. package/harmony/rn_bleplx/obfuscation-rules.txt +18 -0
  9. package/harmony/rn_bleplx/oh-package.json5 +13 -0
  10. package/harmony/rn_bleplx/src/main/cpp/BlePlxPackage.h +36 -0
  11. package/harmony/rn_bleplx/src/main/cpp/CMakeLists.txt +9 -0
  12. package/harmony/rn_bleplx/src/main/cpp/generated/RNOH/generated/BaseReactNativeBlePlxPackage.h +65 -0
  13. package/harmony/rn_bleplx/src/main/cpp/generated/RNOH/generated/turbo_modules/BlePlx.cpp +59 -0
  14. package/harmony/rn_bleplx/src/main/cpp/generated/RNOH/generated/turbo_modules/BlePlx.h +16 -0
  15. package/harmony/rn_bleplx/src/main/cpp/generated/react/renderer/components/react_native_ble_plx/ComponentDescriptors.h +22 -0
  16. package/harmony/rn_bleplx/src/main/cpp/generated/react/renderer/components/react_native_ble_plx/EventEmitters.cpp +18 -0
  17. package/harmony/rn_bleplx/src/main/cpp/generated/react/renderer/components/react_native_ble_plx/EventEmitters.h +19 -0
  18. package/harmony/rn_bleplx/src/main/cpp/generated/react/renderer/components/react_native_ble_plx/Props.cpp +21 -0
  19. package/harmony/rn_bleplx/src/main/cpp/generated/react/renderer/components/react_native_ble_plx/Props.h +20 -0
  20. package/harmony/rn_bleplx/src/main/cpp/generated/react/renderer/components/react_native_ble_plx/ShadowNodes.cpp +19 -0
  21. package/harmony/rn_bleplx/src/main/cpp/generated/react/renderer/components/react_native_ble_plx/ShadowNodes.h +25 -0
  22. package/harmony/rn_bleplx/src/main/cpp/generated/react/renderer/components/react_native_ble_plx/States.cpp +18 -0
  23. package/harmony/rn_bleplx/src/main/cpp/generated/react/renderer/components/react_native_ble_plx/States.h +23 -0
  24. package/harmony/rn_bleplx/src/main/ets/BleDevice.ts +99 -0
  25. package/harmony/rn_bleplx/src/main/ets/BleModule.ts +1219 -0
  26. package/harmony/rn_bleplx/src/main/ets/BlePlxInterface.ts +27 -0
  27. package/harmony/rn_bleplx/src/main/ets/BlePlxModule.ts +246 -0
  28. package/harmony/rn_bleplx/src/main/ets/BlePlxPackage.ets +47 -0
  29. package/harmony/rn_bleplx/src/main/ets/BlePlxPackage.ts +46 -0
  30. package/harmony/rn_bleplx/src/main/ets/Characteristic.ts +179 -0
  31. package/harmony/rn_bleplx/src/main/ets/CommonConstants.ts +30 -0
  32. package/harmony/rn_bleplx/src/main/ets/Descriptor.ts +143 -0
  33. package/harmony/rn_bleplx/src/main/ets/Service.ts +85 -0
  34. package/harmony/rn_bleplx/src/main/ets/common/BleError.ts +90 -0
  35. package/harmony/rn_bleplx/src/main/ets/common/BleErrorToJsObjectConverter.ts +63 -0
  36. package/harmony/rn_bleplx/src/main/ets/common/BleEvent.ts +33 -0
  37. package/harmony/rn_bleplx/src/main/ets/common/BleUtils.ts +86 -0
  38. package/harmony/rn_bleplx/src/main/ets/common/IdGenerator.ts +49 -0
  39. package/harmony/rn_bleplx/src/main/ets/common/IdGeneratorKey.ts +70 -0
  40. package/harmony/rn_bleplx/src/main/ets/common/InstanceIdGenerator.ts +37 -0
  41. package/harmony/rn_bleplx/src/main/ets/common/Logger.ts +64 -0
  42. package/harmony/rn_bleplx/src/main/ets/common/PermissionHandler.ts +98 -0
  43. package/harmony/rn_bleplx/src/main/ets/common/ServiceFactory.ts +37 -0
  44. package/harmony/rn_bleplx/src/main/ets/generated/components/ts.ts +5 -0
  45. package/harmony/rn_bleplx/src/main/ets/generated/index.ets +5 -0
  46. package/harmony/rn_bleplx/src/main/ets/generated/ts.ts +6 -0
  47. package/harmony/rn_bleplx/src/main/ets/generated/turboModules/BlePlx.ts +100 -0
  48. package/harmony/rn_bleplx/src/main/ets/generated/turboModules/ts.ts +5 -0
  49. package/harmony/rn_bleplx/src/main/module.json5 +7 -0
  50. package/harmony/rn_bleplx/ts.ets +26 -0
  51. package/harmony/rn_bleplx/ts.ts +26 -0
  52. package/harmony/rn_bleplx.har +0 -0
  53. package/package.json +185 -0
  54. package/src/BleError.js +555 -0
  55. package/src/BleManager.js +1287 -0
  56. package/src/BleModule.js +847 -0
  57. package/src/Characteristic.js +166 -0
  58. package/src/Descriptor.js +82 -0
  59. package/src/Device.js +370 -0
  60. package/src/NativeBlePlx.ts +121 -0
  61. package/src/Service.js +188 -0
  62. package/src/TypeDefinition.js +360 -0
  63. package/src/Utils.js +26 -0
  64. package/src/index.d.ts +2113 -0
  65. package/src/index.js +20 -0
@@ -0,0 +1,1287 @@
1
+ // @flow
2
+ 'use strict'
3
+
4
+ import { Device } from './Device'
5
+ import { Service } from './Service'
6
+ import { Characteristic } from './Characteristic'
7
+ import { Descriptor } from './Descriptor'
8
+ import { State, LogLevel, type BleErrorCodeMessageMapping, ConnectionPriority } from './TypeDefinition'
9
+ // import { BleModule, EventEmitter } from './BleModule'
10
+ import { EventEmitter } from './BleModule'
11
+ import BleModule from './NativeBlePlx'
12
+ import {
13
+ parseBleError,
14
+ BleError,
15
+ BleErrorCode,
16
+ BleErrorCodeMessage,
17
+ BleATTErrorCode,
18
+ BleAndroidErrorCode,
19
+ BleIOSErrorCode
20
+ } from './BleError'
21
+ import type { NativeDevice, NativeCharacteristic, NativeDescriptor, NativeBleRestoredState } from './BleModule'
22
+ import type {
23
+ Subscription,
24
+ DeviceId,
25
+ Identifier,
26
+ UUID,
27
+ TransactionId,
28
+ Base64,
29
+ ScanOptions,
30
+ ConnectionOptions,
31
+ BleManagerOptions
32
+ } from './TypeDefinition'
33
+ import { Platform } from 'react-native'
34
+
35
+ const enableDisableDeprecatedMessage =
36
+ 'react-native-ble-plx: The enable and disable feature is no longer supported. In Android SDK 31+ there were major changes in permissions, which may cause problems with these functions, and in SDK 33+ they were completely removed.'
37
+
38
+ /**
39
+ *
40
+ * BleManager is an entry point for react-native-ble-plx library. It provides all means to discover and work with
41
+ * {@link Device} instances. It should be initialized only once with `new` keyword and method
42
+ * {@link #blemanagerdestroy|destroy()} should be called on its instance when user wants to deallocate all resources.
43
+ *
44
+ * In case you want to properly support Background Mode, you should provide `restoreStateIdentifier` and
45
+ * `restoreStateFunction` in {@link BleManagerOptions}.
46
+ *
47
+ * @example
48
+ * const manager = new BleManager();
49
+ * // ... work with BLE manager ...
50
+ * manager.destroy();
51
+ */
52
+ export class BleManager {
53
+ // Scan subscriptions
54
+ // $FlowIssue[missing-type-arg]
55
+ _scanEventSubscription: ?EventEmitter
56
+ // Listening to BleModule events
57
+ // $FlowIssue[missing-type-arg]
58
+ _eventEmitter: EventEmitter
59
+ // Unique identifier used to create internal transactionIds
60
+ _uniqueId: number
61
+ // Map of active promises with functions to forcibly cancel them
62
+ _activePromises: { [id: string]: (error: BleError) => void }
63
+ // Map of active subscriptions
64
+ _activeSubscriptions: { [id: string]: Subscription }
65
+
66
+ // Map of error codes to error messages
67
+ _errorCodesToMessagesMapping: BleErrorCodeMessageMapping
68
+
69
+ /**
70
+ * Creates an instance of {@link BleManager}.
71
+ */
72
+ constructor(options: BleManagerOptions = {}) {
73
+ this._eventEmitter = new EventEmitter(BleModule)
74
+ this._uniqueId = 0
75
+ this._activePromises = {}
76
+ this._activeSubscriptions = {}
77
+
78
+ const restoreStateFunction = options.restoreStateFunction
79
+ if (restoreStateFunction != null && options.restoreStateIdentifier != null) {
80
+ // $FlowIssue[prop-missing]
81
+ this._activeSubscriptions[this._nextUniqueID()] = this._eventEmitter.addListener(
82
+ Platform.OS === 'harmony' ? 'RestoreStateEvent' : BleModule.RestoreStateEvent,
83
+ (nativeRestoredState: NativeBleRestoredState) => {
84
+ if (nativeRestoredState == null) {
85
+ restoreStateFunction(null)
86
+ return
87
+ }
88
+ restoreStateFunction({
89
+ connectedPeripherals: nativeRestoredState.connectedPeripherals.map(
90
+ nativeDevice => new Device(nativeDevice, this)
91
+ )
92
+ })
93
+ }
94
+ )
95
+ }
96
+
97
+ this._errorCodesToMessagesMapping = options.errorCodesToMessagesMapping
98
+ ? options.errorCodesToMessagesMapping
99
+ : BleErrorCodeMessage
100
+
101
+ BleModule.createClient(options.restoreStateIdentifier || null)
102
+ }
103
+
104
+ /**
105
+ * Destroys all promises which are in progress.
106
+ * @private
107
+ */
108
+ _destroyPromises() {
109
+ const destroyedError = new BleError(
110
+ {
111
+ errorCode: BleErrorCode.BluetoothManagerDestroyed,
112
+ attErrorCode: (null: ?$Values<typeof BleATTErrorCode>),
113
+ iosErrorCode: (null: ?$Values<typeof BleIOSErrorCode>),
114
+ androidErrorCode: (null: ?$Values<typeof BleAndroidErrorCode>),
115
+ reason: (null: ?string)
116
+ },
117
+ this._errorCodesToMessagesMapping
118
+ )
119
+ for (const id in this._activePromises) {
120
+ this._activePromises[id](destroyedError)
121
+ }
122
+ }
123
+
124
+ /**
125
+ * Destroys all subscriptions.
126
+ * @private
127
+ */
128
+ _destroySubscriptions() {
129
+ for (const id in this._activeSubscriptions) {
130
+ this._activeSubscriptions[id].remove()
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Destroys {@link BleManager} instance. A new instance needs to be created to continue working with
136
+ * this library. All operations which were in progress completes with
137
+ * @returns {Promise<void>} Promise may return an error when the function cannot be called.
138
+ * {@link #bleerrorcodebluetoothmanagerdestroyed|BluetoothManagerDestroyed} error code.
139
+ */
140
+ destroy = async (): Promise<void> => {
141
+ const response = await this._callPromise(BleModule.destroyClient())
142
+
143
+ // Unsubscribe from any subscriptions
144
+ if (this._scanEventSubscription != null) {
145
+ this._scanEventSubscription.remove()
146
+ this._scanEventSubscription = null
147
+ }
148
+ this._destroySubscriptions()
149
+
150
+ // Destroy all promises
151
+ this._destroyPromises()
152
+
153
+ return response
154
+ }
155
+
156
+ /**
157
+ * Generates new unique identifier to be used internally.
158
+ *
159
+ * @returns {string} New identifier.
160
+ * @private
161
+ */
162
+ _nextUniqueID(): string {
163
+ this._uniqueId += 1
164
+ return this._uniqueId.toString()
165
+ }
166
+
167
+ /**
168
+ * Calls promise and checks if it completed successfully
169
+ *
170
+ * @param {Promise<T>} promise Promise to be called
171
+ * @returns {Promise<T>} Value of called promise.
172
+ * @private
173
+ */
174
+ async _callPromise<T>(promise: Promise<T>): Promise<T> {
175
+ const id = this._nextUniqueID()
176
+ try {
177
+ const destroyPromise = new Promise((resolve, reject) => {
178
+ this._activePromises[id] = reject
179
+ })
180
+ const value = await Promise.race([destroyPromise, promise])
181
+ delete this._activePromises[id]
182
+ // $FlowIssue[incompatible-return]
183
+ return value
184
+ } catch (error) {
185
+ delete this._activePromises[id]
186
+ throw parseBleError(error.message, this._errorCodesToMessagesMapping)
187
+ }
188
+ }
189
+
190
+ // Mark: Common ------------------------------------------------------------------------------------------------------
191
+
192
+ /**
193
+ * Sets new log level for native module's logging mechanism.
194
+ * @param {LogLevel} logLevel New log level to be set.
195
+ * @returns {Promise<LogLevel>} Current log level.
196
+ */
197
+ setLogLevel(logLevel: $Keys<typeof LogLevel>): Promise<$Keys<typeof LogLevel> | void> {
198
+ return this._callPromise(BleModule.setLogLevel(logLevel))
199
+ }
200
+
201
+ /**
202
+ * Get current log level for native module's logging mechanism.
203
+ * @returns {Promise<LogLevel>} Current log level.
204
+ */
205
+ logLevel(): Promise<$Keys<typeof LogLevel>> {
206
+ return this._callPromise(BleModule.logLevel())
207
+ }
208
+
209
+ /**
210
+ * Cancels pending transaction.
211
+ *
212
+ * Few operations such as monitoring characteristic's value changes can be cancelled by a user. Basically every API
213
+ * entry which accepts `transactionId` allows to call `cancelTransaction` function. When cancelled operation is a
214
+ * promise or a callback which registers errors, {@link #bleerror|BleError} with error code
215
+ * {@link #bleerrorcodeoperationcancelled|OperationCancelled} will be emitted in that case. Cancelling transaction
216
+ * which doesn't exist is ignored.
217
+ *
218
+ * @example
219
+ * const transactionId = 'monitor_battery';
220
+ *
221
+ * // Monitor battery notifications
222
+ * manager.monitorCharacteristicForDevice(
223
+ * device.id, '180F', '2A19',
224
+ * (error, characteristic) => {
225
+ * // Handle battery level changes...
226
+ * }, transactionId);
227
+ *
228
+ * // Cancel after specified amount of time
229
+ * setTimeout(() => manager.cancelTransaction(transactionId), 2000);
230
+ *
231
+ * @param {TransactionId} transactionId Id of pending transactions.
232
+ * @returns {Promise<void>}
233
+ */
234
+ cancelTransaction(transactionId: TransactionId) {
235
+ return this._callPromise(BleModule.cancelTransaction(transactionId))
236
+ }
237
+
238
+ // Mark: Monitoring state --------------------------------------------------------------------------------------------
239
+
240
+ /**
241
+ * Enable Bluetooth. This function blocks until BLE is in PoweredOn state. [Android only]
242
+ *
243
+ * @param {?TransactionId} transactionId Transaction handle used to cancel operation
244
+ * @returns {Promise<BleManager>} Promise completes when state transition was successful.
245
+ */
246
+ async enable(transactionId: ?TransactionId): Promise<BleManager> {
247
+ if (!transactionId) {
248
+ transactionId = this._nextUniqueID()
249
+ }
250
+ await this._callPromise(BleModule.enable(transactionId))
251
+ return this
252
+ }
253
+
254
+ /**
255
+ * Deprecated
256
+ * Disable Bluetooth. This function blocks until BLE is in PoweredOff state. [Android only]
257
+ *
258
+ * @param {?TransactionId} transactionId Transaction handle used to cancel operation
259
+ * @returns {Promise<BleManager>} Promise completes when state transition was successful.
260
+ */
261
+ async disable(transactionId: ?TransactionId): Promise<BleManager> {
262
+ console.warn(enableDisableDeprecatedMessage)
263
+ if (!transactionId) {
264
+ transactionId = this._nextUniqueID()
265
+ }
266
+ await this._callPromise(BleModule.disable(transactionId))
267
+ return this
268
+ }
269
+
270
+ /**
271
+ * Current, global {@link State} of a {@link BleManager}. All APIs are working only when active state
272
+ * is "PoweredOn".
273
+ *
274
+ * @returns {Promise<State>} Promise which emits current state of BleManager.
275
+ */
276
+ state = (): Promise<$Keys<typeof State>> => {
277
+ return this._callPromise(BleModule.state())
278
+ }
279
+
280
+ /**
281
+ * Notifies about {@link State} changes of a {@link BleManager}.
282
+ *
283
+ * @example
284
+ * const subscription = this.manager.onStateChange((state) => {
285
+ * if (state === 'PoweredOn') {
286
+ * this.scanAndConnect();
287
+ * subscription.remove();
288
+ * }
289
+ * }, true);
290
+ *
291
+ * @param {function(newState: State)} listener Callback which emits state changes of BLE Manager.
292
+ * Look at {@link State} for possible values.
293
+ * @param {boolean} [emitCurrentState=false] If true, current state will be emitted as well. Defaults to false.
294
+ *
295
+ * @returns {Subscription} Subscription on which `remove()` function can be called to unsubscribe.
296
+ */
297
+ onStateChange = (
298
+ listener: (newState: $Keys<typeof State>) => void,
299
+ emitCurrentState: boolean = false
300
+ ): Subscription => {
301
+ const subscription: Subscription = this._eventEmitter.addListener(Platform.OS === 'harmony' ? 'StateChangeEvent' : BleModule.StateChangeEvent, listener)
302
+ const id = this._nextUniqueID()
303
+ var wrappedSubscription: Subscription
304
+
305
+ if (emitCurrentState) {
306
+ var cancelled = false
307
+ this._callPromise(this.state()).then(currentState => {
308
+ console.log(currentState)
309
+ if (!cancelled) {
310
+ listener(currentState)
311
+ }
312
+ })
313
+
314
+ wrappedSubscription = {
315
+ remove: () => {
316
+ if (this._activeSubscriptions[id] != null) {
317
+ cancelled = true
318
+ delete this._activeSubscriptions[id]
319
+ subscription.remove()
320
+ }
321
+ }
322
+ }
323
+ } else {
324
+ wrappedSubscription = {
325
+ remove: () => {
326
+ if (this._activeSubscriptions[id] != null) {
327
+ delete this._activeSubscriptions[id]
328
+ subscription.remove()
329
+ }
330
+ }
331
+ }
332
+ }
333
+
334
+ this._activeSubscriptions[id] = wrappedSubscription
335
+ return wrappedSubscription
336
+ }
337
+
338
+ // Mark: Scanning ----------------------------------------------------------------------------------------------------
339
+
340
+ /**
341
+ * Starts device scanning. When previous scan is in progress it will be stopped before executing this command.
342
+ *
343
+ * @param {?Array<UUID>} UUIDs Array of strings containing {@link UUID}s of {@link Service}s which are registered in
344
+ * scanned {@link Device}. If `null` is passed, all available {@link Device}s will be scanned.
345
+ * @param {?ScanOptions} options Optional configuration for scanning operation.
346
+ * @param {function(error: ?BleError, scannedDevice: ?Device)} listener Function which will be called for every scanned
347
+ * @returns {Promise<void>} Promise may return an error when the function cannot be called.
348
+ * {@link Device} (devices may be scanned multiple times). It's first argument is potential {@link Error} which is set
349
+ * to non `null` value when scanning failed. You have to start scanning process again if that happens. Second argument
350
+ * is a scanned {@link Device}.
351
+ * @returns {Promise<void>} the promise may be rejected if the operation is impossible to perform.
352
+ */
353
+ async startDeviceScan(
354
+ UUIDs: ?Array<UUID>,
355
+ options: ?ScanOptions,
356
+ listener: (error: ?BleError, scannedDevice: ?Device) => Promise<void>
357
+ ) {
358
+ const scanListener = ([error, nativeDevice]: [?string, ?NativeDevice]) => {
359
+ listener(
360
+ error ? parseBleError(error, this._errorCodesToMessagesMapping) : null,
361
+ nativeDevice ? new Device(nativeDevice, this) : null
362
+ )
363
+ }
364
+ // $FlowFixMe: Flow cannot deduce EmitterSubscription type.
365
+ this._scanEventSubscription = this._eventEmitter.addListener(Platform.OS === 'harmony' ? 'ScanEvent' : BleModule.ScanEvent, scanListener)
366
+
367
+ return this._callPromise(BleModule.startDeviceScan(UUIDs, options))
368
+ }
369
+
370
+ /**
371
+ * Stops {@link Device} scan if in progress.
372
+ * @returns {Promise<void>} the promise may be rejected if the operation is impossible to perform.
373
+ */
374
+ stopDeviceScan = async (): Promise<void> => {
375
+ if (this._scanEventSubscription != null) {
376
+ this._scanEventSubscription.remove()
377
+ this._scanEventSubscription = null
378
+ }
379
+
380
+ return this._callPromise(BleModule.stopDeviceScan())
381
+ }
382
+
383
+ /**
384
+ * Request a connection parameter update. This functions may update connection parameters on Android API level 21 or
385
+ * above.
386
+ *
387
+ * @param {DeviceId} deviceIdentifier Device identifier.
388
+ * @param {ConnectionPriority} connectionPriority: Connection priority.
389
+ * @param {?TransactionId} transactionId Transaction handle used to cancel operation.
390
+ * @returns {Promise<Device>} Connected device.
391
+ */
392
+ async requestConnectionPriorityForDevice(
393
+ deviceIdentifier: DeviceId,
394
+ connectionPriority: $Values<typeof ConnectionPriority>,
395
+ transactionId: ?TransactionId
396
+ ): Promise<Device> {
397
+ if (!transactionId) {
398
+ transactionId = this._nextUniqueID()
399
+ }
400
+ const nativeDevice = await this._callPromise(
401
+ BleModule.requestConnectionPriorityForDevice(deviceIdentifier, connectionPriority, transactionId)
402
+ )
403
+ return new Device(nativeDevice, this)
404
+ }
405
+
406
+ /**
407
+ * Reads RSSI for connected device.
408
+ *
409
+ * @param {DeviceId} deviceIdentifier Device identifier.
410
+ * @param {?TransactionId} transactionId Transaction handle used to cancel operation
411
+ * @returns {Promise<Device>} Connected device with updated RSSI value.
412
+ */
413
+ async readRSSIForDevice(deviceIdentifier: DeviceId, transactionId: ?TransactionId): Promise<Device> {
414
+ if (!transactionId) {
415
+ transactionId = this._nextUniqueID()
416
+ }
417
+ const nativeDevice = await this._callPromise(BleModule.readRSSIForDevice(deviceIdentifier, transactionId))
418
+ return new Device(nativeDevice, this)
419
+ }
420
+
421
+ /**
422
+ * Request new MTU value for this device. This function currently is not doing anything
423
+ * on iOS platform as MTU exchange is done automatically. Since Android 14,
424
+ * mtu management has been changed, more information can be found at the link:
425
+ * https://developer.android.com/about/versions/14/behavior-changes-all#mtu-set-to-517
426
+ * @param {DeviceId} deviceIdentifier Device identifier.
427
+ * @param {number} mtu New MTU to negotiate.
428
+ * @param {?TransactionId} transactionId Transaction handle used to cancel operation
429
+ * @returns {Promise<Device>} Device with updated MTU size. Default value is 23 (517 since Android 14)..
430
+ */
431
+ async requestMTUForDevice(deviceIdentifier: DeviceId, mtu: number, transactionId: ?TransactionId): Promise<Device> {
432
+ if (!transactionId) {
433
+ transactionId = this._nextUniqueID()
434
+ }
435
+ const nativeDevice = await this._callPromise(BleModule.requestMTUForDevice(deviceIdentifier, mtu, transactionId))
436
+ return new Device(nativeDevice, this)
437
+ }
438
+
439
+ // Mark: Connection management ---------------------------------------------------------------------------------------
440
+
441
+ /**
442
+ * Returns a list of known devices by their identifiers.
443
+ * @param {Array<DeviceId>} deviceIdentifiers List of device identifiers.
444
+ * @returns {Promise<Array<Device>>} List of known devices by their identifiers.
445
+ */
446
+ async devices(deviceIdentifiers: Array<DeviceId>): Promise<Array<Device>> {
447
+ const nativeDevices = await this._callPromise(BleModule.devices(deviceIdentifiers))
448
+ return nativeDevices.map((nativeDevice: NativeDevice) => {
449
+ return new Device(nativeDevice, this)
450
+ })
451
+ }
452
+
453
+ /**
454
+ * Returns a list of the peripherals (containing any of the specified services) currently connected to the system
455
+ * which have discovered services. Returned devices **may not be connected** to your application. Make sure to check
456
+ * if that's the case with function {@link #blemanagerisdeviceconnected|isDeviceConnected}.
457
+ * @param {Array<UUID>} serviceUUIDs List of service UUIDs. Device must contain at least one of them to be listed.
458
+ * @returns {Promise<Array<Device>>} List of known devices with discovered services as stated in the parameter.
459
+ */
460
+ async connectedDevices(serviceUUIDs: Array<UUID>): Promise<Array<Device>> {
461
+ const nativeDevices = await this._callPromise(BleModule.connectedDevices(serviceUUIDs))
462
+ return nativeDevices.map((nativeDevice: NativeDevice) => {
463
+ return new Device(nativeDevice, this)
464
+ })
465
+ }
466
+
467
+ // Mark: Connection management ---------------------------------------------------------------------------------------
468
+
469
+ /**
470
+ * Connects to {@link Device} with provided ID.
471
+ *
472
+ * @param {DeviceId} deviceIdentifier {@link Device} identifier.
473
+ * @param {?ConnectionOptions} options Platform specific options for connection establishment.
474
+ * @returns {Promise<Device>} Connected {@link Device} object if successful.
475
+ */
476
+ async connectToDevice(deviceIdentifier: DeviceId, options: ?ConnectionOptions): Promise<Device> {
477
+ if (Platform.OS === 'android' && (await this.isDeviceConnected(deviceIdentifier))) {
478
+ await this.cancelDeviceConnection(deviceIdentifier)
479
+ }
480
+ const nativeDevice = await this._callPromise(BleModule.connectToDevice(deviceIdentifier, options))
481
+ return new Device(nativeDevice, this)
482
+ }
483
+
484
+ /**
485
+ * Disconnects from {@link Device} if it's connected or cancels pending connection.
486
+ *
487
+ * @param {DeviceId} deviceIdentifier {@link Device} identifier to be closed.
488
+ * @returns {Promise<Device>} Returns closed {@link Device} when operation is successful.
489
+ */
490
+ async cancelDeviceConnection(deviceIdentifier: DeviceId): Promise<Device> {
491
+ const nativeDevice = await this._callPromise(BleModule.cancelDeviceConnection(deviceIdentifier))
492
+ return new Device(nativeDevice, this)
493
+ }
494
+
495
+ /**
496
+ * Monitors if {@link Device} was disconnected due to any errors or connection problems.
497
+ *
498
+ * @param {DeviceId} deviceIdentifier {@link Device} identifier to be monitored.
499
+ * @param {function(error: ?BleError, device: Device)} listener - callback returning error as a reason of disconnection
500
+ * if available and {@link Device} object. If an error is null, that means the connection was terminated by
501
+ * {@link #blemanagercanceldeviceconnection|bleManager.cancelDeviceConnection()} call.
502
+ * @returns {Subscription} Subscription on which `remove()` function can be called to unsubscribe.
503
+ */
504
+ onDeviceDisconnected(deviceIdentifier: DeviceId, listener: (error: ?BleError, device: Device) => void): Subscription {
505
+ const disconnectionListener = ([error, nativeDevice]: [?string, NativeDevice]) => {
506
+ if (deviceIdentifier !== nativeDevice.id) {
507
+ return
508
+ }
509
+ listener(error ? parseBleError(error, this._errorCodesToMessagesMapping) : null, new Device(nativeDevice, this))
510
+ }
511
+
512
+ const subscription: Subscription = this._eventEmitter.addListener(
513
+ Platform.OS === 'harmony' ? 'DisconnectionEvent' : BleModule.DisconnectionEvent,
514
+ disconnectionListener
515
+ )
516
+
517
+ const id = this._nextUniqueID()
518
+ const wrappedSubscription = {
519
+ remove: () => {
520
+ if (this._activeSubscriptions[id] != null) {
521
+ delete this._activeSubscriptions[id]
522
+ subscription.remove()
523
+ }
524
+ }
525
+ }
526
+ this._activeSubscriptions[id] = wrappedSubscription
527
+ return wrappedSubscription
528
+ }
529
+
530
+ /**
531
+ * Check connection state of a {@link Device}.
532
+ *
533
+ * @param {DeviceId} deviceIdentifier {@link Device} identifier.
534
+ * @returns {Promise<boolean>} Promise which emits `true` if device is connected, and `false` otherwise.
535
+ */
536
+ isDeviceConnected(deviceIdentifier: DeviceId): Promise<boolean> {
537
+ return this._callPromise(BleModule.isDeviceConnected(deviceIdentifier))
538
+ }
539
+
540
+ // Mark: Discovery ---------------------------------------------------------------------------------------------------
541
+
542
+ /**
543
+ * Discovers all {@link Service}s, {@link Characteristic}s and {@link Descriptor}s for {@link Device}.
544
+ *
545
+ * @param {DeviceId} deviceIdentifier {@link Device} identifier.
546
+ * @param {?TransactionId} transactionId Transaction handle used to cancel operation
547
+ * @returns {Promise<Device>} Promise which emits {@link Device} object if all available services and
548
+ * characteristics have been discovered.
549
+ */
550
+ async discoverAllServicesAndCharacteristicsForDevice(
551
+ deviceIdentifier: DeviceId,
552
+ transactionId: ?TransactionId
553
+ ): Promise<Device> {
554
+ if (!transactionId) {
555
+ transactionId = this._nextUniqueID()
556
+ }
557
+ const nativeDevice = await this._callPromise(
558
+ BleModule.discoverAllServicesAndCharacteristicsForDevice(deviceIdentifier, transactionId)
559
+ )
560
+ return new Device(nativeDevice, this)
561
+ }
562
+
563
+ // Mark: Service and characteristic getters --------------------------------------------------------------------------
564
+
565
+ /**
566
+ * List of discovered {@link Service}s for {@link Device}.
567
+ *
568
+ * @param {DeviceId} deviceIdentifier {@link Device} identifier.
569
+ * @returns {Promise<Array<Service>>} Promise which emits array of {@link Service} objects which are discovered for a
570
+ * {@link Device}.
571
+ */
572
+ async servicesForDevice(deviceIdentifier: DeviceId): Promise<Array<Service>> {
573
+ const services = await this._callPromise(BleModule.servicesForDevice(deviceIdentifier))
574
+ return services.map(nativeService => {
575
+ return new Service(nativeService, this)
576
+ })
577
+ }
578
+
579
+ /**
580
+ * List of discovered {@link Characteristic}s for given {@link Device} and {@link Service}.
581
+ *
582
+ * @param {DeviceId} deviceIdentifier {@link Device} identifier.
583
+ * @param {UUID} serviceUUID {@link Service} UUID.
584
+ * @returns {Promise<Array<Characteristic>>} Promise which emits array of {@link Characteristic} objects which are
585
+ * discovered for a {@link Device} in specified {@link Service}.
586
+ */
587
+ characteristicsForDevice(deviceIdentifier: DeviceId, serviceUUID: UUID): Promise<Array<Characteristic>> {
588
+ return this._handleCharacteristics(BleModule.characteristicsForDevice(deviceIdentifier, serviceUUID))
589
+ }
590
+
591
+ /**
592
+ * List of discovered {@link Characteristic}s for unique {@link Service}.
593
+ *
594
+ * @param {Identifier} serviceIdentifier {@link Service} ID.
595
+ * @returns {Promise<Array<Characteristic>>} Promise which emits array of {@link Characteristic} objects which are
596
+ * discovered in unique {@link Service}.
597
+ * @private
598
+ */
599
+ _characteristicsForService(serviceIdentifier: Identifier): Promise<Array<Characteristic>> {
600
+ return this._handleCharacteristics(BleModule.characteristicsForService(serviceIdentifier))
601
+ }
602
+
603
+ /**
604
+ * Common code for handling NativeCharacteristic fetches.
605
+ *
606
+ * @param {Promise<Array<NativeCharacteristic>>} characteristicsPromise Native characteristics.
607
+ * @returns {Promise<Array<Characteristic>>} Promise which emits array of {@link Characteristic} objects which are
608
+ * discovered in unique {@link Service}.
609
+ * @private
610
+ */
611
+ async _handleCharacteristics(
612
+ characteristicsPromise: Promise<Array<NativeCharacteristic>>
613
+ ): Promise<Array<Characteristic>> {
614
+ const characteristics = await this._callPromise(characteristicsPromise)
615
+ return characteristics.map(nativeCharacteristic => {
616
+ return new Characteristic(nativeCharacteristic, this)
617
+ })
618
+ }
619
+
620
+ /**
621
+ * List of discovered {@link Descriptor}s for given {@link Device}, {@link Service} and {@link Characteristic}.
622
+ *
623
+ * @param {DeviceId} deviceIdentifier {@link Device} identifier.
624
+ * @param {UUID} serviceUUID {@link Service} UUID.
625
+ * @param {UUID} characteristicUUID {@link Characteristic} UUID.
626
+ * @returns {Promise<Array<Descriptor>>} Promise which emits array of {@link Descriptor} objects which are
627
+ * discovered for a {@link Device}, {@link Service} in specified {@link Characteristic}.
628
+ */
629
+ descriptorsForDevice(
630
+ deviceIdentifier: DeviceId,
631
+ serviceUUID: UUID,
632
+ characteristicUUID: UUID
633
+ ): Promise<Array<Descriptor>> {
634
+ return this._handleDescriptors(BleModule.descriptorsForDevice(deviceIdentifier, serviceUUID, characteristicUUID))
635
+ }
636
+
637
+ /**
638
+ * List of discovered {@link Descriptor}s for given {@link Service} and {@link Characteristic}.
639
+ *
640
+ * @param {Identifier} serviceIdentifier {@link Service} identifier.
641
+ * @param {UUID} characteristicUUID {@link Characteristic} UUID.
642
+ * @returns {Promise<Array<Descriptor>>} Promise which emits array of {@link Descriptor} objects which are
643
+ * discovered for a {@link Service} in specified {@link Characteristic}.
644
+ * @private
645
+ */
646
+ _descriptorsForService(serviceIdentifier: Identifier, characteristicUUID: UUID): Promise<Array<Descriptor>> {
647
+ return this._handleDescriptors(BleModule.descriptorsForService(serviceIdentifier, characteristicUUID))
648
+ }
649
+
650
+ /**
651
+ * List of discovered {@link Descriptor}s for given {@link Characteristic}.
652
+ *
653
+ * @param {Identifier} characteristicIdentifier {@link Characteristic} identifier.
654
+ * @returns {Promise<Array<Descriptor>>} Promise which emits array of {@link Descriptor} objects which are
655
+ * discovered in specified {@link Characteristic}.
656
+ * @private
657
+ */
658
+ _descriptorsForCharacteristic(characteristicIdentifier: Identifier): Promise<Array<Descriptor>> {
659
+ return this._handleDescriptors(BleModule.descriptorsForCharacteristic(characteristicIdentifier))
660
+ }
661
+
662
+ /**
663
+ * Common code for handling NativeDescriptor fetches.
664
+ * @param {Promise<Array<NativeDescriptor>>} descriptorsPromise Native descriptors.
665
+ * @returns {Promise<Array<Descriptor>>} Promise which emits array of {@link Descriptor} objects which are
666
+ * discovered in unique {@link Characteristic}.
667
+ * @private
668
+ */
669
+ async _handleDescriptors(descriptorsPromise: Promise<Array<NativeDescriptor>>): Promise<Array<Descriptor>> {
670
+ const descriptors = await this._callPromise(descriptorsPromise)
671
+ return descriptors.map(nativeDescriptor => {
672
+ return new Descriptor(nativeDescriptor, this)
673
+ })
674
+ }
675
+
676
+ // Mark: Characteristics operations ----------------------------------------------------------------------------------
677
+
678
+ /**
679
+ * Read {@link Characteristic} value.
680
+ *
681
+ * @param {DeviceId} deviceIdentifier {@link Device} identifier.
682
+ * @param {UUID} serviceUUID {@link Service} UUID.
683
+ * @param {UUID} characteristicUUID {@link Characteristic} UUID.
684
+ * @param {?TransactionId} transactionId optional `transactionId` which can be used in
685
+ * {@link #blemanagercanceltransaction|cancelTransaction()} function.
686
+ * @returns {Promise<Characteristic>} Promise which emits first {@link Characteristic} object matching specified
687
+ * UUID paths. Latest value of {@link Characteristic} will be stored inside returned object.
688
+ */
689
+ async readCharacteristicForDevice(
690
+ deviceIdentifier: DeviceId,
691
+ serviceUUID: UUID,
692
+ characteristicUUID: UUID,
693
+ transactionId: ?TransactionId
694
+ ): Promise<Characteristic> {
695
+ if (!transactionId) {
696
+ transactionId = this._nextUniqueID()
697
+ }
698
+ const nativeCharacteristic = await this._callPromise(
699
+ BleModule.readCharacteristicForDevice(deviceIdentifier, serviceUUID, characteristicUUID, transactionId)
700
+ )
701
+ return new Characteristic(nativeCharacteristic, this)
702
+ }
703
+
704
+ /**
705
+ * Read {@link Characteristic} value.
706
+ *
707
+ * @param {Identifier} serviceIdentifier {@link Service} ID.
708
+ * @param {UUID} characteristicUUID {@link Characteristic} UUID.
709
+ * @param {?TransactionId} transactionId optional `transactionId` which can be used in
710
+ * {@link #blemanagercanceltransaction|cancelTransaction()} function.
711
+ * @returns {Promise<Characteristic>} Promise which emits first {@link Characteristic} object matching specified
712
+ * UUID paths. Latest value of {@link Characteristic} will be stored inside returned object.
713
+ * @private
714
+ */
715
+ async _readCharacteristicForService(
716
+ serviceIdentifier: Identifier,
717
+ characteristicUUID: UUID,
718
+ transactionId: ?TransactionId
719
+ ): Promise<Characteristic> {
720
+ if (!transactionId) {
721
+ transactionId = this._nextUniqueID()
722
+ }
723
+ const nativeCharacteristic = await this._callPromise(
724
+ BleModule.readCharacteristicForService(serviceIdentifier, characteristicUUID, transactionId)
725
+ )
726
+ return new Characteristic(nativeCharacteristic, this)
727
+ }
728
+
729
+ /**
730
+ * Read {@link Characteristic} value.
731
+ *
732
+ * @param {Identifier} characteristicIdentifier {@link Characteristic} ID.
733
+ * @param {?TransactionId} transactionId optional `transactionId` which can be used in
734
+ * {@link #blemanagercanceltransaction|cancelTransaction()} function.
735
+ * @returns {Promise<Characteristic>} Promise which emits first {@link Characteristic} object matching specified ID.
736
+ * Latest value of {@link Characteristic} will be stored inside returned object.
737
+ * @private
738
+ */
739
+ async _readCharacteristic(
740
+ characteristicIdentifier: Identifier,
741
+ transactionId: ?TransactionId
742
+ ): Promise<Characteristic> {
743
+ if (!transactionId) {
744
+ transactionId = this._nextUniqueID()
745
+ }
746
+ const nativeCharacteristic = await this._callPromise(
747
+ BleModule.readCharacteristic(characteristicIdentifier, transactionId)
748
+ )
749
+ return new Characteristic(nativeCharacteristic, this)
750
+ }
751
+
752
+ /**
753
+ * Write {@link Characteristic} value with response.
754
+ *
755
+ * @param {DeviceId} deviceIdentifier {@link Device} identifier.
756
+ * @param {UUID} serviceUUID {@link Service} UUID.
757
+ * @param {UUID} characteristicUUID {@link Characteristic} UUID.
758
+ * @param {Base64} base64Value Value in Base64 format.
759
+ * @param {?TransactionId} transactionId optional `transactionId` which can be used in
760
+ * {@link #blemanagercanceltransaction|cancelTransaction()} function.
761
+ * @returns {Promise<Characteristic>} Promise which emits first {@link Characteristic} object matching specified
762
+ * UUID paths. Latest value of characteristic may not be stored inside returned object.
763
+ */
764
+ async writeCharacteristicWithResponseForDevice(
765
+ deviceIdentifier: DeviceId,
766
+ serviceUUID: UUID,
767
+ characteristicUUID: UUID,
768
+ base64Value: Base64,
769
+ transactionId: ?TransactionId
770
+ ): Promise<Characteristic> {
771
+ if (!transactionId) {
772
+ transactionId = this._nextUniqueID()
773
+ }
774
+ const nativeCharacteristic = await this._callPromise(
775
+ BleModule.writeCharacteristicForDevice(
776
+ deviceIdentifier,
777
+ serviceUUID,
778
+ characteristicUUID,
779
+ base64Value,
780
+ true,
781
+ transactionId
782
+ )
783
+ )
784
+ return new Characteristic(nativeCharacteristic, this)
785
+ }
786
+
787
+ /**
788
+ * Write {@link Characteristic} value with response.
789
+ *
790
+ * @param {Identifier} serviceIdentifier {@link Service} ID.
791
+ * @param {UUID} characteristicUUID {@link Characteristic} UUID.
792
+ * @param {Base64} base64Value Value in Base64 format.
793
+ * @param {?TransactionId} transactionId optional `transactionId` which can be used in
794
+ * {@link #blemanagercanceltransaction|cancelTransaction()} function.
795
+ * @returns {Promise<Characteristic>} Promise which emits first {@link Characteristic} object matching specified
796
+ * UUID paths. Latest value of characteristic may not be stored inside returned object.
797
+ * @private
798
+ */
799
+ async _writeCharacteristicWithResponseForService(
800
+ serviceIdentifier: Identifier,
801
+ characteristicUUID: UUID,
802
+ base64Value: Base64,
803
+ transactionId: ?TransactionId
804
+ ): Promise<Characteristic> {
805
+ if (!transactionId) {
806
+ transactionId = this._nextUniqueID()
807
+ }
808
+ const nativeCharacteristic = await this._callPromise(
809
+ BleModule.writeCharacteristicForService(serviceIdentifier, characteristicUUID, base64Value, true, transactionId)
810
+ )
811
+ return new Characteristic(nativeCharacteristic, this)
812
+ }
813
+
814
+ /**
815
+ * Write {@link Characteristic} value with response.
816
+ *
817
+ * @param {Identifier} characteristicIdentifier {@link Characteristic} ID.
818
+ * @param {Base64} base64Value Value in Base64 format.
819
+ * @param {?TransactionId} transactionId optional `transactionId` which can be used in
820
+ * {@link #blemanagercanceltransaction|cancelTransaction()} function.
821
+ * @returns {Promise<Characteristic>} Promise which emits first {@link Characteristic} object matching specified ID.
822
+ * Latest value of characteristic may not be stored inside returned object.
823
+ * @private
824
+ */
825
+ async _writeCharacteristicWithResponse(
826
+ characteristicIdentifier: Identifier,
827
+ base64Value: Base64,
828
+ transactionId: ?TransactionId
829
+ ): Promise<Characteristic> {
830
+ if (!transactionId) {
831
+ transactionId = this._nextUniqueID()
832
+ }
833
+ const nativeCharacteristic = await this._callPromise(
834
+ BleModule.writeCharacteristic(characteristicIdentifier, base64Value, true, transactionId)
835
+ )
836
+ return new Characteristic(nativeCharacteristic, this)
837
+ }
838
+
839
+ /**
840
+ * Write {@link Characteristic} value without response.
841
+ *
842
+ * @param {DeviceId} deviceIdentifier {@link Device} identifier.
843
+ * @param {UUID} serviceUUID {@link Service} UUID.
844
+ * @param {UUID} characteristicUUID {@link Characteristic} UUID.
845
+ * @param {Base64} base64Value Value in Base64 format.
846
+ * @param {?TransactionId} transactionId optional `transactionId` which can be used in
847
+ * {@link #blemanagercanceltransaction|cancelTransaction()} function.
848
+ * @returns {Promise<Characteristic>} Promise which emits first {@link Characteristic} object matching specified
849
+ * UUID paths. Latest value of characteristic may not be stored inside returned object.
850
+ */
851
+ async writeCharacteristicWithoutResponseForDevice(
852
+ deviceIdentifier: DeviceId,
853
+ serviceUUID: UUID,
854
+ characteristicUUID: UUID,
855
+ base64Value: Base64,
856
+ transactionId: ?TransactionId
857
+ ): Promise<Characteristic> {
858
+ if (!transactionId) {
859
+ transactionId = this._nextUniqueID()
860
+ }
861
+ const nativeCharacteristic = await this._callPromise(
862
+ BleModule.writeCharacteristicForDevice(
863
+ deviceIdentifier,
864
+ serviceUUID,
865
+ characteristicUUID,
866
+ base64Value,
867
+ false,
868
+ transactionId
869
+ )
870
+ )
871
+ return new Characteristic(nativeCharacteristic, this)
872
+ }
873
+
874
+ /**
875
+ * Write {@link Characteristic} value without response.
876
+ *
877
+ * @param {Identifier} serviceIdentifier {@link Service} ID.
878
+ * @param {UUID} characteristicUUID {@link Characteristic} UUID.
879
+ * @param {Base64} base64Value Value in Base64 format.
880
+ * @param {?TransactionId} transactionId optional `transactionId` which can be used in
881
+ * {@link #blemanagercanceltransaction|cancelTransaction()} function.
882
+ * @returns {Promise<Characteristic>} Promise which emits first {@link Characteristic} object matching specified
883
+ * UUID paths. Latest value of characteristic may not be stored inside returned object.
884
+ * @private
885
+ */
886
+ async _writeCharacteristicWithoutResponseForService(
887
+ serviceIdentifier: Identifier,
888
+ characteristicUUID: UUID,
889
+ base64Value: Base64,
890
+ transactionId: ?TransactionId
891
+ ): Promise<Characteristic> {
892
+ if (!transactionId) {
893
+ transactionId = this._nextUniqueID()
894
+ }
895
+ const nativeCharacteristic = await this._callPromise(
896
+ BleModule.writeCharacteristicForService(serviceIdentifier, characteristicUUID, base64Value, false, transactionId)
897
+ )
898
+ return new Characteristic(nativeCharacteristic, this)
899
+ }
900
+
901
+ /**
902
+ * Write {@link Characteristic} value without response.
903
+ *
904
+ * @param {Identifier} characteristicIdentifier {@link Characteristic} UUID.
905
+ * @param {Base64} base64Value Value in Base64 format.
906
+ * @param {?TransactionId} transactionId optional `transactionId` which can be used in
907
+ * {@link #blemanagercanceltransaction|cancelTransaction()} function.
908
+ * @returns {Promise<Characteristic>} Promise which emits first {@link Characteristic} object matching specified ID.
909
+ * Latest value of characteristic may not be stored inside returned object.
910
+ * @private
911
+ */
912
+ async _writeCharacteristicWithoutResponse(
913
+ characteristicIdentifier: Identifier,
914
+ base64Value: Base64,
915
+ transactionId: ?TransactionId
916
+ ): Promise<Characteristic> {
917
+ if (!transactionId) {
918
+ transactionId = this._nextUniqueID()
919
+ }
920
+ const nativeCharacteristic = await this._callPromise(
921
+ BleModule.writeCharacteristic(characteristicIdentifier, base64Value, false, transactionId)
922
+ )
923
+ return new Characteristic(nativeCharacteristic, this)
924
+ }
925
+
926
+ /**
927
+ * Monitor value changes of a {@link Characteristic}. If notifications are enabled they will be used
928
+ * in favour of indications.
929
+ *
930
+ * @param {DeviceId} deviceIdentifier {@link Device} identifier.
931
+ * @param {UUID} serviceUUID {@link Service} UUID.
932
+ * @param {UUID} characteristicUUID {@link Characteristic} UUID.
933
+ * @param {function(error: ?BleError, characteristic: ?Characteristic)} listener - callback which emits
934
+ * {@link Characteristic} objects with modified value for each notification.
935
+ * @param {?TransactionId} transactionId optional `transactionId` which can be used in
936
+ * {@link #blemanagercanceltransaction|cancelTransaction()} function.
937
+ * @returns {Subscription} Subscription on which `remove()` function can be called to unsubscribe.
938
+ */
939
+ monitorCharacteristicForDevice(
940
+ deviceIdentifier: DeviceId,
941
+ serviceUUID: UUID,
942
+ characteristicUUID: UUID,
943
+ listener: (error: ?BleError, characteristic: ?Characteristic) => void,
944
+ transactionId: ?TransactionId
945
+ ): Subscription {
946
+ const filledTransactionId = transactionId || this._nextUniqueID()
947
+ return this._handleMonitorCharacteristic(
948
+ BleModule.monitorCharacteristicForDevice(deviceIdentifier, serviceUUID, characteristicUUID, filledTransactionId),
949
+ filledTransactionId,
950
+ listener
951
+ )
952
+ }
953
+
954
+ /**
955
+ * Monitor value changes of a {@link Characteristic}. If notifications are enabled they will be used
956
+ * in favour of indications.
957
+ *
958
+ * @param {Identifier} serviceIdentifier {@link Service} ID.
959
+ * @param {UUID} characteristicUUID {@link Characteristic} UUID.
960
+ * @param {function(error: ?BleError, characteristic: ?Characteristic)} listener - callback which emits
961
+ * {@link Characteristic} objects with modified value for each notification.
962
+ * @param {?TransactionId} transactionId optional `transactionId` which can be used in
963
+ * {@link #blemanagercanceltransaction|cancelTransaction()} function.
964
+ * @returns {Subscription} Subscription on which `remove()` function can be called to unsubscribe.
965
+ * @private
966
+ */
967
+ _monitorCharacteristicForService(
968
+ serviceIdentifier: Identifier,
969
+ characteristicUUID: UUID,
970
+ listener: (error: ?BleError, characteristic: ?Characteristic) => void,
971
+ transactionId: ?TransactionId
972
+ ): Subscription {
973
+ const filledTransactionId = transactionId || this._nextUniqueID()
974
+ return this._handleMonitorCharacteristic(
975
+ BleModule.monitorCharacteristicForService(serviceIdentifier, characteristicUUID, filledTransactionId),
976
+ filledTransactionId,
977
+ listener
978
+ )
979
+ }
980
+
981
+ /**
982
+ * Monitor value changes of a {@link Characteristic}. If notifications are enabled they will be used
983
+ * in favour of indications.
984
+ *
985
+ * @param {Identifier} characteristicIdentifier - {@link Characteristic} ID.
986
+ * @param {function(error: ?BleError, characteristic: ?Characteristic)} listener - callback which emits
987
+ * {@link Characteristic} objects with modified value for each notification.
988
+ * @param {?TransactionId} transactionId optional `transactionId` which can be used in
989
+ * {@link #blemanagercanceltransaction|cancelTransaction()} function.
990
+ * @returns {Subscription} Subscription on which `remove()` function can be called to unsubscribe.
991
+ * @private
992
+ */
993
+ _monitorCharacteristic(
994
+ characteristicIdentifier: Identifier,
995
+ listener: (error: ?BleError, characteristic: ?Characteristic) => void,
996
+ transactionId: ?TransactionId
997
+ ): Subscription {
998
+ const filledTransactionId = transactionId || this._nextUniqueID()
999
+ return this._handleMonitorCharacteristic(
1000
+ BleModule.monitorCharacteristic(characteristicIdentifier, filledTransactionId),
1001
+ filledTransactionId,
1002
+ listener
1003
+ )
1004
+ }
1005
+
1006
+ /**
1007
+ * Common code to handle characteristic monitoring.
1008
+ *
1009
+ * @param {Promise<void>} monitorPromise Characteristic monitoring promise
1010
+ * @param {TransactionId} transactionId TransactionId of passed promise
1011
+ * @param {function(error: ?BleError, characteristic: ?Characteristic)} listener - callback which emits
1012
+ * {@link Characteristic} objects with modified value for each notification.
1013
+ * @returns {Subscription} Subscription on which `remove()` function can be called to unsubscribe.
1014
+ * @private
1015
+ */
1016
+ _handleMonitorCharacteristic(
1017
+ monitorPromise: Promise<void>,
1018
+ transactionId: TransactionId,
1019
+ listener: (error: ?BleError, characteristic: ?Characteristic) => void
1020
+ ): Subscription {
1021
+ const monitorListener = ([error, characteristic, msgTransactionId]: [
1022
+ ?string,
1023
+ NativeCharacteristic,
1024
+ TransactionId
1025
+ ]) => {
1026
+ if (transactionId !== msgTransactionId) {
1027
+ return
1028
+ }
1029
+ if (error) {
1030
+ listener(parseBleError(error, this._errorCodesToMessagesMapping), null)
1031
+ return
1032
+ }
1033
+ listener(null, new Characteristic(characteristic, this))
1034
+ }
1035
+
1036
+ const subscription: Subscription = this._eventEmitter.addListener(Platform.OS === 'harmony' ? 'ReadEvent' : BleModule.ReadEvent, monitorListener)
1037
+
1038
+ const id = this._nextUniqueID()
1039
+ const wrappedSubscription: Subscription = {
1040
+ remove: () => {
1041
+ if (this._activeSubscriptions[id] != null) {
1042
+ delete this._activeSubscriptions[id]
1043
+ subscription.remove()
1044
+ }
1045
+ }
1046
+ }
1047
+ this._activeSubscriptions[id] = wrappedSubscription
1048
+
1049
+ this._callPromise(monitorPromise).then(
1050
+ () => {
1051
+ wrappedSubscription.remove()
1052
+ },
1053
+ (error: BleError) => {
1054
+ listener(error, null)
1055
+ wrappedSubscription.remove()
1056
+ }
1057
+ )
1058
+
1059
+ return {
1060
+ remove: () => {
1061
+ BleModule.cancelTransaction(transactionId)
1062
+ }
1063
+ }
1064
+ }
1065
+
1066
+ // Mark: Descriptors operations ----------------------------------------------------------------------------------
1067
+
1068
+ /**
1069
+ * Read {@link Descriptor} value.
1070
+ *
1071
+ * @param {DeviceId} deviceIdentifier {@link Device} identifier.
1072
+ * @param {UUID} serviceUUID {@link Service} UUID.
1073
+ * @param {UUID} characteristicUUID {@link Characteristic} UUID.
1074
+ * @param {UUID} descriptorUUID {@link Descriptor} UUID.
1075
+ * @param {?TransactionId} transactionId optional `transactionId` which can be used in
1076
+ * {@link #blemanagercanceltransaction|cancelTransaction()} function.
1077
+ * @returns {Promise<Descriptor>} Promise which emits first {@link Descriptor} object matching specified
1078
+ * UUID paths. Latest value of {@link Descriptor} will be stored inside returned object.
1079
+ */
1080
+ async readDescriptorForDevice(
1081
+ deviceIdentifier: DeviceId,
1082
+ serviceUUID: UUID,
1083
+ characteristicUUID: UUID,
1084
+ descriptorUUID: UUID,
1085
+ transactionId: ?TransactionId
1086
+ ): Promise<Descriptor> {
1087
+ if (!transactionId) {
1088
+ transactionId = this._nextUniqueID()
1089
+ }
1090
+ const nativeDescriptor = await this._callPromise(
1091
+ BleModule.readDescriptorForDevice(
1092
+ deviceIdentifier,
1093
+ serviceUUID,
1094
+ characteristicUUID,
1095
+ descriptorUUID,
1096
+ transactionId
1097
+ )
1098
+ )
1099
+ return new Descriptor(nativeDescriptor, this)
1100
+ }
1101
+
1102
+ /**
1103
+ * Read {@link Descriptor} value.
1104
+ *
1105
+ * @param {Identifier} serviceIdentifier {@link Service} identifier.
1106
+ * @param {UUID} characteristicUUID {@link Characteristic} UUID.
1107
+ * @param {UUID} descriptorUUID {@link Descriptor} UUID.
1108
+ * @param {?TransactionId} transactionId optional `transactionId` which can be used in
1109
+ * {@link #blemanagercanceltransaction|cancelTransaction()} function.
1110
+ * @returns {Promise<Descriptor>} Promise which emits first {@link Descriptor} object matching specified
1111
+ * UUID paths. Latest value of {@link Descriptor} will be stored inside returned object.
1112
+ * @private
1113
+ */
1114
+ async _readDescriptorForService(
1115
+ serviceIdentifier: Identifier,
1116
+ characteristicUUID: UUID,
1117
+ descriptorUUID: UUID,
1118
+ transactionId: ?TransactionId
1119
+ ): Promise<Descriptor> {
1120
+ if (!transactionId) {
1121
+ transactionId = this._nextUniqueID()
1122
+ }
1123
+ const nativeDescriptor = await this._callPromise(
1124
+ BleModule.readDescriptorForService(serviceIdentifier, characteristicUUID, descriptorUUID, transactionId)
1125
+ )
1126
+ return new Descriptor(nativeDescriptor, this)
1127
+ }
1128
+
1129
+ /**
1130
+ * Read {@link Descriptor} value.
1131
+ *
1132
+ * @param {Identifier} characteristicIdentifier {@link Characteristic} identifier.
1133
+ * @param {UUID} descriptorUUID {@link Descriptor} UUID.
1134
+ * @param {?TransactionId} transactionId optional `transactionId` which can be used in
1135
+ * {@link #blemanagercanceltransaction|cancelTransaction()} function.
1136
+ * @returns {Promise<Descriptor>} Promise which emits first {@link Descriptor} object matching specified
1137
+ * UUID paths. Latest value of {@link Descriptor} will be stored inside returned object.
1138
+ * @private
1139
+ */
1140
+ async _readDescriptorForCharacteristic(
1141
+ characteristicIdentifier: Identifier,
1142
+ descriptorUUID: UUID,
1143
+ transactionId: ?TransactionId
1144
+ ): Promise<Descriptor> {
1145
+ if (!transactionId) {
1146
+ transactionId = this._nextUniqueID()
1147
+ }
1148
+ const nativeDescriptor = await this._callPromise(
1149
+ BleModule.readDescriptorForCharacteristic(characteristicIdentifier, descriptorUUID, transactionId)
1150
+ )
1151
+ return new Descriptor(nativeDescriptor, this)
1152
+ }
1153
+
1154
+ /**
1155
+ * Read {@link Descriptor} value.
1156
+ *
1157
+ * @param {Identifier} descriptorIdentifier {@link Descriptor} identifier.
1158
+ * @param {?TransactionId} transactionId optional `transactionId` which can be used in
1159
+ * {@link #blemanagercanceltransaction|cancelTransaction()} function.
1160
+ * @returns {Promise<Descriptor>} Promise which emits first {@link Descriptor} object matching specified
1161
+ * UUID paths. Latest value of {@link Descriptor} will be stored inside returned object.
1162
+ * @private
1163
+ */
1164
+ async _readDescriptor(descriptorIdentifier: Identifier, transactionId: ?TransactionId): Promise<Descriptor> {
1165
+ if (!transactionId) {
1166
+ transactionId = this._nextUniqueID()
1167
+ }
1168
+ const nativeDescriptor = await this._callPromise(BleModule.readDescriptor(descriptorIdentifier, transactionId))
1169
+ return new Descriptor(nativeDescriptor, this)
1170
+ }
1171
+
1172
+ /**
1173
+ * Write {@link Descriptor} value.
1174
+ *
1175
+ * @param {DeviceId} deviceIdentifier Connected device identifier
1176
+ * @param {UUID} serviceUUID Service UUID
1177
+ * @param {UUID} characteristicUUID Characteristic UUID
1178
+ * @param {UUID} descriptorUUID Descriptor UUID
1179
+ * @param {Base64} valueBase64 Value to be set coded in Base64
1180
+ * @param {?TransactionId} transactionId Transaction handle used to cancel operation
1181
+ * @returns {Promise<Descriptor>} Descriptor which saved passed value
1182
+ */
1183
+ async writeDescriptorForDevice(
1184
+ deviceIdentifier: DeviceId,
1185
+ serviceUUID: UUID,
1186
+ characteristicUUID: UUID,
1187
+ descriptorUUID: UUID,
1188
+ valueBase64: Base64,
1189
+ transactionId: ?TransactionId
1190
+ ): Promise<Descriptor> {
1191
+ if (!transactionId) {
1192
+ transactionId = this._nextUniqueID()
1193
+ }
1194
+ const nativeDescriptor = await this._callPromise(
1195
+ BleModule.writeDescriptorForDevice(
1196
+ deviceIdentifier,
1197
+ serviceUUID,
1198
+ characteristicUUID,
1199
+ descriptorUUID,
1200
+ valueBase64,
1201
+ transactionId
1202
+ )
1203
+ )
1204
+ return new Descriptor(nativeDescriptor, this)
1205
+ }
1206
+
1207
+ /**
1208
+ * Write {@link Descriptor} value.
1209
+ *
1210
+ * @param {Identifier} serviceIdentifier Service identifier
1211
+ * @param {UUID} characteristicUUID Characteristic UUID
1212
+ * @param {UUID} descriptorUUID Descriptor UUID
1213
+ * @param {Base64} valueBase64 Value to be set coded in Base64
1214
+ * @param {?TransactionId} transactionId Transaction handle used to cancel operation
1215
+ * @returns {Promise<Descriptor>} Descriptor which saved passed value
1216
+ * @private
1217
+ */
1218
+ async _writeDescriptorForService(
1219
+ serviceIdentifier: Identifier,
1220
+ characteristicUUID: UUID,
1221
+ descriptorUUID: UUID,
1222
+ valueBase64: Base64,
1223
+ transactionId: ?TransactionId
1224
+ ): Promise<Descriptor> {
1225
+ if (!transactionId) {
1226
+ transactionId = this._nextUniqueID()
1227
+ }
1228
+ const nativeDescriptor = await this._callPromise(
1229
+ BleModule.writeDescriptorForService(
1230
+ serviceIdentifier,
1231
+ characteristicUUID,
1232
+ descriptorUUID,
1233
+ valueBase64,
1234
+ transactionId
1235
+ )
1236
+ )
1237
+ return new Descriptor(nativeDescriptor, this)
1238
+ }
1239
+
1240
+ /**
1241
+ * Write {@link Descriptor} value.
1242
+ *
1243
+ * @param {Identifier} characteristicIdentifier Characteristic identifier
1244
+ * @param {UUID} descriptorUUID Descriptor UUID
1245
+ * @param {Base64} valueBase64 Value to be set coded in Base64
1246
+ * @param {?TransactionId} transactionId Transaction handle used to cancel operation
1247
+ * @returns {Promise<Descriptor>} Descriptor which saved passed value
1248
+ * @private
1249
+ */
1250
+ async _writeDescriptorForCharacteristic(
1251
+ characteristicIdentifier: Identifier,
1252
+ descriptorUUID: UUID,
1253
+ valueBase64: Base64,
1254
+ transactionId: ?TransactionId
1255
+ ): Promise<Descriptor> {
1256
+ if (!transactionId) {
1257
+ transactionId = this._nextUniqueID()
1258
+ }
1259
+ const nativeDescriptor = await this._callPromise(
1260
+ BleModule.writeDescriptorForCharacteristic(characteristicIdentifier, descriptorUUID, valueBase64, transactionId)
1261
+ )
1262
+ return new Descriptor(nativeDescriptor, this)
1263
+ }
1264
+
1265
+ /**
1266
+ * Write {@link Descriptor} value.
1267
+ *
1268
+ * @param {Identifier} descriptorIdentifier Descriptor identifier
1269
+ * @param {Base64} valueBase64 Value to be set coded in Base64
1270
+ * @param {?TransactionId} transactionId Transaction handle used to cancel operation
1271
+ * @returns {Promise<Descriptor>} Descriptor which saved passed value
1272
+ * @private
1273
+ */
1274
+ async _writeDescriptor(
1275
+ descriptorIdentifier: Identifier,
1276
+ valueBase64: Base64,
1277
+ transactionId: ?TransactionId
1278
+ ): Promise<Descriptor> {
1279
+ if (!transactionId) {
1280
+ transactionId = this._nextUniqueID()
1281
+ }
1282
+ const nativeDescriptor = await this._callPromise(
1283
+ BleModule.writeDescriptor(descriptorIdentifier, valueBase64, transactionId)
1284
+ )
1285
+ return new Descriptor(nativeDescriptor, this)
1286
+ }
1287
+ }