@stoprocent/noble 1.9.2-16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/.editorconfig +11 -0
  2. package/.eslintrc.js +25 -0
  3. package/.github/FUNDING.yml +2 -0
  4. package/.github/workflows/fediverse-action.yml +16 -0
  5. package/.github/workflows/nodepackage.yml +77 -0
  6. package/.github/workflows/npm-publish.yml +26 -0
  7. package/.github/workflows/prebuild.yml +65 -0
  8. package/.nycrc.json +4 -0
  9. package/CHANGELOG.md +119 -0
  10. package/LICENSE +20 -0
  11. package/MAINTAINERS.md +1 -0
  12. package/README.md +833 -0
  13. package/assets/noble-logo.png +0 -0
  14. package/assets/noble-logo.svg +13 -0
  15. package/binding.gyp +19 -0
  16. package/codecov.yml +5 -0
  17. package/examples/advertisement-discovery.js +65 -0
  18. package/examples/cache-gatt-discovery.js +198 -0
  19. package/examples/cache-gatt-reconnect.js +164 -0
  20. package/examples/echo.js +104 -0
  21. package/examples/enter-exit.js +78 -0
  22. package/examples/peripheral-explorer-async.js +133 -0
  23. package/examples/peripheral-explorer.js +225 -0
  24. package/examples/pizza/README.md +15 -0
  25. package/examples/pizza/central.js +194 -0
  26. package/examples/pizza/pizza.js +60 -0
  27. package/index.d.ts +203 -0
  28. package/index.js +6 -0
  29. package/lib/characteristic.js +161 -0
  30. package/lib/characteristics.json +449 -0
  31. package/lib/descriptor.js +72 -0
  32. package/lib/descriptors.json +47 -0
  33. package/lib/distributed/bindings.js +326 -0
  34. package/lib/hci-socket/acl-stream.js +60 -0
  35. package/lib/hci-socket/bindings.js +788 -0
  36. package/lib/hci-socket/crypto.js +74 -0
  37. package/lib/hci-socket/gap.js +432 -0
  38. package/lib/hci-socket/gatt.js +809 -0
  39. package/lib/hci-socket/hci-status.json +71 -0
  40. package/lib/hci-socket/hci.js +1264 -0
  41. package/lib/hci-socket/signaling.js +76 -0
  42. package/lib/hci-socket/smp.js +140 -0
  43. package/lib/hci-uart/bindings.js +569 -0
  44. package/lib/hci-uart/hci-serial-parser.js +70 -0
  45. package/lib/hci-uart/hci.js +1336 -0
  46. package/lib/mac/binding.gyp +26 -0
  47. package/lib/mac/bindings.js +11 -0
  48. package/lib/mac/src/ble_manager.h +41 -0
  49. package/lib/mac/src/ble_manager.mm +435 -0
  50. package/lib/mac/src/callbacks.cc +222 -0
  51. package/lib/mac/src/callbacks.h +84 -0
  52. package/lib/mac/src/napi_objc.h +12 -0
  53. package/lib/mac/src/napi_objc.mm +50 -0
  54. package/lib/mac/src/noble_mac.h +34 -0
  55. package/lib/mac/src/noble_mac.mm +264 -0
  56. package/lib/mac/src/objc_cpp.h +26 -0
  57. package/lib/mac/src/objc_cpp.mm +126 -0
  58. package/lib/mac/src/peripheral.h +23 -0
  59. package/lib/manufacture.js +48 -0
  60. package/lib/noble.js +593 -0
  61. package/lib/peripheral.js +219 -0
  62. package/lib/resolve-bindings-web.js +9 -0
  63. package/lib/resolve-bindings.js +44 -0
  64. package/lib/service.js +72 -0
  65. package/lib/services.json +92 -0
  66. package/lib/webbluetooth/bindings.js +368 -0
  67. package/lib/websocket/bindings.js +321 -0
  68. package/lib/win/binding.gyp +23 -0
  69. package/lib/win/bindings.js +11 -0
  70. package/lib/win/src/ble_manager.cc +802 -0
  71. package/lib/win/src/ble_manager.h +77 -0
  72. package/lib/win/src/callbacks.cc +274 -0
  73. package/lib/win/src/callbacks.h +33 -0
  74. package/lib/win/src/napi_winrt.cc +76 -0
  75. package/lib/win/src/napi_winrt.h +12 -0
  76. package/lib/win/src/noble_winrt.cc +308 -0
  77. package/lib/win/src/noble_winrt.h +34 -0
  78. package/lib/win/src/notify_map.cc +62 -0
  79. package/lib/win/src/notify_map.h +50 -0
  80. package/lib/win/src/peripheral.h +23 -0
  81. package/lib/win/src/peripheral_winrt.cc +296 -0
  82. package/lib/win/src/peripheral_winrt.h +82 -0
  83. package/lib/win/src/radio_watcher.cc +125 -0
  84. package/lib/win/src/radio_watcher.h +61 -0
  85. package/lib/win/src/winrt_cpp.cc +82 -0
  86. package/lib/win/src/winrt_cpp.h +11 -0
  87. package/lib/win/src/winrt_guid.cc +12 -0
  88. package/lib/win/src/winrt_guid.h +13 -0
  89. package/misc/nrf52840dk.hex +6921 -0
  90. package/misc/prj.conf +43 -0
  91. package/package.json +96 -0
  92. package/test/lib/characteristic.test.js +791 -0
  93. package/test/lib/descriptor.test.js +249 -0
  94. package/test/lib/distributed/bindings.test.js +918 -0
  95. package/test/lib/hci-socket/acl-stream.test.js +188 -0
  96. package/test/lib/hci-socket/bindings.test.js +1756 -0
  97. package/test/lib/hci-socket/crypto.test.js +55 -0
  98. package/test/lib/hci-socket/gap.test.js +1089 -0
  99. package/test/lib/hci-socket/gatt.test.js +2392 -0
  100. package/test/lib/hci-socket/hci.test.js +1891 -0
  101. package/test/lib/hci-socket/signaling.test.js +94 -0
  102. package/test/lib/hci-socket/smp.test.js +268 -0
  103. package/test/lib/manufacture.test.js +77 -0
  104. package/test/lib/peripheral.test.js +623 -0
  105. package/test/lib/resolve-bindings.test.js +102 -0
  106. package/test/lib/service.test.js +195 -0
  107. package/test/lib/webbluetooth/bindings.test.js +190 -0
  108. package/test/lib/websocket/bindings.test.js +456 -0
  109. package/test/noble.test.js +1565 -0
  110. package/test.js +131 -0
  111. package/with-bindings.js +5 -0
  112. package/ws-slave.js +404 -0
