『瀚思彼岸』» 智能家居技术论坛

 找回密码
 立即注册
查看: 19021|回复: 47

[修仙教程] 【ESPHome】蓝牙体重秤/体脂秤接入思路:云麦好轻mini 2S为例

[复制链接]

105

主题

2954

帖子

1万

积分

超级版主

智能家居&单板滑雪痴迷爱好者

Rank: 8Rank: 8

积分
12103
金钱
9084
HASS币
460

教程狂人突出贡献

发表于 2021-9-9 10:34:25 | 显示全部楼层 |阅读模式
本帖最后由 XCray 于 2023-5-10 10:27 编辑

esphome内置了小米两代体重秤的支持,其实我感觉绝大多数蓝牙秤应该都可以很方便地利用esphome接入,这里以手上的这款为例,详细介绍分析和实现的思路。

云麦这家公司好像也属于小米生态链,米家app添加设备时可以搜到这款产品,但添加不了(小米的豆腐渣工程?)。

使用厂家提供的“好轻”app,打开app、站到秤上、读数稳定后app收到数据,无需配对,所以推测也是用蓝牙广播实现的。没试过“小米运动”app,不知道是否兼容。

消息分析过程如下:

1. 仅使用esp32_ble_tracker,称重后发现设备,没有name,按电平推测应该就是:
[09:28:23][D][esp32_ble_tracker:620]: Found device AA:BB:CC:XX:YY:ZZ RSSI=-66
[09:28:23][D][esp32_ble_tracker:641]:   Address Type: PUBLIC

2. 增加on_ble_advertise自动化,再次称重:
[09:35:43][D][ble_adv:034]: New BLE device
[09:35:43][D][ble_adv:035]:   address: AA:BB:CC:XX:YY:ZZ
[09:35:43][D][ble_adv:037]:   Advertised service UUIDs:
[09:35:43][D][ble_adv:039]:     - 0x1320
[09:35:43][D][ble_adv:045]:   Advertised manufacturer data:
[09:35:43][D][ble_adv:047]:     - 0xYYZZ: (length 14)

值得注意的是,广播数据所用的UUID,为MAC地址的后两个字节YYZZ。

3. 打印出这个广播数据,消息内容有变化,部分消息有重复,最多看到过8次:

Advertised manufacturer data:
  - 0xYYZZ: XX.CC.BB.AA.02.32.1C.VV.KK.WW.WW.RR.RR.xx (14)
很明显,UUID和数据的前4个字节拼到一起就是完整的MAC地址AABBCCXXYYZZ。

其后的3个字节02.32.1C固定不变,可能是是厂家标识或序列号之类的。
再其后一个字节VV很可能是累计称重次数,每次称重+1。
最后的6个字节为体重和体脂(阻抗)数据,观察到有几种

4. 体重体脂数据猜解:
几次称重(光脚),提取出类似如下数据:
01.04.7E.00.00.A2
01.1A.3A.00.00.F9
02.1B.2F.00.00.E8
03.1B.2F.01.CC.24
00.00.00.00.00.VV

猜测:首字节KK为数据可信度标识,3为最稳定读数、00为称重结束
确认:其后两个字节WW.WW(即1B.2F)为体重,精确到0.01公斤(10克);与屏幕及app显示结果一致。
          每次称重最后一条连续5个字节00为称重结束,最后一个字节VV为累计称重次数;
确认:可信度为03的体重之后的两个字节RR.RR(即01.CC)为阻抗值;
          参考:esphome的miscale2组件代码显示,阻抗值应<3000(0x0BB8)、且为两个字节
          那么最后一个字节又会是啥?校验和?除称重结束外每条消息的最后一个字节都是校验和?

~~~~220511补充~~~~
穿鞋或袜子称重,显然不会有阻抗数据,而其它标志也有差异:
02.52.0C.VV.01.WW.WW.00.00.80
02.52.0C.VV.02.WW.WW.00.00.83

即:
前面光脚称的 02.32.1C 变成了 02.52.0C;数据可信度标识只有01和02,不会出现03;体重正常,阻抗变成了00.00;

5. 结论
显然,这个消息格式不符合小米的文档,系云麦自己定义的格式。
利用esphome已有的miscale2代码简单修改,即可用于此款产品接入,估计云麦其他产品也可以兼容。

补充:体脂秤所谓的体脂率以及其他指标比如肌肉率、身体年龄、健康指数、骨量、含水量、蛋白质比例等等,都是根据性别身高年龄腰围臀围胸围等输入、以及体重阻抗这两个测量值由app根据某种模型计算得出的,体重秤本身只能给出体重和阻抗这两个数值。

