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

标题: 【足够强大】ESPHome+ESP32打造通用蓝牙网关,比小米自家的好 [打印本页]

作者: XCray    时间: 2022-5-8 21:22
标题: 【足够强大】ESPHome+ESP32打造通用蓝牙网关,比小米自家的好
本帖最后由 XCray 于 2023-4-26 18:56 编辑

玩ESPHome已经一年多了,碰到了很多问题,有的解决了,有的放弃了,有的耿耿于怀至今。。。

简单小结一下蓝牙通用网关

其实说通用有一点点夸张哈,大部分使用蓝牙广播的设备都可以接入,由于esphome的限制,基于ble_client的还不能与基于广播的用一个esp32搞定。

我自己现在在用的设备可以分为两类:

1. ESPHome内置组件,根据文档直接在yaml里面配置即可:
- 花花草草传感器
- 蓝牙温湿度计2
- 云米燃气灶
2. 自制组件(把ESPHome内置组件拿来修改),把代码保存至指定目录后与前面的设备一起在yaml里配置,即一个esp32即可:
- 榉树门锁
- yeelight调光开关
- 云麦好轻体脂秤
这几个代码之前已经发过帖子,感兴趣的找来看吧。

~~~~~~~~~~~~~~~~~~~~~~~~~
重点说说一个难题,就是广播扫描参数的设置问题。前期试过多种设置,总会偶尔发生收不到设备发出的广播消息的现象

其它设备都还好,或者说偶尔丢一次消息无所谓,最关心的是蓝牙门锁,一次也不想错过。

错过门锁广播消息的现象,大概十几天能观察到一次,而同时在用小米的蓝牙网关却每次都能收到。

这几个组件都是基于 esp32_ble_tracker 的,反复阅读官方文档以及其中提到的TI的文档,可能影响的参数就两个:
扫描间隔和扫描窗口

esphome默认的设置分别时320ms和30ms,丢消息的现象比较明显;目前我在用的是160/120ms,有明显改善,但仍然会丢。

一个极端的想法是把扫描窗口设置为和扫描间隔一样大,但必须把网络连接方式改成以太网,难度太大。

如果继续使用WiFi,那么注定扫描窗口就必须小于扫描间隔(必须为WiFi预留出必要的时间),也就意味着这个简单的思路总会有错过蓝牙广播消息的可能。

小米自己的网关也是用的WiFi,它是怎么设置能够做到不错过广播消息的呢?一直也没有看到有具体的说明,小米设备蓝牙广播的参数设置也没看到过说明

那么我们应该怎么设置才好呢?耗电的事情都可以完全忽视,只求不错过广播消息!
~~~~~~~~~~~~~~~~
根据TI的文档(详见),简单描述一下技术背景:

广播发送设备可以设置使用1~3各广播信道、也可以设置广播间隔(20ms~10.24s),每次在一个信道上的广播最多需要10ms:

                               
登录/注册后可看大图

而广播接收侧不能选择信道,必须3个信道顺序扫描:

                               
登录/注册后可看大图


~~~~~~~~~220621补充~~~~~~~~~
把间隔设置为120ms、窗口设置为100ms,已经观察了两个多月了,未再发生丢消息的现象,wifi连接也没啥问题,感觉基本可以解决之前头疼的问题了。

~~~~~~~~~230426补充~~~~~~~~~
ESPHome自2022.12.x版本开始,存在严重bug,个人能力有限无法判定具体问题,但现象很明确:
运行5个小时左右会出现蓝牙功能失效,就是esp32硬件本身还在运行,但不再接收解析任何蓝牙消息,其他功能正常。只有断电重启才能恢复,然后过几个小时又会出现(2023.3.x~2023.4.x好像若干小时会自行崩溃重启)。


经多次尝试,发现最后一个稳定可靠的版本是2022.11.5。
另外,论坛里有些朋友用于连接LD2410B,也存在非常相像的问题,怀疑根因是一个(帖子)。


供参考。

作者: Brewer    时间: 2022-5-8 23:52
请善用论坛的搜索功能,你的求助一搜就有答案。  可参考下以下这贴:https://bbs.hassbian.com/forum.php?mod=viewthread&tid=16331&highlight=esp32&mobile=2
作者: XCray    时间: 2022-5-9 06:43
本帖最后由 XCray 于 2022-5-9 07:25 编辑

