Подключение к весам Bluetooth smart / LE с помощью bluez / bluetoothctl / gatttool

Что я хочу делать:

Я хочу подключить свой Raspberry Pi 2 к Bluetooth Smart Weight Scale (Medisana BS440) и получить свои данные.

Что я знаю:

Есть только одна интересная первичная услуга с 5 характеристиками:

 - handle: 0x001a
     -  properties: 0x20 (Indication), char value handle: 0x1b uuid:00008a21-0000-1000-8000-00805f9b34fb
 - handle: 0x001d
     -  properties: 0x20 (Indication), char value handle: 0x1e uuid:00008a22-0000-1000-8000-00805f9b34fb
 - handle: 0x0020
     -  properties: 0x02 (Read-Only),  char value handle: 0x21 uuid:00008a20-00..
 - handle: 0x0022
     -  properties: 0x08 (Write-Only), char value handle: 0x23 uuid:00008a81-00..
 - handle: 0x0024
     -  properties: 0x20 (Indication), char value handle: 0x25 uuid:00008a82-00..

Я использовал HCI-Snoop-Developer-Funktion своего Android-телефона, чтобы увидеть, как соответствующее приложение взаимодействует с моими весами.

  1. Записать 0200 -> 0x1f (включить индикацию 0x1d)
  2. читать 0x21 -> 0x21 (значение: 37fb)
  3. написать 0200 -> 0x1c (включить индикацию 0x1a)
  4. написать 0200 -> 0x26 (включить индикацию 0x24)
  5. напишите 02a31e2c0b -> 0x23 (я не совсем понимаю это здесь, но я знаю, если вы берете байты после 02 (a3 1e 2c 0b -> 0b 2c 1e a3 -> это текущая временная метка Unix, но для года? 1975?)

после шага 4. появляется первая индикация (дескриптор 0x25), которая дает мне сохраненные личные данные обо мне (мой рост, пол, возраст и т. д.)

после шага 5. есть некоторые индикации (дескриптор 0x1b и дескриптор 0x1e), которые должны передавать мои измеренные данные. (В это время не анализировал шестнадцатеричные значения)

Что я сделал:

Я установил bluez.5.32 на свой raspi (ядро 4.1.13) и выполнил шаги 1–5 с помощью gatttool, и все работает нормально до шага 5. Я не получаю любые сообщения-индикации от дескриптора 0x1b и 0x1e) После шага 5 ничего не происходит.

gatttool -t random -b DE:70:4A:XX:XX:XX -I
char-write-cmd 0x1f 0200
char-read-hnd 0x21 (37fb)
char-write-cmd 0x1c 0200
char-write-cmd 0x26 0200
char-write-cmd 0x23 0000000000

(Я даже делаю то же самое с unix-timestamp-for 1975 .. не получилось)

Спустя миллиарды часов у меня на распи работал bluetoothctl (возникла проблема с dbus), и я попробовал то же самое с bluetoothctl. Я включил все индикации и записал 0000000000 в hnd = 0x23. Переключился на дескриптор 0x1a, и все заработало! Я получаю много шестнадцатеричных значений, которые должны быть данными, которые я ищу.

Так в чем проблема? Я хочу использовать gatttool для своих целей или, по крайней мере, я хочу понять, почему это не сработало с gatttool

Когда я использую bluetoothctl, я просто могу выбрать и посмотреть один атрибут, и после получения данных мои весы автоматически отключаются от моей малины. Поэтому, когда я выбираю характеристику 0x1a, я не могу видеть сообщения индикации характеристики 0x01d и наоборот.

Есть ли другое соединение между моим Pi и моей шкалой, когда я использую gatttool или когда я использую bluetoothctl? Или есть разница в том, как они взаимодействуют с моей шкалой?


person Edmundo Del Gusto    schedule 14.12.2015    source источник


Ответы (2)


Кажется, что весы можно подключить только на короткий период времени после измерения веса и т. Д. Я использовал неинтерактивный режим gatttool в сценарии bash, например:

gatttool -t random -b F1:37:57:XX:XX:XX --char-write --handle 0x001f -n 0200
gatttool -t random -b F1:37:57:XX:XX:XX --char-read --handle 0x0021
gatttool -t random -b F1:37:57:XX:XX:XX --char-write --handle 0x001c -n 0200
gatttool -t random -b F1:37:57:XX:XX:XX --char-write --handle 0x0026 -n 0200
gatttool -t random -b F1:37:57:XX:XX:XX --char-write-req --handle 0x0023 -n 0000000000 --listen