6. 干货
这是修改并验证过的代码:
yunmai_scale.zip (3.25 KB, 下载次数: 177)
解压后放到ESPHome的配置数据目录里指定的外部组件目录,比如“mine”,根据自己的MAC地址修改yunmai_scale.cpp第48行,就是取MAC地址的后两个字节,因为它们被用作广播数据的UUID(是的,完全可以让程序从MAC地址自动截取,但我懒,就采用了简单粗暴的办法)。
注:这个代码只处理光脚称重数据,如需处理穿鞋或穿袜子的体重,自行修改吧。

然后在 yaml 里如此配置即可:
external_components:
  - source: mine
esp32_ble_tracker:
sensor:
  - platform: yunmai_scale
    mac_address: 'AA:BB:CC:XX:YY:ZZ'
    weight:
      name: "Yunmai Scale Weight"
    impedance:
      name: "Yunmai Scale Impedance"
应该可以兼容云麦所有产品。其他品牌蓝牙体重秤/体脂秤也完全可以参照这个思路实现,非常简单。

有编程能力的话,还可以增加一个传感器:称重次数,数据是现成的,只是用处实在不大。

7. 进阶玩法
到上一步,只是把体重和阻抗测量值接入到了HA,如果想要更高级玩法,比如自动区分人员、自动计算体脂率以及其他指标比如肌肉率、身体年龄、健康指数、骨量、含水量、蛋白质比例等等,请参考:
Xiaomi Miscale2 Sensors — ESPHome
https://github.com/dckiller51/bodymiscale

注意:这些计算出的数值很可能和原厂app里的结果不一样,这是很正常的,原因是他们使用了不同的模型,说不上哪个对哪个错。

非要说准不准的话,可以说都不大准。唯一准确的办法就是把人宰了、趁新鲜把骨骼肌肉蛋白质脂肪水分都分离开单独过秤!!!(就这都很难做到真正的准确)。

~~~~~~~~~~~~补充~~~~~~~~~~

开始我把问题想简单了。由于厂家设计人员的脑回路不同,蓝牙秤的通讯方式有两种:
- 广播数据,比如小米和我用的云麦;
- gatt连接,需要app先连接体重秤然后再在点对点的连接中传送数据,跟帖的几位朋友反馈的两种就是。
这种方式,需要esp32或带蓝牙的ha主机以client的方式连接体重秤、然后从特定的service:characteristic读取数据,可能还需要先向体重秤写入称重指令。
显然,广播方式更合理一些。

回复

使用道具 举报

8

主题

690

帖子

4556

积分

论坛元老

Rank: 8Rank: 8

积分
4556
金钱
3861
HASS币
0
QQ
发表于 2021-9-9 13:42:05 | 显示全部楼层
蓝牙属实让你玩明白了
回复

使用道具 举报

33

主题

2196

帖子

5838

积分

论坛元老

Rank: 8Rank: 8

积分
5838
金钱
3642
HASS币
60
QQ
发表于 2021-9-9 19:21:02 | 显示全部楼层
大佬蓝牙吃得透哦。
我不生产技术,我只是技术的搬运工。
回复

使用道具 举报

105

主题

2954

帖子

1万

积分

超级版主

智能家居&单板滑雪痴迷爱好者

Rank: 8Rank: 8

积分
12103
金钱
9084
HASS币
460

教程狂人突出贡献

 楼主| 发表于 2021-9-9 19:37:14 | 显示全部楼层
本帖最后由 XCray 于 2022-5-11 11:32 编辑

两位过奖了,这算是个学习笔记吧。

从产品逻辑和使用习惯推测,蓝牙体重秤应该都是大同小异的,也就是广播数据略有区别,感觉这个方法可以实现绝大多数蓝牙秤的接入。
我们知道,把大象关进冰箱也就需要3步;差不多的是,把一个蓝牙体重秤/体脂秤接入ESPHome&HA也只需要3步:

1. 信息收集
包括MAC地址、数据广播参数、数据广播内容

1.1 先使用如下代码获取MAC地址,编译写入ESP32模块后,打开LOGS,然后把体重秤放在距离模块很近的地方,站上去,观察日志,根据电平很容易找出体重秤的MAC地址。
esp32_ble_tracker:
其他基本代码略去不提,不知道的同学先去熟悉了解再来尝试。

1.2 当然,如果你可以从产品包装、说明书、背面铭牌或app里找到MAC地址,上一小步就可以跳过去了,直接用下面的代码收集数据广播参数:
esp32_ble_tracker:
  on_ble_advertise:
    - mac_address: 11:22:33:44:55:66
      then:
        - lambda: |-
            ESP_LOGD("ble_adv", "New BLE device");
            ESP_LOGD("ble_adv", "  address: %s", x.address_str().c_str());
            ESP_LOGD("ble_adv", "  name: %s", x.get_name().c_str());
            ESP_LOGD("ble_adv", "  Advertised service UUIDs:");
            for (auto uuid : x.get_service_uuids()) {
                ESP_LOGD("ble_adv", "    - %s", uuid.to_string().c_str());
            }
            ESP_LOGD("ble_adv", "  Advertised service data:");
            for (auto data : x.get_service_datas()) {
                ESP_LOGD("ble_adv", "    - %s: (length %i)", data.uuid.to_string().c_str(), data.data.size());
            }
            ESP_LOGD("ble_adv", "  Advertised manufacturer data:");
            for (auto data : x.get_manufacturer_datas()) {
                ESP_LOGD("ble_adv", "    - %s: (length %i)", data.uuid.to_string().c_str(), data.data.size());
            }