TI的文档中有一段有些参考价值:
Optimizing Scanning: How to get data fast?
In a time-constrained application, when the user needs to receive the data as fast as possible, make sure that scanning window is more than the advertising interval + 10ms to guarantee discovery. (The 10 ms extra account for the 0 ms to 10 ms of pseudo-random delay in between each advertising event, assuming no interference.) Following this rule will increase the chance of receiving the advertising packet on the first scan.

就是扫描窗口要大于发射间隔再加10ms,问题是找不到小米关于广播间隔的说明呀!
作者: ghostist    时间: 2022-5-9 08:39
XCray 发表于 2022-5-9 06:43
TI的文档中有一段有些参考价值:
就是扫描窗口要大于发射间隔再加10ms,问题是找不到小米关于广播间隔的说 ...

不是很懂
来个不负责的猜测:
小米门锁会强制在扫描窗口发送报文
网关和门锁肯定有授时报文(门锁的远程设置密码就是根据时间来的,指定时间内有有效期)
如果两端能保证时间一致(就算差个几ms)
那么就可以做到门锁在扫描窗口发送报文
作者: XCray    时间: 2022-5-9 10:00
ghostist 发表于 2022-5-9 08:39
不是很懂
来个不负责的猜测:
小米门锁会强制在扫描窗口发送报文

你把它想的太好了

网关和门锁没有授时机制,甚至网关里根本没有时钟(它当然有晶振但不知道年月日时分秒)。远程临时密码是半小时有效的,对时钟同步的要求很低,并且只是是根据固定算法生成的。

手机app倒是可以校准门锁内的时钟。

让门锁主动在网关的扫描窗口发送报文,这个可以肯定是不可能的
作者: riceball    时间: 2022-5-9 18:05
很难了,你这个配置已经接近极限了,除非单独WIFI/蓝牙独立通道, 另外小米用的是ESP32芯片么? 在手机/电脑/笔记本/盒子上可以看看会不会漏(非ESP32芯片). 如果ESP32上要作蓝牙持续扫描,除非禁用wifi.

另外那个duration没有搞懂是啥意思. 和wifi啥关系?
作者: XCray    时间: 2022-5-10 07:41
ryanh7 发表于 2022-5-9 12:59
重发次数和重发间隔定义在小米蓝牙模组,sdk或者基于esp32的蓝牙网关的固件总得搞到一个,或许能从里面提取 ...

逆向难度太大了。

没接触过小米的模组和sdk,现有公开的资料又没有涉及到这么细的细节

不切实际地期待业内人士透露吧。。。
作者: XCray    时间: 2022-5-10 07:52
riceball 发表于 2022-5-9 18:05
很难了,你这个配置已经接近极限了,除非单独WIFI/蓝牙独立通道, 另外小米用的是ESP32芯片么? 在手机/电脑/笔 ...

是的,除非用以太网,否则wifi和蓝牙公用一个天线,总会有空挡无法进行扫描。在和发射侧无法良好匹配的情况下,错失消息在所难免。

小米有多种型号的蓝牙模组,其中也有esp32,可惜搞不到sdk。

在电脑上搞个程序思路倒是不错,可是实现难度好像更大(编程基础太差),另外漏掉消息的现象几率很低,得长期观察才行。

那个duration根据文档,似乎没有任何实际影响,仅用于蓝牙栈的调试,默认5分钟也很长了。
作者: riceball    时间: 2022-5-10 09:58
XCray 发表于 2022-5-10 07:52
是的,除非用以太网,否则wifi和蓝牙公用一个天线,总会有空挡无法进行扫描。在和发射侧无法良好匹配的情 ...

电脑上如果测试用 bluetoothctl 即可,写个简单的 bash 脚本 记录下来, 就可进行对比比较. 如果喜欢用python,也有Bluetoothctl wrapper: https://gist.github.com/egorf/66d88056a9d703928f93

另外 可以读读 ble_monitor 的代码, 它使用的是python的异步`aioblescan`蓝牙扫描库,专门用于接收蓝牙广播消息,安装模块后可以直接使用:

