Chromium Code Reviews| Index: chrome/common/extensions/docs/templates/articles/app_bluetooth.html |
| diff --git a/chrome/common/extensions/docs/templates/articles/app_bluetooth.html b/chrome/common/extensions/docs/templates/articles/app_bluetooth.html |
| index 29c8fbd171866ead6b9377230e086e975943d1d1..0fc6b8abfbd6e25fc6bef479f0a4f289a6d9e700 100644 |
| --- a/chrome/common/extensions/docs/templates/articles/app_bluetooth.html |
| +++ b/chrome/common/extensions/docs/templates/articles/app_bluetooth.html |
| @@ -507,3 +507,419 @@ chrome.bluetoothSocket.onAccept.addListener(function(acceptInfo) { |
| <pre> |
| chrome.bluetoothSocket.disconnect(serverSocketId); |
| </pre> |
| + |
| +<h2 id="low-energy">Interacting with Low Energy devices</h2> |
| + |
| +<p> |
| + Bluetooth Low Energy or (Bluetooth Smart) is a wireless technology aimed at |
| + reduced power consumption. The following sections describe how to discover, |
| + connect to, and interact with Bluetooth Low Energy peripherals. |
|
keybuk
2014/07/14 20:02:26
Comment from elsewhere:
this should explicitly me
armansito
2014/07/19 05:22:56
Done. I mentioned it in two separate places. Let m
|
| +</p> |
| + |
| +<h3 id="le-discovery">Discovering and connecting to peripherals</h3> |
| + |
| +<p> |
| + As with traditional Bluetooth devices, LE peripherals can be discovered |
| + using the methods described in <a href="#discovery">Discovering nearby devices |
| + </a>. An LE device makes itself discoverable by sending data packets called |
| + "Advertising Data" and the device is said to be in <em>advertising mode</em>. |
| + The advertising data may contain UUIDs of services that are available on the |
| + device. If present, these UUIDs will be accessible using the |
| + <code>uuids</code> property of the corresponding $(ref:bluetooth.Device) |
| + object. |
| +</p> |
| + |
| +<p> |
| + Once discovered, an LE device can be connected to by calling |
| + $(ref:bluetoothLowEnergy.connect) so that the application can interact with |
| + its services: |
| +</p> |
| + |
| +<pre> |
| +chrome.bluetooth.onDeviceAdded.addListener(function(device) { |
| + var uuid = '0000180d-0000-1000-8000-00805f9b34fb'; |
| + if (!device.uuids || device.uuids.indexOf(uuid) < 0) |
| + return; |
| + |
| + // The device has a service with the desired UUID. |
| + chrome.bluetoothLowEnergy.connect(device.address, function () { |
| + if (chrome.runtime.lastError) { |
| + console.log('Failed to connect: ' + chrome.runtime.lastError.message); |
| + return; |
| + } |
| + |
| + // Connected! Do stuff... |
| + ... |
| + }); |
| +}); |
| +</pre> |
| + |
| +<p> |
| + Once connected, the <code>connected</code> property of the corresponding |
| + $(ref:bluetooth.Device) object will have the value <code>true</code>. Calling |
| + $(ref:bluetoothLowEnergy.connect) establishes a claim by the application on |
| + the physical connection to the device. A physical connection to the device |
| + can exist without ever calling $(ref:bluetoothLowEnergy.connect) (for example |
| + due to another application). In this case, while your application can still |
| + interact with the services of the device, it should always call |
| + $(ref:bluetoothLowEnergy.connect) to prevent another application from |
| + disconnecting the physical link. |
| +</p> |
| + |
| +<p> |
| + Once your application no longer needs to be connected, it can remove its |
| + claim on the connection by calling $(ref:bluetoothLowEnergy.disconnect): |
| +</p> |
| + |
| +<pre> |
| +chrome.bluetoothLowEnergy.disconnect(deviceAddress); |
| +</pre> |
| + |
| +<p> |
| + Note that this won't necessarily destroy the physical link to the device, as |
| + there may be other applications who have active connections to the device. |
| + Sometimes the device might become disconnected due to reasons that are beyond |
| + the control of the application (e.g. if the device disappears or gets |
| + explicitly disconnected by the user through utilities of the operating |
| + system). Your application should observe the $(ref:bluetooth.onDeviceChanged) |
| + event to get notified of changes to the connection and reconnect if necessary. |
| +</p> |
| + |
| +<p> |
| + Once connected, the device that is running Chrome will be in the |
| + so called <em>central role</em>, while the remote device is said to be in the |
| + <em>peripheral role</em>. At this point, your application can interact with |
| + the services on the device using the methods described in the following |
| + section. |
| +</p> |
| + |
| +<h3 id="gatt">Services, Characteristics, and Descriptors</h3> |
| + |
| +<p> |
| +Bluetooth Low Energy is based on a simple request-response protocol called the |
| +<em>Attribute Protocol</em> (ATT). Using ATT, a central device interacts with |
| +the so called <em>attributes</em> on a peripheral device by conforming to a |
| +special Bluetooth profile called the <em>Generic Attribute Profile</em> (GATT). |
| +GATT defines the following high level concepts: |
| +</p> |
| + |
| +<ul style="list-style-type: none;"> |
| + <li> |
| + <span style="font-weight: bold;">Service:</span> A GATT service |
| + represents a collection of data and associated behaviors to accomplish a |
| + particular function of a device. For example, a heart rate monitor will |
| + typically have at least one "Heart Rate Service". Information about a |
| + GATT service is contained in a $(ref:bluetoothLowEnergy.Service) object. |
| + </li> |
| + <li> |
| + <span style="font-weight: bold;">Characteristic:</span> A GATT |
| + characteristic is a basic data element used to construct a GATT service, |
| + containing a value along with properties that define how that value can |
| + be accessed. For example, the "Heart Rate Service" has the "Heart Rate |
| + Measurement" characteristic, which is used to obtain the value of the |
| + user's heart rate. Information about a GATT characteristic is contained |
| + in a $(ref:bluetoothLowEnergy.Characteristic) object. |
| + </li> |
| + <li> |
| + <span style="font-weight: bold;">Descriptor:</span> A GATT characteristic |
| + descriptor contains further information about a characteristic. Information |
| + about a GATT characteristic descriptor is contained in a |
| + $(ref:bluetoothLowEnergy.Descriptor) object. |
| + </li> |
| +</ul> |
| + |
| +<p> |
| + The <a href="bluetoothLowEnergy.html">Bluetooth Low Energy</a> API allows |
| + applications to find information about a device's services, characteristics, |
| + and descriptors by calling $(ref:bluetoothLowEnergy.getServices), |
| + $(ref:bluetoothLowEnergy.getCharacteristics), and |
| + $(ref:bluetoothLowEnergy.getDescriptors). Apps can filter through services, |
| + characteristics, and descriptors by comparing their <code>uuid</code> field |
| + to the desired GATT UUID: |
| +</p> |
| + |
| +<pre> |
| +chrome.bluetoothLowEnergy.getServices(deviceAddress, function(services) { |
| + ... |
| + for (var i = 0; i < services.length; i++) { |
| + if (services[i].uuid == HEART_RATE_SERVICE_UUID) { |
| + heartRateService = services[i]; |
| + break; |
| + } |
| + } |
| + ... |
| +}); |
| +</pre> |
| + |
| +<p> |
| + Each service, characteristic, and descriptor accessible through the API is |
| + assigned a unique instance identifier, which can be obtained using the |
| + <code>instanceId</code> field. This instance ID can be used to identify a |
| + GATT object and to perform specific operations on it: |
| +</p> |
| + |
| +<pre> |
| +chrome.bluetoothLowEnergy.getCharacteristics(heartRateService.instanceId, |
| + function(chracteristics) { |
| + ... |
| + for (var i = 0; i < characteristics.length; i++) { |
| + if (characteristics[i].uuid == HEART_RATE_MEASUREMENT_UUID) { |
| + measurementChar = characteristics[i]; |
| + break; |
| + } |
| + } |
| + ... |
| + chrome.bluetoothLowEnergy.getDescriptors(measurementChar.instanceId, |
| + function(descriptors) { |
| + ... |
| + }); |
| +}); |
| +</pre> |
| + |
| +<h3 id="service-events">Service events</h3> |
| + |
| +<p> |
| + Once a device is connected, Chrome will discover its services. As each service |
| + is discovered and removed, the application will receive the |
| + $(ref:bluetoothLowEnergy.onServiceAdded) and |
| + $(ref:bluetoothLowEnergy.onServiceRemoved) events: |
| +</p> |
| + |
| +<pre> |
| + var initializeService = function(service) { |
| + if (!service) { |
| + console.log('No service selected!'); |
| + // Reset UI, etc. |
| + ... |
| + return; |
| + } |
| + |
| + myService = service; |
| + |
| + // Get all the characteristics and descriptors and bootstrap the app. |
| + ... |
| + }; |
| + |
| + chrome.bluetoothLowEnergy.onServiceAdded.addListener(function(service) { |
| + if (service.uuid == MY_SERVICE_UUID) |
| + initializeService(service); |
| + }); |
| + |
| + chrome.bluetoothLowEnergy.onServiceRemoved.addListener(function(service) { |
| + if (service.instanceId == myService.instanceId) |
| + initializeService(null); |
| + }); |
| +</pre> |
| + |
| +<p> |
| + Chrome discovers all characteristics and descriptors of a service |
| + asynchronously. This means that, at the time a |
| + $(ref:bluetoothLowEnergy.onServiceAdded) event is sent to the app, not all |
| + characteristics of a service may have been discovered yet. Each time a |
| + characteristic or a descriptor is added through discovery, the app will |
| + receive the $(ref:bluetoothLowEnergy.onServiceChanged) event. This event will |
| + also be sent if a notification is received from the remote device telling |
| + Chrome that the service definition itself has changed: |
| +</p> |
| + |
| +<pre> |
| + chrome.bluetoothLowEnergy.onServiceChanged.addListener(function(service) { |
| + if (service.instanceId != myService.instanceId) |
| + return; |
| + |
| + // Get characteristics |
| + chrome.bluetoothLowEnergy.getCharacteristics(service.instanceId, |
| + function(result) { |
| + ... |
| + if (result.length == 0) { |
| + console.log('Characteristics not discovered yet'); |
| + return; |
| + } |
| + |
| + for (var i = 0; i < result.length; i++) { |
| + if (result[i].uuid == MY_CHARACTERISTIC_UUID) { |
| + myChar = result[i]; |
| + break; |
| + } |
| + |
| + if (!myChar) { |
| + console.log('The relevant characteristic not discovered yet.'); |
| + return; |
| + } |
| + ... |
| + } |
| + }); |
| + }); |
| +</pre> |
| + |
| +<h3 id="gatt-read-write">Reading and writing a characteristic's value</h3> |
| + |
| +<p> |
| + A GATT characteristic encodes one aspect of its service. A central app reads, |
| + acts on, and modifies the state of a peripheral's service by operating on a |
| + characteristic's value. The characteristic value is a sequence of bytes and |
| + its meaning is defined by the high-level specification that defines a certain |
| + characteristic. For example, the value of the <em>Heart Rate Measurement</em> |
| + characteristic encodes the user's heart rate and the total amount of calories |
| + they burned, while the <em>Body Sensor Location</em> characteristic encodes |
| + where in the body the heart rate sensor should be worn. |
| +</p> |
| + |
| +<p> |
| + Chrome provides the $(ref:bluetoothLowEnergy.readCharacteristicValue) method |
| + to read the value of a characteristic: |
| +</p> |
| + |
| +<pre> |
| +chrome.bluetoothLowEnergy.readCharacteristicValue(chrc.instanceId, |
| + function(result) { |
| + if (chrome.runtime.lastError) { |
| + console.log('Failed to read value: ' + chrome.runtime.lastError.message); |
| + return; |
| + } |
| + |
| + var bytes = new Uint8Array(result.value); |
| + |
| + // Do stuff with the bytes. |
| + ... |
| +}); |
| +</pre> |
| + |
| +<p> |
| + Some characteristics are writable, especially those that behave as "Control |
| + Points", where writing the value has side effects. For example, the <em>Heart |
| + Rate Control Point</em> characteristic is used to tell a heart rate sensor to |
| + reset its count of total calories burned and only supports writes. To achieve |
| + this, Chrome provides the $(ref:bluetootLowEnergy.writeCharacteristicValue) |
| + method: |
| +</p> |
| + |
| +<pre> |
| +var myBytes = new Uint8Array([ ... ]); |
| +chrome.bluetoothLowEnergy.writeCharacteristicValue(chrc.instanceId, |
| + myBytes.buffer, |
| + function() { |
| + if (chrome.runtime.lastError) { |
| + console.log('Failed to write value: ' + |
| + chrome.runtime.lastError.message); |
| + return; |
| + } |
| + |
| + // Value is written now. |
| +}); |
| +</pre> |
| + |
| +<p> |
| + Characteristic descriptors behave the same way and can be readable and/or |
| + writable. Chrome provides the $(ref:bluetoothLowEnergy.readDescriptorValue) |
| + and $(ref:bluetoothLowEnergy.writeDescriptorValue) methods to read and write |
| + the value of a descriptor. |
| +</p> |
| + |
| +<p> |
| + To check if a characteristic supports reads or writes, an application can |
| + check the <code>properties</code> field of a |
| + $(ref:bluetoothLowEnergy.Characteristic) object. While this field does not |
| + contain information about the security requirements to access a value, it does |
| + describe which value operation the characteristic supports in general. |
| +</p> |
| + |
| +<h3 id="gatt-notifications">Handling value notifications</h3> |
| + |
| +<p> |
| + Some characteristics make their value known using notifications or |
| + indications. For example the <em>Heart Rate Measurement</em> characteristic is |
| + neither readable nor writable but sends updates on its current value at |
| + regular intervals. Applications can listen to these notifications using the |
| + $(ref:bluetoothLowEnergy.onCharacteristicValueChanged) event. |
| +</p> |
| + |
| +<pre> |
| + chrome.bluetoothLowEnergy.onCharacteristicValueChanged.addListener( |
| + function(chrc) { |
| + if (chrc.instanceId != myCharId) |
| + return; |
| + |
| + var bytes = new Uint8Array(chrc.value); |
| + |
| + // Do stuff with the bytes. |
| + ... |
| + }); |
| +</pre> |
| + |
| +<p> |
| + Even if a characteristic supports notifications/indications, they aren't |
| + enabled by default. An application should call the |
| + $(ref:bluetoothLowEnergy.startCharacteristicNotifications) and |
| + $(ref:bluetoothLowEnergy.stopCharacteristicNotifications) methods to start or |
| + stop receiving the $(ref:bluetoothLowEnergy.onCharacteristicValueChanged) |
| + event. |
| +</p> |
| + |
| +<pre> |
| + // Start receiving characteristic value notifications. |
| + var notifying = false; |
| + chrome.bluetoothLowEnergy.startCharacteristicNotifications(chrc.instanceId, |
| + function() { |
| + if (chrome.runtime.lastError) { |
| + console.log('Failed to enable notifications: ' + |
| + chrome.runtime.lastError.message); |
| + return; |
| + } |
| + |
| + notifying = true; |
| + }); |
| + |
| + ... |
| + |
| + // No longer interested in notifications from this characteristic. |
| + if (notifying) { |
| + chrome.bluetoothLowEnergy.stopCharacteristicNotifications( |
| + chrc.instanceId); |
| + } |
| +</pre> |
| + |
| +<p> |
| + Once notifications are started, the application will receive the |
| + $(ref:bluetoothLowEnergy.onCharacteristicValueChanged) every time a |
| + notification or indication is received from the characteristic. If the |
| + characteristic supports reads, then this event will also be sent after a |
| + successful call to $(ref:bluetoothLowEnergy.readCharacteristicValue). This |
| + allows apps to unify the control flow of a value update triggered through a |
| + read request and notifications: |
| +</p> |
| + |
| +<pre> |
| + chrome.bluetoothLowEnergy.onCharacteristicValueChanged.addListener( |
| + function(chrc) { |
| + // Process the value. |
| + ... |
| + }); |
| + |
| + chrome.bluetoothLowEnergy.startCharacteristicNotifications(chrc.instanceId, |
| + function() { |
| + // Notifications started. Read the initial value. |
| + chrome.bluetoothLowEnergy.readCharacteristicValue(chrc.instanceId, |
| + function(result) { |
| + ... |
| + // No need to do anything here since onCharacteristicValueChanged |
| + // will handle it. |
| + }); |
| + }); |
| +</pre> |
| + |
| +<p> |
| + If a characteristic supports notifications, its <code>properties</code> field |
| + will contain either the <code>"notify"</code> or <code>"indicate"</code> |
| + property. |
| +</p> |
| + |
| +<p> |
| + <span style="font-weight: bold;">NOTE:</span> If a characteristic supports |
| + notifications/indications, it will have the "Client Characteristic |
| + Configuration" descriptor to enable/disable notifications. Chrome does not |
| + permit apps to write to this descriptor. Apps should instead use the |
| + $(ref:bluetoothLowEnergy.startCharacteristicNotifications) and |
| + $(ref:bluetoothLowEnergy.stopCharacteristicNotifications) methods to control |
| + notification behavior. |
| +</p> |