这都是esphome官方文档里的代码,我一点都没有改。把其中的MAC地址改成你的体重秤的地址,编译写入esp32(推荐ota),然后还是打开LOGS,再次站到秤上,找到带有(length xx)的那一行,就是我们要利用的广播数据。
这里我们说的“数据广播参数”,包括两个东西:
- 广播类型(Advertised manufacturer data?还是 Advertised service data?)
- UUID,就是(length xx)前面的0xXXXX
- 对了,还有消息长度

1.3 根据上面的判断,修改代码,找到对应的 Advertised manufacturer data 或者 Advertised service data 那一行,修改如下:
ESP_LOGD("ble_adv", "    - %s:%s", data.uuid.to_string().c_str(), hexencode(data.data).c_str());
新版本esphome废弃了hexencode()函数,改为format_hex_pretty(),直接替换即可。

其余输出可以尽数删掉了,省得一堆垃圾信息看着心烦。
然后再次编译刷写esp32模块、打开LOGS再次称重,得到完整的数据广播消息内容;同时从秤上的显示屏或者手机app观察记录体重数值。

2. 数据分析猜解
把从秤上或app上看到的体重数值转成16进制,在1.3步骤中得到的消息体中查找。相信绝大多数体重秤都不会加密,很容易就可以找到。
如果你实在找不到的话,不妨发出来一起看看。

3. 修改代码实现接入
根据上一步的分析结论,修改我提供的代码,需要修改的地方我都在行后加了注释。然后重新编译写入,完工。
主贴里提到的高级玩法,有兴趣的话自己试吧。
说实话,我对体重秤接入HA其实没多大兴趣,这个帖子只是一时兴起,发出来供有兴趣的朋友参考。

评分

参与人数 1金钱 +5 收起 理由
ciasdmxhxjjpd@c + 5

查看全部评分

回复

使用道具 举报

123

主题

4661

帖子

1万

积分

管理员

囧死

Rank: 9Rank: 9Rank: 9

积分
16410
金钱
11664
HASS币
45
发表于 2021-9-9 21:30:05 | 显示全部楼层
x大太牛啦
回复

使用道具 举报

105

主题

2954

帖子

1万

积分

超级版主

智能家居&单板滑雪痴迷爱好者

Rank: 8Rank: 8

积分
12103
金钱
9084
HASS币
460

教程狂人突出贡献

 楼主| 发表于 2021-9-10 10:58:22 | 显示全部楼层

囧大过奖,这个其实并不复杂,差不多是最简单的蓝牙用法了。
回复

使用道具 举报

9

主题

106

帖子

1436

积分

金牌会员

Rank: 6Rank: 6

积分
1436
金钱
1330
HASS币
0
发表于 2021-9-15 23:41:32 | 显示全部楼层
QQ截图20210915234012.png
回复

使用道具 举报

9

主题

106

帖子

1436

积分

金牌会员

Rank: 6Rank: 6

积分
1436
金钱
1330
HASS币
0
发表于 2021-9-15 23:42:36 | 显示全部楼层
这个是什么情况,荣耀的体脂秤
回复

使用道具 举报

105

主题

2954

帖子

1万

积分

超级版主

智能家居&单板滑雪痴迷爱好者

Rank: 8Rank: 8

积分
12103
金钱
9084
HASS币
460

教程狂人突出贡献

 楼主| 发表于 2021-9-16 06:31:49 | 显示全部楼层
dyq12345600 发表于 2021-9-15 23:42
这个是什么情况,荣耀的体脂秤

很反感这家公司,没用过。

但从你的截图上来看,很显然那条消息只是MAC地址,BBAACCXXYYZZ的顺序。

你需要称重时的消息。
回复

使用道具 举报

46

主题

332

帖子

3394

积分

论坛元老

Rank: 8Rank: 8

积分
3394
金钱
3062
HASS币
0
发表于 2021-9-20 01:44:33 | 显示全部楼层
貌似只看到mac地址,没有称重的信息是什么原因
WX20210920-014118@2x.png
WX20210920-014220@2x.png
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Hassbian

GMT+8, 2024-11-24 20:09 , Processed in 0.345724 second(s), 37 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表