Информация взята из Pratik Sinha, здесь. Чтобы отобразить ответ, явно необходимо указать --listen, после чего будет получено около 25 строк данных (чередование ответов 1b и 1e). Спасибо за информацию, сэкономили мне дни работы!

С новым годом!

РЕДАКТИРОВАТЬ:

Использование Python и модуля pygatt сводится к следующему:

import pygatt.backends
from binascii import hexlify

def printIndication(handle, value):
    print('Indication received {} : {}'.format(hex(handle), hexlify(str(value))))

adapter = pygatt.backends.GATTToolBackend()
adapter.start()
# wait for someone to step on the scale
while True:  
    try:
        device = adapter.connect('f1:37:57:xx:xx:xx', 5, 'random')
        break
    except pygatt.exceptions.NotConnectedError:
        print('Waiting...')
device.subscribe('00008a22-0000-1000-8000-00805f9b34fb', callback = printIndication, indication = True)
device.subscribe('00008a21-0000-1000-8000-00805f9b34fb', callback = printIndication, indication = True)
device.subscribe('00008a82-0000-1000-8000-00805f9b34fb', callback = printIndication, indication = True)
try:
    device.char_write_handle(0x23, [02,00,00,00,00], True)
except pygatt.exceptions.NotificationTimeout:
    pass
device.disconnect()
adapter.stop()

ПРИМЕЧАНИЯ:

  • По моему опыту, дескриптор чтения 0x21 не имеет смысла
  • Запись дескриптора 0x23 с 02, за которым следует временная метка unix, синхронизирует RTC шкалы
  • Используйте многобайтовый модифицированный pygatt (pull 34), чтобы иметь возможность получать несколько байтов в индикации.
  • Хотя запись в 0x23 не приведет к уведомлению, необходимо дождаться уведомления, чтобы получить сообщения 0x1b и 0x1e. Когда было получено последнее Индикация, получено исключение NotificationTimeout.
person Keptenkurk    schedule 01.01.2016
comment
просто хотел добавить эту информацию, но вы были быстрее. Я добавил ссылку в свой ответ (еще один вопрос по stackoverflow). В этом посте я попросил помощи, потому что не знал, как интерпретировать шестнадцатеричные значения, которые предоставляет 0x1b и 0x1e. (Решил сам позже) Может быть интересно вам и другим. Вы также использовали Medisana BS440? - person Edmundo Del Gusto; 22.01.2016
comment
Да, я тоже использую BS440, и другой ваш пост тоже мне очень помог! Я просто не понимаю, почему нужно ждать уведомления, чтобы начать получать показания (на самом деле проблема, с которой вы столкнулись вначале). Во всяком случае .., это работает. Другое дело, что когда измеряется человек x, он передает последние 30 сохраненных результатов только этого человека. - person Keptenkurk; 24.01.2016

Хорошо .. Я решил это сам ... все, что мне нужно было сделать, это изменить ,, char-write-cmd "на ,, char-write-req" .. В лог-файле моего Android-Hci-Snoop это всегда требовалась запись. Не знаю, почему я все время не узнавал этого ...

Если у кого-то такая же проблема с bluez / bluetoothd / bluetoothctl & dbus, как у меня (чтобы использовать команды "list-attributes", "select" "write" в bluetoothctl, вам нужно выполнить bluetoothd в экспериментальном режиме, например, bluetoothd -n - E ", но каждый раз, когда я это делал, я получал сообщения об ошибках вроде" D-Bus: имя уже используется "или что-то вроде" сбой настройки d'bus: соединение не разрешено владеть сервисом из-за безопасности ... " (не помню точное сообщение об ошибке))

Что я сделал:

  • установка bluez с помощью ./configure [...] --enable-experimental (прочитать ReadMe-файл)

  • судо нано /etc/dbus-1/system.d/bluetooth.conf

    -> скопировал весь блок, который начинается с> policy user = "root">, и вставил его под этим блоком. Затем я изменил "root" на "pi" в одном из двух блоков.

Если кто-то хочет узнать, как эта шкала обеспечивает результаты измерений, перейдите по этой ссылке: Маленькая игра / викторина: Вы видите мои значения? (Интерпретация шестнадцатеричных значений)

person Edmundo Del Gusto    schedule 15.12.2015
comment
Вы можете принять свой ответ, вместо того, чтобы добавлять к заголовку слово «РЕШЕНО». blog.stackoverflow.com/2009/01/accept-your-own-answers - person timss; 06.01.2016