Web Bluetooth

Поразбирался тут с Web Bluetooth. Это такой API в Chrome, через который можно из браузера коннектиться к BLE устройствам (только BLE) и работать с ними. Короче IoT и вот это вот всё ;)

Смысл в том, что после соединения с устройством доступен некий набор характеристик (это типа портов в которые можно писать, читать, либо подписываться на изменения) и сервисов (это типа папок для характеристик). Есть стандартизированные сервисы и характеристики (типа "battery_service" / "battery_level" = 0x180f / 0x2a19) и есть уникальные для данного устройства.  

Купил простенький гигрометры/термометры MJ_HT_V1 и Mi Flora и потратил три дня, чтобы через это API вытащить из них температуру и влажность. Хотя результат отрицательный, в процессе много чего осознал. В общем и целом есть две проблемы:

1.Производители законченных BLE устройств крайне не заинтересованы в том, чтобы для них писали сторонние приложения. Поэтому ситуация такова что, с одной стороны, да - они следуют стандарту. С другой, чтобы из этого конкретного девайса прочитать температуру, народ сниффил обмен данными фирменного приложения Mi Home и выяснил что, оказывается, некая characteristic (это типа порта), которая заявлена как WRITE (only) становится READ, если предварительно записать определённые байты в другую characteristic (причём, на это есть 12 секунд, после чего происходит disconnect). Выяснилось, что с моим точно таким же девайсом именно это уже не срабатывает (видимо, более новый revision), плюс к тому, даётся на всё действия до disconnect'a уже секунды 3-5. Без проблем можно прочесть разве что уровень разряда батарейки (это вообще базовая штука, которая всеми BLE девайсами, по-видимому, предоставляется без вопросов и одинаково).

2.API реализованный в Chrome - не поддерживает (пока) очень существенные фичи. В частности, работая через более прямые API (скажем, если писать на Java под Android или использовать утилиты типа gatttool работающие через Bluez stack в Linux), выше описанные танцы с вышеупомянутым девайсом, как пишут, вообще не были бы нужны - всё куда проще и работает независимо от его revision'a.

Сам процесс подключения к устройству через Web Bluetooth - не для слабонервных.
Во-первых, API в целях безопасности сделано так, что соединение с устройством может быть программно инициировано только как результат клика на что-нибудь в браузере (именно поэтому во всех примерах всегда есть некая html кнопка, при нажатии на которую вызывается функция, содержащая вызов navigator.bluetooth.requestDevice() ).
При вызове requestDevice() Chrome открывает окно с надписью по центру "Совместимые устройства не найдены" (в этом месте нормальный пользователь уже завязал бы с таким сайтом, но мы не нормальный пользователь, верно? ;) Если подождать 10...30 секунд, то с вероятностью процентов 80 в списке начнут появляться обнаруженные устройства (соответственно, с вероятностью процентов 20 не появится ничего, и это не связано с уровнем сигнала или работоспособностью устройств - просто где-то что-то не срослось).

В списке эти устройства будут представлены как повезёт - либо под своим названием (типа Mi Band 2 или MJ_HT_V1), либо как "Неизвестное устройство [MAC]". Причём, MAC адрес вы увидеть никак не сможете (см. скриншот), поэтому если устройств несколько, единственный способ присоединиться к правильному - это угадать.

Даже после того, как вы уже успешно соединились с устройством, при каждой повторной загрузке страницы (точнее, при вызове requestDevice() ) эту неприятную процедуру необходимо повторять вновь и вновь. В перспективе, для решения этой проблемы будет ещё Permission API.

Вся эта радость более-менее реализована и работает пока только в Chrome (для Win, Linux, MacOS, Android). Изнутри worker'ов не работает (пока?). Здесь список багов.

Простой пример:

<html>
<body bgcolor="#000000">
<script>

async function Test() {

  console.log('Requesting Web BT device...');

  const device = await navigator.bluetooth.requestDevice({
   filters: [{
    services: ['battery_service'],   // list BT devices announcing battery_service
   }],

  })

  console.log('device',device)  
 console.log(`Connecting to device's GATT Server...`)

  const server = await device.gatt.connect()

  console.log('server:',server)  

  let service = await server.getPrimaryService('battery_service') 

  console.log('service',service)

  let characteristic = await service.getCharacteristic('battery_level')

  console.log('chs',characteristic)

  let value = await characteristic.readValue()

  console.log('battery level:',value.getUint8(0))

}

window.onload = () => {      

      const button = document.getElementById('but')

      button.addEventListener('pointerup', function(event) {

        Test()

      });

}

</script>

<button id="but">Click!</button>
</body>
</html>

Упомяну неочевидный момент: для нестандартных services их uid обязательно надо включать в optionalServices. Иначе потом их не будет видно по getServices   

navigator.bluetooth.requestDevice({
               filters: [{
                 name: 'MJ_HT_V1',
               }],
               optionalServices: ['0000fff0-0000-1000-8000-00805f9b34fb']
             })

К слову — на фильтр по name особо не рассчитывайте. У меня это практически никогда не работало. И сразу скажу, что фильтра по MAC по идеологическим причинам не предусмотрено.

Примеры от Google тут.

Отдельно замечу, что в Windows 7 в самой ОС отсутствует поддержка BLE и пока никто не сподобился её реализовать. Каждое BLE устройство, чтобы работать с Win7, требует своего драйвера. Поэтому Web Bluetooth API - не ниже Win 8.1+.

Напоследок, чтобы два раза не вставать - существует ещё Web USB API. Кое в чём напоминает Web Bluetooth. Основное назначение - работа с нестандартными USB устройствами (какая-нибудь там плата на Arduino с USB разъемом). Т.е. с вашей клавиатурой, мышью или вебкамерой оно работать не будет, так как ко всему, для чего в системе уже установлены драйвера, Chrome прямого доступа не имеет.

Для проверок и экспериментов удобно использовать приложение BLE Scanner для Android.

Error

Anonymous comments are disabled in this journal

default userpic

Your reply will be screened

Your IP address will be recorded