Important: Use strings for UUIDs
master'2220'). Do not pass them as integers.repository·master·Indexed 21 days ago
https://github.com/don/cordova-plugin-ble-centralA Bluetooth Low Energy (BLE) Central plugin for Apache Cordova and Capacitor (version 2.0.0) that enables mobile applications to scan, connect, and communicate with BLE peripherals. The plugin supports standard services such as Battery and Heart Rate, as well as hardware like Adafruit Bluefruit LE, MetaWear, and RedBear Lab BLE boards.
'2220'). Do not pass them as integers.Cordova hooks are scripts that allow you to customize Cordova commands by executing code before or after specific lifecycle events. This is useful for integrating custom build systems, version control, or automated tasks.
before_prepare/ runs before the prepare command).Cordova Hooks are scripts used to customize Cordova commands. They are executed before or after specific Cordova CLI commands. This is useful for integrating custom build systems or version control workflows.
Key Requirements:
Cordova hooks are scripts used to customize Cordova commands. They are executed either before or after specific Cordova CLI commands. This is useful for integrating custom build systems or version control workflows into the Cordova lifecycle.
Important Requirements:
When scanning or connecting, the plugin returns peripheral objects. The structure changes depending on the connection state.
Scanning State: Contains basic info like name, id, advertising (raw bytes or dictionary), and rssi.
Connected State: Includes the scanning data plus services, characteristics (with service, characteristic, and properties), and descriptors (with uuid).
Example Connected Peripheral Object:
{
"name": "Battery Demo",
"id": "20:FF:D0:FF:D1:C0",
"rssi": -55,
"services": ["1800", "1801", "180f"],
"characteristics": [
{
"service": "180f",
"characteristic": "2a19",
"properties": ["Read"],
"descriptors": [{ "uuid": "2901" }]
}
]
}L2CAP (Logical Link Control and Adaptation Protocol) provides a duplex byte stream interface, similar to a network socket, which is more efficient for binary data transfer than standard GATT operations. This is useful for streaming applications like the Bluetooth Object Transfer Service.
Supported Platforms: iOS, Android (>= 10).
Key Operations:
l2cap.open with a device_id and a psm (Protocol/Service Multiplexer). On Android, you can specify a secureChannel boolean in the options object to control encryption.l2cap.write. If data exceeds the transmit buffer, it is automatically sent in chunks.l2cap.receiveData to set a callback that triggers whenever new bytes arrive on the channel.l2cap.close to abort pending operations and close the stream.// Open an L2CAP channel with promises
await ble.withPromises.l2cap.open(device_id, { psm: psm, secureChannel: true }, disconnectCallback);
// Write data
await ble.withPromises.l2cap.write(device_id, psm, data);
// Receive data
ble.l2cap.receiveData(device_id, psm, (data) => {
console.log('Received:', data);
});
// Close channel
await ble.withPromises.l2cap.close(device_id, psm);Cordova Hooks are special scripts used to customize Cordova commands during the build process. They allow developers to inject custom logic at specific lifecycle events (e.g., before a build starts or after a plugin is installed).
Hooks are executed serially in this order:
/hooks directory.config.xml.plugin.xml.Important: Ensure your script files are marked as executable.
To run the Adafruit UART example on an Android device, use the following Cordova commands.
Troubleshooting Android Scanning:
Some Android devices fail to find peripherals when filtering by a specific Service UUID. If your device cannot find the Bluetooth peripheral, modify the ble.scan call to use an empty array [] instead of a specific service UUID to remove the filter.
cordova platform add android
cordova run android --deviceble.scan([bluefruit.serviceUUID], 5, app.onDiscoverDevice, app.onError);
ble.scan([], 5, app.onDiscoverDevice, app.onError);
Plugin developers can define hooks in plugin.xml. Certain hooks are exclusive to the plugin lifecycle:
before_plugin_install / after_plugin_install: Executed exclusively when the plugin is being installed.before_plugin_uninstall: Executed exclusively when the plugin is being uninstalled.<hook type="before_plugin_install" src="scripts/beforeInstall.js" />
<hook type="after_build" src="scripts/afterBuild.js" /><hook type="before_plugin_install" src="scripts/beforeInstall.js" />
<hook type="after_build" src="scripts/afterBuild.js" />
<platform name="wp8">
<hook type="before_plugin_install" src="scripts/wp8BeforeInstall.js" />
<hook type="before_build" src="scripts/wp8BeforeBuild.js" />
</platform>Advertising data format varies significantly between Android and iOS.
Returns an ArrayBuffer in the advertising field. You must convert this to a Uint8Array and parse it manually using GAP type constants.
var adData = new Uint8Array(peripheral.advertising);Returns a dictionary of data using Apple's Advertisement Data Retrieval Keys (e.g., kCBAdvDataLocalName). Some values like kCBAdvDataManufacturerData are ArrayBuffers. Convert them using:
const mfgData = new Uint8Array(device.advertising.kCBAdvDataManufacturerData);To achieve consistent payloads across platforms, consider using the ble-central-advertisements module.
function onDiscoverDevice(device) {
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);The plugin uses TypedArrays or ArrayBuffers for all data transfers. You must convert your application data (like strings) to ArrayBuffers before sending, and convert received ArrayBuffers back to your desired format.
Example: ASCII String Conversion
// Convert string to ArrayBuffer
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;
}
// Convert ArrayBuffer to string
function bytesToString(buffer) {
return String.fromCharCode.apply(null, new Uint8Array(buffer));
}// 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 define hooks by creating subfolders inside a hooks directory named after the hook type. Any script placed in that subfolder will be automatically executed when that hook type is fired.
Example structure:
# This script runs automatically after every build
hooks/after_build/after_build_custom_action.jshooks/after_build/after_build_custom_action.js