Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 <h1>Bluetooth</h1> | 1 <h1>Bluetooth</h1> |
| 2 | 2 |
| 3 <p> | 3 <p> |
| 4 This document describes how to use the <a href="bluetooth.html">Bluetooth</a>, | 4 This document describes how to use the <a href="bluetooth.html">Bluetooth</a>, |
| 5 <a href="bluetoothSocket.html">Bluetooth Socket</a> and | 5 <a href="bluetoothSocket.html">Bluetooth Socket</a> and |
| 6 <a href="bluetoothLowEnergy.html">Bluetooth Low Energy</a> APIs to | 6 <a href="bluetoothLowEnergy.html">Bluetooth Low Energy</a> APIs to |
| 7 communicate with Bluetooth and Bluetooth Low Energy devices. | 7 communicate with Bluetooth and Bluetooth Low Energy devices. |
| 8 </p> | 8 </p> |
| 9 | 9 |
| 10 <p> | 10 <p> |
| (...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 500 <h3 id="stop-accepting">Stop accepting client connections</h3> | 500 <h3 id="stop-accepting">Stop accepting client connections</h3> |
| 501 | 501 |
| 502 <p> | 502 <p> |
| 503 To stop accepting client connections and unpublish the service use | 503 To stop accepting client connections and unpublish the service use |
| 504 $(ref:bluetoothSocket.disconnect). | 504 $(ref:bluetoothSocket.disconnect). |
| 505 </p> | 505 </p> |
| 506 | 506 |
| 507 <pre> | 507 <pre> |
| 508 chrome.bluetoothSocket.disconnect(serverSocketId); | 508 chrome.bluetoothSocket.disconnect(serverSocketId); |
| 509 </pre> | 509 </pre> |
| 510 | |
| 511 <h2 id="low-energy">Interacting with Low Energy devices</h2> | |
| 512 | |
| 513 <p> | |
| 514 Bluetooth Low Energy or (Bluetooth Smart) is a wireless technology aimed at | |
| 515 reduced power consumption. The following sections describe how to discover, | |
| 516 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
| |
| 517 </p> | |
| 518 | |
| 519 <h3 id="le-discovery">Discovering and connecting to peripherals</h3> | |
| 520 | |
| 521 <p> | |
| 522 As with traditional Bluetooth devices, LE peripherals can be discovered | |
| 523 using the methods described in <a href="#discovery">Discovering nearby devices | |
| 524 </a>. An LE device makes itself discoverable by sending data packets called | |
| 525 "Advertising Data" and the device is said to be in <em>advertising mode</em>. | |
| 526 The advertising data may contain UUIDs of services that are available on the | |
| 527 device. If present, these UUIDs will be accessible using the | |
| 528 <code>uuids</code> property of the corresponding $(ref:bluetooth.Device) | |
| 529 object. | |
| 530 </p> | |
| 531 | |
| 532 <p> | |
| 533 Once discovered, an LE device can be connected to by calling | |
| 534 $(ref:bluetoothLowEnergy.connect) so that the application can interact with | |
| 535 its services: | |
| 536 </p> | |
| 537 | |
| 538 <pre> | |
| 539 chrome.bluetooth.onDeviceAdded.addListener(function(device) { | |
| 540 var uuid = '0000180d-0000-1000-8000-00805f9b34fb'; | |
| 541 if (!device.uuids || device.uuids.indexOf(uuid) < 0) | |
| 542 return; | |
| 543 | |
| 544 // The device has a service with the desired UUID. | |
| 545 chrome.bluetoothLowEnergy.connect(device.address, function () { | |
| 546 if (chrome.runtime.lastError) { | |
| 547 console.log('Failed to connect: ' + chrome.runtime.lastError.message); | |
| 548 return; | |
| 549 } | |
| 550 | |
| 551 // Connected! Do stuff... | |
| 552 ... | |
| 553 }); | |
| 554 }); | |
| 555 </pre> | |
| 556 | |
| 557 <p> | |
| 558 Once connected, the <code>connected</code> property of the corresponding | |
| 559 $(ref:bluetooth.Device) object will have the value <code>true</code>. Calling | |
| 560 $(ref:bluetoothLowEnergy.connect) establishes a claim by the application on | |
| 561 the physical connection to the device. A physical connection to the device | |
| 562 can exist without ever calling $(ref:bluetoothLowEnergy.connect) (for example | |
| 563 due to another application). In this case, while your application can still | |
| 564 interact with the services of the device, it should always call | |
| 565 $(ref:bluetoothLowEnergy.connect) to prevent another application from | |
| 566 disconnecting the physical link. | |
| 567 </p> | |
| 568 | |
| 569 <p> | |
| 570 Once your application no longer needs to be connected, it can remove its | |
| 571 claim on the connection by calling $(ref:bluetoothLowEnergy.disconnect): | |
| 572 </p> | |
| 573 | |
| 574 <pre> | |
| 575 chrome.bluetoothLowEnergy.disconnect(deviceAddress); | |
| 576 </pre> | |
| 577 | |
| 578 <p> | |
| 579 Note that this won't necessarily destroy the physical link to the device, as | |
| 580 there may be other applications who have active connections to the device. | |
| 581 Sometimes the device might become disconnected due to reasons that are beyond | |
| 582 the control of the application (e.g. if the device disappears or gets | |
| 583 explicitly disconnected by the user through utilities of the operating | |
| 584 system). Your application should observe the $(ref:bluetooth.onDeviceChanged) | |
| 585 event to get notified of changes to the connection and reconnect if necessary. | |
| 586 </p> | |
| 587 | |
| 588 <p> | |
| 589 Once connected, the device that is running Chrome will be in the | |
| 590 so called <em>central role</em>, while the remote device is said to be in the | |
| 591 <em>peripheral role</em>. At this point, your application can interact with | |
| 592 the services on the device using the methods described in the following | |
| 593 section. | |
| 594 </p> | |
| 595 | |
| 596 <h3 id="gatt">Services, Characteristics, and Descriptors</h3> | |
| 597 | |
| 598 <p> | |
| 599 Bluetooth Low Energy is based on a simple request-response protocol called the | |
| 600 <em>Attribute Protocol</em> (ATT). Using ATT, a central device interacts with | |
| 601 the so called <em>attributes</em> on a peripheral device by conforming to a | |
| 602 special Bluetooth profile called the <em>Generic Attribute Profile</em> (GATT). | |
| 603 GATT defines the following high level concepts: | |
| 604 </p> | |
| 605 | |
| 606 <ul style="list-style-type: none;"> | |
| 607 <li> | |
| 608 <span style="font-weight: bold;">Service:</span> A GATT service | |
| 609 represents a collection of data and associated behaviors to accomplish a | |
| 610 particular function of a device. For example, a heart rate monitor will | |
| 611 typically have at least one "Heart Rate Service". Information about a | |
| 612 GATT service is contained in a $(ref:bluetoothLowEnergy.Service) object. | |
| 613 </li> | |
| 614 <li> | |
| 615 <span style="font-weight: bold;">Characteristic:</span> A GATT | |
| 616 characteristic is a basic data element used to construct a GATT service, | |
| 617 containing a value along with properties that define how that value can | |
| 618 be accessed. For example, the "Heart Rate Service" has the "Heart Rate | |
| 619 Measurement" characteristic, which is used to obtain the value of the | |
| 620 user's heart rate. Information about a GATT characteristic is contained | |
| 621 in a $(ref:bluetoothLowEnergy.Characteristic) object. | |
| 622 </li> | |
| 623 <li> | |
| 624 <span style="font-weight: bold;">Descriptor:</span> A GATT characteristic | |
| 625 descriptor contains further information about a characteristic. Information | |
| 626 about a GATT characteristic descriptor is contained in a | |
| 627 $(ref:bluetoothLowEnergy.Descriptor) object. | |
| 628 </li> | |
| 629 </ul> | |
| 630 | |
| 631 <p> | |
| 632 The <a href="bluetoothLowEnergy.html">Bluetooth Low Energy</a> API allows | |
| 633 applications to find information about a device's services, characteristics, | |
| 634 and descriptors by calling $(ref:bluetoothLowEnergy.getServices), | |
| 635 $(ref:bluetoothLowEnergy.getCharacteristics), and | |
| 636 $(ref:bluetoothLowEnergy.getDescriptors). Apps can filter through services, | |
| 637 characteristics, and descriptors by comparing their <code>uuid</code> field | |
| 638 to the desired GATT UUID: | |
| 639 </p> | |
| 640 | |
| 641 <pre> | |
| 642 chrome.bluetoothLowEnergy.getServices(deviceAddress, function(services) { | |
| 643 ... | |
| 644 for (var i = 0; i < services.length; i++) { | |
| 645 if (services[i].uuid == HEART_RATE_SERVICE_UUID) { | |
| 646 heartRateService = services[i]; | |
| 647 break; | |
| 648 } | |
| 649 } | |
| 650 ... | |
| 651 }); | |
| 652 </pre> | |
| 653 | |
| 654 <p> | |
| 655 Each service, characteristic, and descriptor accessible through the API is | |
| 656 assigned a unique instance identifier, which can be obtained using the | |
| 657 <code>instanceId</code> field. This instance ID can be used to identify a | |
| 658 GATT object and to perform specific operations on it: | |
| 659 </p> | |
| 660 | |
| 661 <pre> | |
| 662 chrome.bluetoothLowEnergy.getCharacteristics(heartRateService.instanceId, | |
| 663 function(chracteristics) { | |
| 664 ... | |
| 665 for (var i = 0; i < characteristics.length; i++) { | |
| 666 if (characteristics[i].uuid == HEART_RATE_MEASUREMENT_UUID) { | |
| 667 measurementChar = characteristics[i]; | |
| 668 break; | |
| 669 } | |
| 670 } | |
| 671 ... | |
| 672 chrome.bluetoothLowEnergy.getDescriptors(measurementChar.instanceId, | |
| 673 function(descriptors) { | |
| 674 ... | |
| 675 }); | |
| 676 }); | |
| 677 </pre> | |
| 678 | |
| 679 <h3 id="service-events">Service events</h3> | |
| 680 | |
| 681 <p> | |
| 682 Once a device is connected, Chrome will discover its services. As each service | |
| 683 is discovered and removed, the application will receive the | |
| 684 $(ref:bluetoothLowEnergy.onServiceAdded) and | |
| 685 $(ref:bluetoothLowEnergy.onServiceRemoved) events: | |
| 686 </p> | |
| 687 | |
| 688 <pre> | |
| 689 var initializeService = function(service) { | |
| 690 if (!service) { | |
| 691 console.log('No service selected!'); | |
| 692 // Reset UI, etc. | |
| 693 ... | |
| 694 return; | |
| 695 } | |
| 696 | |
| 697 myService = service; | |
| 698 | |
| 699 // Get all the characteristics and descriptors and bootstrap the app. | |
| 700 ... | |
| 701 }; | |
| 702 | |
| 703 chrome.bluetoothLowEnergy.onServiceAdded.addListener(function(service) { | |
| 704 if (service.uuid == MY_SERVICE_UUID) | |
| 705 initializeService(service); | |
| 706 }); | |
| 707 | |
| 708 chrome.bluetoothLowEnergy.onServiceRemoved.addListener(function(service) { | |
| 709 if (service.instanceId == myService.instanceId) | |
| 710 initializeService(null); | |
| 711 }); | |
| 712 </pre> | |
| 713 | |
| 714 <p> | |
| 715 Chrome discovers all characteristics and descriptors of a service | |
| 716 asynchronously. This means that, at the time a | |
| 717 $(ref:bluetoothLowEnergy.onServiceAdded) event is sent to the app, not all | |
| 718 characteristics of a service may have been discovered yet. Each time a | |
| 719 characteristic or a descriptor is added through discovery, the app will | |
| 720 receive the $(ref:bluetoothLowEnergy.onServiceChanged) event. This event will | |
| 721 also be sent if a notification is received from the remote device telling | |
| 722 Chrome that the service definition itself has changed: | |
| 723 </p> | |
| 724 | |
| 725 <pre> | |
| 726 chrome.bluetoothLowEnergy.onServiceChanged.addListener(function(service) { | |
| 727 if (service.instanceId != myService.instanceId) | |
| 728 return; | |
| 729 | |
| 730 // Get characteristics | |
| 731 chrome.bluetoothLowEnergy.getCharacteristics(service.instanceId, | |
| 732 function(result) { | |
| 733 ... | |
| 734 if (result.length == 0) { | |
| 735 console.log('Characteristics not discovered yet'); | |
| 736 return; | |
| 737 } | |
| 738 | |
| 739 for (var i = 0; i < result.length; i++) { | |
| 740 if (result[i].uuid == MY_CHARACTERISTIC_UUID) { | |
| 741 myChar = result[i]; | |
| 742 break; | |
| 743 } | |
| 744 | |
| 745 if (!myChar) { | |
| 746 console.log('The relevant characteristic not discovered yet.'); | |
| 747 return; | |
| 748 } | |
| 749 ... | |
| 750 } | |
| 751 }); | |
| 752 }); | |
| 753 </pre> | |
| 754 | |
| 755 <h3 id="gatt-read-write">Reading and writing a characteristic's value</h3> | |
| 756 | |
| 757 <p> | |
| 758 A GATT characteristic encodes one aspect of its service. A central app reads, | |
| 759 acts on, and modifies the state of a peripheral's service by operating on a | |
| 760 characteristic's value. The characteristic value is a sequence of bytes and | |
| 761 its meaning is defined by the high-level specification that defines a certain | |
| 762 characteristic. For example, the value of the <em>Heart Rate Measurement</em> | |
| 763 characteristic encodes the user's heart rate and the total amount of calories | |
| 764 they burned, while the <em>Body Sensor Location</em> characteristic encodes | |
| 765 where in the body the heart rate sensor should be worn. | |
| 766 </p> | |
| 767 | |
| 768 <p> | |
| 769 Chrome provides the $(ref:bluetoothLowEnergy.readCharacteristicValue) method | |
| 770 to read the value of a characteristic: | |
| 771 </p> | |
| 772 | |
| 773 <pre> | |
| 774 chrome.bluetoothLowEnergy.readCharacteristicValue(chrc.instanceId, | |
| 775 function(result) { | |
| 776 if (chrome.runtime.lastError) { | |
| 777 console.log('Failed to read value: ' + chrome.runtime.lastError.message); | |
| 778 return; | |
| 779 } | |
| 780 | |
| 781 var bytes = new Uint8Array(result.value); | |
| 782 | |
| 783 // Do stuff with the bytes. | |
| 784 ... | |
| 785 }); | |
| 786 </pre> | |
| 787 | |
| 788 <p> | |
| 789 Some characteristics are writable, especially those that behave as "Control | |
| 790 Points", where writing the value has side effects. For example, the <em>Heart | |
| 791 Rate Control Point</em> characteristic is used to tell a heart rate sensor to | |
| 792 reset its count of total calories burned and only supports writes. To achieve | |
| 793 this, Chrome provides the $(ref:bluetootLowEnergy.writeCharacteristicValue) | |
| 794 method: | |
| 795 </p> | |
| 796 | |
| 797 <pre> | |
| 798 var myBytes = new Uint8Array([ ... ]); | |
| 799 chrome.bluetoothLowEnergy.writeCharacteristicValue(chrc.instanceId, | |
| 800 myBytes.buffer, | |
| 801 function() { | |
| 802 if (chrome.runtime.lastError) { | |
| 803 console.log('Failed to write value: ' + | |
| 804 chrome.runtime.lastError.message); | |
| 805 return; | |
| 806 } | |
| 807 | |
| 808 // Value is written now. | |
| 809 }); | |
| 810 </pre> | |
| 811 | |
| 812 <p> | |
| 813 Characteristic descriptors behave the same way and can be readable and/or | |
| 814 writable. Chrome provides the $(ref:bluetoothLowEnergy.readDescriptorValue) | |
| 815 and $(ref:bluetoothLowEnergy.writeDescriptorValue) methods to read and write | |
| 816 the value of a descriptor. | |
| 817 </p> | |
| 818 | |
| 819 <p> | |
| 820 To check if a characteristic supports reads or writes, an application can | |
| 821 check the <code>properties</code> field of a | |
| 822 $(ref:bluetoothLowEnergy.Characteristic) object. While this field does not | |
| 823 contain information about the security requirements to access a value, it does | |
| 824 describe which value operation the characteristic supports in general. | |
| 825 </p> | |
| 826 | |
| 827 <h3 id="gatt-notifications">Handling value notifications</h3> | |
| 828 | |
| 829 <p> | |
| 830 Some characteristics make their value known using notifications or | |
| 831 indications. For example the <em>Heart Rate Measurement</em> characteristic is | |
| 832 neither readable nor writable but sends updates on its current value at | |
| 833 regular intervals. Applications can listen to these notifications using the | |
| 834 $(ref:bluetoothLowEnergy.onCharacteristicValueChanged) event. | |
| 835 </p> | |
| 836 | |
| 837 <pre> | |
| 838 chrome.bluetoothLowEnergy.onCharacteristicValueChanged.addListener( | |
| 839 function(chrc) { | |
| 840 if (chrc.instanceId != myCharId) | |
| 841 return; | |
| 842 | |
| 843 var bytes = new Uint8Array(chrc.value); | |
| 844 | |
| 845 // Do stuff with the bytes. | |
| 846 ... | |
| 847 }); | |
| 848 </pre> | |
| 849 | |
| 850 <p> | |
| 851 Even if a characteristic supports notifications/indications, they aren't | |
| 852 enabled by default. An application should call the | |
| 853 $(ref:bluetoothLowEnergy.startCharacteristicNotifications) and | |
| 854 $(ref:bluetoothLowEnergy.stopCharacteristicNotifications) methods to start or | |
| 855 stop receiving the $(ref:bluetoothLowEnergy.onCharacteristicValueChanged) | |
| 856 event. | |
| 857 </p> | |
| 858 | |
| 859 <pre> | |
| 860 // Start receiving characteristic value notifications. | |
| 861 var notifying = false; | |
| 862 chrome.bluetoothLowEnergy.startCharacteristicNotifications(chrc.instanceId, | |
| 863 function() { | |
| 864 if (chrome.runtime.lastError) { | |
| 865 console.log('Failed to enable notifications: ' + | |
| 866 chrome.runtime.lastError.message); | |
| 867 return; | |
| 868 } | |
| 869 | |
| 870 notifying = true; | |
| 871 }); | |
| 872 | |
| 873 ... | |
| 874 | |
| 875 // No longer interested in notifications from this characteristic. | |
| 876 if (notifying) { | |
| 877 chrome.bluetoothLowEnergy.stopCharacteristicNotifications( | |
| 878 chrc.instanceId); | |
| 879 } | |
| 880 </pre> | |
| 881 | |
| 882 <p> | |
| 883 Once notifications are started, the application will receive the | |
| 884 $(ref:bluetoothLowEnergy.onCharacteristicValueChanged) every time a | |
| 885 notification or indication is received from the characteristic. If the | |
| 886 characteristic supports reads, then this event will also be sent after a | |
| 887 successful call to $(ref:bluetoothLowEnergy.readCharacteristicValue). This | |
| 888 allows apps to unify the control flow of a value update triggered through a | |
| 889 read request and notifications: | |
| 890 </p> | |
| 891 | |
| 892 <pre> | |
| 893 chrome.bluetoothLowEnergy.onCharacteristicValueChanged.addListener( | |
| 894 function(chrc) { | |
| 895 // Process the value. | |
| 896 ... | |
| 897 }); | |
| 898 | |
| 899 chrome.bluetoothLowEnergy.startCharacteristicNotifications(chrc.instanceId, | |
| 900 function() { | |
| 901 // Notifications started. Read the initial value. | |
| 902 chrome.bluetoothLowEnergy.readCharacteristicValue(chrc.instanceId, | |
| 903 function(result) { | |
| 904 ... | |
| 905 // No need to do anything here since onCharacteristicValueChanged | |
| 906 // will handle it. | |
| 907 }); | |
| 908 }); | |
| 909 </pre> | |
| 910 | |
| 911 <p> | |
| 912 If a characteristic supports notifications, its <code>properties</code> field | |
| 913 will contain either the <code>"notify"</code> or <code>"indicate"</code> | |
| 914 property. | |
| 915 </p> | |
| 916 | |
| 917 <p> | |
| 918 <span style="font-weight: bold;">NOTE:</span> If a characteristic supports | |
| 919 notifications/indications, it will have the "Client Characteristic | |
| 920 Configuration" descriptor to enable/disable notifications. Chrome does not | |
| 921 permit apps to write to this descriptor. Apps should instead use the | |
| 922 $(ref:bluetoothLowEnergy.startCharacteristicNotifications) and | |
| 923 $(ref:bluetoothLowEnergy.stopCharacteristicNotifications) methods to control | |
| 924 notification behavior. | |
| 925 </p> | |
| OLD | NEW |