API Web Bluetooth позволяет веб-сайтам взаимодействовать с устройствами Bluetooth.
Что, если бы я сказал вам, что веб-сайты могут безопасно и с сохранением конфиденциальности взаимодействовать с находящимися поблизости устройствами Bluetooth? Таким образом, пульсометры, поющие лампочки и даже черепахи смогут напрямую взаимодействовать с веб-сайтом.
До сих пор возможность взаимодействия с устройствами Bluetooth была возможна только для приложений, специфичных для конкретной платформы. API Web Bluetooth призван изменить эту ситуацию и перенести его и в веб-браузеры.
Прежде чем мы начнем
В этом документе предполагается, что у вас есть базовые знания о том, как работают Bluetooth Low Energy (BLE) и общий профиль атрибутов .
Несмотря на то, что спецификация Web Bluetooth API еще не доработана, авторы спецификации активно ищут разработчиков-энтузиастов, которые могли бы опробовать этот API и оставить отзыв о спецификации и отзывах о реализации .
Подмножество Web Bluetooth API доступно в ChromeOS, Chrome для Android 6.0, Mac (Chrome 56) и Windows 10 (Chrome 70). Это означает, что вы должны иметь возможность запрашивать и подключаться к ближайшим устройствам Bluetooth Low Energy, считывать / записывать характерис��ики Bluetooth, получать уведомления GATT , знать, когда устройство Bluetooth отключается , и даже читать и записывать дескрипторы Bluetooth . Дополнительную информацию см. в таблице совместимости браузеров MDN.
Для Linux и более ранних версий Windows включите флаг #experimental-web-platform-features
в about://flags
.
Доступно для исходных пробных версий
Чтобы получить как можно больше отзывов от разработчиков, использующих Web Bluetooth API на местах, Chrome ранее добавил эту функцию в Chrome 53 в качестве исходной пробной версии для ChromeOS, Android и Mac.
Судебный процесс успешно завершился в январе 2017 года.
Требования безопасности
Чтобы понять компромиссы в области безопасности, я рекомендую статью о модели безопасности Web Bluetooth от Джеффри Яскина, инженера-программиста из команды Chrome, ��а��отаю��е��о над спецификацией API Web Bluetooth.
только HTTPS
Поскольку этот экспериментальный API представляет собой новую мощную функцию, добавленную в Интернет, он доступен только для защищенных контекстов . Это означает, что вам нужно будет строить с учетом TLS .
Требуется жест пользователя
В целях безопасности обнаружение устройств Bluetooth с помощью navigator.bluetooth.requestDevice
должно запускаться жестом пользователя , например прикосновением или щелчком мыши. Мы говорим о прослушивании событий pointerup
, click
и touchend
.
button.addEventListener('pointerup', function(event) {
// Call navigator.bluetooth.requestDevice
});
Вникнуть в код
API Web Bluetooth в значительной степени опирается на обещания JavaScript. Если вы с ними не знакомы, ознакомьтесь с этим замечательным руководством по Promises . Еще одна вещь: () => {}
— это стрелочные функции ECMAScript 2015.
Запросить устройства Bluetooth
Эта версия спецификации Web Bluetooth API позволяет веб-сайтам, работающим в центральной роли, подключаться к удаленным серверам GATT через соединение BLE. Он поддерживает связь между устройствами, поддерживающими Bluetooth 4.0 или более поздней версии.
Когда веб-сайт запрашивает доступ к близлежащим устройствам с помощью navigator.bluetooth.requestDevice
, браузер предлагает пользователю выбрать устройство, где он может выбрать одно устройство или отменить ��апрос.
Функция navigator.bluetooth.requestDevice()
принимает обязательный объект, определяющий фильтры. Эти фильтры используются для возврата только устройств, которые соответствуют некоторым рекламируемым службам Bluetooth GATT и/или имени устройства.
Фильтр услуг
Например, чтобы запросить устройства Bluetooth, рекламирующие службу аккумуляторов Bluetooth GATT :
navigator.bluetooth.requestDevice({ filters: [{ services: ['battery_service'] }] })
.then(device => { /* … */ })
.catch(error => { console.error(error); });
Если вашей службы Bluetooth GATT нет в списке стандартизированных служб Bluetooth GATT , вы можете предоставить либо полный UUID Bluetooth, либо короткую 16- или 32-битную форму.
navigator.bluetooth.requestDevice({
filters: [{
services: [0x1234, 0x12345678, '99999999-0000-1000-8000-00805f9b34fb']
}]
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });
Фильтр имен
Вы также можете запросить устройства Bluetooth на основе имени устройства, рекламируемого с помощью ключа фильтров name
, или даже префикса этого имени с помощью ключа фильтров namePrefix
. Обратите внимание, что в этом случае вам также необходимо будет определить ключ optionalServices
, чтобы иметь возможность доступа к любым службам, не включенным в фильтр служб. Если вы этого не сделаете, позже при попытке доступа к ним вы получите сообщение об ошибке.
navigator.bluetooth.requestDevice({
filters: [{
name: 'Francois robot'
}],
optionalServices: ['battery_service'] // Required to access service later.
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });
Фильтр данных производителя
Также можно запросить устройства Bluetooth на основе конкретных данных производителя, которые объявляются с помощью ключа фильтров manufacturerData
. Этот ключ представляет собой массив объектов с обязательным ключом идентификатора компании Bluetooth с именем companyIdentifier
. Вы также можете указать префикс данных, который фильтрует данные производителя с устройств Bluetooth, которые начинаются с него. Обратите внимание, что вам также потребуется определить ключ optionalServices
, чтобы иметь возможность доступа к любым службам, не включенным в фильтр служб. Если вы этого не сделаете, позже при попытке доступа к ним вы получите сообщение об ошибке.
// Filter Bluetooth devices from Google company with manufacturer data bytes
// that start with [0x01, 0x02].
navigator.bluetooth.requestDevice({
filters: [{
manufacturerData: [{
companyIdentifier: 0x00e0,
dataPrefix: new Uint8Array([0x01, 0x02])
}]
}],
optionalServices: ['battery_service'] // Required to access service later.
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });
Маску также можно использовать с префиксом данных для соответствия некоторым шаблонам в данных производителя. Чтобы узнать больше, ознакомьтесь с объяснением фильтров данных Bluetooth .
Фильтры исключения
Параметр exclusionFilters
в navigator.bluetooth.requestDevice()
позволяет исключить некоторые устройства из средства выбора браузера. Его можно использовать для исключения устройств, соответствующих более широкому фильтру, но не поддерживаемых.
// Request access to a bluetooth device whose name starts with "Created by".
// The device named "Created by Francois" has been reported as unsupported.
navigator.bluetooth.requestDevice({
filters: [{
namePrefix: "Created by"
}],
exclusionFilters: [{
name: "Created by Francois"
}],
optionalServices: ['battery_service'] // Required to access service later.
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });
Без фильтров
Наконец, вместо filters
вы можете использовать клавишу acceptAllDevices
, чтобы отобразить все ближайшие устройства Bluetooth. Вам также потребуется определить ключ optionalServices
, чтобы иметь доступ к некоторым сервисам. Если вы этого не сделаете, позже при попытке доступа к ним вы получите сообщение об ошибке.
navigator.bluetooth.requestDevice({
acceptAllDevices: true,
optionalServices: ['battery_service'] // Required to access service later.
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });
Подключитесь к устройству Bluetooth
Итак, что же делать теперь, когда у вас есть BluetoothDevice
? Давайте подключимся к удаленному серверу GATT Bluetooth, который содержит определения служб и характеристик.
navigator.bluetooth.requestDevice({ filters: [{ services: ['battery_service'] }] })
.then(device => {
// Human-readable name of the device.
console.log(device.name);
// Attempts to connect to remote GATT Server.
return device.gatt.connect();
})
.then(server => { /* … */ })
.catch(error => { console.error(error); });
Чтение характеристики Bluetooth
Здесь мы подключаемся к GATT-серверу удаленного устройства Bluetooth. Теперь мы хотим по��уч��ть ��е��в��чн��ю услугу GATT и прочитать характеристику, принадлежащую этой службе. Попробуем, например, прочитать текущий уровень заряда аккумулятора устройства.
В приведенном ниже примере battery_level
— это стандартизированная характеристика уровня заряда батареи .
navigator.bluetooth.requestDevice({ filters: [{ services: ['battery_service'] }] })
.then(device => device.gatt.connect())
.then(server => {
// Getting Battery Service…
return server.getPrimaryService('battery_service');
})
.then(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)}`);
})
.catch(error => { console.error(error); });
Если вы используете пользовательскую характеристику Bluetooth GATT, вы можете предоставить для service.getCharacteristic
либо полный UUID Bluetooth, либо короткую 16- или 32-битную форму.
Обратите внимание, что вы также можете добавить прослушиватель событий characteristicvaluechanged
» для характеристики, чтобы обрабатывать чтение ее значения. Ознакомьтесь с примером чтения измененного значения характеристики , чтобы узнать, как дополнительно обрабатывать предстоящие уведомления GATT.
…
.then(characteristic => {
// Set up event listener for when characteristic value changes.
characteristic.addEventListener('characteristicvaluechanged',
handleBatteryLevelChanged);
// Reading Battery Level…
return characteristic.readValue();
})
.catch(error => { console.error(error); });
function handleBatteryLevelChanged(event) {
const batteryLevel = event.target.value.getUint8(0);
console.log('Battery percentage is ' + batteryLevel);
}
Запись в характеристику Bluetooth
Записать характеристику Bluetooth GATT так же просто, как и прочитать ее. На этот раз давайте воспользуемся точкой контроля сердечного ритма, чтобы сбросить значение поля «Затраченная энергия» на 0 на устройстве мониторинга сердечного ритма.
Обещаю, здесь нет никакой магии. Все это объясняется на странице «Характеристика контрольной точки сердечного ритма» .
navigator.bluetooth.requestDevice({ filters: [{ services: ['heart_rate'] }] })
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService('heart_rate'))
.then(service => service.getCharacteristic('heart_rate_control_point'))
.then(characteristic => {
// Writing 1 is the signal to reset energy expended.
const resetEnergyExpended = Uint8Array.of(1);
return characteristic.writeValue(resetEnergyExpended);
})
.then(_ => {
console.log('Energy expended has been reset.');
})
.catch(error => { console.error(error); });
Получать уведомления ГАТТ
Теперь давайте посмотрим, как получать уведомления об изменении характеристики измерения сердечного ритма на устройстве:
navigator.bluetooth.requestDevice({ filters: [{ services: ['heart_rate'] }] })
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService('heart_rate'))
.then(service => service.getCharacteristic('heart_rate_measurement'))
.then(characteristic => characteristic.startNotifications())
.then(characteristic => {
characteristic.addEventListener('characteristicvaluechanged',
handleCharacteristicValueChanged);
console.log('Notifications have been started.');
})
.catch(error => { console.error(error); });
function handleCharacteristicValueChanged(event) {
const value = event.target.value;
console.log('Received ' + value);
// TODO: Parse Heart Rate Measurement value.
// See https://github.com/WebBluetoothCG/demos/blob/gh-pages/heart-rate-sensor/heartRateSensor.js
}
В примере уведомлений показано, как остановить уведомления с помощью stopNotifications()
и правильно удалить добавленный прослушиватель событий characteristicvaluechanged
.
Отключиться от устройства Bluetooth
Чтобы обеспечить лучшее взаимодействие с пользователем, вы можете прослушивать события отключения и предлагать пользователю повторно подключиться:
navigator.bluetooth.requestDevice({ filters: [{ name: 'Francois robot' }] })
.then(device => {
// Set up 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(error => { console.error(error); });
function onDisconnected(event) {
const device = event.target;
console.log(`Device ${device.name} is disconnected.`);
}
Вы также можете вызвать device.gatt.disconnect()
, чтобы отключить веб-приложение от устройства Bluetooth. Это запустит существующие прослушиватели событий gattserverdisconnected
. Обратите внимание, что связь с устройством Bluetooth НЕ прекратится, если другое приложение уже обменивается данными с устройством Bluetooth. Чтобы узнать больше, ознакомьтесь с примером отключения устройства и примером автоматического повторного подключения .
Чтение и запись в дескрипторы Bluetooth
Дескрипторы Bluetooth GATT — это атрибуты, описывающие характеристическое значение. Вы можете читать и записывать их аналогично характеристикам Bluetooth GATT.
Давайте посмотрим, например, как прочитать пользовательское описание интервала измерения термометра здоровья устройства.
В приведенном ниже примере health_thermometer
— это сервис Health Thermometer , measurement_interval
характеристика интервала измерения , а gatt.characteristic_user_description
дескриптор описания характеристики пользователя .
navigator.bluetooth.requestDevice({ filters: [{ services: ['health_thermometer'] }] })
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService('health_thermometer'))
.then(service => service.getCharacteristic('measurement_interval'))
.then(characteristic => characteristic.getDescriptor('gatt.characteristic_user_description'))
.then(descriptor => descriptor.readValue())
.then(value => {
const decoder = new TextDecoder('utf-8');
console.log(`User Description: ${decoder.decode(value)}`);
})
.catch(error => { console.error(error); });
Теперь, когда мы прочитали пользовательское описание интервала измерения термометра здоровья устройства, давайте посмотрим, как его обновить и записать собственное значение.
navigator.bluetooth.requestDevice({ filters: [{ services: ['health_thermometer'] }] })
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService('health_thermometer'))
.then(service => service.getCharacteristic('measurement_interval'))
.then(characteristic => characteristic.getDescriptor('gatt.characteristic_user_description'))
.then(descriptor => {
const encoder = new TextEncoder('utf-8');
const userDescription = encoder.encode('Defines the time between measurements.');
return descriptor.writeValue(userDescription);
})
.catch(error => { console.error(error); });
Примеры, демо и кодлабы
Все приведенные ниже образцы Web Bluetooth прошли успешное тестирование. Чтобы в полной мере насладиться этими образцами, я рекомендую вам установить [приложение BLE Peripheral Simulator для Android], которое имитирует периферийное устройство BLE с помощью службы батареи, службы измерения сердечного ритма или службы термометра здоровья.
Новичок
- Информация об устройстве — получение основной информации об устройстве с устройства BLE.
- Уровень заряда батареи — получение информации о батарее с устройства BLE, рекламирующего информацию о батарее.
- Сброс энергии — сброс энергии, затраченной на устройство BLE, сообщающее частоту сердечных сокращений.
- Свойства характеристики — отображение всех свойств определенной характеристики устройства BLE.
- Уведомления — запуск и остановка характерных уведомлений с устройства BLE.
- Отключение устройства — отключитесь и получите уведомление об отключении устройства BLE после подключения к нему.
- Получить характеристики — получить все характеристики рекламируемой услуги с устройства BLE.
- Получить дескрипторы — получить дескрипторы всех характеристик рекламируемой услуги с устройства BLE.
- Фильтр данных производителя — получение базовой информации об устройстве с устройства BLE, которая соответствует данным производителя.
- Фильтры исключений — получение основной информации об устройстве с устройства BLE с помощью базовых фильтров исключения.
Объединение нескольких операций
- Характеристики GAP — получите все характеристики GAP устройства BLE.
- Характеристики информации об устройстве — получите все характеристики информации об устройстве для устройства BLE.
- Потеря соединения — ��становите характеристику уровня оповещения устройства BLE (readValue и writeValue).
- Откройте для себя службы и характеристики — откройте для себя все доступные основные службы и их характеристики с устройства BLE.
- Автоматическое переподключение — повторное подключение к отключенному устройству BLE с использованием алгоритма экспоненциальной задержки.
- Чтение измененного значения характеристики — читайте уровень заряда батареи и получайте уведомления об изменениях с устройства BLE.
- Чтение дескрипторов — чтение дескрипторов всех характеристик службы с устройства BLE.
- Write Descriptor — запись в дескриптор «Характерное описание пользователя» на устройстве BLE.
Ознакомьтесь также с нашими тщательно подобранными демонстрациями Web Bluetooth и официальными лабораториями Web Bluetooth Codelabs .
Библиотеки
- web-bluetooth-utils — это модуль npm, который добавляет в API некоторые удобные функции.
- Оболочка Web Bluetooth API доступна в Node.js самом популярном центральном модуле BLE Node.js. Это позволяет вам использовать веб-пакеты/браузеры без необходимости использования сервера WebSocket или других плагинов.
- angular-web-bluetooth — это модуль для Angular , который абстрагирует весь шаблон, необходимый для настройки веб-API Bluetooth.
Инструменты
- Начало работы с веб-интерфейсом Bluetooth — это простое веб-приложение, которое сгенерирует весь шаблонный код JavaScript для начала взаимодействия с устройством Bluetooth. Введите имя устройства, услугу, характеристику, определите его свойства, и все готово.
- Если вы уже являетесь разработчиком Bluetooth, плагин Web Bluetooth Developer Studio также сгенерирует JavaScript-код Web Bluetooth для вашего устройства Bluetooth.
Советы
Страница Bluetooth Internals доступна в Chrome по about://bluetooth-internals
, чтобы вы могли проверить все о ближайших устройствах Bluetooth: статус, службы, характеристики и дескрипторы.
![Скриншот внутренней страницы для отладки Bluetooth в Chrome](https://cdn.statically.io/img/developer.chrome.com/static/docs/capabilities/bluetooth/image/screenshot-the-internal-acdfb455a1a38.jpg?hl=ru)
Я также рекомендую посетить официальную страницу «Как зарегистрировать ошибки Web Bluetooth», так как отладка Bluetooth иногда может быть затруднена.
Что дальше
Сначала проверьте статус реализации браузера и платформы , чтобы узнать, какие части Web Bluetooth API реализуются в данный момент.
Хотя он еще не завершен, вот краткий обзор того, чего ожидать в ближайшем будущем:
- Сканирование близлежащих рекламных объявлений BLE будет выполняться с помощью
navigator.bluetooth.requestLEScan()
. - Новое событие
serviceadded
будет отслеживать вновь обнаруженные службы Bluetooth GATT, а событиеserviceremoved
будет отслеживать удаленные. Новое событиеservicechanged
сработает, когда какая-либо характеристика и/или дескриптор будет добавлена или удалена из службы Bluetooth GATT.
Показать поддержку API
Планируете ли вы использовать Web Bluetooth API? Ваша публичная поддержка помогает команде Chrome расставлять приоритеты в функциях и показывает другим поставщикам браузеров, насколько важно их поддерживать.
Отправьте твит @ChromiumDev , используя хэштег #WebBluetooth
, и сообщите нам, где и как вы его используете.
Ресурсы
- Переполнение стека
- Статус функции Chrome
- Ошибки реализации Chrome
- Веб-спецификация Bluetooth
- Проблемы со спецификациями на GitHub
- Приложение BLE Peripheral Simulator
Благодарности
Спасибо Кейси Басков за рецензию на эту статью. Изображение героя от SparkFun Electronics из Боулдера, США .