Skip to content

Commit 5199457

Browse files
authored
Merge pull request #673 from jholzer-cciq/master
Add retrievePeripheralsByAddress method for finding paired devices in iOS by address
2 parents 01fb2ce + ad432d7 commit 5199457

File tree

8 files changed

+199
-0
lines changed

8 files changed

+199
-0
lines changed

readme.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ This plugin allows you to interact with Bluetooth LE devices on Android, iOS, an
6464
- [isLocationEnabled](#islocationenabled)
6565
- [requestLocation](#requestlocation)
6666
- [setPin](#setPin)
67+
- [retrievePeripheralsByAddress](#retrievePeripheralsByAddress)
6768
- [Peripheral Life Cycle](#peripheral-life-cycle)
6869
- [Initilization](#initilization)
6970
- [Notifications](#notifications)
@@ -239,6 +240,7 @@ Neither Android nor iOS support Bluetooth on emulators, so you'll need to test o
239240
* [bluetoothle.requestPermission](#requestpermission) (Android 6+)
240241
* [bluetoothle.isLocationEnabled](#islocationenabled) (Android 6+)
241242
* [bluetoothle.requestLocation](#requestlocation) (Android 6+)
243+
* [bluetoothle.retrievePeripheralsByAddress](#retrievePeripheralsByAddress) (iOS)
242244
* [bluetoothle.initializePeripheral](#initializeperipheral)
243245
* [bluetoothle.addService](#addservice)
244246
* [bluetoothle.removeService](#removeservice)
@@ -290,6 +292,7 @@ Whenever the error callback is executed, the return object will contain the erro
290292
* isDisconnected - Device is disconnected (Don't call disconnect)
291293
* isBonded - Operation is unsupported. (Is the device Android?)
292294
* setPin - Operation is unsupported. (Is the device Android?)
295+
* retrievePeripheralsByAddress - Operation is unsupported (Is the device iOS?)
293296

294297
For example:
295298
```javascript
@@ -1749,6 +1752,38 @@ bluetoothle.requestLocation(requestLocationSuccess, requestLocationError);
17491752

17501753

17511754

1755+
### retrievePeripheralsByAddress ###
1756+
Retrieve paired Bluetooth LE devices based on their address. Wraps the iOS method [CBCentralManager.retrievePeripheralsWithIdentifiers](https://developer.apple.com/documentation/corebluetooth/cbcentralmanager/1519127-retrieveperipheralswithidentifie?language=objc). iOS support only. Will return an error if used on Android.
1757+
1758+
```javascript
1759+
bluetoothle.retrievePeripheralsByAddress(success, error, params);
1760+
```
1761+
1762+
##### Params #####
1763+
* addresses = An arrays of addresses/identifiers to lookup devices by. If no addresses are specified, no devices will be returned
1764+
1765+
```javascript
1766+
{
1767+
"addresses": ["ECC037FD-72AE-AFC5-9213-CA785B3B5C63"]
1768+
}
1769+
```
1770+
1771+
##### Success #####
1772+
Returns an array of device objects:
1773+
* name = the device's display name
1774+
* address = the device's address / identifier for connecting to the object
1775+
1776+
```javascript
1777+
[
1778+
{
1779+
"name": "Polar H7 3B321015",
1780+
"address": "ECC037FD-72AE-AFC5-9213-CA785B3B5C63"
1781+
}
1782+
]
1783+
```
1784+
1785+
1786+
17521787
## Peripheral Life Cycle ##
17531788

17541789
1. initializePeripheral

src/android/BluetoothLePlugin.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ public class BluetoothLePlugin extends CordovaPlugin {
213213
private final String errorDescriptor = "descriptor";
214214
private final String errorRequestConnectionPriority = "requestConnectPriority";
215215
private final String errorMtu = "mtu";
216+
private final String errorRetrievePeripheralsByAddress = "retrievePeripheralsByAddress";
216217

217218
//Error Messages
218219
//Initialization
@@ -424,6 +425,11 @@ public boolean execute(String action, final JSONArray args, final CallbackContex
424425
notifyAction(args, callbackContext);
425426
} else if ("setPin".equals(action)) {
426427
setPinAction(args, callbackContext);
428+
} else if ("retrievePeripheralsByAddress".equals(action)) {
429+
JSONObject returnObj = new JSONObject();
430+
addProperty(returnObj, keyError, errorRetrievePeripheralsByAddress);
431+
addProperty(returnObj, keyMessage, logOperationUnsupported);
432+
callbackContext.error(returnObj);
427433
} else {
428434
return false;
429435
}

src/ios/BluetoothLePlugin.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
- (void)requestPermission:(CDVInvokedUrlCommand *)command;
6363
- (void)isLocationEnabled:(CDVInvokedUrlCommand *)command;
6464
- (void)requestLocation:(CDVInvokedUrlCommand *)command;
65+
- (void)retrievePeripheralsByAddress:(CDVInvokedUrlCommand *)command;
6566

6667
- (void)initializePeripheral:(CDVInvokedUrlCommand *)command;
6768
- (void)addService:(CDVInvokedUrlCommand *)command;

src/ios/BluetoothLePlugin.m

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
NSString *const keyMessage = @"message";
99
NSString *const keyName = @"name";
1010
NSString *const keyAddress = @"address";
11+
NSString *const keyAddresses = @"addresses";
1112
NSString *const keyProperties = @"properties";
1213
NSString *const keyRssi = @"rssi";
1314
NSString *const keyAdvertisement = @"advertisement";
@@ -842,6 +843,43 @@ - (void)retrieveConnected:(CDVInvokedUrlCommand *)command {
842843
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
843844
}
844845

846+
- (void)retrievePeripheralsByAddress:(CDVInvokedUrlCommand *)command {
847+
//Ensure Bluetooth is enabled
848+
if ([self isNotInitialized:command]) {
849+
return;
850+
}
851+
852+
//Get an array of addresses to filter by
853+
NSDictionary *obj = [self getArgsObject:command.arguments];
854+
NSMutableArray* addresses = nil;
855+
if (obj != nil) {
856+
addresses = [self getAddresses:obj forType:keyAddresses];
857+
}
858+
859+
//retrievePeripheralsWithIdentifiers doesn't like nil UUID array
860+
if (addresses == nil) {
861+
addresses = [NSMutableArray array];
862+
}
863+
864+
//Get paired peripherals with specified addresses/identifiers
865+
NSArray* peripherals = [centralManager retrievePeripheralsWithIdentifiers:addresses];
866+
867+
//Array to store returned peripherals
868+
NSMutableArray* peripheralsOut = [[NSMutableArray alloc] init];
869+
870+
//Create an object from each peripheral containing connection ID and name, and add to array
871+
for (CBPeripheral* peripheral in peripherals) {
872+
NSMutableDictionary* peripheralOut = [NSMutableDictionary dictionary];
873+
[self addDevice:peripheral :peripheralOut];
874+
[peripheralsOut addObject:peripheralOut];
875+
}
876+
877+
//Return the array
878+
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:peripheralsOut];
879+
[pluginResult setKeepCallbackAsBool:false];
880+
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
881+
}
882+
845883
- (void)bond:(CDVInvokedUrlCommand *)command {
846884
NSDictionary* returnObj = [NSDictionary dictionaryWithObjectsAndKeys: errorBond, keyError, logOperationUnsupported, keyMessage, nil];
847885
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:returnObj];
@@ -3450,6 +3488,38 @@ -(NSUUID*) getAddress:(NSDictionary *)obj {
34503488
return [[NSUUID UUID] initWithUUIDString:addressString];
34513489
}
34523490

3491+
-(NSMutableArray*) getAddresses:(NSDictionary *) dictionary forType:(NSString*) type {
3492+
NSMutableArray* addresses = [[NSMutableArray alloc] init];
3493+
3494+
NSArray* addressStrings = [dictionary valueForKey:type];
3495+
3496+
if (addressStrings == nil) {
3497+
return nil;
3498+
}
3499+
3500+
if (![addressStrings isKindOfClass:[NSArray class]]) {
3501+
return nil;
3502+
}
3503+
3504+
for (NSString* addressString in addressStrings) {
3505+
if (![addressString isKindOfClass:[NSString class]]) {
3506+
continue;
3507+
}
3508+
3509+
NSUUID* address = [[NSUUID UUID] initWithUUIDString:addressString];
3510+
3511+
if (address != nil) {
3512+
[addresses addObject:address];
3513+
}
3514+
}
3515+
3516+
if (addresses.count == 0) {
3517+
return nil;
3518+
}
3519+
3520+
return addresses;
3521+
}
3522+
34533523
-(NSNumber*) getRequest:(NSDictionary *)obj {
34543524
NSNumber* request = [obj valueForKey:keyRequest];
34553525

src/osx/BluetoothLePlugin.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
- (void)requestPermission:(CDVInvokedUrlCommand *)command;
5555
- (void)isLocationEnabled:(CDVInvokedUrlCommand *)command;
5656
- (void)requestLocation:(CDVInvokedUrlCommand *)command;
57+
- (void)retrievePeripheralsByAddress:(CDVInvokedUrlCommand *)command;
5758

5859
- (void)initializePeripheral:(CDVInvokedUrlCommand *)command;
5960
- (void)addService:(CDVInvokedUrlCommand *)command;

src/osx/BluetoothLePlugin.m

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
NSString *const keyMessage = @"message";
99
NSString *const keyName = @"name";
1010
NSString *const keyAddress = @"address";
11+
NSString *const keyAddresses = @"addresses";
1112
NSString *const keyProperties = @"properties";
1213
NSString *const keyRssi = @"rssi";
1314
NSString *const keyAdvertisement = @"advertisement";
@@ -835,6 +836,43 @@ - (void)retrieveConnected:(CDVInvokedUrlCommand *)command {
835836
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
836837
}
837838

839+
- (void)retrievePeripheralsByAddress:(CDVInvokedUrlCommand *)command {
840+
//Ensure Bluetooth is enabled
841+
if ([self isNotInitialized:command]) {
842+
return;
843+
}
844+
845+
//Get an array of addresses to filter by
846+
NSDictionary *obj = [self getArgsObject:command.arguments];
847+
NSMutableArray* addresses = nil;
848+
if (obj != nil) {
849+
addresses = [self getAddresses:obj forType:keyAddresses];
850+
}
851+
852+
//retrievePeripheralsWithIdentifiers doesn't like nil UUID array
853+
if (addresses == nil) {
854+
addresses = [NSMutableArray array];
855+
}
856+
857+
//Get paired peripherals with specified addresses/identifiers
858+
NSArray* peripherals = [centralManager retrievePeripheralsWithIdentifiers:addresses];
859+
860+
//Array to store returned peripherals
861+
NSMutableArray* peripheralsOut = [[NSMutableArray alloc] init];
862+
863+
//Create an object from each peripheral containing connection ID and name, and add to array
864+
for (CBPeripheral* peripheral in peripherals) {
865+
NSMutableDictionary* peripheralOut = [NSMutableDictionary dictionary];
866+
[self addDevice:peripheral :peripheralOut];
867+
[peripheralsOut addObject:peripheralOut];
868+
}
869+
870+
//Return the array
871+
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:peripheralsOut];
872+
[pluginResult setKeepCallbackAsBool:false];
873+
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
874+
}
875+
838876
- (void)bond:(CDVInvokedUrlCommand *)command {
839877
NSDictionary* returnObj = [NSDictionary dictionaryWithObjectsAndKeys: errorBond, keyError, logOperationUnsupported, keyMessage, nil];
840878
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:returnObj];
@@ -3419,6 +3457,38 @@ -(NSUUID*) getAddress:(NSDictionary *)obj {
34193457
return [[NSUUID UUID] initWithUUIDString:addressString];
34203458
}
34213459

3460+
-(NSMutableArray*) getAddresses:(NSDictionary *) dictionary forType:(NSString*) type {
3461+
NSMutableArray* addresses = [[NSMutableArray alloc] init];
3462+
3463+
NSArray* addressStrings = [dictionary valueForKey:type];
3464+
3465+
if (addressStrings == nil) {
3466+
return nil;
3467+
}
3468+
3469+
if (![addressStrings isKindOfClass:[NSArray class]]) {
3470+
return nil;
3471+
}
3472+
3473+
for (NSString* addressString in addressStrings) {
3474+
if (![addressString isKindOfClass:[NSString class]]) {
3475+
continue;
3476+
}
3477+
3478+
NSUUID* address = [[NSUUID UUID] initWithUUIDString:addressString];
3479+
3480+
if (address != nil) {
3481+
[addresses addObject:address];
3482+
}
3483+
}
3484+
3485+
if (addresses.count == 0) {
3486+
return nil;
3487+
}
3488+
3489+
return addresses;
3490+
}
3491+
34223492
-(NSNumber*) getRequest:(NSDictionary *)obj {
34233493
NSNumber* request = [obj valueForKey:keyRequest];
34243494

types/index.d.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,19 @@ declare namespace BluetoothlePlugin {
434434
requestLocationSuccess: (result: { requestLocation: boolean }) => void,
435435
requestLocationError: (error: Error) => void): void;
436436

437+
/**
438+
* Retrieve paired Bluetooth LE devices based on their address. Wraps the iOS method CBCentralManager.retrievePeripheralsWithIdentifiers.
439+
* iOS support only. Will return an error if used on Android.
440+
* @param success The success callback that is passed an array of device objects
441+
* @param error The callback that will be triggered when the operation fails
442+
* @param params An array of service IDs to filter the retrieval by. If no service IDs are specified, no devices will be returned.
443+
*
444+
*/
445+
retrievePeripheralsByAddress(
446+
success: (devices: DeviceInfo[]) => void,
447+
error: (error: Error) => void,
448+
params?: { addresses?: string[] }): void;
449+
437450
/**
438451
* Initialize Bluetooth on the device. Must be called before anything else.
439452
* Callback will continuously be used whenever Bluetooth is enabled or disabled.

www/bluetoothle.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ var bluetoothle = {
114114
requestLocation: function(successCallback, errorCallback) {
115115
cordova.exec(successCallback, errorCallback, bluetoothleName, "requestLocation", []);
116116
},
117+
retrievePeripheralsByAddress: function(successCallback, errorCallback, params) {
118+
cordova.exec(successCallback, errorCallback, bluetoothleName, "retrievePeripheralsByAddress", [params])
119+
},
117120
initializePeripheral: function(successCallback, errorCallback, params) {
118121
cordova.exec(successCallback, errorCallback, bluetoothleName, "initializePeripheral", [params]);
119122
},

0 commit comments

Comments
 (0)