How To See Bluetooth Services And Characteristics
Communicating with Bluetooth devices over JavaScript
The Web Bluetooth API allows websites to communicate with Bluetooth devices.
— Updated
What if I told yous websites could communicate with nearby Bluetooth devices in a secure and privacy-preserving fashion? This style, center rate monitors, singing lightbulbs, and fifty-fifty turtles could interact directly with a website.
Until now, the ability to interact with Bluetooth devices has been possible only for platform-specific apps. The Web Bluetooth API aims to alter this and brings it to web browsers besides.
Before we start #
This article assumes you have some basic knowledge of how Bluetooth Low Energy (BLE) and the Generic Attribute Profile (GATT) piece of work.
Even though the Web Bluetooth API specification is not finalized however, the spec authors are actively looking for enthusiastic developers to try out this API and give feedback on the spec and feedback on the implementation.
A subset of the Web Bluetooth API is available in Chrome OS, Chrome for Android 6.0, Mac (Chrome 56) and Windows 10 (Chrome seventy). This ways you should be able to request and connect to nearby Bluetooth Depression Energy devices, read/write Bluetooth characteristics, receive GATT Notifications, know when a Bluetooth device gets disconnected, and fifty-fifty read and write to Bluetooth descriptors. See MDN's Browser compatibility table for more information.
For Linux and earlier versions of Windows, enable the #experimental-web-platform-features
flag in about://flags
.
Bachelor for origin trials #
In order to get as much feedback as possible from developers using the Spider web Bluetooth API in the field, Chrome has previously added this feature in Chrome 53 every bit an origin trial for Chrome OS, Android, and Mac.
The trial has successfully ended in Jan 2017.
Security requirements #
To understand the security tradeoffs, I recommend the Web Bluetooth Security Model mail from Jeffrey Yasskin, a software engineer on the Chrome team, working on the Web Bluetooth API specification.
HTTPS only #
Because this experimental API is a powerful new feature added to the web, it is fabricated available only to secure contexts. This ways you'll need to build with TLS in listen.
User gesture required #
As a security feature, discovering Bluetooth devices with navigator.bluetooth.requestDevice
must exist triggered by a user gesture such as a touch or a mouse click. We're talking almost listening to pointerup
, click
, and touchend
events.
button. addEventListener ( 'pointerup' , role ( effect ) {
// Phone call navigator.bluetooth.requestDevice
} ) ;
Get into the lawmaking #
The Web Bluetooth API relies heavily on JavaScript Promises. If you're not familiar with them, check out this neat Promises tutorial. One more than thing, () => {}
are merely ECMAScript 2015 Arrow functions.
Request Bluetooth devices #
This version of the Spider web Bluetooth API specification allows websites, running in the Fundamental function, to connect to remote GATT Servers over a BLE connection. It supports communication amidst devices that implement Bluetooth 4.0 or later.
When a website requests access to nearby devices using navigator.bluetooth.requestDevice
, the browser prompts user with a device chooser where they can pick one device or simply cancel the request.
The navigator.bluetooth.requestDevice()
function takes a mandatory object that defines filters. These filters are used to return only devices that match some advertised Bluetooth GATT services and/or the device name.
Services filter #
For instance, to asking Bluetooth devices ad the Bluetooth GATT Battery Service:
navigator.bluetooth. requestDevice ( { filters: [ { services: [ 'battery_service' ] } ] } )
. then ( device => { /* … */ } )
. catch ( error => { panel. mistake (error) ; } ) ;
If your Bluetooth GATT Service is non on the list of the standardized Bluetooth GATT services though, you may provide either the total Bluetooth UUID or a short 16- or 32-bit form.
navigator.bluetooth. requestDevice ( {
filters: [ {
services: [ 0x1234 , 0x12345678 , '99999999-0000-1000-8000-00805f9b34fb' ]
} ]
} )
. so ( device => { /* … */ } )
. take hold of ( mistake => { panel. error (error) ; } ) ;
Name filter #
You can also asking Bluetooth devices based on the device name being advertised with the name
filters fundamental, or even a prefix of this proper name with the namePrefix
filters primal. Note that in this case, y'all will also need to define the optionalServices
cardinal to be able to access whatsoever services not included in a service filter. If y'all don't, you'll become an error after when trying to admission them.
navigator.bluetooth. requestDevice ( {
filters: [ {
name: 'Francois robot'
} ] ,
optionalServices: [ 'battery_service' ] // Required to admission service subsequently.
} )
. and then ( device => { /* … */ } )
. grab ( error => { console. error (error) ; } ) ;
Manufacturer data filter #
Information technology is also possible to request Bluetooth devices based on the manufacturer specific data being advertised with the manufacturerData
filters key. This primal is an array of objects with a mandatory Bluetooth company identifier key named companyIdentifier
. You tin also provide a data prefix that filters manufacturer data from Bluetooth devices that start with it. Note that you volition likewise demand to define the optionalServices
fundamental to exist able to access whatsoever services non included in a service filter. If y'all don't, y'all'll become an error subsequently when trying to access them.
// Filter Bluetooth devices from Google company with manufacturer data bytes
// that starting time with [0x01, 0x02].
navigator.bluetooth. requestDevice ( {
filters: [ {
manufacturerData: [ {
companyIdentifier: 0x00e0 ,
dataPrefix: new Uint8Array ( [ 0x01 , 0x02 ] )
} ]
} ] ,
optionalServices: [ 'battery_service' ] // Required to access service afterwards.
} )
. then ( device => { /* … */ } )
. catch ( error => { console. error (error) ; } ) ;
A mask can too be used with a data prefix to match some patterns in manufacturer information. Check out the Bluetooth data filters explainer to learn more.
No filters #
Finally, instead of filters
yous can use the acceptAllDevices
central to evidence all nearby Bluetooth devices. You will likewise demand to define the optionalServices
cardinal to exist able to access some services. If y'all don't, y'all'll get an error later when trying to access them.
navigator.bluetooth. requestDevice ( {
acceptAllDevices: true ,
optionalServices: [ 'battery_service' ] // Required to admission service later.
} )
. then ( device => { /* … */ } )
. catch ( error => { console. error (error) ; } ) ;
Connect to a Bluetooth device #
So what practice you do now that yous have a BluetoothDevice
? Let'southward connect to the Bluetooth remote GATT Server which holds the service and characteristic definitions.
navigator.bluetooth. requestDevice ( { filters: [ { services: [ 'battery_service' ] } ] } )
. then ( device => {
// Human being-readable name of the device.
panel. log (device.name) ; // Attempts to connect to remote GATT Server.
return device.gatt. connect ( ) ;
} )
. and so ( server => { /* … */ } )
. catch ( mistake => { panel. error (error) ; } ) ;
Read a Bluetooth Feature #
Hither nosotros are connected to the GATT Server of the remote Bluetooth device. Now we want to go a Primary GATT Service and read a characteristic that belongs to this service. Let'due south try, for example, to read the current charge level of the device's battery.
In the case below, battery_level
is the standardized Battery Level Characteristic.
navigator.bluetooth. requestDevice ( { filters: [ { services: [ 'battery_service' ] } ] } )
. so ( device => device.gatt. connect ( ) )
. then ( server => {
// Getting Battery Service…
return server. getPrimaryService ( 'battery_service' ) ;
} )
. so ( service => {
// Getting Battery Level Characteristic…
return service. getCharacteristic ( 'battery_level' ) ;
} )
. then ( characteristic => {
// Reading Battery Level…
return characteristic. readValue ( ) ;
} )
. then ( value => {
console. log ( ` Battery percentage is ${value. getUint8 ( 0 ) } ` ) ;
} )
. grab ( fault => { console. error (fault) ; } ) ;
If y'all utilize a custom Bluetooth GATT characteristic, you may provide either the total Bluetooth UUID or a short 16- or 32-bit form to service.getCharacteristic
.
Note that you tin also add a characteristicvaluechanged
event listener on a characteristic to handle reading its value. Check out the Read Characteristic Value Changed Sample to see how to optionally handle upcoming GATT notifications as well.
…
. and so ( characteristic => {
// Ready event listener for when characteristic value changes.
feature. addEventListener ( 'characteristicvaluechanged' ,
handleBatteryLevelChanged) ;
// Reading Battery Level…
return characteristic. readValue ( ) ;
} )
. catch ( error => { console. fault (mistake) ; } ) ; function handleBatteryLevelChanged ( issue ) {
const batteryLevel = effect.target.value. getUint8 ( 0 ) ;
panel. log ( 'Battery percentage is ' + batteryLevel) ;
}
Write to a Bluetooth Characteristic #
Writing to a Bluetooth GATT Characteristic is as easy every bit reading it. This fourth dimension, let'south use the Heart Rate Command Signal to reset the value of the Free energy Expended field to 0 on a heart rate monitor device.
I promise in that location is no magic here. It's all explained in the Middle Rate Control Point Characteristic folio.
navigator.bluetooth. requestDevice ( { filters: [ { services: [ 'heart_rate' ] } ] } )
. and then ( device => device.gatt. connect ( ) )
. so ( server => server. getPrimaryService ( 'heart_rate' ) )
. and then ( service => service. getCharacteristic ( 'heart_rate_control_point' ) )
. then ( characteristic => {
// Writing ane is the signal to reset energy expended.
const resetEnergyExpended = Uint8Array. of ( 1 ) ;
return feature. writeValue (resetEnergyExpended) ;
} )
. so ( _ => {
console. log ( 'Free energy expended has been reset.' ) ;
} )
. grab ( error => { console. fault (error) ; } ) ;
Receive GATT notifications #
Now, let'due south see how to exist notified when the Heart Rate Measurement characteristic changes on the device:
navigator.bluetooth. requestDevice ( { filters: [ { services: [ 'heart_rate' ] } ] } )
. and so ( device => device.gatt. connect ( ) )
. then ( server => server. getPrimaryService ( 'heart_rate' ) )
. then ( service => service. getCharacteristic ( 'heart_rate_measurement' ) )
. then ( characteristic => characteristic. startNotifications ( ) )
. so ( characteristic => {
characteristic. addEventListener ( 'characteristicvaluechanged' ,
handleCharacteristicValueChanged) ;
console. log ( 'Notifications accept been started.' ) ;
} )
. take hold of ( error => { console. fault (error) ; } ) ; role handleCharacteristicValueChanged ( result ) {
const value = issue.target.value;
console. log ( 'Received ' + value) ;
// TODO: Parse Heart Charge per unit Measurement value.
// See https://github.com/WebBluetoothCG/demos/blob/gh-pages/heart-rate-sensor/heartRateSensor.js
}
The Notifications Sample shows yous to how to stop notifications with stopNotifications()
and properly remove the added characteristicvaluechanged
event listener.
Disconnect from a Bluetooth Device #
To provide a better user experience, you may desire to listen for disconnection events and invite the user to reconnect:
navigator.bluetooth. requestDevice ( { filters: [ { name: 'Francois robot' } ] } )
. so ( device => {
// Prepare event listener for when device gets disconnected.
device. addEventListener ( 'gattserverdisconnected' , onDisconnected) ; // Attempts to connect to remote GATT Server.
return device.gatt. connect ( ) ;
} )
. then ( server => { /* … */ } )
. catch ( mistake => { console. error (error) ; } ) ;
function onDisconnected ( upshot ) {
const device = event.target;
panel. log ( ` Device ${device.name} is asunder. ` ) ;
}
You can also call device.gatt.disconnect()
to disconnect your web app from the Bluetooth device. This volition trigger existing gattserverdisconnected
result listeners. Note that it will Not cease bluetooth device communication if some other app is already communicating with the Bluetooth device. Check out the Device Disconnect Sample and the Automatic Reconnect Sample to swoop deeper.
Read and write to Bluetooth descriptors #
Bluetooth GATT descriptors are attributes that describe a characteristic value. You can read and write them to in a similar style to Bluetooth GATT characteristics.
Let's run into for example how to read the user clarification of the measurement interval of the device'south health thermometer.
In the case below, health_thermometer
is the Health Thermometer service, measurement_interval
the Measurement Interval characteristic, and gatt.characteristic_user_description
the Characteristic User Description descriptor.
navigator.bluetooth. requestDevice ( { filters: [ { services: [ 'health_thermometer' ] } ] } )
. so ( device => device.gatt. connect ( ) )
. so ( server => server. getPrimaryService ( 'health_thermometer' ) )
. then ( service => service. getCharacteristic ( 'measurement_interval' ) )
. then ( characteristic => characteristic. getDescriptor ( 'gatt.characteristic_user_description' ) )
. and then ( descriptor => descriptor. readValue ( ) )
. so ( value => {
const decoder = new TextDecoder ( 'utf-8' ) ;
console. log ( ` User Description: ${decoder. decode (value) } ` ) ;
} )
. grab ( error => { console. error (fault) ; } ) ;
Now that we've read the user description of the measurement interval of the device's health thermometer, permit's see how to update information technology and write a custom value.
navigator.bluetooth. requestDevice ( { filters: [ { services: [ 'health_thermometer' ] } ] } )
. and so ( device => device.gatt. connect ( ) )
. and then ( server => server. getPrimaryService ( 'health_thermometer' ) )
. and so ( service => service. getCharacteristic ( 'measurement_interval' ) )
. then ( characteristic => characteristic. getDescriptor ( 'gatt.characteristic_user_description' ) )
. and then ( descriptor => {
const encoder = new TextEncoder ( 'utf-8' ) ;
const userDescription = encoder. encode ( 'Defines the fourth dimension between measurements.' ) ;
render descriptor. writeValue (userDescription) ;
} )
. grab ( error => { console. error (error) ; } ) ;
Samples, demos and codelabs #
All Spider web Bluetooth samples beneath take been successfully tested. To enjoy these samples to their fullest, I recommend you install the BLE Peripheral Simulator Android App which simulates a BLE peripheral with a Battery Service, a Heart Charge per unit Service, or a Health Thermometer Service.
Beginner #
- Device Info - retrieve basic device data from a BLE Device.
- Bombardment Level - retrieve battery information from a BLE Device advertising Bombardment information.
- Reset Energy - reset energy expended from a BLE Device advertising Heart Rate.
- Characteristic Properties - display all properties of a specific characteristic from a BLE Device.
- Notifications - starting time and cease characteristic notifications from a BLE Device.
- Device Disconnect - disconnect and get notified from a disconnection of a BLE Device after connecting to it.
- Get Characteristics - get all characteristics of an advertised service from a BLE Device.
- Go Descriptors - get all characteristics' descriptors of an advertised service from a BLE Device.
- Manufacturer Information Filter - think basic device information from a BLE Device that matches manufacturer data.
Combining multiple operations #
- GAP Characteristics - go all GAP characteristics of a BLE Device.
- Device Information Characteristics - get all Device Information characteristics of a BLE Device.
- Link Loss - prepare the Alert Level characteristic of a BLE Device (readValue & writeValue).
- Discover Services & Characteristics - discover all attainable primary services and their characteristics from a BLE Device.
- Automatic Reconnect - reconnect to a disconnected BLE device using an exponential backoff algorithm.
- Read Feature Value Changed - read battery level and be notified of changes from a BLE Device.
- Read Descriptors - read all characteristic's descriptors of a service from a BLE Device.
- Write Descriptor - write to the descriptor "Characteristic User Description" on a BLE Device.
Bank check out our curated Web Bluetooth Demos and official Spider web Bluetooth Codelabs every bit well.
Libraries #
- spider web-bluetooth-utils is a npm module that adds some convenience functions to the API.
- A Web Bluetooth API shim is available in noble, the most popular Node.js BLE central module. This allows you to webpack/browserify noble without the demand for a WebSocket server or other plugins.
- angular-web-bluetooth is a module for Athwart that abstracts away all the average needed to configure the Web Bluetooth API.
- Get Started with Spider web Bluetooth is a unproblematic Web App that will generate all the JavaScript boilerplate code to offset interacting with a Bluetooth device. Enter a device name, a service, a characteristic, define its properties and y'all're skilful to go.
- If you're already a Bluetooth developer, the Web Bluetooth Developer Studio Plugin will also generate the Spider web Bluetooth JavaScript code for your Bluetooth device.
Tips #
A Bluetooth Internals page is bachelor in Chrome at nearly://bluetooth-internals
then that yous can inspect everything about nearby Bluetooth devices: status, services, characteristics, and descriptors.