package/README.md ADDED
@@ -0,0 +1,833 @@
1
+ # ![noble](assets/noble-logo.png)
2
+
3
+ [![Build Status](https://travis-ci.org/abandonware/noble.svg?branch=master)](https://travis-ci.org/abandonware/noble)
4
+ [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/abandonware/noble?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![OpenCollective](https://opencollective.com/noble/backers/badge.svg)](#backers)
5
+ [![OpenCollective](https://opencollective.com/noble/sponsors/badge.svg)](#sponsors)
6
+
7
+ A Node.js BLE (Bluetooth Low Energy) central module.
8
+
9
+ Want to implement a peripheral? Check out [bleno](https://github.com/abandonware/bleno).
10
+
11
+ __Note:__ macOS / Mac OS X, Linux, FreeBSD and Windows are currently the only supported OSes.
12
+
13
+ ## Documentation
14
+
15
+ * [Quick Start Example](#quick-start-example)
16
+ * [Installation](#installation)
17
+ * [API docs](#api-docs)
18
+ * [Advanced usage](#advanced-usage)
19
+ * [Common problems](#common-problems)
20
+
21
+ ## Quick Start Example
22
+
23
+ ```javascript
24
+ // Read the battery level of the first found peripheral exposing the Battery Level characteristic
25
+
26
+ const noble = require('@abandonware/noble')({extended: false});
27
+
28
+ noble.on('stateChange', async (state) => {
29
+ if (state === 'poweredOn') {
30
+ await noble.startScanningAsync(['180f'], false);
31
+ }
32
+ });
33
+
34
+ noble.on('discover', async (peripheral) => {
35
+ await noble.stopScanningAsync();
36
+ await peripheral.connectAsync();
37
+ const {characteristics} = await peripheral.discoverSomeServicesAndCharacteristicsAsync(['180f'], ['2a19']);
38
+ const batteryLevel = (await characteristics[0].readAsync())[0];
39
+
40
+ console.log(`${peripheral.address} (${peripheral.advertisement.localName}): ${batteryLevel}%`);
41
+
42
+ await peripheral.disconnectAsync();
43
+ process.exit(0);
44
+ });
45
+ ```
46
+
47
+ ## Installation
48
+
49
+ * [Prerequisites](#prerequisites)
50
+ * [UART](#uart)
51
+ * [OS X](#os-x)
52
+ * [Linux](#linux)
53
+ * [Ubuntu, Debian, Raspbian](#ubuntu-debian-raspbian)
54
+ * [Fedora and other RPM-based distributions](#fedora-and-other-rpm-based-distributions)
55
+ * [Intel Edison](#intel-edison)
56
+ * [FreeBSD](#freebsd)
57
+ * [Windows](#windows)
58
+ * [Docker](#docker)
59
+ * [Installing and using the package](#installing-and-using-the-package)
60
+
61
+ ### Prerequisites
62
+
63
+ #### UART
64
+
65
+ The reason for this fork was to create more universal transport that can work across multiple operating systems.
66
+ Idea is to use Zephyr HCI over UART firmware and create noble driver to interface with HCI over UART.
67
+
68
+ ##### Known Issues
69
+ What I have found so far that when using extended MTU and sending large amount of data Zephyr stops responding in rare cases. I have played with Zephyr configuration parameters in order to increase buffer sizes but with some luck. Sometimes when transfering fast, large payloads, with high MTU you can still hit the limit and Zephyr needs to be rebooted.
70
+
71
+ ##### How to use this?
72
+
73
+ 1. You will need NRF5x module (e.g. nRF52840 PDK)
74
+ 2. If you have `nRF52840 PDK` you can in fact just use compiled HEX [misc/nrf52840dk.hex](misc/nrf52840dk.hex) (Buad Rate set to `1000000`)
75
+ 3. If you want to compile it yourself:
76
+ 1. You will need to install Zephyr ([https://docs.zephyrproject.org/latest/getting_started/index.html](https://docs.zephyrproject.org/latest/getting_started/index.html))
77
+ 2. Compile HCI UART Example - `west build -p auto -b <your-board-name> zephyr/samples/bluetooth/hci_uart`
78
+ - e.g. When using `nRF52840 PDK` call `west build -p auto -b nrf52840dk_nrf52840 zephyr/samples/bluetooth/hci_uart`
79
+ 4. Flash the firmware to Nordic Board e.g. using `nrfjprog`
80
+ - e.g. `nrfjprog -f NRF52 --program misc/nrf52840dk.hex –-chiperase --reset`
81
+ 5. When you get a nordic board connected to the PC/Mac etc. with UART interface you are good to go.
82
+ 6. In order to run any example from the examples folder or your own code you have to provide UART port by defining env variable: `NOBLE_HCI_UART_PORT`. Optionally if you use different Baud Rate you can change it by specifing `NOBLE_HCI_UART_BAUD_RATE`. Default value is `1000000`
83
+ 7. e.g. `NOBLE_HCI_UART_PORT=/dev/tty.usbmodem0006837533091 node examples/peripheral-explorer.js b8:27:eb:83:9b:19`
84
+
85
+ #### OS X
86
+
87
+ * Install [Xcode](https://itunes.apple.com/ca/app/xcode/id497799835?mt=12)
88
+ * On newer versions of OSX, allow bluetooth access on the terminal app: "System Preferences" —> "Security & Privacy" —> "Bluetooth" -> Add terminal app (see [Sandboxed terminal](#sandboxed-terminal))
89
+
90
+ #### Linux
91
+
92
+ * Kernel version 3.6 or above
93
+ * `libbluetooth-dev` needs to be installed. For instructions for specific distributions, see below.
94
+ * To set the necessary privileges to run without sudo, [see this section](#running-without-rootsudo-linux-specific). This is required for all distributions (Raspbian, Ubuntu, Fedora, etc). You will not get any errors if running without sudo, but nothing will happen.
95
+
96
+ ##### Ubuntu, Debian, Raspbian
97
+
98
+ See the [generic Linux notes above](#linux) first.
99
+
100
+ ```sh
101
+ sudo apt-get install bluetooth bluez libbluetooth-dev libudev-dev
102
+ ```
103
+
104
+ Make sure `node` is on your `PATH`. If it's not, some options:
105
+ * Symlink `nodejs` to `node`: `sudo ln -s /usr/bin/nodejs /usr/bin/node`
106
+ * [Install Node.js using the NodeSource package](https://nodejs.org/en/download/package-manager/#debian-and-ubuntu-based-linux-distributions)
107
+
108
+ If you are having trouble connecting to BLE devices on a Raspberry Pi, you should disable the `pnat` plugin. Add the following line at the bottom of `/etc/bluetooth/main.conf`:
109
+
110
+ ```
111
+ DisablePlugins=pnat
112
+ ```
113
+
114
+ Then restart the system.
115
+
116
+ See [Issue #425 · OpenWonderLabs/homebridge-switchbot](https://github.com/OpenWonderLabs/homebridge-switchbot/issues/425#issuecomment-1190864279).
117
+
118
+ ##### Fedora and other RPM-based distributions
119
+
120
+ See the [generic Linux notes above](#linux) first.
121
+
122
+ ```sh
123
+ sudo yum install bluez bluez-libs bluez-libs-devel
124
+ ```
125
+
126
+ ##### Intel Edison
127
+
128
+ See the [generic Linux notes above](#linux) first.
129
+
130
+ See [Configure Intel Edison for Bluetooth LE (Smart) Development](http://rexstjohn.com/configure-intel-edison-for-bluetooth-le-smart-development/).
131
+
132
+ #### FreeBSD
133
+
134
+ Make sure you have GNU Make:
135
+
136
+ ```sh
137
+ sudo pkg install gmake
138
+ ```
139
+
140
+ Disable automatic loading of the default Bluetooth stack by putting [no-ubt.conf](https://gist.github.com/myfreeweb/44f4f3e791a057bc4f3619a166a03b87) into `/usr/local/etc/devd/no-ubt.conf` and restarting devd (`sudo service devd restart`).
141
+
142
+ Unload `ng_ubt` kernel module if already loaded:
143
+
144
+ ```sh
145
+ sudo kldunload ng_ubt
146
+ ```
147
+
148
+ Make sure you have read and write permissions on the `/dev/usb/*` device that corresponds to your Bluetooth adapter.
149
+
150
+ #### Windows
151
+
152
+ [node-gyp requirements for Windows](https://github.com/TooTallNate/node-gyp#installation)
153
+
154
+ Install the required tools and configurations using Microsoft's [windows-build-tools](https://github.com/felixrieseberg/windows-build-tools) from an elevated PowerShell or cmd.exe (run as Administrator).
155
+
156
+ ```cmd
157
+ npm install --global --production windows-build-tools
158
+ ```
159
+
160
+ [node-bluetooth-hci-socket prerequisites](#windows)
161
+ * Compatible Bluetooth 5.0 Zephyr HCI-USB adapter (you need to add BLUETOOTH_HCI_SOCKET_USB_VID and BLUETOOTH_HCI_SOCKET_USB_PID to the process env)
162
+ * Compatible Bluetooth 4.0 USB adapter
163
+ * [WinUSB](https://msdn.microsoft.com/en-ca/library/windows/hardware/ff540196(v=vs.85).aspx) driver setup for Bluetooth 4.0 USB adapter, using [Zadig tool](http://zadig.akeo.ie/)
164
+
165
+ See [@don](https://github.com/don)'s setup guide on [Bluetooth LE with Node.js and Noble on Windows](https://www.youtube.com/watch?v=mL9B8wuEdms&feature=youtu.be&t=1m46s)
166
+
167
+ #### Docker
168
+
169
+ Make sure your container runs with `--network=host` options and all specific environment preriquisites are verified.
170
+
171
+ ### Installing and using the package
172
+
173
+ ```sh
174
+ npm install @abandonware/noble
175
+ ```
176
+
177
+ In Windows OS add your custom hci-usb dongle to the process env
178
+ ```sh
179
+ set BLUETOOTH_HCI_SOCKET_USB_VID=xxx
180
+ set BLUETOOTH_HCI_SOCKET_USB_PID=xxx
181
+ ```
182
+
183
+ ```javascript
184
+ const noble = require('@abandonware/noble')({extended: false});
185
+ ```
186
+
187
+ ## API docs
188
+
189
+ All operations have two API variants – one expecting a callback, one returning a Promise (denoted by `Async` suffix).
190
+
191
+ Additionally, there are events corresponding to each operation (and a few global events).
192
+
193
+ For example, in case of the "discover services" operation of Peripheral:
194
+
195
+ * There's a `discoverServices` method expecting a callback:
196
+ ```javascript
197
+ peripheral.discoverServices((error, services) => {
198
+ // callback - handle error and services
199
+ });
200
+ ```
201
+ * There's a `discoverServicesAsync` method returning a Promise:
202
+ ```javascript
203
+ try {
204
+ const services = await peripheral.discoverServicesAsync();
205
+ // handle services
206
+ } catch (e) {
207
+ // handle error
208
+ }
209
+ ```
210
+ * There's a `servicesDiscover` event emitted after services are discovered:
211
+ ```javascript
212
+ peripheral.once('servicesDiscover', (services) => {
213
+ // handle services
214
+ });
215
+ ```
216
+
217
+ API structure:
218
+
219
+ * [Scanning and discovery](#scanning-and-discovery)
220
+ * [_Event: Adapter state changed_](#event-adapter-state-changed)
221
+ * [Start scanning](#start-scanning)
222
+ * [_Event: Scanning started_](#event-scanning-started)
223
+ * [Stop scanning](#stop-scanning)
224
+ * [_Event: Scanning stopped_](#event-scanning-stopped)
225
+ * [_Event: Peripheral discovered_](#event-peripheral-discovered)
226
+ * [_Event: Warning raised_](#event-warning-raised)
227
+ * [Reset device](#reset-device)
228
+ * [Peripheral](#peripheral)
229
+ * [Connect](#connect)
230
+ * [_Event: Connected_](#event-connected)
231
+ * [Cancel a pending connection](#cancel-a-pending-connection)
232
+ * [Disconnect](#disconnect)
233
+ * [_Event: Disconnected_](#event-disconnected)
234
+ * [Update RSSI](#update-rssi)
235
+ * [_Event: RSSI updated_](#event-rssi-updated)
236
+ * [Discover services](#discover-services)
237
+ * [Discover all services and characteristics](#discover-all-services-and-characteristics)
238
+ * [Discover some services and characteristics](#discover-some-services-and-characteristics)
239
+ * [_Event: Services discovered_](#event-services-discovered)
240
+ * [Read handle](#read-handle)
241
+ * [_Event: Handle read_](#event-handle-read)
242
+ * [Write handle](#write-handle)
243
+ * [_Event: Handle written_](#event-handle-written)
244
+ * [Service](#service)
245
+ * [Discover included services](#discover-included-services)
246
+ * [_Event: Included services discovered_](#event-included-services-discovered)
247
+ * [Discover characteristics](#discover-characteristics)
248
+ * [_Event: Characteristics discovered_](#event-characteristics-discovered)
249
+ * [Characteristic](#characteristic)
250
+ * [Read](#read)
251
+ * [_Event: Data read_](#event-data-read)
252
+ * [Write](#write)
253
+ * [_Event: Data written_](#event-data-written)
254
+ * [Broadcast](#broadcast)
255
+ * [_Event: Broadcast sent_](#event-broadcast-sent)
256
+ * [Subscribe](#subscribe)
257
+ * [_Event: Notification received_](#event-notification-received)
258
+ * [Unsubscribe](#unsubscribe)
259
+ * [Discover descriptors](#discover-descriptors)
260
+ * [_Event: Descriptors discovered_](#event-descriptors-discovered)
261
+ * [Descriptor](#descriptor)
262
+ * [Read value](#read-value)
263
+ * [_Event: Value read_](#event-value-read)
264
+ * [Write value](#write-value)
265
+ * [_Event: Value written_](#event-value-written)
266
+
267
+ ### Scanning and discovery
268
+
269
+ #### _Event: Adapter state changed_
270
+
271
+ ```javascript
272
+ noble.on('stateChange', callback(state));
273
+ ```
274
+
275
+ `state` can be one of:
276
+ * `unknown`
277
+ * `resetting`
278
+ * `unsupported`
279
+ * `unauthorized`
280
+ * `poweredOff`
281
+ * `poweredOn`
282
+
283
+ #### Start scanning
284
+
285
+ ```javascript
286
+ noble.startScanning(); // any service UUID, no duplicates
287
+
288
+
289
+ noble.startScanning([], true); // any service UUID, allow duplicates
290
+
291
+
292
+ var serviceUUIDs = ['<service UUID 1>', ...]; // default: [] => all
293
+ var allowDuplicates = falseOrTrue; // default: false
294
+
295
+ noble.startScanning(serviceUUIDs, allowDuplicates[, callback(error)]); // particular UUIDs
296
+ ```
297
+
298
+ __NOTE:__ `noble.state` must be `poweredOn` before scanning is started. `noble.on('stateChange', callback(state));` can be used to listen for state change events.
299
+
300
+ #### _Event: Scanning started_
301
+
302
+ ```javascript
303
+ noble.on('scanStart', callback);
304
+ ```
305
+
306
+ The event is emitted when:
307
+ * Scanning is started
308
+ * Another application enables scanning
309
+ * Another application changes scanning settings
310
+
311
+ #### Stop scanning
312
+
313
+ ```javascript
314
+ noble.stopScanning();
315
+ ```
316
+
317
+ #### _Event: Scanning stopped_
318
+
319
+ ```javascript
320
+ noble.on('scanStop', callback);
321
+ ```
322
+
323
+ The event is emitted when:
324
+ * Scanning is stopped
325
+ * Another application stops scanning
326
+
327
+
328
+ #### _Event: Peripheral discovered_
329
+
330
+ ```javascript
331
+ noble.on('discover', callback(peripheral));
332
+ ```
333
+
334
+ * `peripheral`:
335
+ ```javascript
336
+ {
337
+ id: '<id>',
338
+ address: '<BT address'>, // Bluetooth Address of device, or 'unknown' if not known
339
+ addressType: '<BT address type>', // Bluetooth Address type (public, random), or 'unknown' if not known
340
+ connectable: trueOrFalseOrUndefined, // true or false, or undefined if not known
341
+ advertisement: {
342
+ localName: '<name>',
343
+ txPowerLevel: someInteger,
344
+ serviceUuids: ['<service UUID>', ...],
345
+ serviceSolicitationUuid: ['<service solicitation UUID>', ...],
346
+ manufacturerData: someBuffer, // a Buffer
347
+ serviceData: [
348
+ {
349
+ uuid: '<service UUID>',
350
+ data: someBuffer // a Buffer
351
+ },
352
+ // ...
353
+ ]
354
+ },
355
+ rssi: integerValue,
356
+ mtu: integerValue // MTU will be null, until device is connected and hci-socket is used
357
+ };
358
+ ```
359
+
360
+ __Note:__ On macOS, the address will be set to '' if the device has not been connected previously.
361
+
362
+
363
+ #### _Event: Warning raised_
364
+
365
+ ```javascript
366
+ noble.on('warning', callback(message));
367
+ ```
368
+
369
+ ### Reset device
370
+
371
+ ```javascript
372
+ noble.reset()
373
+ ```
374
+
375
+ ### Peripheral
376
+
377
+ #### Connect
378
+
379
+ ```javascript
380
+ peripheral.connect([callback(error)]);
381
+ ```
382
+
383
+ Some of the bluetooth devices doesn't connect seamlessly, may be because of bluetooth device firmware or kernel. Do reset the device with noble.reset() API before connect API.
384
+
385
+ #### _Event: Connected_
386
+
387
+ ```javascript
388
+ peripheral.once('connect', callback);
389
+ ```
390
+
391
+ #### Cancel a pending connection
392
+
393
+ ```javascript
394
+ peripheral.cancelConnect();
395
+ // Will emit a 'connect' event with error
396
+ ```
397
+
398
+ #### Disconnect
399
+
400
+ ```javascript
401
+ peripheral.disconnect([callback(error)]);
402
+ ```
403
+
404
+ #### _Event: Disconnected_
405
+
406
+ ```javascript
407
+ peripheral.once('disconnect', callback);
408
+ ```
409
+
410
+ #### Update RSSI
411
+
412
+ ```javascript
413
+ peripheral.updateRssi([callback(error, rssi)]);
414
+ ```
415
+
416
+ #### _Event: RSSI updated_
417
+
418
+ ```javascript
419
+ peripheral.once('rssiUpdate', callback(rssi));
420
+ ```
421
+
422
+ #### Discover services
423
+
424
+ ```javascript
425
+ peripheral.discoverServices(); // any service UUID
426
+
427
+ var serviceUUIDs = ['<service UUID 1>', ...];
428
+ peripheral.discoverServices(serviceUUIDs[, callback(error, services)]); // particular UUIDs
429
+ ```
430
+
431
+ #### Discover all services and characteristics
432
+
433
+ ```javascript
434
+ peripheral.discoverAllServicesAndCharacteristics([callback(error, services, characteristics)]);
435
+ ```
436
+
437
+ #### Discover some services and characteristics
438
+
439
+ ```javascript
440
+ var serviceUUIDs = ['<service UUID 1>', ...];
441
+ var characteristicUUIDs = ['<characteristic UUID 1>', ...];
442
+ peripheral.discoverSomeServicesAndCharacteristics(serviceUUIDs, characteristicUUIDs, [callback(error, services, characteristics));
443
+ ```
444
+
445
+ #### _Event: Services discovered_
446
+
447
+ ```javascript
448
+ peripheral.once('servicesDiscover', callback(services));
449
+ ```
450
+
451
+ #### Read handle
452
+
453
+ ```javascript
454
+ peripheral.readHandle(handle, callback(error, data));
455
+ ```
456
+
457
+ #### _Event: Handle read_
458
+
459
+ ```javascript
460
+ peripheral.once('handleRead<handle>', callback(data)); // data is a Buffer
461
+ ```
462
+
463
+ `<handle>` is the handle identifier.
464
+
465
+ #### Write handle
466
+
467
+ ```javascript
468
+ peripheral.writeHandle(handle, data, withoutResponse, callback(error));
469
+ ```
470
+
471
+ #### _Event: Handle written_
472
+
473
+ ```javascript
474
+ peripheral.once('handleWrite<handle>', callback());
475
+ ```
476
+
477
+ `<handle>` is the handle identifier.
478
+
479
+ ### Service
480
+
481
+ #### Discover included services
482
+
483
+ ```javascript
484
+ service.discoverIncludedServices(); // any service UUID
485
+
486
+ var serviceUUIDs = ['<service UUID 1>', ...];
487
+ service.discoverIncludedServices(serviceUUIDs[, callback(error, includedServiceUuids)]); // particular UUIDs
488
+ ```
489
+
490
+ #### _Event: Included services discovered_
491
+
492
+ ```javascript
493
+ service.once('includedServicesDiscover', callback(includedServiceUuids));
494
+ ```
495
+
496
+ #### Discover characteristics
497
+
498
+ ```javascript
499
+ service.discoverCharacteristics() // any characteristic UUID
500
+
501
+ var characteristicUUIDs = ['<characteristic UUID 1>', ...];
502
+ service.discoverCharacteristics(characteristicUUIDs[, callback(error, characteristics)]); // particular UUIDs
503
+ ```
504
+
505
+ #### _Event: Characteristics discovered_
506
+
507
+ ```javascript
508
+ service.once('characteristicsDiscover', callback(characteristics));
509
+ ```
510
+
511
+ * `characteristics`
512
+ ```javascript
513
+ {
514
+ uuid: '<uuid>',
515
+ properties: ['...'] // 'broadcast', 'read', 'writeWithoutResponse', 'write', 'notify', 'indicate', 'authenticatedSignedWrites', 'extendedProperties'
516
+ };
517
+ ```
518
+
519
+ ### Characteristic
520
+
521
+ #### Read
522
+
523
+ ```javascript
524
+ characteristic.read([callback(error, data)]);
525
+ ```
526
+
527
+ #### _Event: Data read_
528
+
529
+ ```javascript
530
+ characteristic.on('data', callback(data, isNotification));
531
+
532
+ characteristic.once('read', callback(data, isNotification)); // legacy
533
+ ```
534
+
535
+ Emitted when:
536
+ * Characteristic read has completed, result of `characteristic.read(...)`
537
+ * Characteristic value has been updated by peripheral via notification or indication, after having been enabled with `characteristic.notify(true[, callback(error)])`
538
+
539
+ **Note:** `isNotification` event parameter value MAY be `undefined` depending on platform. The parameter is **deprecated** after version 1.8.1, and not supported on macOS High Sierra and later.
540
+
541
+ #### Write
542
+
543
+ ```javascript
544
+ characteristic.write(data, withoutResponse[, callback(error)]); // data is a Buffer, withoutResponse is true|false
545
+ ```
546
+
547
+ * `withoutResponse`:
548
+ * `false`: send a write request, used with "write" characteristic property
549
+ * `true`: send a write command, used with "write without response" characteristic property
550
+
551
+
552
+ #### _Event: Data written_
553
+
554
+ ```javascript
555
+ characteristic.once('write', withoutResponse, callback());
556
+ ```
557
+
558
+ Emitted when characteristic write has completed, result of `characteristic.write(...)`.
559
+
560
+ #### Broadcast
561
+
562
+ ```javascript
563
+ characteristic.broadcast(broadcast[, callback(error)]); // broadcast is true|false
564
+ ```
565
+
566
+ #### _Event: Broadcast sent_
567
+
568
+ ```javascript
569
+ characteristic.once('broadcast', callback(state));
570
+ ```
571
+
572
+ Emitted when characteristic broadcast state changes, result of `characteristic.broadcast(...)`.
573
+
574
+ #### Subscribe
575
+
576
+ ```javascript
577
+ characteristic.subscribe([callback(error)]);
578
+ ```
579
+
580
+ Subscribe to a characteristic.
581
+
582
+ Triggers `data` events when peripheral sends a notification or indication. Use for characteristics with "notify" or "indicate" properties.
583
+
584
+ #### _Event: Notification received_
585
+
586
+ ```javascript
587
+ characteristic.once('notify', callback(state));
588
+ ```
589
+
590
+ Emitted when characteristic notification state changes, result of `characteristic.notify(...)`.
591
+
592
+ #### Unsubscribe
593
+
594
+ ```javascript
595
+ characteristic.unsubscribe([callback(error)]);
596
+ ```
597
+
598
+ Unsubscribe from a characteristic.
599
+
600
+ Use for characteristics with "notify" or "indicate" properties
601
+
602
+ #### Discover descriptors
603
+
604
+ ```javascript
605
+ characteristic.discoverDescriptors([callback(error, descriptors)]);
606
+ ```
607
+
608
+ #### _Event: Descriptors discovered_
609
+
610
+ ```javascript
611
+ characteristic.once('descriptorsDiscover', callback(descriptors));
612
+ ```
613
+ * `descriptors`:
614
+ ```javascript
615
+ [
616
+ {
617
+ uuid: '<uuid>'
618
+ },
619
+ // ...
620
+ ]
621
+ ```
622
+
623
+ ### Descriptor
624
+
625
+ #### Read value
626
+
627
+ ```javascript
628
+ descriptor.readValue([callback(error, data)]);
629
+ ```
630
+
631
+ #### _Event: Value read_
632
+
633
+ ```javascript
634
+ descriptor.once('valueRead', data); // data is a Buffer
635
+ ```
636
+
637
+ #### Write value
638
+
639
+ ```javascript
640
+ descriptor.writeValue(data[, callback(error)]); // data is a Buffer
641
+ ```
642
+
643
+ #### _Event: Value written_
644
+
645
+ ```javascript
646
+ descriptor.once('valueWrite');
647
+ ```
648
+
649
+ ## Advanced usage
650
+
651
+ ### Override default bindings
652
+
653
+ By default, noble will select appropriate Bluetooth device bindings based on your platform. You can provide custom bindings using the `with-bindings` module.
654
+
655
+ ```javascript
656
+ var noble = require('@abandonware/noble/with-bindings')(require('./my-custom-bindings'));
657
+ ```
658
+
659
+ ### Running without root/sudo (Linux-specific)
660
+
661
+ Run the following command:
662
+
663
+ ```sh
664
+ sudo setcap cap_net_raw+eip $(eval readlink -f `which node`)
665
+ ```
666
+
667
+ This grants the `node` binary `cap_net_raw` privileges, so it can start/stop BLE advertising.
668
+
669
+ __Note:__ The above command requires `setcap` to be installed.
670
+ It can be installed the following way:
671
+
672
+ * apt: `sudo apt-get install libcap2-bin`
673
+ * yum: `su -c \'yum install libcap2-bin\'`
674
+
675
+ ### Multiple Adapters (Linux-specific)
676
+
677
+ `hci0` is used by default.
678
+
679
+ To override, set the `NOBLE_HCI_DEVICE_ID` environment variable to the interface number.
680
+
681
+ For example, to specify `hci1`:
682
+
683
+ ```sh
684
+ sudo NOBLE_HCI_DEVICE_ID=1 node <your file>.js
685
+ ```
686
+
687
+ If you are using multiple HCI devices in one setup you can run two instances of noble with different binding configurations by initializing them seperatly in code:
688
+
689
+ ```
690
+ const HCIBindings = require('@abandonware/noble/lib/hci-socket/bindings');
691
+ const Noble = require('@abandonware/noble/lib/noble');
692
+
693
+ const params = {
694
+ deviceId: 0,
695
+ userChannel: true,
696
+ extended: false
697
+ };
698
+
699
+ const noble = new Noble(new HCIBindings(params));
700
+ ```
701
+
702
+ ### Reporting all HCI events (Linux-specific)
703
+
704
+ By default, noble waits for both the advertisement data and scan response data for each Bluetooth address. If your device does not use scan response, the `NOBLE_REPORT_ALL_HCI_EVENTS` environment variable can be used to bypass it.
705
+
706
+ ```sh
707
+ sudo NOBLE_REPORT_ALL_HCI_EVENTS=1 node <your file>.js
708
+ ```
709
+
710
+ ### bleno compatibility (Linux-specific)
711
+
712
+ By default, noble will respond with an error whenever a GATT request message is received. If your intention is to use bleno in tandem with noble, the `NOBLE_MULTI_ROLE` environment variable can be used to bypass this behaviour.
713
+
714
+ __Note:__ this requires a Bluetooth 4.1 adapter.
715
+
716
+ ```sh
717
+ sudo NOBLE_MULTI_ROLE=1 node <your file>.js
718
+ ```
719
+
720
+ ## Common problems
721
+
722
+ ### Maximum simultaneous connections
723
+
724
+ This limit is imposed by the Bluetooth adapter hardware as well as its firmware.
725
+
726
+ | Platform | |
727
+ | :-------------------------------- | --------------------- |
728
+ | OS X 10.11 (El Capitan) | 6 |
729
+ | Linux/Windows - Adapter-dependent | 5 (CSR based adapter) |
730
+
731
+ ### Sandboxed terminal
732
+
733
+ On newer versions of OSX, the terminal app is sandboxed to not allow bluetooth connections by default. If you run a script that tries to access it, you will get an `Abort trap: 6` error.
734
+
735
+ To enable bluetooth, go to "System Preferences" —> "Security & Privacy" —> "Bluetooth" -> Add your terminal into allowed apps.
736
+
737
+ ### Adapter-specific known issues
738
+
739
+ Some BLE adapters cannot connect to a peripheral while they are scanning (examples below). You will get the following messages when trying to connect:
740
+
741
+ Sena UD-100 (Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)): `Error: Command disallowed`
742
+
743
+ Intel Dual Band Wireless-AC 7260 (Intel Corporation Wireless 7260 (rev 73)): `Error: Connection Rejected due to Limited Resources (0xd)`
744
+
745
+ You need to stop scanning before trying to connect in order to solve this issue.
746
+
747
+ ## Backers
748
+
749
+ Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/noble#backer)]
750
+
751
+ <a href="https://opencollective.com/noble/backer/0/website" target="_blank"><img src="https://opencollective.com/noble/backer/0/avatar.svg"></a>
752
+ <a href="https://opencollective.com/noble/backer/1/website" target="_blank"><img src="https://opencollective.com/noble/backer/1/avatar.svg"></a>
753
+ <a href="https://opencollective.com/noble/backer/2/website" target="_blank"><img src="https://opencollective.com/noble/backer/2/avatar.svg"></a>
754
+ <a href="https://opencollective.com/noble/backer/3/website" target="_blank"><img src="https://opencollective.com/noble/backer/3/avatar.svg"></a>
755
+ <a href="https://opencollective.com/noble/backer/4/website" target="_blank"><img src="https://opencollective.com/noble/backer/4/avatar.svg"></a>
756
+ <a href="https://opencollective.com/noble/backer/5/website" target="_blank"><img src="https://opencollective.com/noble/backer/5/avatar.svg"></a>
757
+ <a href="https://opencollective.com/noble/backer/6/website" target="_blank"><img src="https://opencollective.com/noble/backer/6/avatar.svg"></a>
758
+ <a href="https://opencollective.com/noble/backer/7/website" target="_blank"><img src="https://opencollective.com/noble/backer/7/avatar.svg"></a>
759
+ <a href="https://opencollective.com/noble/backer/8/website" target="_blank"><img src="https://opencollective.com/noble/backer/8/avatar.svg"></a>
760
+ <a href="https://opencollective.com/noble/backer/9/website" target="_blank"><img src="https://opencollective.com/noble/backer/9/avatar.svg"></a>
761
+ <a href="https://opencollective.com/noble/backer/10/website" target="_blank"><img src="https://opencollective.com/noble/backer/10/avatar.svg"></a>
762
+ <a href="https://opencollective.com/noble/backer/11/website" target="_blank"><img src="https://opencollective.com/noble/backer/11/avatar.svg"></a>
763
+ <a href="https://opencollective.com/noble/backer/12/website" target="_blank"><img src="https://opencollective.com/noble/backer/12/avatar.svg"></a>
764
+ <a href="https://opencollective.com/noble/backer/13/website" target="_blank"><img src="https://opencollective.com/noble/backer/13/avatar.svg"></a>
765
+ <a href="https://opencollective.com/noble/backer/14/website" target="_blank"><img src="https://opencollective.com/noble/backer/14/avatar.svg"></a>
766
+ <a href="https://opencollective.com/noble/backer/15/website" target="_blank"><img src="https://opencollective.com/noble/backer/15/avatar.svg"></a>
767
+ <a href="https://opencollective.com/noble/backer/16/website" target="_blank"><img src="https://opencollective.com/noble/backer/16/avatar.svg"></a>
768
+ <a href="https://opencollective.com/noble/backer/17/website" target="_blank"><img src="https://opencollective.com/noble/backer/17/avatar.svg"></a>
769
+ <a href="https://opencollective.com/noble/backer/18/website" target="_blank"><img src="https://opencollective.com/noble/backer/18/avatar.svg"></a>
770
+ <a href="https://opencollective.com/noble/backer/19/website" target="_blank"><img src="https://opencollective.com/noble/backer/19/avatar.svg"></a>
771
+ <a href="https://opencollective.com/noble/backer/20/website" target="_blank"><img src="https://opencollective.com/noble/backer/20/avatar.svg"></a>
772
+ <a href="https://opencollective.com/noble/backer/21/website" target="_blank"><img src="https://opencollective.com/noble/backer/21/avatar.svg"></a>
773
+ <a href="https://opencollective.com/noble/backer/22/website" target="_blank"><img src="https://opencollective.com/noble/backer/22/avatar.svg"></a>
774
+ <a href="https://opencollective.com/noble/backer/23/website" target="_blank"><img src="https://opencollective.com/noble/backer/23/avatar.svg"></a>
775
+ <a href="https://opencollective.com/noble/backer/24/website" target="_blank"><img src="https://opencollective.com/noble/backer/24/avatar.svg"></a>
776
+ <a href="https://opencollective.com/noble/backer/25/website" target="_blank"><img src="https://opencollective.com/noble/backer/25/avatar.svg"></a>
777
+ <a href="https://opencollective.com/noble/backer/26/website" target="_blank"><img src="https://opencollective.com/noble/backer/26/avatar.svg"></a>
778
+ <a href="https://opencollective.com/noble/backer/27/website" target="_blank"><img src="https://opencollective.com/noble/backer/27/avatar.svg"></a>
779
+ <a href="https://opencollective.com/noble/backer/28/website" target="_blank"><img src="https://opencollective.com/noble/backer/28/avatar.svg"></a>
780
+ <a href="https://opencollective.com/noble/backer/29/website" target="_blank"><img src="https://opencollective.com/noble/backer/29/avatar.svg"></a>
781
+
782
+ ## Sponsors
783
+
784
+ Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/noble#sponsor)]
785
+
786
+ <a href="https://opencollective.com/noble/sponsor/0/website" target="_blank"><img src="https://opencollective.com/noble/sponsor/0/avatar.svg"></a>
787
+ <a href="https://opencollective.com/noble/sponsor/1/website" target="_blank"><img src="https://opencollective.com/noble/sponsor/1/avatar.svg"></a>
788
+ <a href="https://opencollective.com/noble/sponsor/2/website" target="_blank"><img src="https://opencollective.com/noble/sponsor/2/avatar.svg"></a>
789
+ <a href="https://opencollective.com/noble/sponsor/3/website" target="_blank"><img src="https://opencollective.com/noble/sponsor/3/avatar.svg"></a>
790
+ <a href="https://opencollective.com/noble/sponsor/4/website" target="_blank"><img src="https://opencollective.com/noble/sponsor/4/avatar.svg"></a>
791
+ <a href="https://opencollective.com/noble/sponsor/5/website" target="_blank"><img src="https://opencollective.com/noble/sponsor/5/avatar.svg"></a>
792
+ <a href="https://opencollective.com/noble/sponsor/6/website" target="_blank"><img src="https://opencollective.com/noble/sponsor/6/avatar.svg"></a>
793
+ <a href="https://opencollective.com/noble/sponsor/7/website" target="_blank"><img src="https://opencollective.com/noble/sponsor/7/avatar.svg"></a>
794
+ <a href="https://opencollective.com/noble/sponsor/8/website" target="_blank"><img src="https://opencollective.com/noble/sponsor/8/avatar.svg"></a>
795
+ <a href="https://opencollective.com/noble/sponsor/9/website" target="_blank"><img src="https://opencollective.com/noble/sponsor/9/avatar.svg"></a>
796
+ <a href="https://opencollective.com/noble/sponsor/10/website" target="_blank"><img src="https://opencollective.com/noble/sponsor/10/avatar.svg"></a>
797
+ <a href="https://opencollective.com/noble/sponsor/11/website" target="_blank"><img src="https://opencollective.com/noble/sponsor/11/avatar.svg"></a>
798
+ <a href="https://opencollective.com/noble/sponsor/12/website" target="_blank"><img src="https://opencollective.com/noble/sponsor/12/avatar.svg"></a>
799
+ <a href="https://opencollective.com/noble/sponsor/13/website" target="_blank"><img src="https://opencollective.com/noble/sponsor/13/avatar.svg"></a>
800
+ <a href="https://opencollective.com/noble/sponsor/14/website" target="_blank"><img src="https://opencollective.com/noble/sponsor/14/avatar.svg"></a>
801
+ <a href="https://opencollective.com/noble/sponsor/15/website" target="_blank"><img src="https://opencollective.com/noble/sponsor/15/avatar.svg"></a>
802
+ <a href="https://opencollective.com/noble/sponsor/16/website" target="_blank"><img src="https://opencollective.com/noble/sponsor/16/avatar.svg"></a>
803
+ <a href="https://opencollective.com/noble/sponsor/17/website" target="_blank"><img src="https://opencollective.com/noble/sponsor/17/avatar.svg"></a>
804
+ <a href="https://opencollective.com/noble/sponsor/18/website" target="_blank"><img src="https://opencollective.com/noble/sponsor/18/avatar.svg"></a>
805
+ <a href="https://opencollective.com/noble/sponsor/19/website" target="_blank"><img src="https://opencollective.com/noble/sponsor/19/avatar.svg"></a>
806
+ <a href="https://opencollective.com/noble/sponsor/20/website" target="_blank"><img src="https://opencollective.com/noble/sponsor/20/avatar.svg"></a>
807
+ <a href="https://opencollective.com/noble/sponsor/21/website" target="_blank"><img src="https://opencollective.com/noble/sponsor/21/avatar.svg"></a>
808
+ <a href="https://opencollective.com/noble/sponsor/22/website" target="_blank"><img src="https://opencollective.com/noble/sponsor/22/avatar.svg"></a>
809
+ <a href="https://opencollective.com/noble/sponsor/23/website" target="_blank"><img src="https://opencollective.com/noble/sponsor/23/avatar.svg"></a>
810
+ <a href="https://opencollective.com/noble/sponsor/24/website" target="_blank"><img src="https://opencollective.com/noble/sponsor/24/avatar.svg"></a>
811
+ <a href="https://opencollective.com/noble/sponsor/25/website" target="_blank"><img src="https://opencollective.com/noble/sponsor/25/avatar.svg"></a>
812
+ <a href="https://opencollective.com/noble/sponsor/26/website" target="_blank"><img src="https://opencollective.com/noble/sponsor/26/avatar.svg"></a>
813
+ <a href="https://opencollective.com/noble/sponsor/27/website" target="_blank"><img src="https://opencollective.com/noble/sponsor/27/avatar.svg"></a>
814
+ <a href="https://opencollective.com/noble/sponsor/28/website" target="_blank"><img src="https://opencollective.com/noble/sponsor/28/avatar.svg"></a>
815
+ <a href="https://opencollective.com/noble/sponsor/29/website" target="_blank"><img src="https://opencollective.com/noble/sponsor/29/avatar.svg"></a>
816
+
817
+ ## Useful links
818
+
819
+ * [Bluetooth Development Portal](http://developer.bluetooth.org)
820
+ * [GATT Specifications](https://www.bluetooth.com/specifications/gatt/)
821
+ * [Bluetooth: ATT and GATT](http://epx.com.br/artigos/bluetooth_gatt.php)
822
+
823
+ ## License
824
+
825
+ Copyright (C) 2015 Sandeep Mistry <sandeep.mistry@gmail.com>
826
+
827
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
828
+
829
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
830
+
831
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
832
+
833
+ [![Analytics](https://ga-beacon.appspot.com/UA-56089547-1/sandeepmistry/noble?pixel)](https://github.com/igrigorik/ga-beacon)