```bash
pip3 install aioblescan
aioblescan -h
# or run python3 -m aioblescan
```

作者: XCray    时间: 2022-5-10 10:44
riceball 发表于 2022-5-10 09:58
电脑上如果测试用 bluetoothctl 即可,写个简单的 bash 脚本 记录下来, 就可进行对比比较. 如果喜欢用pyth ...

翻了翻aioblescan的源码,它考虑的更简单,基本就是 window = interval

对于使用以太网、或者wifi和蓝牙独立天线的情况下当然没问题,但esp32肯定不行,window 太接近 interval 都会导致wifi链接出问题。我现在给wifi留了1/4,感觉再压缩的空间已经不大。
作者: riceball    时间: 2022-5-11 07:45
XCray 发表于 2022-5-10 10:44
翻了翻aioblescan的源码,它考虑的更简单,基本就是 window = interval

对于使用以太网、或者wifi和 ...

我的C3 设置 320/120 就已经开始报错了:  `[E][wifi:381]: Scan timeout!` 虽然能连.

用ESP32只能走LAN,或者加一块ESP8266
作者: trz0332    时间: 2022-5-15 21:42
其实我也遇到了这个问题,自己diy的蓝牙称的时候也出现了有时候扫描不到蓝牙广播,,一直无解,后来就放弃了,下次可以去买个以太网模块走有线试试
作者: XCray    时间: 2022-5-21 17:00
trz0332 发表于 2022-5-15 21:42
其实我也遇到了这个问题,自己diy的蓝牙称的时候也出现了有时候扫描不到蓝牙广播,,一直无解,后来就放弃 ...

我最近在用的配置:
  1. wifi:
  2.   ssid: $wifi_ssid
  3.   password: $wifi_password
  4.   fast_connect: on
  5.   reboot_timeout: 23min
  6.   
  7. esp32_ble_tracker:
  8.   scan_parameters:
  9.    interval: 120ms
  10.    window: 100ms
复制代码


每次蓝牙广播的时长接近 30ms,我现在只拿出20ms给wifi(只有一个ssid故不用扫描),应该可以达到不错过蓝牙广播的效果,这几天用着还行,wifi没啥异常、也没碰到丢消息的现象,继续观察ing
作者: koranayle    时间: 2022-6-6 11:57
大神有没有抓包瞧瞧你丢的那一包前后有没有别的消息或广播
作者: XCray    时间: 2022-6-6 16:08
koranayle 发表于 2022-6-6 11:57
大神有没有抓包瞧瞧你丢的那一包前后有没有别的消息或广播

抓包太麻烦了,没弄主要是问题发生的概率很低,懒得弄个机子长期抓包。

如15楼所述修改间隔和窗口后已经用了快一个月了,还没有再碰到丢消息的现象,似乎勉强可以解决了。
作者: neroxps    时间: 2022-6-30 17:21
我的鹿客 Q2 门锁,广播包,1秒会发两个,用USB 蓝牙接收器抓的话,几乎全部都能抓到,很少丢,esp32 还是会丢。放的位置wifi信号也不是很强(-65)。

但我感觉有时候创米小白都会丢消息。
作者: XCray    时间: 2022-6-30 17:52
neroxps 发表于 2022-6-30 17:21
我的鹿客 Q2 门锁,广播包,1秒会发两个,用USB 蓝牙接收器抓的话,几乎全部都能抓到,很少丢,esp32 还是 ...

丢消息的问题确实让人头疼,和wifi的冲突、处理能力都可能。另外我还怀疑多个蓝牙网关可能也会造成问题——我用的榉树锁广播是manufacturer data,蓝牙网关不只是接收、还需要在收到adv_ind消息后再主动发一条scan_req消息、然后门锁再回复一条响应scan_rsp(米家用的service data,纯单向)。如果存在多个蓝牙网关,那么都会向门锁发送scan_req,然后门锁就得向每个网关回复scan_rsp,这里门锁的处理能力、蓝牙网关间的时间冲突都有可能造成丢消息。

也不知道我这是不是瞎想

                               
登录/注册后可看大图

