Контроль забраслетом у ритмі BlueZ

Експерименти я розпочав з вивчення набору сервісів та характеристик, доступних через Bluetooth 4.0 (або Bluetooth Low Energy, далі – BLE). Щось неважко було знайти в мережі, і ця інформація мені дуже допомогла, але вона стосувалася попередньої версії без потрібного мені датчика. Тому я почав із BLE-сканера.

Натиснувши на “OPEN TAB” і потім “CONNECT”, отримав набір сервісів:

Ідентифікатор вимірювача пульсу виявився стандартним для таких пристроїв – 0x180D. Забігаючи наперед, скажу, що зрадів я рано.

Як ретранслятор я використовував Raspberry Pi (модель B) та BLE-usb-адаптер BT400 від ASUS. Також були потрібні BlueZ – справжній швейцарський ніж для роботи з Bluetooth під Linux та пара додаткових модулів для Python.

Для Raspberry Pi використовувався образ Raspbian. Після apt-get update та apt-get upgrade перевірив адаптер:

Відмінно, мій адаптер у першому рядку. Встановив BlueZ. Рекомендується завантажити останній архів коду, на момент підготовки статті це був BlueZ 5.37, розпакувати та скомпілювати. Я задовольнився версією 5.23, яка встановлюється через apt-get. Коригування установки можна перевірити, виконавши команду gatttool –help. Gatttool — інструмент BlueZ для роботи з GATT, загальним профілем атрибутів BLE пристроїв. У старих версіях gatttool за умовчанням не встановлювався, потрібно було «прикручувати» руками, але тут help був доступний і отже, маю майже все необхідне для роботи з браслетом. Через pip встановив Pexpect для роботи з BlueZ з Python. Перезавантажив Raspberry та ввімкнув адаптер. Статус адаптера перевірив командою hciconfig:

Прапор DOWN показав, що адаптер вимкнено, ввімкнув його командою: sudo hciconfig hci0 up

Перш ніж писати код для Raspberry, мені потрібно було переконатися, щовсі необхідні мені послуги (частота пульсу, рівень заряду акумулятора і вібродзвінок) доступні в термінальному режимі з BlueZ. Просканував BLE оточення і без проблем знайшов браслет:

Підключився до браслету командою connect, запустивши gatttool в інтерактивному режимі (ключ I):

З'єднання в інтерактивному режимі без спарювання зазвичай триває 20 секунд. Це так званий низький рівень секретності, він використовується за умовчанням. Список доступних сервісів виводиться командою primary:

Визначити, що за сервіс можна за чотирма цифрами після uuid. Вийшло два загальні сервіси (generic), два сервіси, задані виробником (fee0 і fee1), HRM сервіс (180d) та алертинг (1802). Перелік характеристик браслета виводиться командою char-desc у порядку зростання покажчиків (handles). Знайшов у списку характеристику з ідентифікатором ff0c: handle: 0x002c, uuid: 0000ff0c-0000-1000-8000-00805f9b34fb, Покажчик 0x002c для рівня заряду акуму. Спробував вважати дані командою char-read-hnd (прочитати дані за вказівником):

Другим «підкорився» вібродзвінок. За даними MCP я припустив, що це Immediate Alert, а Alert Level це команда, яку потрібно надіслати на ідентифікатор 0x2A06:

У списку характеристик цьому ідентифікатору відповідає рядок: handle: 0x0051, uuid: 00002a06-0000-1000-8000-00805f9b34fb Направив команду на покажчик 0x0051 зі значенням 0

Браслет відгукнувся двома слабкими дзижчаннями, значення 02 це двічі по 01, тобто. чотири сигнали, а 03 - два, але сильніших. З частотою пульсу виявилося значно складніше. MCP показав наступне:

Пов'язані з цим сервісом характеристики:

Нічого не вийшло, значення успішно записувалося, аленіяких повідомлень не надходило, браслет просто вимикався за кілька секунд. Запуск gatttool у консольному режимі з ключем – listen також не дав результатів, gatttool просто «зависав» в очікуванні. Загадка, одним словом.

Для прояснення ситуації довелося використовувати BLE-сніфер (на ноутбуці з Windows 8). В основі був перепрошитий BLE-usb-донгл на чіпі СС2540 від Texas Instruments та програма Smart Packet Sniffer того ж виробника. Все необхідне, включаючи програматор, можна легко знайти у вигляді набору для розробника, а програму і прошивку я вільно скачав з сайту TI.

Так виглядають пакети у сніффері в режимі презентації:

Тут видно, як значення 0100 записується в CCC з покажчиком 0x004C, дозволяючи повідомлення про частоту пульсу.

Під час аналізу пакетів вдалося з'ясувати таке:

  1. Щоразу при з'єднанні в браслет надсилаються всі дозволи повідомлень (CCC з ідентифікатором 2902)
  2. Далі відбувається передача інформації про користувача
  3. Потім, за вказівником 0x0028 записуються дата та час
  4. Після цього зчитуються дані про рівень заряду батареї та кількість пройдених за день кроків
  5. Перед тим як отримати повідомлення про частоту пульсу за вказівником 0x004E, відповідним характеристикою «точка контролю пульсу» записується послідовність 0x15 0x00 0x00 (припустимо, що це скидання)
  6. Потім туди записується 0x15 0x02 0x01, що в моєму випадку відповідає лівій руці
  7. Після цього, через 15-20 секунд, надходить повідомлення з частотою пульсу у двох байтах, наприклад 06 40. Другий байт і є частота пульсу в hex
У теорії, щоб отримати частоту пульсу, потрібно було повторити всі ці транзакції, можливо виключивши 3-й і 4-й пункти. Як виявилось, можнаобійтися і без скидання. Вручну це зробити неможливо, браслет відключився б раніше, ніж я встиг би ввести всі команди. Тому я підготував Python-скрипт:

Скрипт виводить рівень заряду батареї, відправляє повідомлення, чекає та друкує частоту пульсу. Загадка вирішена, залишилося навчитися відправляти дані в хмарний сервіс, як я вирішив використовувати Thingspeak. Це безкоштовний сервіс із простим API та готовою візуалізацією.

Налаштування Thingspeak зайняло не більше п'яти хвилин. Необхідно зареєструватися та увійти до персонального простору. Далі, створити новий канал, в налаштуваннях каналу вказати назву, кількість та мітки полів. Зберегти установки та перейти на вкладку API Keys. Там скопіювати API-ключ для запису (Write API Key):

Після цього – перейти на вкладку Private View (якщо при налаштуванні каналу не було вказано “Make Public”).

За відправку даних у Thingspeak відповідає ось така конструкція на Python:

У штатному режимі роботи в консоль виводиться номер надсилання даних, починаючи з одиниці. Радіус дії ретранслятора 3-4 метри у прямій видимості, що нормально для медичної палати. Однак, браслет на такій відстані легко екранується долонею.

Тестував систему, що вийшла, в процесі тренування на велотренажері, 20 хвилин. Інтервал між вимірюваннями – 3 хвилини, кількість вимірювань – 8. Браслет схильний завищувати частоту пульсу при нещільному контакті зі шкірою, для більшої точності помістив датчик із тильного боку зап'ястя. Результат на Thingspeak:

Як видно з графіка, 8 вимірів ніяк не вплинули на заряд акумулятора. Думаю, експеримент можна вважати цілком успішним і отриманий досвід використовуватиме проектування власного пристрою або, наприклад, пошукати ОЕМ.