@abandonware/noble 中文文档教程
Node.js BLE(低功耗蓝牙)中央模块。
想要实现外设? 查看 bleno。
注意:macOS / Mac OS X、Linux、FreeBSD 和 Windows 是目前唯一受支持的操作系统。
Documentation
Quick Start Example
// Read the battery level of the first found peripheral exposing the Battery Level characteristic
const noble = require('@abandonware/noble');
noble.on('stateChange', async (state) => {
if (state === 'poweredOn') {
await noble.startScanningAsync(['180f'], false);
}
});
noble.on('discover', async (peripheral) => {
await noble.stopScanningAsync();
await peripheral.connectAsync();
const {characteristics} = await peripheral.discoverSomeServicesAndCharacteristicsAsync(['180f'], ['2a19']);
const batteryLevel = (await characteristics[0].readAsync())[0];
console.log(`${peripheral.address} (${peripheral.advertisement.localName}): ${batteryLevel}%`);
await peripheral.disconnectAsync();
process.exit(0);
});
Installation
Prerequisites
OS X
- Install Xcode
- On newer versions of OSX, allow bluetooth access on the terminal app: "System Preferences" —> "Security & Privacy" —> "Bluetooth" -> Add terminal app (see Sandboxed terminal)
Linux
- Kernel version 3.6 or above
libbluetooth-dev
needs to be installed. For instructions for specific distributions, see below.- To set the necessary privileges to run without sudo, see this section. This is required for all distributions (Raspbian, Ubuntu, Fedora, etc). You will not get any errors if running without sudo, but nothing will happen.
Ubuntu, Debian, Raspbian
请先查看上面的通用 Linux 注释。
sudo apt-get install bluetooth bluez libbluetooth-dev libudev-dev
确保 node
在您的 PATH
上。 如果不是,一些选项:
- Symlink
nodejs
tonode
:sudo ln -s /usr/bin/nodejs /usr/bin/node
- Install Node.js using the NodeSource package
Fedora and other RPM-based distributions
首先查看上面的通用 Linux 注释。
sudo yum install bluez bluez-libs bluez-libs-devel
Intel Edison
请先查看上面的通用 Linux 注释。
FreeBSD
确保你有 GNU Make:
sudo pkg install gmake
通过将 no-ubt.conf 放入 来禁用默认蓝牙堆栈的自动加载/usr/local/etc/devd/no-ubt.conf
并重新启动 devd(sudo service devd restart
)。
卸载 ng_ubt
内核模块(如果已加载):
sudo kldunload ng_ubt
确保您对与蓝牙适配器对应的 /dev/usb/*
设备具有读写权限。
Windows
使用 Microsoft 的 windows-build-tools 来自提升的 PowerShell 或 cmd.exe(以管理员身份运行)。
npm install --global --production windows-build-tools
node-bluetooth-hci-socket 先决条件
- Compatible Bluetooth 4.0 USB adapter
- WinUSB driver setup for Bluetooth 4.0 USB adapter, using Zadig tool
请参阅 @don 在 < a href="https://www.youtube.com/watch?v=mL9B8wuEdms&feature=youtu.be&t=1m46s">Bluetooth LE with Node.js and Noble on Windows
Docker
确保您的容器运行使用 --network=host
选项并验证所有特定环境先决条件。
Installing and using the package
npm install @abandonware/noble
const noble = require('@abandonware/noble');
API docs
所有操作都有两种 API 变体——一种期望回调,一种返回 Promise(由 Async
后缀表示)。
此外,还有与每个操作对应的事件(以及一些全局事件)。
例如,在 Peripheral 的“发现服务”操作的情况下:
- There's a
discoverServices
method expecting a callback:
peripheral.discoverServices((error, services) => {
// callback - handle error and services
});
- There's a
discoverServicesAsync
method returning a Promise:
try {
const services = await peripheral.discoverServicesAsync();
// handle services
} catch (e) {
// handle error
}
- There's a
servicesDiscover
event emitted after services are discovered:
peripheral.once('servicesDiscover', (services) => {
// handle services
});
API 结构:
- Scanning and discovery
- Event: Adapter state changed
- Start scanning
- Event: Scanning started
- Stop scanning
- Event: Scanning stopped
- Event: Peripheral discovered
- Event: Warning raised
- Reset device
- Peripheral
- Connect
- Event: Connected
- Cancel a pending connection
- Disconnect
- Event: Disconnected
- Update RSSI
- Event: RSSI updated
- Discover services
- Discover all services and characteristics
- Discover some services and characteristics
- Event: Services discovered
- Read handle
- Event: Handle read
- Write handle
- Event: Handle written
- Service
- Discover included services
- Event: Included services discovered
- Discover characteristics
- Event: Characteristics discovered
- Characteristic
- Read
- Event: Data read
- Write
- Event: Data written
- Broadcast
- Event: Broadcast sent
- Subscribe
- Event: Notification received
- Unsubscribe
- Discover descriptors
- Event: Descriptors discovered
- Descriptor
- Read value
- Event: Value read
- Write value
- Event: Value written
Scanning and discovery
Event: Adapter state changed
noble.on('stateChange', callback(state));
state
可以是以下之一:
unknown
resetting
unsupported
unauthorized
poweredOff
poweredOn
Start scanning
noble.startScanning(); // any service UUID, no duplicates
noble.startScanning([], true); // any service UUID, allow duplicates
var serviceUUIDs = ['<service UUID 1>', ...]; // default: [] => all
var allowDuplicates = falseOrTrue; // default: false
noble.startScanning(serviceUUIDs, allowDuplicates[, callback(error)]); // particular UUIDs
注意: noble.state
必须在扫描开始前 poweredOn
。 noble.on('stateChange', callback(state));
可用于监听状态变化事件。
Event: Scanning started
noble.on('scanStart', callback);
事件触发时间:
- Scanning is started
- Another application enables scanning
- Another application changes scanning settings
Stop scanning
noble.stopScanning();
Event: Scanning stopped
noble.on('scanStop', callback);
事件触发时间:
- Scanning is stopped
- Another application stops scanning
Event: Peripheral discovered
noble.on('discover', callback(peripheral));
peripheral
:
{
id: '<id>',
address: '<BT address'>, // Bluetooth Address of device, or 'unknown' if not known
addressType: '<BT address type>', // Bluetooth Address type (public, random), or 'unknown' if not known
connectable: trueOrFalseOrUndefined, // true or false, or undefined if not known
advertisement: {
localName: '<name>',
txPowerLevel: someInteger,
serviceUuids: ['<service UUID>', ...],
serviceSolicitationUuid: ['<service solicitation UUID>', ...],
manufacturerData: someBuffer, // a Buffer
serviceData: [
{
uuid: '<service UUID>',
data: someBuffer // a Buffer
},
// ...
]
},
rssi: integerValue,
mtu: integerValue // MTU will be null, until device is connected and hci-socket is used
};
注意 在 macOS 上,如果之前未连接设备,地址将设置为 ''。
Event: Warning raised
noble.on('warning', callback(message));
Reset device
noble.reset()
Peripheral
Connect
peripheral.connect([callback(error)]);
某些蓝牙设备无法无缝连接,可能是因为蓝牙设备固件或内核。 请在连接 API 之前使用 noble.reset() API 重置设备。
Event: Connected
peripheral.once('connect', callback);
Cancel a pending connection
peripheral.cancelConnect();
// Will emit a 'connect' event with error
Disconnect
peripheral.disconnect([callback(error)]);
Event: Disconnected
peripheral.once('disconnect', callback);
Update RSSI
peripheral.updateRssi([callback(error, rssi)]);
Event: RSSI updated
peripheral.once('rssiUpdate', callback(rssi));
Discover services
peripheral.discoverServices(); // any service UUID
var serviceUUIDs = ['<service UUID 1>', ...];
peripheral.discoverServices(serviceUUIDs[, callback(error, services)]); // particular UUIDs
Discover all services and characteristics
peripheral.discoverAllServicesAndCharacteristics([callback(error, services, characteristics)]);
Discover some services and characteristics
var serviceUUIDs = ['<service UUID 1>', ...];
var characteristicUUIDs = ['<characteristic UUID 1>', ...];
peripheral.discoverSomeServicesAndCharacteristics(serviceUUIDs, characteristicUUIDs, [callback(error, services, characteristics));
Event: Services discovered
peripheral.once('servicesDiscover', callback(services));
Read handle
peripheral.readHandle(handle, callback(error, data));
Event: Handle read
peripheral.once('handleRead<handle>', callback(data)); // data is a Buffer
是句柄标识符。
Write handle
peripheral.writeHandle(handle, data, withoutResponse, callback(error));
Event: Handle written
peripheral.once('handleWrite<handle>', callback());
是句柄标识符。
Service
Discover included services
service.discoverIncludedServices(); // any service UUID
var serviceUUIDs = ['<service UUID 1>', ...];
service.discoverIncludedServices(serviceUUIDs[, callback(error, includedServiceUuids)]); // particular UUIDs
Event: Included services discovered
service.once('includedServicesDiscover', callback(includedServiceUuids));
Discover characteristics
service.discoverCharacteristics() // any characteristic UUID
var characteristicUUIDs = ['<characteristic UUID 1>', ...];
service.discoverCharacteristics(characteristicUUIDs[, callback(error, characteristics)]); // particular UUIDs
Event: Characteristics discovered
service.once('characteristicsDiscover', callback(characteristics));
characteristics
{
uuid: '<uuid>',
properties: ['...'] // 'broadcast', 'read', 'writeWithoutResponse', 'write', 'notify', 'indicate', 'authenticatedSignedWrites', 'extendedProperties'
};
Characteristic
Read
characteristic.read([callback(error, data)]);
Event: Data read
characteristic.on('data', callback(data, isNotification));
characteristic.once('read', callback(data, isNotification)); // legacy
发出时间:
- Characteristic read has completed, result of
characteristic.read(...)
- Characteristic value has been updated by peripheral via notification or indication, after having been enabled with
characteristic.notify(true[, callback(error)])
注意 isNotification
事件参数值可以未定义
,具体取决于平台。 该参数在 1.8.1 版本后被弃用,并且在 macOS High Sierra 及更高版本上不受支持。
Write
characteristic.write(data, withoutResponse[, callback(error)]); // data is a Buffer, withoutResponse is true|false
withoutResponse
:false
: send a write request, used with "write" characteristic propertytrue
: send a write command, used with "write without response" characteristic property
Event: Data written
characteristic.once('write', withoutResponse, callback());
当特征写入完成时发出,characteristic.write(...)
的结果。
Broadcast
characteristic.broadcast(broadcast[, callback(error)]); // broadcast is true|false
Event: Broadcast sent
characteristic.once('broadcast', callback(state));
当特征广播状态改变时发出,characteristic.broadcast(...)
的结果。
Subscribe
characteristic.subscribe([callback(error)]);
订阅一个特征。
当外设发送通知或指示时触发 data
事件。 用于具有“通知”或“指示”属性的特性。
Event: Notification received
characteristic.once('notify', callback(state));
当特征通知状态改变时发出,characteristic.notify(...)
的结果。
Unsubscribe
characteristic.unsubscribe([callback(error)]);
取消订阅特征。
用于具有“notify”或“indicate”属性的特性
Discover descriptors
characteristic.discoverDescriptors([callback(error, descriptors)]);
Event: Descriptors discovered
characteristic.once('descriptorsDiscover', callback(descriptors));
descriptors
:
[
{
uuid: '<uuid>'
},
// ...
]
Descriptor
Read value
descriptor.readValue([callback(error, data)]);
Event: Value read
descriptor.once('valueRead', data); // data is a Buffer
Write value
descriptor.writeValue(data[, callback(error)]); // data is a Buffer
Event: Value written
descriptor.once('valueWrite');
Advanced usage
Override default bindings
默认情况下,noble 将根据您的平台选择合适的蓝牙设备绑定。 您可以使用 with-bindings
模块提供自定义绑定。
var noble = require('@abandonware/noble/with-bindings')(require('./my-custom-bindings'));
Running without root/sudo (Linux-specific)
运行以下命令:
sudo setcap cap_net_raw+eip $(eval readlink -f `which node`)
这将授予 node
二进制 cap_net_raw
权限,因此它可以启动/停止 BLE 广播。
注意:以上命令需要安装setcap
。
它可以通过以下方式安装:
- apt:
sudo apt-get install libcap2-bin
- yum:
su -c \'yum install libcap2-bin\'
Multiple Adapters (Linux-specific)
默认使用hci0
。
要覆盖,请将 NOBLE_HCI_DEVICE_ID
环境变量设置为接口编号。
例如,要指定 hci1
:
sudo NOBLE_HCI_DEVICE_ID=1 node <your file>.js
如果您在一个设置中使用多个 HCI 设备,您可以运行两个具有不同绑定配置的 noble 实例,方法是在代码中分别初始化它们:
const HCIBindings = require('@abandonware/noble/lib/hci-socket/bindings');
const Noble = require('@abandonware/noble/lib/noble');
const params = {
deviceId: 0,
userChannel: true
};
const noble = new Noble(new HCIBindings(params));
Reporting all HCI events (Linux-specific)
默认情况下,noble 等待两个每个蓝牙地址的广告数据和扫描响应数据。 如果您的设备不使用扫描响应,则可以使用 NOBLE_REPORT_ALL_HCI_EVENTS
环境变量来绕过它。
sudo NOBLE_REPORT_ALL_HCI_EVENTS=1 node <your file>.js
bleno compatibility (Linux-specific)
默认情况下,每当收到 GATT 请求消息时,noble 都会以错误响应。 如果您打算将 bleno 与 noble 一起使用,则可以使用 NOBLE_MULTI_ROLE
环境变量来绕过此行为。
注意:这需要蓝牙 4.1 适配器。
sudo NOBLE_MULTI_ROLE=1 node <your file>.js
Common problems
Maximum simultaneous connections
此限制由蓝牙适配器硬件及其固件强加。
Platform | |
---|---|
OS X 10.11 (El Capitan) | 6 |
Linux/Windows - Adapter-dependent | 5 (CSR based adapter) |
Sandboxed terminal
在较新版本的 OSX 上,终端应用程序被沙盒化以默认不允许蓝牙连接。 如果您运行试图访问它的脚本,您将收到 Abort trap: 6
错误。
要启用蓝牙,请转到“系统偏好设置”—> “安全与隐私”——> “蓝牙”-> 将您的终端添加到允许的应用程序中。
Adapter-specific known issues
某些 BLE 适配器在扫描时无法连接到外围设备(以下示例)。 尝试连接时您将收到以下消息:
Sena UD-100(Cambridge Silicon Radio, Ltd Bluetooth Dongle(HCI 模式)):Error: Command disallowed
Intel Dual Band Wireless-AC 7260 (Intel Corporation Wireless 7260 (rev 73): Error: Connection Rejected due to Limited Resources (0xd)
为了解决这个问题,您需要在尝试连接之前停止扫描。
Backers
支持我们每月捐款并帮助我们继续我们的活动。 [成为支持者]
Sponsors
成为赞助商并在 Github 上的自述文件中获取您的徽标以及指向您网站的链接。 [成为赞助商]
Useful links
License
版权所有 (C) 2015 Sandeep Mistry sandeep.mistry@gmail.com
特此免费授予任何权限获得本软件和相关文档文件(“软件”)副本的人,可以不受限制地处理本软件,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或出售的权利软件的副本,并允许获得软件的人这样做,但须满足以下条件:
上述版权声明和本许可声明应包含在软件的所有副本或重要部分中。
本软件“按原样”提供,不提供任何明示或暗示的保证,包括但不限于对适销性、特定用途的适用性和非侵权的保证。 在任何情况下,作者或版权持有人均不对任何索赔、损害或其他责任负责,无论是在合同诉讼、侵权行为还是其他方面,由软件或软件的使用或其他交易引起、由软件引起或与之相关软件。