作者: involute    时间: 2022-6-30 21:16
XCray 发表于 2022-6-30 17:52
丢消息的问题确实让人头疼,和wifi的冲突、处理能力都可能。另外我还怀疑多个蓝牙网关可能也会造成问题— ...

我一开始Loock门锁丢消息丢得厉害(小米多模网关),后来找了Loock售后,换了个新锁。

好了。
作者: XCray    时间: 2022-6-30 21:45
involute 发表于 2022-6-30 21:16
我一开始Loock门锁丢消息丢得厉害(小米多模网关),后来找了Loock售后,换了个新锁。

好了。 ...

听着像蓝牙发射功率太低……

我这儿情况不一样:门锁赠送的蓝牙网关不丢消息,所以没理由找厂家(貌似都倒闭了哈哈)
作者: neroxps    时间: 2022-7-1 08:19
involute 发表于 2022-6-30 21:16
我一开始Loock门锁丢消息丢得厉害(小米多模网关),后来找了Loock售后,换了个新锁。

好了。 ...

看来是鹿客通病,其他小米的都很正常,而且鹿客的协议不按照米家的来,门内开门是蓝牙事件,上提把手是布防。
作者: 梅林听风    时间: 2022-7-8 11:12
我找人弄了一块板子,现在是有线ESPHOME,别说居然还成功了。。
作者: leonarddo    时间: 2022-7-10 07:28
楼主你好,我看了你的帖子买了esp32,尝试用来做网关和定位。网关试过了,想咨询一下室内定位的问题。我使用了esphome官方提供的ble-tracker方法,代码如下

# Example configuration entry
esp32_ble_tracker:
  scan_parameters:
    interval: 120ms
    window: 99ms


binary_sensor:
  - platform: ble_presence
    mac_address: C0:09:13:05:1D:CC
    name: "mi_band"

sensor:
  - platform: ble_rssi
    mac_address: C0:09:13:05:1D:CC
    name: "mi_band"

可以追踪到,并且显示信号强度。但是信号强度刷新速度很不稳定,快的时候一秒一次,慢的时候十几秒。请问有办法可以改善吗
作者: XCray    时间: 2022-7-10 07:36
leonarddo 发表于 2022-7-10 07:28
楼主你好,我看了你的帖子买了esp32,尝试用来做网关和定位。网关试过了,想咨询一下室内定位的问题。我使 ...

定位我没弄过,不过从原理上来推测,esp32只是被动接收,排除丢消息现象,这个刷新只取决于手环广播。也就是说,手环广播一次,esp32就有一次rssi数值,手环不广播的时候,esp32根本无从知晓手环的存在。

如果能有手段设置手环广播的周期就好了。
作者: leonarddo    时间: 2022-7-10 07:45
XCray 发表于 2022-7-10 07:36
定位我没弄过,不过从原理上来推测,esp32只是被动接收,排除丢消息现象,这个刷新只取决于手环广播。也 ...

也就是说,刷新速度不稳定是手环方面的问题?那只能凑合用了。。。有可靠的替代吗
作者: XCray    时间: 2022-7-10 09:11
leonarddo 发表于 2022-7-10 07:45
也就是说,刷新速度不稳定是手环方面的问题?那只能凑合用了。。。有可靠的替代吗 ...

ibeacon,广播周期固定,大多数还可以调节,甚至可以100ms发射一次。

另外,安卓手机有ibeacon模拟软件,苹果手机可以用irk识别,也是一个选择。

被动接收的思路只能这样了。

另一个大的思路是主动,比如我之前有个帖子介绍的monitor,主动查询手机等蓝牙设备,周期也可以控制,也有esp32的实现,name查询。。。慢慢了解吧
作者: leonarddo    时间: 2022-7-11 19:31
XCray 发表于 2022-7-10 09:11
ibeacon,广播周期固定,大多数还可以调节,甚至可以100ms发射一次。

另外,安卓手机有ibeacon模拟软件 ...

