This plugin enables communication between a phone and Bluetooth Low Energy (BLE) peripherals.
The plugin provides a simple JavaScript API for iOS and Android.
Advertising information is returned when scanning for peripherals. Service, characteristic, and property info is returned when connecting to a peripheral. All access is via service and characteristic UUIDs. The plugin manages handles internally.
Simultaneous connections to multiple peripherals are supported.
This plugin isn't intended for scanning beacons. Try cordova-plugin-ibeacon for iBeacons.
If you want to create Bluetooth devices, try cordova-plugin-ble-peripheral.
See the examples for ideas on how this plugin can be used.
$ npm install cordova-plugin-ble-central
$ npx cap sync
The plugin can be further configured via the cordova preferences section of the capacitor config file:
const config = {
...
cordova: {
preferences: {
...
bluetooth_restore_state: "true",
accessBackgroundLocation: "false",
},
}
}
bluetooth_restore_state
: [iOS] Enable Bluetooth state restoration, allowing an app to be woken up to receive scan results and peripheral notifications. This is needed for background scanning support. See iOS restore state. For more information about background operation with this plugin, see Background Scanning and Notifications on iOS.
accessBackgroundLocation
: [Android] Tells the plugin to request the ACCESS_BACKGROUND_LOCATION
permission on Android 10 & Android 11 in order for scanning to function when the app is not visible.
After installation, the following additions should be made to the app's Info.plist
bluetooth-central
to UIBackgroundModes to enable background receipt of scan information and BLE notifications$ cordova plugin add cordova-plugin-ble-central --variable BLUETOOTH_USAGE_DESCRIPTION="Your description here" --variable IOS_INIT_ON_LOAD=true|false --variable BLUETOOTH_RESTORE_STATE=true|false --variable ACCESS_BACKGROUND_LOCATION=true|false
It's recommended to always use the latest cordova and cordova platform packages in order to ensure correct function. This plugin generally best supports the following platforms and version ranges:
cordova | cordova-ios | cordova-android | cordova-browser |
---|---|---|---|
10+ | 6.2.0+ | 10.0+ | not tested |
All variables can be modified after installation by updating the values in package.json
.
BLUETOOTH_USAGE_DESCRIPTION
: [iOS] defines the values for NSBluetoothAlwaysUsageDescription.
IOS_INIT_ON_LOAD
: [iOS] Prevents the Bluetooth plugin from being initialised until first access to the ble
window object. This allows an application to warn the user before the Bluetooth access permission is requested.
BLUETOOTH_RESTORE_STATE
: [iOS] Enable Bluetooth state restoration, allowing an app to be woken up to receive scan results and peripheral notifications. This is needed for background scanning support. See iOS restore state. For more information about background operation with this plugin, see Background Scanning and Notifications on iOS.
ACCESS_BACKGROUND_LOCATION
: [Android] Tells the plugin to request the ACCESS_BACKGROUND_LOCATION permission on Android 10 & Android 11 in order for scanning to function when the app is not visible.
TypeScript definitions are provided by this plugin. These can be added to a file by adding a triple-slash reference at the top of any file using this plugin:
/// <reference types="cordova-plugin-ble-central" />
If you are having Android permissions conflicts with other plugins, try using the slim
variant of the plugin instead with cordova plugin add cordova-plugin-ble-central@slim
. This variant excludes all Android permissions, leaving it to the developer to ensure the right entries are added manually to the AndroidManifest.xml
(see below for an example).
To include the default set of permissions the plugin installs on Android SDK v31+, add the following snippet in your config.xml
file, in the <platform name="android">
section:
<config-file target="AndroidManifest.xml" parent="/manifest">
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="28" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
</config-file>
For the best understanding about which permissions are needed for which combinations of target SDK version & OS version, see Android Bluetooth permissions
Scan and discover BLE peripherals.
ble.scan(services, seconds, success, failure);
Function scan
scans for BLE devices. The success callback is called each time a peripheral is discovered. Scanning automatically stops after the specified number of seconds.
{
"name": "TI SensorTag",
"id": "BD922605-1B07-4D55-8D09-B66653E51BBA",
"rssi": -79,
"advertising": /* ArrayBuffer or map */
}
Advertising information format varies depending on your platform. See Advertising Data for more information.
With Android SDK >= 23 (6.0), additional permissions are required for Bluetooth low energy scanning. The location permission ACCESS_COARSE_LOCATION is required because Bluetooth beacons can be used to determine a user's location. If necessary, the plugin will prompt the user to allow the app to access to device's location. If the user denies permission, the scan failure callback will receive the error "Location permission not granted".
Location Services must be enabled for Bluetooth scanning. If location services are disabled, the failure callback will receive the error "Location services are disabled". If you want to manage location permission and screens, try the cordova-diagonostic-plugin or the Ionic Native Diagnostic plugin.
ble.scan(
[],
5,
function (device) {
console.log(JSON.stringify(device));
},
failure
);
Scan and discover BLE peripherals.
ble.startScan(services, success, failure);
Function startScan
scans for BLE devices. The success callback is called each time a peripheral is discovered. Scanning will continue until stopScan
is called.
{
"name": "TI SensorTag",
"id": "BD922605-1B07-4D55-8D09-B66653E51BBA",
"rssi": -79,
"advertising": /* ArrayBuffer or map */
}
Advertising information format varies depending on your platform. See Advertising Data for more information.
See the location permission notes above for information about Location Services in Android SDK >= 23.
ble.startScan(
[],
function (device) {
console.log(JSON.stringify(device));
},
failure
);
setTimeout(
ble.stopScan,
5000,
function () {
console.log('Scan complete');
},
function () {
console.log('stopScan failed');
}
);
Scan and discover BLE peripherals, specifying scan options.
ble.startScanWithOptions(services, options, success, failure);
Function startScanWithOptions
scans for BLE devices. It operates similarly to the startScan
function, but allows you to specify extra options (like allowing duplicate device reports). The success callback is called each time a peripheral is discovered. Scanning will continue until stopScan
is called.
{
"name": "TI SensorTag",
"id": "BD922605-1B07-4D55-8D09-B66653E51BBA",
"rssi": -79,
"advertising": /* ArrayBuffer or map */
}
Advertising information format varies depending on your platform. See Advertising Data for more information.
See the location permission notes above for information about Location Services in Android SDK >= 23.
ble.startScanWithOptions([],
{ reportDuplicates: true }
function(device) {
console.log(JSON.stringify(device));
},
failure);
setTimeout(ble.stopScan,
5000,
function() { console.log("Scan complete"); },
function() { console.log("stopScan failed"); }
);
Stop scanning for BLE peripherals.
ble.stopScan(success, failure);
// Or using await with promises
await ble.withPromises.stopScan();
Function stopScan
stops scanning for BLE devices.
ble.startScan(
[],
function (device) {
console.log(JSON.stringify(device));
},
failure
);
setTimeout(
ble.stopScan,
5000,
function () {
console.log('Scan complete');
},
function () {
console.log('stopScan failed');
}
);
/* Alternate syntax
setTimeout(function() {
ble.stopScan(
function() { console.log("Scan complete"); },
function() { console.log("stopScan failed"); }
);
}, 5000);
*/
Set device pin
ble.setPin(pin, [success], [failure]);
// Or using await with promises
await ble.withPromises.setPin(pin);
Function setPin
sets the pin when device requires it.
Initiate a bond with a remote device
ble.bond(device_id, [success], [failure], [options]);
// Or using await with promises
await ble.withPromises.bond(device_id);
await ble.withPromises.bond(device_id, { usePairingDialog: true });
Function bond
initialises a bond with a peripheral. The success callback will be called when the
bonding is complete. The bonding process may prompt the user to confirm the pairing process.
Remove a bond for a remote device
ble.unbond(device_id, [success], [failure]);
// Or using await with promises
await ble.withPromises.unbond(device_id);
Function unbond
removes an existing bond for a remote device. The success callback will be called when the
bond has been removed.
Get the bond state of a device as a string
ble.readBondState(device_id, [success], [failure]);
// Or using await with promises
const bondState = await ble.withPromises.readBondState(device_id);
Function readBondState
retrieves the current bond state of the device.
States
Connect to a peripheral.
ble.connect(device_id, connectCallback, disconnectCallback);
Function connect
connects to a BLE peripheral. The callback is long running. The connect callback will be called when the connection is successful. Service and characteristic info will be passed to the connect callback in the peripheral object.
The disconnect callback is called if the connection fails, or later if the peripheral disconnects. When possible, a peripheral object is passed to the failure callback. The disconnect callback is only called when the peripheral initates the disconnection. The disconnect callback is not called when the application calls ble.disconnect. The disconnect callback is how your app knows the peripheral inintiated a disconnect.
Android can connect to peripherals using MAC address without scanning. If the MAC address is not found the connection will time out.
For iOS, the plugin needs to know about any device UUID before calling connect. You can do this by calling ble.scan, ble.startScan, ble.connectedPeripheralsWithServices, or ble.peripheralsWithIdentifiers so the plugin has a list of available peripherals.
Establish an automatic connection to a peripheral.
ble.autoConnect(device_id, connectCallback, disconnectCallback);
Automatically connect to a device when it is in range of the phone. When the device connects, the connect callback is called with a peripheral object. The call to autoConnect will not time out. It will wait forever until the device is in range. When the peripheral disconnects, the disconnect callback is called with a peripheral object.
Calling ble.disconnect will stop the automatic reconnection.
Both the connect and disconnect callbacks can be called many times as the device connects and disconnects. Do not wrap this function in a Promise or Observable.
On iOS, background notifications on ios must be enabled if you want to run in the background. On Android, this relies on the autoConnect argument of BluetoothDevice.connectGatt()
. Not all Android devices implement this feature correctly.
See notes about scanning before connecting
Disconnect.
ble.disconnect(device_id, [success], [failure]);
// Or using await with promises
await ble.withPromises.disconnect(device_id);
Function disconnect
disconnects the selected device.
requestMtu
ble.requestMtu(device_id, new_mtu, [success], [failure]);
// Or using await with promises
const actual_mtu = await ble.withPromises.requestMtu(device_id, new_mtu);
This function may be used to request (on Android) a larger MTU size to be able to send more data at once. This can be useful when performing a write request operation (write without response), the data sent is truncated to the MTU size. The resulting MTU size is sent to the success callback. The requested and resulting MTU sizes are not necessarily equal.
ble.requestMtu(
device_id,
new_mtu,
function (mtu) {
alert('MTU set to: ' + mtu);
},
function (failure) {
alert('Failed to request MTU.');
}
);
requestConnectionPriority
ble.requestConnectionPriority(device_id, priority, [success], [failure]);
// Or using await with promises
await ble.withPromises.requestConnectionPriority(device_id, priority);
When Connecting to a peripheral android can request for the connection priority for better communication. See BluetoothGatt#requestConnectionPriority for technical details
Connection priority can be one of:
"balanced"
- CONNECTION_PRIORITY_BALANCED"high"
- CONNECTION_PRIORITY_HIGH"low"
- CONNECTION_PRIORITY_LOW_POWER"high"
, "balanced"
or "low"
ble.requestConnectionPriority(
device_id,
'high',
function () {
alert('success');
},
function (failure) {
alert('Failed to request connection priority: ' + failure);
}
);
refreshDeviceCache
ble.refreshDeviceCache(deviceId, timeoutMillis, [success], [failure]);
Some poorly behaved devices show old cached services and characteristics info. (Usually because they don't implement Service Changed 0x2a05 on Generic Attribute Service 0x1801 and the central doesn't know the data needs to be refreshed.) This method might help.
NOTE Since this uses an undocumented API it's not guaranteed to work.
Reads the value of a characteristic.
ble.read(device_id, service_uuid, characteristic_uuid, success, failure);
// Or using await with promises
const data = await ble.withPromises.read(device_id, service_uuid, characteristic_uuid);
Function read
reads the value of the characteristic.
Raw data is passed from native code to the callback as an ArrayBuffer.
Retrieves an ArrayBuffer when reading data.
// read data from a characteristic, do something with output data
ble.read(
device_id,
service_uuid,
characteristic_uuid,
function (data) {
console.log('Hooray we have data' + JSON.stringify(data));
alert('Successfully read data from device.' + JSON.stringify(data));
},
function (failure) {
alert('Failed to read characteristic from device.');
}
);
Writes data to a characteristic.
ble.write(device_id, service_uuid, characteristic_uuid, data, success, failure);
// Or using await with promises
await ble.withPromises.write(device_id, service_uuid, characteristic_uuid, data);
Function write
writes data to a characteristic.
Use an ArrayBuffer when writing data.
// send 1 byte to switch a light on
var data = new Uint8Array(1);
data[0] = 1;
ble.write(device_id, 'FF10', 'FF11', data.buffer, success, failure);
// send a 3 byte value with RGB color
var data = new Uint8Array(3);
data[0] = 0xff; // red
data[1] = 0x00; // green
data[2] = 0xff; // blue
ble.write(device_id, 'ccc0', 'ccc1', data.buffer, success, failure);
// send a 32 bit integer
var data = new Uint32Array(1);
data[0] = counterInput.value;
ble.write(device_id, SERVICE, CHARACTERISTIC, data.buffer, success, failure);
Writes data to a characteristic without confirmation from the peripheral.
ble.writeWithoutResponse(device_id, service_uuid, characteristic_uuid, data, success, failure);
// Or using await with promises
await ble.withPromises.writeWithoutResponse(device_id, service_uuid, characteristic_uuid, data);
Function writeWithoutResponse
writes data to a characteristic without a response from the peripheral. You are not notified if the write fails in the BLE stack. The success callback is be called when the characteristic is written.
Register to be notified when the value of a characteristic changes.
ble.startNotification(device_id, service_uuid, characteristic_uuid, success, failure);
// Or using await with promises
// Note, initial promise resolves or rejects depending on whether the subscribe was successful
await ble.withPromises.startNotification(device_id, success, failure);
Function startNotification
registers a callback that is called every time the value of a characteristic changes. This method handles both notifications
and indications
. The success callback is called multiple times.
Raw data is passed from native code to the success callback as an ArrayBuffer.
See Background Notifications on iOS
var onData = function (buffer) {
// Decode the ArrayBuffer into a typed Array based on the data you expect
var data = new Uint8Array(buffer);
alert('Button state changed to ' + data[0]);
};
ble.startNotification(device_id, 'FFE0', 'FFE1', onData, failure);
Stop being notified when the value of a characteristic changes.
ble.stopNotification(device_id, service_uuid, characteristic_uuid, success, failure);
// Or using await with promises
await ble.withPromises.stopNotification(device_id);
Function stopNotification
stops a previously registered notification callback.
Reports the connection status.
// Callbacks
ble.isConnected(device_id, success, failure);
// Promises with boolean return
const isConnected = await ble.withPromises.isConnected(device_id, false);
// Promises with rejection
await ble.withPromises.isConnected(device_id); // throws if not connected
Function isConnected
calls the success callback when the peripheral is connected and the failure callback when not connected.
NOTE that for many apps isConnected is unncessary. The app can track the connected state. Ater calling connect the app is connected when the success callback function is called. If the device disconnects at any point in the future, the failure callback of connect will be called.
// Callbacks
ble.isConnected(
'FFCA0B09-CB1D-4DC0-A1EF-31AFD3EDFB53',
function () {
console.log('Peripheral is connected');
},
function () {
console.log('Peripheral is *not* connected');
}
);
// Promises with boolean return
const isConnected = await ble.withPromises.isConnected(device_id, false);
if (isConnected) {
console.log('Peripheral is connected');
} else {
console.log('Peripheral is *not* connected');
}
// Promises with rejection
try {
await ble.withPromises.isConnected(device_id);
console.log('Peripheral is connected');
} catch (e) {
console.log('Peripheral is *not* connected');
}
Reports if bluetooth is enabled.
ble.isEnabled(success, failure);
Function isEnabled
calls the success callback when Bluetooth is enabled and the failure callback when Bluetooth is not enabled.
ble.isEnabled(
function () {
console.log('Bluetooth is enabled');
},
function () {
console.log('Bluetooth is *not* enabled');
}
);
Reports if location services are enabled.
ble.isLocationEnabled(success, failure);
Function isLocationEnabled
calls the success callback when location services are enabled and the failure callback when location services are not enabled. On some devices, location services must be enabled in order to scan for peripherals.
ble.isLocationEnabled(
function () {
console.log('location services are enabled');
},
function () {
console.log('location services are *not* enabled');
}
);
Registers to be notified when Location service state changes on the device.
ble.startLocationStateNotifications(success, failure);
// Or using await with promises
// Note, initial promise resolves or rejects depending on whether the subscribe was successful
await ble.withPromises.startLocationStateNotifications(success, failure);
Function startLocationStateNotifications
calls the success callback when the Location service is enabled or disabled on the device.
ble.startLocationStateNotifications(function (enabled) {
console.log('Location is ' + enabled);
});
Stops state notifications.
ble.stopLocationStateNotifications(success, failure);
// Or using await with promises
await ble.withPromises.stopLocationStateNotifications();
Function stopLocationStateNotifications
calls the success callback when Location state notifications have been stopped.
Registers to be notified when Bluetooth state changes on the device.
ble.startStateNotifications(success, failure);
// Or using await with promises
// Note, initial promise resolves or rejects depending on whether the subscribe was successful
await ble.withPromises.startStateNotifications(success, failure);
Function startStateNotifications
calls the success callback when the Bluetooth is enabled or disabled on the device.
States
ble.startStateNotifications(function (state) {
console.log('Bluetooth is ' + state);
});
Stops state notifications.
ble.stopStateNotifications(success, failure);
// Or using await with promises
await ble.withPromises.stopStateNotifications();
Function stopStateNotifications
calls the success callback when Bluetooth state notifications have been stopped.
Show the Bluetooth settings on the device.
ble.showBluetoothSettings(success, failure);
// Or using await with promises
await ble.withPromises.showBluetoothSettings();
Function showBluetoothSettings
opens the Bluetooth settings for the operating systems.
showBluetoothSettings
is not available on iOS. Plugins like cordova-diagonostic-plugin and the Ionic Native Diagnostic plugin have APIs to open Bluetooth and other settings, but will often get apps rejected by Apple.
ble.showBluetoothSettings();
Enable Bluetooth on the device.
ble.enable(success, failure);
// Or using await with promises
ble.withPromises.enable();
Function enable
prompts the user to enable Bluetooth.
enable
is only supported on Android and does not work on iOS.
If enable
is called when Bluetooth is already enabled, the user will not prompted and the success callback will be invoked.
ble.enable(
function () {
console.log('Bluetooth is enabled');
},
function () {
console.log('The user did *not* enable Bluetooth');
}
);
Read the RSSI value on the device connection.
ble.readRSSI(device_id, success, failure);
Samples the RSSI value (a measure of signal strength) on the connection to a bluetooth device. Requires that you have established a connection before invoking (otherwise an error will be raised).
var rssiSample;
ble.connect(
device_id,
function (device) {
rssiSample = setInterval(function () {
ble.readRSSI(
device_id,
function (rssi) {
console.log('read RSSI', rssi, 'with device', device_id);
},
function (err) {
console.error('unable to read RSSI', err);
clearInterval(rssiSample);
}
);
}, 5000);
},
function (err) {
console.error('error connecting to device');
}
);
Find the connected peripherals offering the listed service UUIDs.
ble.connectedPeripheralsWithServices([service], success, failure);
Retreives a list of the peripherals (containing any of the specified services) currently connected to the system. The peripheral list is sent to the success callback. This function wraps CBCentralManager.retrieveConnectedPeripheralsWithServices:
Find the connected peripherals offering the listed peripheral UUIDs.
ble.peripheralsWithIdentifiers([uuids], success, failure);
Sends a list of known peripherals by their identifiers to the success callback. This function wraps CBCentralManager.retrievePeripheralsWithIdentifiers:
Retrieve the CBManager restoration state (if applicable)
ble.restoredBluetoothState(success, failure);
// Or using await with promises
await ble.withPromises.restoredBluetoothState();
Use of this feature requires the BLUETOOTH_RESTORE_STATE variable to be set to true. For more information about background operation, see Background Scanning and Notifications on iOS.
Retrives the state dictionary that iOS State Preservation and Restoration will supply when the application was launched by iOS.
If the application has no state restored, this will return an empty object.
Lists all peripherals discovered by the plugin due to scanning or connecting since app launch.
ble.list(success, failure);
// Or using await with promises
await ble.withPromises.list();
Sends a list of bonded low energy peripherals to the success callback.
Find the bonded devices.
ble.bondedDevices(success, failure);
// Or using await with promises
await ble.withPromises.bondedDevices();
Sends a list of bonded low energy peripherals to the success callback.
Open an L2CAP channel with a connected peripheral. The PSM is assigned by the peripheral, or possibly defined by the Bluetooth standard.
ble.l2cap.open(device_id, psm, connectCallback, disconnectCallback);
// Or using await with promises
await ble.withPromises.l2cap.open(device_id, psm, disconnectCallback);
Android supports additional arguments in the psm flag to select whether the L2CAP channel is insecure or secure (iOS does this automatically):
ble.l2cap.open(device_id, { psm: psm, secureChannel: true }, connectCallback, disconnectCallback);
// Or using await with promises
await ble.withPromises.l2cap.open(device_id, { psm: psm, secureChannel: true }, disconnectCallback);
An L2CAP channel is a duplex byte stream interface (similar to a network socket) that can be used for much more efficient binary data transfer. This is used in some streaming applications, such as the Bluetooth Object Transfer Service.
The PSM (protocol/service multiplexer) is specified by the peripheral when it opens the channel. Some channels have predefined identifiers controlled by Bluetooth organisation. Apple has also outlined a generic design for PSM exchange. To advertise an L2CAP channel on a specific service, a characteristic with the UUID "ABDD3056-28FA-441D-A470-55A75A52553A" is added to that service, and updated by the peripheral when the L2CAP channel is opened.
psm
key, with an optional secureChannel
boolean setting to control whether the channel is encrypted or not (Android-only)Close an L2CAP channel.
ble.l2cap.close(device_id, psm, success, failure);
// Or using await with promises
await ble.withPromises.l2cap.close(device_id, psm);
Closes an open L2CAP channel with the selected device. All pending reads and writes are aborted.
Receive data from an L2CAP channel.
ble.l2cap.receiveData(device_id, psm, dataCallback);
Sets the function to be called whenever bytes are received on the L2CAP channel. This function will be used as long as the L2CAP connection remains open.
Write data to an L2CAP channel.
ble.l2cap.write(device_id, psm, data, success, failure);
// Or using await with promises
await ble.withPromises.l2cap.write(device_id, psm, data);
Writes all data to an open L2CAP channel. If the data exceeds the available space in the transmit buffer, the data will be automatically sent in chunks as space becomes available. The success callback is called only once after all the supplied bytes have been written to the transmit stream.
Peripheral Data is passed to the success callback when scanning and connecting. Limited data is passed when scanning.
{
"name": "Battery Demo",
"id": "20:FF:D0:FF:D1:C0",
"advertising": [2, 1, 6, 3, 3, 15, 24, 8, 9, 66, 97, 116, 116, 101, 114, 121],
"rssi": -55
}
After connecting, the peripheral object also includes service, characteristic and descriptor information.
{
"name": "Battery Demo",
"id": "20:FF:D0:FF:D1:C0",
"advertising": [2, 1, 6, 3, 3, 15, 24, 8, 9, 66, 97, 116, 116, 101, 114, 121],
"rssi": -55,
"services": ["1800", "1801", "180f"],
"characteristics": [
{
"service": "1800",
"characteristic": "2a00",
"properties": ["Read"]
},
{
"service": "1800",
"characteristic": "2a01",
"properties": ["Read"]
},
{
"service": "1801",
"characteristic": "2a05",
"properties": ["Read"]
},
{
"service": "180f",
"characteristic": "2a19",
"properties": ["Read"],
"descriptors": [
{
"uuid": "2901"
},
{
"uuid": "2904"
}
]
}
]
}
Bluetooth advertising data is returned in when scanning for devices. The format varies depending on your platform. On Android advertising data will be the raw advertising bytes. iOS does not allow access to raw advertising data, so a dictionary of data is returned.
The advertising information for both Android and iOS appears to be a combination of advertising data and scan response data.
To get consistent advertising data payloads across platforms, you can use the ble-central-advertisements module.
{
"name": "demo",
"id": "00:1A:7D:DA:71:13",
"advertising": ArrayBuffer,
"rssi": -37
"connectable":"true" /*Only on Android >= API Level 26*/
}
Convert the advertising info to a Uint8Array for processing. var adData = new Uint8Array(peripheral.advertising)
. You application is responsible for parsing all the information out of the advertising ArrayBuffer using the GAP type constants. For example to get the service data from the advertising info, I parse the advertising info into a map and then get the service data to retrieve a characteristic value that is being broadcast.
Note that iOS uses the string value of the constants for the Advertisement Data Retrieval Keys. This will likely change in the future.
{
"name": "demo"
"id": "15B4F1C5-C9C0-4441-BD9F-1A7ED8F7A365",
"advertising": {
"kCBAdvDataLocalName": "demo",
"kCBAdvDataManufacturerData": {}, // arraybuffer data not shown
"kCBAdvDataServiceUUIDs": [
"721b"
],
"kCBAdvDataIsConnectable": true,
"kCBAdvDataServiceData": {
"BBB0": {} // arraybuffer data not shown
},
},
"rssi": -61
}
Some of the values such as kCBAdvDataManufacturerData
are ArrayBuffers
. The data won't print out, but you can convert it to bytes using new Uint8Array(peripheral.advertisting.kCBAdvDataManufacturerData)
. Your application is responsible for parsing and decoding any binary data such as kCBAdvDataManufacturerData
or kCBAdvDataServiceData
.
function onDiscoverDevice(device) {
// log the device as JSON
console.log('Found Device', JSON.stringify(device, null, 2));
// on iOS, print the manufacturer data if it exists
if (device.advertising && device.advertising.kCBAdvDataManufacturerData) {
const mfgData = new Uint8Array(device.advertising.kCBAdvDataManufacturerData);
console.log('Manufacturer Data is', mfgData);
}
}
ble.scan([], 5, onDiscoverDevice, onError);
Enable: chrome://flags/#enable-experimental-web-platform-features and chrome://flags/#enable-web-bluetooth-new-permissions-backend
Scan must be initiated from a user action (click, touch, etc).
This plugin uses typed Arrays or ArrayBuffers for sending and receiving data.
This means that you need convert your data to ArrayBuffers before sending and from ArrayBuffers when receiving.
// ASCII only
function stringToBytes(string) {
var array = new Uint8Array(string.length);
for (var i = 0, l = string.length; i < l; i++) {
array[i] = string.charCodeAt(i);
}
return array.buffer;
}
// ASCII only
function bytesToString(buffer) {
return String.fromCharCode.apply(null, new Uint8Array(buffer));
}
You can read more about typed arrays in these articles on MDN and HTML5 Rocks.
UUIDs are always strings and not numbers. Some 16-bit UUIDs, such as '2220' look like integers, but they're not. (The integer 2220 is 0x8AC in hex.) This isn't a problem with 128 bit UUIDs since they look like strings 82b9e6e1-593a-456f-be9b-9215160ebcac. All 16-bit UUIDs should also be passed to methods as strings.
Android applications will continue to receive notification while the application is in the background.
iOS applications need additional configuration to allow Bluetooth to run in the background.
Add a new section to config.xml
<platform name="ios">
<config-file parent="UIBackgroundModes" target="*-Info.plist">
<array>
<string>bluetooth-central</string>
</array>
</config-file>
</platform>
See ble-background example project for more details.
Additionally, iOS state restoration should be enabled if long-running scans or connects should be restarted after the phone is rebooted or the app is suspended by iOS. See iOS restore state for the details and limitations of this feature.
To activate iOS state restoration, set the BLUETOOTH_RESTORE_STATE to true when adding the plugin to the project:
--variable BLUETOOTH_RESTORE_STATE=true
By default, the app id (otherwise known as the bundle identifier) will be used as the iOS restore identifier key. This can be overridden by setting the variable to the desired key directly. For example:
--variable BLUETOOTH_RESTORE_STATE=my.custom.restoration.identifier.key
It's important to note that iOS will not automatically relaunch an application under some conditions. For a detailed list of these conditions, see the iOS Technical QA on the subject.
Tests require the Cordova Plugin Test Framework
Create a new project
git clone https://github.com/don/cordova-plugin-ble-central
cordova create ble-test com.example.ble.test BLETest
cd ble-test
cordova platform add android
cordova plugin add ../cordova-plugin-ble-central
cordova plugin add ../cordova-plugin-ble-central/tests
cordova plugin add cordova-plugin-test-framework
Change the start page in config.xml
<content src="https://github.com/don/cordova-plugin-ble-central/raw/master/cdvtests/index.html" />
Run the app on your phone
cordova run android --device
npm version prepatch --preid=alpha
plugin.xml
version with npm versionnpm publish --tag alpha
npm version patch
npm publish
git merge master
package.json
and plugin.xml
versionsnpm publish --tag slim
If you need Nordic DFU capability, Tomáš Bedřich has a fork of this plugin that adds an updateFirmware()
method that allows users to upgrade nRF5x based chips over the air. https://github.com/fxe-gear/cordova-plugin-ble-central
Apache 2.0
Try the code. If you find an problem or missing feature, file an issue or create a pull request.