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 |
| 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> |
| 521 |
| 522 <h3 id="le-discovery">Discovering and connecting to peripherals</h3> |
| 523 |
| 524 <p> |
| 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> |
| 534 |
| 535 <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> |
| 540 |
| 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; |
| 546 |
| 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; |
| 552 } |
| 553 |
| 554 // Connected! Do stuff... |
| 555 ... |
| 556 }); |
| 557 }); |
| 558 </pre> |
| 559 |
| 560 <p> |
| 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> |
| 571 |
| 572 <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> |
| 576 |
| 577 <pre> |
| 578 chrome.bluetoothLowEnergy.disconnect(deviceAddress); |
| 579 </pre> |
| 580 |
| 581 <p> |
| 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> |
| 590 |
| 591 <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> |
| 599 |
| 600 <h3 id="gatt">Services, Characteristics, and Descriptors</h3> |
| 601 |
| 602 <p> |
| 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> |
| 609 |
| 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> |
| 634 |
| 635 <p> |
| 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> |
| 644 |
| 645 <pre> |
| 646 chrome.bluetoothLowEnergy.getServices(deviceAddress, function(services) { |
| 647 ... |
| 648 for (var i = 0; i < services.length; i++) { |
| 649 if (services[i].uuid == HEART_RATE_SERVICE_UUID) { |
| 650 heartRateService = services[i]; |
| 651 break; |
| 652 } |
| 653 } |
| 654 ... |
| 655 }); |
| 656 </pre> |
| 657 |
| 658 <p> |
| 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> |
| 664 |
| 665 <pre> |
| 666 chrome.bluetoothLowEnergy.getCharacteristics(heartRateService.instanceId, |
| 667 function(chracteristics) { |
| 668 ... |
| 669 for (var i = 0; i < characteristics.length; i++) { |
| 670 if (characteristics[i].uuid == HEART_RATE_MEASUREMENT_UUID) { |
| 671 measurementChar = characteristics[i]; |
| 672 break; |
| 673 } |
| 674 } |
| 675 ... |
| 676 chrome.bluetoothLowEnergy.getDescriptors(measurementChar.instanceId, |
| 677 function(descriptors) { |
| 678 ... |
| 679 }); |
| 680 }); |
| 681 </pre> |
| 682 |
| 683 <h3 id="service-events">Service events</h3> |
| 684 |
| 685 <p> |
| 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> |
| 691 |
| 692 <pre> |
| 693 var initializeService = function(service) { |
| 694 if (!service) { |
| 695 console.log('No service selected!'); |
| 696 // Reset UI, etc. |
| 697 ... |
| 698 return; |
| 699 } |
| 700 |
| 701 myService = service; |
| 702 |
| 703 // Get all the characteristics and descriptors and bootstrap the app. |
| 704 ... |
| 705 }; |
| 706 |
| 707 chrome.bluetoothLowEnergy.onServiceAdded.addListener(function(service) { |
| 708 if (service.uuid == MY_SERVICE_UUID) |
| 709 initializeService(service); |
| 710 }); |
| 711 |
| 712 chrome.bluetoothLowEnergy.onServiceRemoved.addListener(function(service) { |
| 713 if (service.instanceId == myService.instanceId) |
| 714 initializeService(null); |
| 715 }); |
| 716 </pre> |
| 717 |
| 718 <p> |
| 719 Chrome discovers all characteristics and descriptors of a service |
| 720 asynchronously. This means that, at the time a |
| 721 $(ref:bluetoothLowEnergy.onServiceAdded) event is sent to the app, not all |
| 722 characteristics of a service may have been discovered yet. Each time a |
| 723 characteristic or a descriptor is added through discovery, the app will |
| 724 receive the $(ref:bluetoothLowEnergy.onServiceChanged) event. This event will |
| 725 also be sent if a notification is received from the remote device telling |
| 726 Chrome that the service definition itself has changed: |
| 727 </p> |
| 728 |
| 729 <pre> |
| 730 chrome.bluetoothLowEnergy.onServiceChanged.addListener(function(service) { |
| 731 if (service.instanceId != myService.instanceId) |
| 732 return; |
| 733 |
| 734 // Get characteristics |
| 735 chrome.bluetoothLowEnergy.getCharacteristics(service.instanceId, |
| 736 function(result) { |
| 737 ... |
| 738 if (result.length == 0) { |
| 739 console.log('Characteristics not discovered yet'); |
| 740 return; |
| 741 } |
| 742 |
| 743 for (var i = 0; i < result.length; i++) { |
| 744 if (result[i].uuid == MY_CHARACTERISTIC_UUID) { |
| 745 myChar = result[i]; |
| 746 break; |
| 747 } |
| 748 |
| 749 if (!myChar) { |
| 750 console.log('The relevant characteristic not discovered yet.'); |
| 751 return; |
| 752 } |
| 753 ... |
| 754 } |
| 755 }); |
| 756 }); |
| 757 </pre> |
| 758 |
| 759 <h3 id="gatt-read-write">Reading and writing a characteristic's value</h3> |
| 760 |
| 761 <p> |
| 762 A GATT characteristic encodes one aspect of its service. A central app reads, |
| 763 acts on, and modifies the state of a peripheral's service by operating on a |
| 764 characteristic's value. The characteristic value is a sequence of bytes and |
| 765 its meaning is defined by the high-level specification that defines a certain |
| 766 characteristic. For example, the value of the <em>Heart Rate Measurement</em> |
| 767 characteristic encodes the user's heart rate and the total amount of calories |
| 768 they burned, while the <em>Body Sensor Location</em> characteristic encodes |
| 769 where in the body the heart rate sensor should be worn. |
| 770 </p> |
| 771 |
| 772 <p> |
| 773 Chrome provides the $(ref:bluetoothLowEnergy.readCharacteristicValue) method |
| 774 to read the value of a characteristic: |
| 775 </p> |
| 776 |
| 777 <pre> |
| 778 chrome.bluetoothLowEnergy.readCharacteristicValue(chrc.instanceId, |
| 779 function(result) { |
| 780 if (chrome.runtime.lastError) { |
| 781 console.log('Failed to read value: ' + chrome.runtime.lastError.message); |
| 782 return; |
| 783 } |
| 784 |
| 785 var bytes = new Uint8Array(result.value); |
| 786 |
| 787 // Do stuff with the bytes. |
| 788 ... |
| 789 }); |
| 790 </pre> |
| 791 |
| 792 <p> |
| 793 Some characteristics are writable, especially those that behave as "Control |
| 794 Points", where writing the value has side effects. For example, the <em>Heart |
| 795 Rate Control Point</em> characteristic is used to tell a heart rate sensor to |
| 796 reset its count of total calories burned and only supports writes. To achieve |
| 797 this, Chrome provides the $(ref:bluetootLowEnergy.writeCharacteristicValue) |
| 798 method: |
| 799 </p> |
| 800 |
| 801 <pre> |
| 802 var myBytes = new Uint8Array([ ... ]); |
| 803 chrome.bluetoothLowEnergy.writeCharacteristicValue(chrc.instanceId, |
| 804 myBytes.buffer, |
| 805 function() { |
| 806 if (chrome.runtime.lastError) { |
| 807 console.log('Failed to write value: ' + |
| 808 chrome.runtime.lastError.message); |
| 809 return; |
| 810 } |
| 811 |
| 812 // Value is written now. |
| 813 }); |
| 814 </pre> |
| 815 |
| 816 <p> |
| 817 Characteristic descriptors behave the same way and can be readable and/or |
| 818 writable. Chrome provides the $(ref:bluetoothLowEnergy.readDescriptorValue) |
| 819 and $(ref:bluetoothLowEnergy.writeDescriptorValue) methods to read and write |
| 820 the value of a descriptor. |
| 821 </p> |
| 822 |
| 823 <p> |
| 824 To check if a characteristic supports reads or writes, an application can |
| 825 check the <code>properties</code> field of a |
| 826 $(ref:bluetoothLowEnergy.Characteristic) object. While this field does not |
| 827 contain information about the security requirements to access a value, it does |
| 828 describe which value operation the characteristic supports in general. |
| 829 </p> |
| 830 |
| 831 <h3 id="gatt-notifications">Handling value notifications</h3> |
| 832 |
| 833 <p> |
| 834 Some characteristics make their value known using notifications or |
| 835 indications. For example the <em>Heart Rate Measurement</em> characteristic is |
| 836 neither readable nor writable but sends updates on its current value at |
| 837 regular intervals. Applications can listen to these notifications using the |
| 838 $(ref:bluetoothLowEnergy.onCharacteristicValueChanged) event. |
| 839 </p> |
| 840 |
| 841 <pre> |
| 842 chrome.bluetoothLowEnergy.onCharacteristicValueChanged.addListener( |
| 843 function(chrc) { |
| 844 if (chrc.instanceId != myCharId) |
| 845 return; |
| 846 |
| 847 var bytes = new Uint8Array(chrc.value); |
| 848 |
| 849 // Do stuff with the bytes. |
| 850 ... |
| 851 }); |
| 852 </pre> |
| 853 |
| 854 <p> |
| 855 Even if a characteristic supports notifications/indications, they aren't |
| 856 enabled by default. An application should call the |
| 857 $(ref:bluetoothLowEnergy.startCharacteristicNotifications) and |
| 858 $(ref:bluetoothLowEnergy.stopCharacteristicNotifications) methods to start or |
| 859 stop receiving the $(ref:bluetoothLowEnergy.onCharacteristicValueChanged) |
| 860 event. |
| 861 </p> |
| 862 |
| 863 <pre> |
| 864 // Start receiving characteristic value notifications. |
| 865 var notifying = false; |
| 866 chrome.bluetoothLowEnergy.startCharacteristicNotifications(chrc.instanceId, |
| 867 function() { |
| 868 if (chrome.runtime.lastError) { |
| 869 console.log('Failed to enable notifications: ' + |
| 870 chrome.runtime.lastError.message); |
| 871 return; |
| 872 } |
| 873 |
| 874 notifying = true; |
| 875 }); |
| 876 |
| 877 ... |
| 878 |
| 879 // No longer interested in notifications from this characteristic. |
| 880 if (notifying) { |
| 881 chrome.bluetoothLowEnergy.stopCharacteristicNotifications( |
| 882 chrc.instanceId); |
| 883 } |
| 884 </pre> |
| 885 |
| 886 <p> |
| 887 Once notifications are started, the application will receive the |
| 888 $(ref:bluetoothLowEnergy.onCharacteristicValueChanged) every time a |
| 889 notification or indication is received from the characteristic. If the |
| 890 characteristic supports reads, then this event will also be sent after a |
| 891 successful call to $(ref:bluetoothLowEnergy.readCharacteristicValue). This |
| 892 allows apps to unify the control flow of a value update triggered through a |
| 893 read request and notifications: |
| 894 </p> |
| 895 |
| 896 <pre> |
| 897 chrome.bluetoothLowEnergy.onCharacteristicValueChanged.addListener( |
| 898 function(chrc) { |
| 899 // Process the value. |
| 900 ... |
| 901 }); |
| 902 |
| 903 chrome.bluetoothLowEnergy.startCharacteristicNotifications(chrc.instanceId, |
| 904 function() { |
| 905 // Notifications started. Read the initial value. |
| 906 chrome.bluetoothLowEnergy.readCharacteristicValue(chrc.instanceId, |
| 907 function(result) { |
| 908 ... |
| 909 // No need to do anything here since onCharacteristicValueChanged |
| 910 // will handle it. |
| 911 }); |
| 912 }); |
| 913 </pre> |
| 914 |
| 915 <p> |
| 916 If a characteristic supports notifications, its <code>properties</code> field |
| 917 will contain either the <code>"notify"</code> or <code>"indicate"</code> |
| 918 property. |
| 919 </p> |
| 920 |
| 921 <p> |
| 922 <span style="font-weight: bold;">NOTE:</span> If a characteristic supports |
| 923 notifications/indications, it will have the "Client Characteristic |
| 924 Configuration" descriptor to enable/disable notifications. Chrome does not |
| 925 permit apps to write to this descriptor. Apps should instead use the |
| 926 $(ref:bluetoothLowEnergy.startCharacteristicNotifications) and |
| 927 $(ref:bluetoothLowEnergy.stopCharacteristicNotifications) methods to control |
| 928 notification behavior. |
| 929 </p> |
OLD | NEW |