I also recommend checking out the official How to file Spider web Bluetooth bugs page as debugging Bluetooth tin can be hard sometimes.
What'due south next #
Check the browser and platform implementation status beginning to know which parts of the Web Bluetooth API are currently beingness implemented.
Though it's all the same incomplete, hither'southward a sneak peek of what to look in the virtually hereafter:
- Scanning for nearby BLE advertisements will happen with
navigator.bluetooth.requestLEScan()
. - A new
serviceadded
event will rail newly discovered Bluetooth GATT Services whileserviceremoved
consequence volition track removed ones. A newservicechanged
effect will burn when any feature and/or descriptor gets added or removed from a Bluetooth GATT Service.
Evidence support for the API #
Are y'all planning to use the Web Bluetooth API? Your public support helps the Chrome squad prioritize features and shows other browser vendors how disquisitional it is to support them.
Send a tweet to @ChromiumDev using the hashtag #WebBluetooth
and allow u.s.a. know where and how you lot are using it.
Resources #
- Stack Overflow: https://stackoverflow.com/questions/tagged/web-bluetooth
- Chrome Characteristic Status: https://world wide web.chromestatus.com/feature/5264933985976320
- Chrome Implementation Bugs: https://crbug.com/?q=component:Glimmer>Bluetooth
- Web Bluetooth Spec: https://webbluetoothcg.github.io/web-bluetooth
- Spec Bug: https://github.com/WebBluetoothCG/web-bluetooth/problems
- BLE Peripheral Simulator App: https://github.com/WebBluetoothCG/ble-test-peripheral-android
Acknowledgements #
Thank you to Kayce Basques for reviewing this commodity. Hero image by SparkFun Electronics from Boulder, Us.
Terminal updated: — Improve article
Return to all articles
Source: https://web.dev/bluetooth/
Posted by: cameronlacent.blogspot.com
0 Response to "How To See Bluetooth Services And Characteristics"
Post a Comment