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

4

我的需求:

我想将我的树莓派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..

我使用我的Android手机的HCI-Snoop-Developer-Funktion,以了解相应应用程序如何与我的体重秤通信。
  1. 写入0200 -> 0x1f(启用Indication 0x1d)
  2. 读取0x21 -> 0x21(值:37fb)
  3. 写入0200 -> 0x1c(启用Indication 0x1a)
  4. 写入0200 -> 0x26(启用Indication 0x24)
  5. 写入02a31e2c0b -> 0x23(我不完全理解这里,但我知道如果你取02后面的字节(a3 1e 2c 0b -> 0b 2c 1e a3)这是当前Unix时间戳,但是年份是1975年?)

第4步之后,将出现第一个Indication(句柄0x25),该Indication会向我提供存储的个人数据(我的身高、性别、年龄等) 。

第5步之后,会有一些Indications(句柄0x1b和句柄0x1e),它们应该传输我的测量数据。 (此时没有分析十六进制值)

我的做法:

我在我的树莓派上安装了bluez.5.32 (内核4.1.13),并使用gatttool完成了步骤1-5,在步骤5之后,我没有收到来自句柄0x1b和0x1e的Indication消息)在第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时间戳来表示1975年,但并没有成功。

经过数十亿小时的努力,我终于在我的树莓派上让bluetoothctl工作了(出现了一个dbus问题),然后我又尝试了同样的方法用bluetoothctl。我启用了所有的Indications,并向hnd=0x23写入0000000000。切换到handle 0x1a,它起作用了!我收到了许多十六进制值,应该就是我正在寻找的数据。

那么问题来了: 我想要使用gatttool来完成我的目的,或者至少我想要理解为什么gatttool不能正常工作。

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

当我使用gatttool或bluetoothctl时,我的Pi和Scale之间是否有其他连接?或者它们与我的秤通信的方式有所不同吗?

2个回答

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

这里的信息来自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(拉34)可以接收Indication中的多个字节
  • 虽然向0x23写入不会产生任何通知,但需要等待通知才能接收0x1b和0x1e Indications。当收到最后一个Indication时,将收到NotificationTimeout异常。

我只是想补充一些信息,但你比我快。我在我的答案中添加了一个链接(另一个关于stackoverflow的问题)。在这篇文章中,我寻求帮助,因为我不知道如何解释提供的十六进制值0x1b和0x1e。(后来自己解决了)这可能对你和其他人很有趣。你也使用Medisana BS440吗? - Edmundo Del Gusto
是的,我也使用BS440,你之前的帖子对我很有帮助!但我不太明白为什么需要等待通知才能开始接收指示(实际上这是你一开始遇到的问题)。不管怎样,现在它可以正常工作了。另外一个问题是,当测量人x时,它只会传输该人最近30个存储结果。 - Keptenkurk

3

好的..我自己解决了这个问题..我所需要做的就是将"char-write-cmd"更改为"char-write-req"..在我的Android-Hci-Snoop日志文件中,它始终是一个写入请求。不知道为什么我一直没有意识到这一点...

如果有人像我一样在使用bluez/bluetoothd/bluetoothctl & dbus时遇到了同样的问题(要在bluetoothctl中使用"list-attributes"、"select"和"write"命令,必须像"bluetoothd -n -E"那样在实验模式下执行bluetoothd),但每次我这样做都会得到一些错误信息,比如"D-Bus: name already in use"或者"d'bus setup failed: connection is not allowed to own the service due to security..."(不记得确切的错误消息了) )

我所做的:

  • 用./configure [...] --enable-experimental安装bluez (阅读ReadMe文件)

  • sudo nano /etc/dbus-1/system.d/bluetooth.conf

    -->复制以>policy user="root">开头的整个块,并将其粘贴到该块下面。然后在两个块中的一个中将"root"改为"pi"

如果有人想知道这个比例尺是如何提供测量结果的,请查看以下链接: 一个小游戏/问答:你能看到我的值吗?(解释十六进制值)


你可以接受自己的答案,而不是在标题中添加“已解决”。https://blog.stackoverflow.com/2009/01/accept-your-own-answers/ - timss

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接