使用 bluez/bluetoothctl/gatttool 连接到蓝牙智能/LE 体重秤

Edm*_*sto 4 bluetooth bluetooth-lowenergy bluez

我想做的事:

我想将我的 Raspberry Pi 2 连接到蓝牙智能体重秤 (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..
Run Code Online (Sandbox Code Playgroud)

我使用了我的 Android 手机的 HCI-Snoop-Developer-Funktion,看看相应的应用程序如何与我的体重秤通信。

  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)应该传输我的测量数据。(此时没有分析十六进制值)

我做了什么:

我在我的 raspi (内核 4.1.13)上安装了bluez.5.32,并使用 gatttool 执行了第 1 - 5 步,一切正常,直到第 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
Run Code Online (Sandbox Code Playgroud)

(我什至用 unix-timestamp-for 1975 做这件事……没有解决)

数十亿小时后,我在我的 raspi 上使用 bluetoothctl 工作(有一个 dbus 问题),我用 bluetoothctl 进行了同样的尝试。我启用了所有指示并将 0000000000 写入 hnd=0x23。切换到处理 0x1a 并且它起作用了!我收到许多十六进制值,它们应该是我正在搜索的数据。

所以有什么问题? 我想将 gatttool 用于我的目的,或者至少我想了解,为什么 gatttool 不起作用

我用bluetoothctl的时候,只能选择一个属性看,收到数据后,我的秤自动断开到我的树莓派。因此,当我选择特性 0x1a 时,我看不到特性 0x01d 的指示消息,反之亦然。

当我使用 gatttool 或使用 bluetoothctl 时,我的 Pi 和我的 Scale 之间是否存在其他连接?或者在方式上有什么不同,他们如何与我的体重秤沟通?

Kep*_*urk 5

在测量重量等之后,秤似乎可以连接一小段时间我在 bash 脚本中使用了 gatttool 的非交互模式,如下所示:

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
Run Code Online (Sandbox Code Playgroud)

信息来自此处的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()
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 根据我的经验,读取句柄 0x21 没有任何意义
  • 写入句柄 0x23 与 02 后跟 unix 时间戳同步规模的 RTC
  • 使用多字节修改的 pygatt (pull 34) 可以在一个 Indication 中接收多个字节
  • 尽管写入 0x23 不会产生任何通知,但需要等待通知才能接收 0x1b 和 0x1e 指示。当收到最后一个指示时,会收到 NotificationTimeout 异常。