Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / common / extensions / docs / templates / articles / app_bluetooth.html
blob76794aabb6e59921673cd88e944bf1341924d6e0
1 <h1>Bluetooth</h1>
3 <p>
4 This document describes how to use the <a href="bluetooth.html">Bluetooth</a>,
5 <a href="bluetoothSocket.html">Bluetooth Socket</a> and
6 <a href="bluetoothLowEnergy.html">Bluetooth Low Energy</a> APIs to
7 communicate with Bluetooth and Bluetooth Low Energy devices.
8 </p>
10 <p>
11 For background information about Bluetooth, see the official
12 <a href="http://www.bluetooth.org">Bluetooth specifications</a>.
13 </p>
15 <h2 id="manifest">Manifest requirements</h2>
17 <p>
18 For Chrome Apps that use Bluetooth, add the
19 <a href="manifest/bluetooth">bluetooth</a> entry to the manifest
20 and specify, if appropriate, the UUIDs of profiles, protocols or services
21 you wish to implement along with whether you wish to implement these with the
22 socket and/or Low Energy APIs.
23 </p>
25 <p>
26 For example for a socket implementation:
27 </p>
29 <pre data-filename="manifest.json">
30 "bluetooth": {
31 "uuids": [ "1105", "1106" ],
32 "socket": true
34 </pre>
36 <p>
37 And for a Low Energy implementation:
38 </p>
40 <pre data-filename="manifest.json">
41 "bluetooth": {
42 "uuids": [ "180D", "1809", "180F" ],
43 "low_energy": true
45 </pre>
47 <p>
48 To only access adapter state, discover nearby devices, and obtain basic
49 information about devices, only the entry itself is required:
50 </p>
52 <pre data-filename="manifest.json">
53 "bluetooth": { }
54 </pre>
56 <h2 id="adapter_info">Adapter information</h2>
58 <h3 id="adapter_state">Obtaining adapter state</h3>
60 <p>
61 To obtain the state of the Bluetooth adapter, use the
62 $(ref:bluetooth.getAdapterState) method:
63 </p>
65 <pre>
66 chrome.bluetooth.getAdapterState(function(adapter) {
67 console.log("Adapter " + adapter.address + ": " + adapter.name);
68 });
69 </pre>
71 <h3 id="adapter_notifications">Adapter notifications</h3>
73 <p>
74 The $(ref:bluetooth.onAdapterStateChanged) event is sent
75 whenever the adapter state changes. This can be used, for example, to
76 determine when the adapter radio is powered on or off.
77 </p>
79 <pre>
80 var powered = false;
81 chrome.bluetooth.getAdapterState(function(adapter) {
82 powered = adapter.powered;
83 });
85 chrome.bluetooth.onAdapterStateChanged.addListener(
86 function(adapter) {
87 if (adapter.powered != powered) {
88 powered = adapter.powered;
89 if (powered) {
90 console.log("Adapter radio is on");
91 } else {
92 console.log("Adapter radio is off");
95 });
96 </pre>
98 <h2 id="device_info">Device information</h2>
100 <h3 id="listing_devices">Listing known devices</h3>
103 To get a list of the devices known to the Bluetooth adapter, use the
104 $(ref:bluetooth.getDevices) method:
105 </p>
107 <pre>
108 chrome.bluetooth.getDevices(function(devices) {
109 for (var i = 0; i < devices.length; i++) {
110 console.log(devices[i].address);
113 </pre>
116 All devices are returned, including paired devices and devices recently
117 discovered. It will not begin discovery of new devices (see
118 <a href="#discovery">Discovering nearby devices</a>).
119 </p>
121 <h3 id="device_notifications">Receiving device notifications</h3>
124 Instead of repeatedly calling $(ref:bluetooth.getDevices), you
125 can use the $(ref:bluetooth.onDeviceAdded), $(ref:bluetooth.onDeviceChanged)
126 and $(ref:bluetooth.onDeviceRemoved) events to receive notifications.
127 </p>
130 The $(ref:bluetooth.onDeviceAdded) event is sent whenever a
131 device is discovered by the adapter or makes a connection to the adapter:
132 </p>
134 <pre>
135 chrome.bluetooth.onDeviceAdded.addListener(function(device) {
136 console.log(device.address);
138 </pre>
141 Adding a listener for this event does not begin discovery of devices
142 (see <a href="#discovery">Discovering nearby devices</a>).
143 </p>
146 Changes to devices, including previously discovered devices becoming paired,
147 are notified by the $(ref:bluetooth.onDeviceChanged) event:
148 </p>
150 <pre>
151 chrome.bluetooth.onDeviceChanged.addListener(function(device) {
152 console.log(device.address);
154 </pre>
157 Finally the $(ref:bluetooth.onDeviceRemoved) event is sent
158 whenever a paired device is removed from the system, or a discovered device
159 has not been seen recently:
160 </p>
162 <pre>
163 chrome.bluetooth.onDeviceRemoved.addListener(function(device) {
164 console.log(device.address);
166 </pre>
168 <h3 id="discovery">Discovering nearby devices</h3>
171 To begin discovery of nearby devices, use the
172 $(ref:bluetooth.startDiscovery) method. Discovery can be resource intensive
173 so you should call $(ref:bluetooth.stopDiscovery) when done.
174 </p>
177 You should call $(ref:bluetooth.startDiscovery) whenever your
178 app needs to discover nearby devices. Do not make the call conditional on
179 the <code>discovering</code> property of $(ref:bluetooth.AdapterState). The
180 call will succeed even if another app is discovering nearby devices, and will
181 ensure the adapter continues to perform discovery after that other app has
182 stopped.
183 </p>
186 Information about each newly discovered device is received using the
187 $(ref:bluetooth.onDeviceAdded) event. For devices that have
188 already been discovered recently, or have been previously paired with or
189 connected to, the event will not be sent. Instead you should call
190 $(ref:bluetooth.getDevices) to obtain the current information,
191 and use the $(ref:bluetooth.onDeviceChanged) event to be notified of changes
192 to that information as a result of discovery.
193 </p>
196 Example:
197 </p>
199 <pre>
200 var device_names = {};
201 var updateDeviceName = function(device) {
202 device_names[device.address] = device.name;
204 var removeDeviceName = function(device) {
205 delete device_names[device.address];
208 // Add listeners to receive newly found devices and updates
209 // to the previously known devices.
210 chrome.bluetooth.onDeviceAdded.addListener(updateDeviceName);
211 chrome.bluetooth.onDeviceChanged.addListener(updateDeviceName);
212 chrome.bluetooth.onDeviceRemoved.addListener(removeDeviceName);
214 // With the listeners in place, get the list of devices found in
215 // previous discovery sessions, or any currently active ones,
216 // along with paired devices.
217 chrome.bluetooth.getDevices(function(devices) {
218 for (var i = 0; i < devices.length; i++) {
219 updateDeviceName(devices[i]);
223 // Now begin the discovery process.
224 chrome.bluetooth.startDiscovery(function() {
225 // Stop discovery after 30 seconds.
226 setTimeout(function() {
227 chrome.bluetooth.stopDiscovery(function() {});
228 }, 30000);
230 </pre>
233 If the user turns off the Bluetooth radio, all discovery sessions will be
234 ended and not resumed automatically when the radio is switched on. If this
235 matters to your app, you should watch the
236 $(ref:bluetooth.onAdapterStateChanged) event. If the
237 <code>discovering</code> property changes to <code>false</code>, then your app
238 will need to call $(ref:bluetooth.startDiscovery) again to
239 resume. Be cautious of the resource intensive nature of discovery.
240 </p>
242 <h3 id="identifying_devices">Identifying devices</h3>
245 A number of different options are provided for identifying devices returned
246 by $(ref:bluetooth.getDevices) and the related events.
247 </p>
250 If the device supports the Bluetooth
251 <a href="https://developer.bluetooth.org/TechnologyOverview/Pages/DI.aspx">Device ID specification</a>,
252 several properties are added to the Device object containing the fields
253 defined by that specification. Example:
254 </p>
256 <pre>
257 chrome.bluetooth.getDevices(function(devices) {
258 for (var i = 0; i < devices.length; i++) {
259 if (devices[0].vendorIdSource != undefined) {
260 console.log(devices[0].address + ' = ' +
261 devices[0].vendorIdSource + ':' +
262 devices[0].vendorId.toString(16) + ':' +
263 devices[0].productId.toString(16) + ':' +
264 devices[0].deviceId.toString(16));
268 </pre>
271 The Device ID specification is usually sufficient to identify a particular
272 model, and even revision, of a device from a vendor. Where it is not present,
273 you must instead rely on information about the class or type of the device,
274 optionally combined with the manufacturer prefix in the <code>address</code>.
275 </p>
278 Most Bluetooth devices provide Class of Device information as a bit-field
279 interpreted according to the
280 <a href="https://www.bluetooth.org/en-us/specification/assigned-numbers/baseband">Baseband Assigned Numbers</a>
281 document. This bit-field is available in the <code>deviceClass</code>
282 property.
283 </p>
285 <pre>
286 chrome.bluetooth.getDevices(function(devices) {
287 for (var i = 0; i < devices.length; i++) {
288 if (devices[0].vendorIdSource != undefined) {
289 console.log(devices[0].address + ' = ' +
290 devices[0].deviceClass.toString(16));
294 </pre>
297 Parsing the field can be complex so for the most common device types Chrome
298 handles this for you and sets the <code>type</code> field. Where this is
299 not available, or insufficient for your needs, you'll need to parse the
300 <code>deviceClass</code> yourself.
301 </p>
303 <pre>
304 chrome.bluetooth.getDevices(function(devices) {
305 for (var i = 0; i < devices.length; i++) {
306 if (devices[0].vendorIdSource != undefined) {
307 console.log(devices[0].address + ' = ' + devices[0].type);
311 </pre>
313 <h2 id="using_rfcomm">Using RFCOMM and L2CAP</h2>
316 Chrome Apps may make connections to any device that supports RFCOMM or
317 L2CAP services. This includes the majority of classic Bluetooth devices on
318 the market.
319 </p>
321 <h3 id="connecting">Connecting to a socket</h3>
324 In order to make a connection to a device you need three things. A socket
325 to make the connection with, created using $(ref:bluetoothSocket.create);
326 the address of the device you wish to connect to, and the UUID of the
327 service itself.
328 </p>
331 Before making the connection you should verify that the adapter is aware of
332 the device by using $(ref:bluetooth.getDevice) or the device
333 discovery APIs.
334 </p>
337 The information necessary to establish the underlying connection, including
338 whether the RFCOMM or L2CAP protocol should be used and which channel or PSM,
339 is obtained using SDP discovery on the device.
340 </p>
343 Example:
344 </p>
346 <pre>
347 var uuid = '1105';
348 var onConnectedCallback = function() {
349 if (chrome.runtime.lastError) {
350 console.log("Connection failed: " + chrome.runtime.lastError.message);
351 } else {
352 // Profile implementation here.
356 chrome.bluetoothSocket.create(function(createInfo) {
357 chrome.bluetoothSocket.connect(createInfo.socketId,
358 device.address, uuid, onConnectedCallback);
360 </pre>
363 Keep a handle to the socketId so that you can later send data
364 ($(ref:bluetoothSocket.send)) to this socket.
365 </p>
367 <h3 id="receiving">Receiving from and sending to a socket</h3>
370 Receiving data from and sending to a socket uses <code>ArrayBuffer</code>
371 objects. To learn about ArrayBuffers, check out the overview,
372 <a href="https://developer.mozilla.org/en-US/docs/JavaScript_typed_arrays">JavaScript typed arrays</a>,
373 and the tutorial,
374 <a href="http://updates.html5rocks.com/2012/06/How-to-convert-ArrayBuffer-to-and-from-String">How to convert ArrayBuffer to and from String</a>.
375 </p>
378 To send data you have in <code>arrayBuffer</code> use
379 $(ref:bluetoothSocket.send):
380 </p>
382 <pre>
383 chrome.bluetoothSocket.send(socketId, arrayBuffer, function(bytes_sent) {
384 if (chrome.runtime.lastError) {
385 console.log("Send failed: " + chrome.runtime.lastError.message);
386 } else {
387 console.log("Sent " + bytes_sent + " bytes")
390 </pre>
393 In contrast to the method to send data, data is received in an event
394 ($(ref:bluetoothSocket.onReceive). Sockets are created unpaused (see
395 $(ref:bluetoothSocket.setPaused)) so the listener for this event is
396 typically added between $(ref:bluetoothSocket.create) and
397 $(ref:bluetoothSocket.connect).
398 </p>
400 <pre>
401 chrome.bluetoothSocket.onRecieve.addListener(function(receiveInfo) {
402 if (receiveInfo.socketId != socketId)
403 return;
404 // receiveInfo.data is an ArrayBuffer.
406 </pre>
408 <h3 id="errors">Receiving socket errors and disconnection</h3>
411 To be notified of socket errors, including disconnection, add a listener to
412 the $(ref:bluetoothSocket.onReceiveError) event.
413 </p>
415 <pre>
416 chrome.bluetoothSocket.onReceiveError.addListener(function(errorInfo) {
417 // Cause is in errorInfo.error.
418 console.log(errorInfo.errorMessage);
420 </pre>
422 <h3 id="disconnection">Disconnecting from a socket</h3>
425 To hang up the connection and disconnect the socket use
426 $(ref:bluetoothSocket.disconnect).
427 </p>
429 <pre>
430 chrome.bluetoothSocket.disconnect(socketId);
431 </pre>
433 <h2 id="using_rfcomm">Publishing services</h2>
436 In addition to making outbound connections to devices, Chrome Apps may
437 publish services that may be used by any device that supports RFCOMM or
438 L2CAP.
439 </p>
441 <h3 id="listening">Listening on a socket</h3>
444 Two types of published service are supported. RFCOMM is the most commonly
445 used and covers the majority of devices and profiles:
446 </p>
448 <pre>
449 var uuid = '1105';
450 chrome.bluetoothSocket.create(function(createInfo) {
451 chrome.bluetoothSocket.listenUsingRfcomm(createInfo.socketId,
452 uuid, onListenCallback);
454 </pre>
457 L2CAP is the other and covers other device types and vendor-specific uses
458 such as firmware uploading.
459 </p>
461 <pre>
462 var uuid = '0b87367c-f188-47cd-bc20-a5f4f70973c6';
463 chrome.bluetoothSocket.create(function(createInfo) {
464 chrome.bluetoothSocket.listenUsingL2cap(createInfo.socketId,
465 uuid, onListenCallback);
467 </pre>
470 In both cases an optional $(ref:bluetoothSocket.ListenOptions) may be
471 passed to allocate a specific channel or PSM. The callback indicates error
472 through <code>chrome.runtime.lastError</code> and success otherwise.
473 Keep a handle to the socketId so that you can later accept connections
474 ($(ref:bluetoothSocket.onAccept)) from this socket.
475 </p>
477 <h3 id="accepting">Accepting client connections</h3>
480 Client connections are accepted and passed to your application through the
481 $(ref:bluetoothSocket.onAccept) event.
482 </p>
484 <pre>
485 chrome.bluetoothSocket.onAccept.addListener(function(acceptInfo) {
486 if (info.socketId != serverSocketId)
487 return;
489 // Say hello...
490 chrome.bluetoothSocket.send(acceptInfo.clientSocketId,
491 data, onSendCallback);
493 // Accepted sockets are initially paused,
494 // set the onReceive listener first.
495 chrome.bluetoothSocket.onReceive.addListener(onReceive);
496 chrome.bluetoothSocket.setPaused(false);
498 </pre>
500 <h3 id="stop-accepting">Stop accepting client connections</h3>
503 To stop accepting client connections and unpublish the service use
504 $(ref:bluetoothSocket.disconnect).
505 </p>
507 <pre>
508 chrome.bluetoothSocket.disconnect(serverSocketId);
509 </pre>
511 <h2 id="low-energy">Interacting with Low Energy devices</h2>
514 Bluetooth Low Energy or (Bluetooth Smart) is a wireless technology aimed at
515 reduced power consumption. The
516 <a href="bluetoothLowEnergy.html">Bluetooth Low Energy</a> API allows
517 applications to implement the central role in a LE connection to a
518 peripheral. The following sections describe how to discover,
519 connect to, and interact with Bluetooth Low Energy peripherals.
520 </p>
522 <h3 id="le-discovery">Discovering and connecting to peripherals</h3>
525 As with traditional Bluetooth devices, LE peripherals can be discovered
526 using the methods described in <a href="#discovery">Discovering nearby devices
527 </a>. An LE device makes itself discoverable by sending data packets called
528 "Advertising Data" and the device is said to be in <em>advertising mode</em>.
529 The advertising data may contain UUIDs of services that are available on the
530 device. If present, these UUIDs will be accessible using the
531 <code>uuids</code> property of the corresponding $(ref:bluetooth.Device)
532 object.
533 </p>
536 Once discovered, an LE device can be connected to by calling
537 $(ref:bluetoothLowEnergy.connect) so that the application can interact with
538 its services:
539 </p>
541 <pre>
542 chrome.bluetooth.onDeviceAdded.addListener(function(device) {
543 var uuid = '0000180d-0000-1000-8000-00805f9b34fb';
544 if (!device.uuids || device.uuids.indexOf(uuid) < 0)
545 return;
547 // The device has a service with the desired UUID.
548 chrome.bluetoothLowEnergy.connect(device.address, function () {
549 if (chrome.runtime.lastError) {
550 console.log('Failed to connect: ' + chrome.runtime.lastError.message);
551 return;
554 // Connected! Do stuff...
558 </pre>
561 Once connected, the <code>connected</code> property of the corresponding
562 $(ref:bluetooth.Device) object will have the value <code>true</code>. Calling
563 $(ref:bluetoothLowEnergy.connect) establishes a claim by the application on
564 the physical connection to the device. A physical connection to the device
565 can exist without ever calling $(ref:bluetoothLowEnergy.connect) (for example
566 due to another application). In this case, while your application can still
567 interact with the services of the device, it should always call
568 $(ref:bluetoothLowEnergy.connect) to prevent another application from
569 disconnecting the physical link.
570 </p>
573 Once your application no longer needs to be connected, it can remove its
574 claim on the connection by calling $(ref:bluetoothLowEnergy.disconnect):
575 </p>
577 <pre>
578 chrome.bluetoothLowEnergy.disconnect(deviceAddress);
579 </pre>
582 Note that this won't necessarily destroy the physical link to the device, as
583 there may be other applications who have active connections to the device.
584 Sometimes the device might become disconnected due to reasons that are beyond
585 the control of the application (e.g. if the device disappears or gets
586 explicitly disconnected by the user through utilities of the operating
587 system). Your application should observe the $(ref:bluetooth.onDeviceChanged)
588 event to get notified of changes to the connection and reconnect if necessary.
589 </p>
592 Once connected, the device that is running Chrome will be in the
593 so called <em>central role</em>, while the remote device is said to be in the
594 <em>peripheral role</em>. At this point, your application can interact with
595 the services on the device using the methods described in the following
596 section. <em>Note:</em> The APIs currently do not support acting as a LE
597 peripheral; apps can only implement the central role.
598 </p>
600 <h3 id="gatt">Services, Characteristics, and Descriptors</h3>
603 Bluetooth Low Energy is based on a simple request-response protocol called the
604 <em>Attribute Protocol</em> (ATT). Using ATT, a central device interacts with
605 the so called <em>attributes</em> on a peripheral device by conforming to a
606 special Bluetooth profile called the <em>Generic Attribute Profile</em> (GATT).
607 GATT defines the following high level concepts:
608 </p>
610 <ul style="list-style-type: none;">
611 <li>
612 <span style="font-weight: bold;">Service:</span> A GATT service
613 represents a collection of data and associated behaviors to accomplish a
614 particular function of a device. For example, a heart rate monitor will
615 typically have at least one "Heart Rate Service". Information about a
616 GATT service is contained in a $(ref:bluetoothLowEnergy.Service) object.
617 </li>
618 <li>
619 <span style="font-weight: bold;">Characteristic:</span> A GATT
620 characteristic is a basic data element used to construct a GATT service,
621 containing a value along with properties that define how that value can
622 be accessed. For example, the "Heart Rate Service" has the "Heart Rate
623 Measurement" characteristic, which is used to obtain the value of the
624 user's heart rate. Information about a GATT characteristic is contained
625 in a $(ref:bluetoothLowEnergy.Characteristic) object.
626 </li>
627 <li>
628 <span style="font-weight: bold;">Descriptor:</span> A GATT characteristic
629 descriptor contains further information about a characteristic. Information
630 about a GATT characteristic descriptor is contained in a
631 $(ref:bluetoothLowEnergy.Descriptor) object.
632 </li>
633 </ul>
636 The <a href="bluetoothLowEnergy.html">Bluetooth Low Energy</a> API allows
637 applications to find information about a device's services, characteristics,
638 and descriptors by calling $(ref:bluetoothLowEnergy.getServices),
639 $(ref:bluetoothLowEnergy.getCharacteristics), and
640 $(ref:bluetoothLowEnergy.getDescriptors). Apps can filter through services,
641 characteristics, and descriptors by comparing their <code>uuid</code> field
642 to the desired GATT UUID:
643 </p>
645 <pre>
646 chrome.bluetoothLowEnergy.getServices(deviceAddress, function(services) {
648 for (var i = 0; i < services.length; i++) {
649 if (services[i].uuid == HEART_RATE_SERVICE_UUID) {
650 heartRateService = services[i];
651 break;
656 </pre>
659 Each service, characteristic, and descriptor accessible through the API is
660 assigned a unique instance identifier, which can be obtained using the
661 <code>instanceId</code> field. This instance ID can be used to identify a
662 GATT object and to perform specific operations on it:
663 </p>
665 <pre>
666 chrome.bluetoothLowEnergy.getCharacteristics(heartRateService.instanceId,
667 function(chracteristics) {
669 for (var i = 0; i < characteristics.length; i++) {
670 if (characteristics[i].uuid == HEART_RATE_MEASUREMENT_UUID) {
671 measurementChar = characteristics[i];
672 break;
676 chrome.bluetoothLowEnergy.getDescriptors(measurementChar.instanceId,
677 function(descriptors) {
681 </pre>
683 <h3 id="service-events">Service events</h3>
686 Once a device is connected, Chrome will discover its services. As each service
687 is discovered and removed, the application will receive the
688 $(ref:bluetoothLowEnergy.onServiceAdded) and
689 $(ref:bluetoothLowEnergy.onServiceRemoved) events:
690 </p>
692 <pre>
693 var initializeService = function(service) {
694 if (!service) {
695 console.log('No service selected!');
696 // Reset UI, etc.
698 return;
701 myService = service;
703 // Get all the characteristics and descriptors and bootstrap the app.
707 chrome.bluetoothLowEnergy.onServiceAdded.addListener(function(service) {
708 if (service.uuid == MY_SERVICE_UUID)
709 initializeService(service);
712 chrome.bluetoothLowEnergy.onServiceRemoved.addListener(function(service) {
713 if (service.instanceId == myService.instanceId)
714 initializeService(null);
716 </pre>
719 Chrome discovers all characteristics and descriptors of a service
720 asynchronously and sends the $(ref:bluetoothLowEnergy.onServiceAdded) event
721 once discovery has completed. If the connection to a peripheral terminates,
722 Chrome removes all related services and sends the
723 $(ref:bluetoothLowEnergy.onServiceRemoved) event.
724 </p>
727 Some peripherals may modify their services, e.g. the characteristics of a
728 service may change or services may get added and removed entirely. Chrome
729 notifies apps of these changes using the
730 $(ref:bluetoothLowEnergy.onServiceChanged),
731 $(ref:bluetoothLowEnergy.onServiceAdded), and
732 $(ref:bluetoothLowEnergy.onServiceRemoved) events.
733 </p>
735 <pre>
736 chrome.bluetoothLowEnergy.onServiceChanged.addListener(function(service) {
737 if (service.instanceId != myService.instanceId)
738 return;
740 updateMyService(service);
742 </pre>
744 <h3 id="gatt-read-write">Reading and writing a characteristic's value</h3>
747 A GATT characteristic encodes one aspect of its service. A central app reads,
748 acts on, and modifies the state of a peripheral's service by operating on a
749 characteristic's value. The characteristic value is a sequence of bytes and
750 its meaning is defined by the high-level specification that defines a certain
751 characteristic. For example, the value of the <em>Heart Rate Measurement</em>
752 characteristic encodes the user's heart rate and the total amount of calories
753 they burned, while the <em>Body Sensor Location</em> characteristic encodes
754 where in the body the heart rate sensor should be worn.
755 </p>
758 Chrome provides the $(ref:bluetoothLowEnergy.readCharacteristicValue) method
759 to read the value of a characteristic:
760 </p>
762 <pre>
763 chrome.bluetoothLowEnergy.readCharacteristicValue(chrc.instanceId,
764 function(result) {
765 if (chrome.runtime.lastError) {
766 console.log('Failed to read value: ' + chrome.runtime.lastError.message);
767 return;
770 var bytes = new Uint8Array(result.value);
772 // Do stuff with the bytes.
775 </pre>
778 Some characteristics are writable, especially those that behave as "Control
779 Points", where writing the value has side effects. For example, the <em>Heart
780 Rate Control Point</em> characteristic is used to tell a heart rate sensor to
781 reset its count of total calories burned and only supports writes. To achieve
782 this, Chrome provides the $(ref:bluetoothLowEnergy.writeCharacteristicValue)
783 method:
784 </p>
786 <pre>
787 var myBytes = new Uint8Array([ ... ]);
788 chrome.bluetoothLowEnergy.writeCharacteristicValue(chrc.instanceId,
789 myBytes.buffer,
790 function() {
791 if (chrome.runtime.lastError) {
792 console.log('Failed to write value: ' +
793 chrome.runtime.lastError.message);
794 return;
797 // Value is written now.
799 </pre>
802 Characteristic descriptors behave the same way and can be readable and/or
803 writable. Chrome provides the $(ref:bluetoothLowEnergy.readDescriptorValue)
804 and $(ref:bluetoothLowEnergy.writeDescriptorValue) methods to read and write
805 the value of a descriptor.
806 </p>
809 To check if a characteristic supports reads or writes, an application can
810 check the <code>properties</code> field of a
811 $(ref:bluetoothLowEnergy.Characteristic) object. While this field does not
812 contain information about the security requirements to access a value, it does
813 describe which value operation the characteristic supports in general.
814 </p>
816 <h3 id="gatt-notifications">Handling value notifications</h3>
819 Some characteristics make their value known using notifications or
820 indications. For example the <em>Heart Rate Measurement</em> characteristic is
821 neither readable nor writable but sends updates on its current value at
822 regular intervals. Applications can listen to these notifications using the
823 $(ref:bluetoothLowEnergy.onCharacteristicValueChanged) event.
824 </p>
826 <pre>
827 chrome.bluetoothLowEnergy.onCharacteristicValueChanged.addListener(
828 function(chrc) {
829 if (chrc.instanceId != myCharId)
830 return;
832 var bytes = new Uint8Array(chrc.value);
834 // Do stuff with the bytes.
837 </pre>
840 Even if a characteristic supports notifications/indications, they aren't
841 enabled by default. An application should call the
842 $(ref:bluetoothLowEnergy.startCharacteristicNotifications) and
843 $(ref:bluetoothLowEnergy.stopCharacteristicNotifications) methods to start or
844 stop receiving the $(ref:bluetoothLowEnergy.onCharacteristicValueChanged)
845 event.
846 </p>
848 <pre>
849 // Start receiving characteristic value notifications.
850 var notifying = false;
851 chrome.bluetoothLowEnergy.startCharacteristicNotifications(chrc.instanceId,
852 function() {
853 if (chrome.runtime.lastError) {
854 console.log('Failed to enable notifications: ' +
855 chrome.runtime.lastError.message);
856 return;
859 notifying = true;
864 // No longer interested in notifications from this characteristic.
865 if (notifying) {
866 chrome.bluetoothLowEnergy.stopCharacteristicNotifications(
867 chrc.instanceId);
869 </pre>
872 Once notifications are started, the application will receive the
873 $(ref:bluetoothLowEnergy.onCharacteristicValueChanged) every time a
874 notification or indication is received from the characteristic. If the
875 characteristic supports reads, then this event will also be sent after a
876 successful call to $(ref:bluetoothLowEnergy.readCharacteristicValue). This
877 allows apps to unify the control flow of a value update triggered through a
878 read request and notifications:
879 </p>
881 <pre>
882 chrome.bluetoothLowEnergy.onCharacteristicValueChanged.addListener(
883 function(chrc) {
884 // Process the value.
888 chrome.bluetoothLowEnergy.startCharacteristicNotifications(chrc.instanceId,
889 function() {
890 // Notifications started. Read the initial value.
891 chrome.bluetoothLowEnergy.readCharacteristicValue(chrc.instanceId,
892 function(result) {
894 // No need to do anything here since onCharacteristicValueChanged
895 // will handle it.
898 </pre>
901 If a characteristic supports notifications, its <code>properties</code> field
902 will contain either the <code>"notify"</code> or <code>"indicate"</code>
903 property.
904 </p>
907 <span style="font-weight: bold;">NOTE:</span> If a characteristic supports
908 notifications/indications, it will have the "Client Characteristic
909 Configuration" descriptor to enable/disable notifications. Chrome does not
910 permit apps to write to this descriptor. Apps should instead use the
911 $(ref:bluetoothLowEnergy.startCharacteristicNotifications) and
912 $(ref:bluetoothLowEnergy.stopCharacteristicNotifications) methods to control
913 notification behavior.
914 </p>