A Node.js module for implementing BLE (Bluetooth Low Energy) peripherals
npm install @ycanince/blenoxcode-select --install
libbluetooth-dev`
* `bluetoothd` disabled, if BlueZ 5.14 or later is installed. Use `sudo hciconfig hci0 up` to power Bluetooth adapter up after stopping or disabling `bluetoothd`.
* `System V`:
* `sudo service bluetooth stop` (once)
* `sudo update-rc.d bluetooth remove` (persist on reboot)
* `systemd`
* `sudo systemctl stop bluetooth` (once)
* `sudo systemctl disable bluetooth` (persist on reboot)
If you're using noble and bleno at the same time, connected BLE devices may not be able to retrieve a list of services from the BLE adaptor. Check out noble's documentation on bleno compatibility
#### Ubuntu/Debian/Raspbian
`sh
sudo apt-get install bluetooth bluez libbluetooth-dev libudev-dev
`
Make sure `node` is on your path, if it's not, some options:
* symlink `nodejs` to `node`: `sudo ln -s /usr/bin/nodejs /usr/bin/node`
* install Node.js using the NodeSource package
#### Fedora / Other-RPM based
`sh
sudo yum install bluez bluez-libs bluez-libs-devel
`
#### Intel Edison
See Configure Intel Edison for Bluetooth LE (Smart) Development
$3
Make sure you have GNU Make:
`sh
sudo pkg install gmake
`
Disable automatic loading of the default Bluetooth stack by putting no-ubt.conf into `/usr/local/etc/devd/no-ubt.conf` and restarting devd (`sudo service devd restart`).
Unload `ng_ubt` kernel module if already loaded:
`sh
sudo kldunload ng_ubt
`
Make sure you have read and write permissions on the `/dev/usb/*` device that corresponds to your Bluetooth adapter.
$3
* node-gyp requirements for Windows
* Python 2.7
* Visual Studio (Express)
* node-bluetooth-hci-socket prerequisites
* Compatible Bluetooth 4.0 USB adapter
* WinUSB.aspx) driver setup for Bluetooth 4.0 USB adapter, using Zadig tool
Install
`sh
npm install bleno
`
Usage
`javascript
var bleno = require('bleno');
`
See examples folder for code examples.
$3
#### Advertising
##### Start advertising
NOTE: `bleno.state` must be `poweredOn` before advertising is started. `bleno.on('stateChange', callback(state));` can be used register for state change events.
`javascript
var name = 'name';
var serviceUuids = ['fffffffffffffffffffffffffffffff0']
bleno.startAdvertising(name, serviceUuids[, callback(error)]);
`
__Note:__: there are limits on the name and service UUID's
* name
* maximum 26 bytes
* service UUID's
* 1 128-bit service UUID
* 1 128-bit service UUID + 2 16-bit service UUID's
* 7 16-bit service UUID
##### Start advertising iBeacon
`javascript
var name = 'Bleno'; // maximum 26 bytes
var uuid = 'e2c56db5dffb48d2b060d0f5a71096e0';
var major = 0; // 0x0000 - 0xffff
var minor = 0; // 0x0000 - 0xffff
var measuredPower = -59; // -128 - 127
bleno.startAdvertisingIBeacon(name, uuid, major, minor, measuredPower[, callback(error)]);
`
__Notes:__:
* OS X:
* in iBeacon mode your peripheral is non-connectable!
##### Start advertising with EIR data (__Linux only__)
`javascript
var scanData = Buffer.from(...); // maximum 31 bytes
var advertisementData = Buffer.from(...); // maximum 31 bytes
bleno.startAdvertisingWithEIRData(advertisementData[, scanData, callback(error)]);
`
* For EIR format section Bluetooth Core Specification sections and 8 and 18 for more information the data format.
##### Stop advertising
`javascript
bleno.stopAdvertising([callback]);
`
#### Set services
Set the primary services available on the peripheral.
`javascript
var services = [
... // see PrimaryService for data type
];
bleno.setServices(services[, callback(error)]);
`
#### Disconnect client
`javascript
bleno.disconnect(); // Linux only
`
#### Update RSSI
`javascript
bleno.updateRssi([callback(error, rssi)]); // not available in OS X 10.9
`
$3
`javascript
var PrimaryService = bleno.PrimaryService;
var primaryService = new PrimaryService({
uuid: 'fffffffffffffffffffffffffffffff0', // or 'fff0' for 16-bit
characteristics: [
// see Characteristic for data type
]
});
`
$3
`javascript
var Characteristic = bleno.Characteristic;
var characteristic = new Characteristic({
uuid: 'fffffffffffffffffffffffffffffff1', // or 'fff1' for 16-bit
properties: [ ... ], // can be a combination of 'read', 'write', 'writeWithoutResponse', 'notify', 'indicate'
secure: [ ... ], // enable security for properties, can be a combination of 'read', 'write', 'writeWithoutResponse', 'notify', 'indicate'
value: null, // optional static value, must be of type Buffer - for read only characteristics
descriptors: [
// see Descriptor for data type
],
onReadRequest: null, // optional read request handler, function(offset, callback) { ... }
onWriteRequest: null, // optional write request handler, function(data, offset, withoutResponse, callback) { ...}
onSubscribe: null, // optional notify/indicate subscribe handler, function(maxValueSize, updateValueCallback) { ...}
onUnsubscribe: null, // optional notify/indicate unsubscribe handler, function() { ...}
onNotify: null, // optional notify sent handler, function() { ...}
onIndicate: null // optional indicate confirmation received handler, function() { ...}
});
`
#### Result codes
* Characteristic.RESULT_SUCCESS
* Characteristic.RESULT_INVALID_OFFSET
* Characteristic.RESULT_INVALID_ATTRIBUTE_LENGTH
* Characteristic.RESULT_UNLIKELY_ERROR
#### Read requests
Can specify read request handler via constructor options or by extending Characteristic and overriding onReadRequest.
Parameters to handler are
* `offset` (0x0000 - 0xffff)
* `callback`
`callback` must be called with result and data (of type `Buffer`) - can be async.
`javascript
var result = Characteristic.RESULT_SUCCESS;
var data = Buffer.from( ... );
callback(result, data);
`
#### Write requests
Can specify write request handler via constructor options or by extending Characteristic and overriding onWriteRequest.
Parameters to handler are
* `data` (Buffer)
* `offset` (0x0000 - 0xffff)
* `withoutResponse` (true | false)
* `callback`.
`callback` must be called with result code - can be async.
`javascript
var result = Characteristic.RESULT_SUCCESS;
callback(result);
`
#### Notify subscribe
Can specify notify subscribe handler via constructor options or by extending Characteristic and overriding onSubscribe.
Parameters to handler are
* `maxValueSize` (maximum data size)
* `updateValueCallback` (callback to call when value has changed)
#### Notify unsubscribe
Can specify notify unsubscribe handler via constructor options or by extending Characteristic and overriding onUnsubscribe.
#### Notify value changes
Call the `updateValueCallback` callback (see Notify subscribe), with an argument of type `Buffer`
Can specify notify sent handler via constructor options or by extending Characteristic and overriding onNotify.
$3
`javascript
var Descriptor = bleno.Descriptor;
var descriptor = new Descriptor({
uuid: '2901',
value: 'value' // static value, must be of type Buffer or string if set
});
`
$3
#### Adapter state change
`javascript
state = <"unknown" | "resetting" | "unsupported" | "unauthorized" | "poweredOff" | "poweredOn">
bleno.on('stateChange', callback(state));
`
#### Advertisement started
`javascript
bleno.on('advertisingStart', callback(error));
bleno.on('advertisingStartError', callback(error));
`
#### Advertisement stopped
`javascript
bleno.on('advertisingStop', callback);
`
#### Services set
`javascript
bleno.on('servicesSet', callback(error));
bleno.on('servicesSetError', callback(error));
`
#### Accept
`javascript
bleno.on('accept', callback(clientAddress)); // not available on OS X 10.9
`
#### Disconnect
`javascript
bleno.on('disconnect', callback(clientAddress)); // Linux only
`
#### RSSI Update
`javascript
bleno.on('rssiUpdate', callback(rssi)); // not available on OS X 10.9
`
$3
__Note:__ Make sure you've also checked the Linux Prerequisites
#### Running without root/sudo
Run the following command:
`sh
sudo setcap cap_net_raw+eip $(eval readlink -f which node)
`
This grants the `node` binary `cap_net_raw` privileges, so it can start/stop BLE advertising.
__Note:__ The above command requires `setcap` to be installed, it can be installed using the following:
* apt: `sudo apt-get install libcap2-bin`
* yum: `su -c \'yum install libcap2-bin\'`
#### Multiple Adapters
`hci0` is used by default to override set the `BLENO_HCI_DEVICE_ID` environment variable to the interface number.
Example, specify `hci1`:
`sh
sudo BLENO_HCI_DEVICE_ID=1 node .js
`
#### Set custom device name
By default bleno uses the hostname (`require('os').hostname()`) as the value for the device name (0x2a00) characterisic, to match the behaviour of OS X.
A custom device name can be specified by setting the `BLENO_DEVICE_NAME` environment variable:
`sh
sudo BLENO_DEVICE_NAME="custom device name" node .js
`
or
`js
process.env['BLENO_DEVICE_NAME'] = 'custom device name';
`
#### Set Advertising Interval
bleno uses a 100 ms advertising interval by default.
A custom advertising interval can be specified by setting the `BLENO_ADVERTISING_INTERVAL` environment variable with the desired value in milliseconds:
`sh
sudo BLENO_ADVERTISING_INTERVAL=500 node .js
`
Advertising intervals must be between 20 ms to 10 s (10,000 ms).
Useful tools/links
* Tools
* LightBlue for iOS/OS X
* nRF Master Control Panel (BLE) for Android
* hcitool and `gatttool`` by BlueZ for Linux