谢谢,都大致试了一下,感觉做室内位置判断还是有些勉强。
作者: dfhao123    时间: 2022-7-11 19:33
厉害,准备抽空也试一下!
作者: wuyouning    时间: 2022-7-12 01:33
真的是非常细致的思路,感谢楼主分享
作者: bainiu    时间: 2022-11-24 11:32
大佬,我之前在esp8266 nodemcu 上搞雷达人体、光电传感器、温探传感器都搞过。首次买了个esp32 .
1、在esphome上面用https://esphome.github.io/bluetooth-proxies,网站在线刷写固件,能在hass前端配置(输入KEY)接入小米温度计,人体传感器能看到除了触发传感器外的所有传感器,也能看到小米的全自动智能门锁配置,但是我不知道怎么搞门锁key(提取token和key的软件提取不了门锁的蓝牙key)所以门锁接不了。
2、按https://bbs.hassbian.com/forum.php?mod=viewthread&tid=16331&highlight=esp32自制开源ESPHome通用蓝牙网关(ESP32)帖子,修改相应代码能刷好固件,也能看到网关能识别小米蓝牙设备,但就是在 Passive BLE Monitor 集成上看不到设备(我在82楼有回贴)。
玩到这个时候我开始迷糊了,不知道怎么玩下去了,如果能通过esp32接入小米门锁和其他蓝牙设备,我的多模网关可以关机了(其他设备全在z2m下),请教大佬的esp32固件esphome代码及接入步骤,谢谢。

作者: XCray    时间: 2022-12-13 07:50
bainiu 发表于 2022-11-24 11:32
大佬,我之前在esp8266 nodemcu 上搞雷达人体、光电传感器、温探传感器都搞过。首次买了个esp32 .
1、在esp ...

代码和步骤我在其它帖子里能说的都说过了,慢慢看吧,这东西没办法三言两语交代清楚。
作者: lexcao    时间: 2023-4-2 09:09
两个帖子看下来有点儿懵。
把手头的esp32c3刷成普通的ble网关,能把智能门锁接进来吗?
作者: kkkkllll08    时间: 2023-7-23 13:17
本帖最后由 kkkkllll08 于 2023-7-23 13:20 编辑

PVVX/ATC_MiThermometer项目里面写道“If you have many BLE devices, the adapter must be able to receive BLE advertisements every 3 ms. UART speeds of 921600 baud and even USB1.1 are not enough to transfer information in binary form in the HCI format. Requires BT adapter with USB2.0 HS. Otherwise, there will be many gaps in the reception.

Do not use ESP32xxx - it cannot work with BLE at normal speed and drains the batteries of all BLE devices when connected!

ESPHome does not work with Bluetooth 5.0 and misses a lot of advertising packets from BLE devices.”
不知这个和丢消息是否有关
以及,有很多开源的以太网esp32项目,我现在在调试的就是用以太网的esp32,不过我目前只是接入小米温湿度计,对消息的即时性要求没那么高,不过之前esp32用WiFi接入时会有wifi连接困难的情况,所以改用以太网接入。
作者: XCray    时间: 2023-7-23 22:22
kkkkllll08 发表于 2023-7-23 13:17
PVVX/ATC_MiThermometer项目里面写道“If you have many BLE devices, the adapter must be able to receiv ...

确实是个值得琢磨的说法,虽然我还琢磨不明白
3ms,这是个非常短的时间,不能用esp32的说法也显得很夸张不过ESPHome对蓝牙5.0的支持度确实是个问题

无论如何,对于esp32来说,以太网肯定比wifi更好
作者: jy940006145    时间: 2023-9-8 10:20
neroxps 发表于 2022-6-30 17:21
我的鹿客 Q2 门锁,广播包,1秒会发两个,用USB 蓝牙接收器抓的话,几乎全部都能抓到,很少丢,esp32 还是 ...

大佬,不好意思,请教一下,你的鹿客门锁如何实现本地接入的?我通过几位大佬的资料,找到了beaconkey,但不知道为啥是40位字符,是还需要怎么转换么?
作者: Discard0268    时间: 4 天前
我是小白,我想问下,按照我的理解,树莓派上既有 Wi-Fi 也有蓝牙,能否自建蓝牙网关呢?目前遇到的问题是不知道为什么 bluetoothctl 没办法连接小米蓝牙开关。




欢迎光临 『瀚思彼岸』» 智能家居技术论坛 (https://bbs.hassbian.com/) Powered by Discuz! X3.4