XCray 发表于 2020-7-16 18:31:36

(多个)蓝牙网关 TTL->MQTT,支持任意米家蓝牙设备接入HA/NR

本帖最后由 XCray 于 2021-6-16 11:26 编辑

20210527更新:
改用n大的ESPHome实现方案,我对N大的代码稍微做了修改,主要是mqtt的topic和我以前的代码保持一致,这样之前做的ha侧的配置就不用动了,无缝切换。

直接解压到esphome目录,然后根据自己的需要修改后编译、下载后利用原固件的ota升级即可。以后的修改就完全在ESPHome里完成了。

感谢n大,把我之前想做但没有做到的思路给实现了。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20201103补充,重大缺陷:
小米蓝牙网关只有在完成云端通讯之后才会从TTL接口输出我们需要的消息,这样在网络状况不佳时,时延问题仍然不可避免!并且在外网中断时,TTL接口根本没有有用输出。

20210616补充:
可用的解决方案:用esp32等具备蓝牙接口的东西直接接收解密门锁发出的蓝牙消息,真正的零时延、真本地,详见签名贴。

当然,这个玩法的价值还是有的,只不过不像原来想的辣么好。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
最重要的一句话:可以同时支持多个蓝牙网关、任意蓝牙设备(只要能连接蓝牙网关)本地接入HA/NR,通用固件不用自己编译,含配网、OTA等功能。

当然,说的都是米家app里的东西,包括小米/米家和各个生态链企业的各种蓝牙产品。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
前段时间在killadm和jstormx等大神神贴的基础上,使用ESP-01S模块实现了从蓝牙网关TTL接口获取数据、转发至MQTT,从而实现了将蓝牙门锁、花花草草、蓝牙温湿度计2等蓝牙设备接入HASS,解决了之前最为头疼的门锁无法本地利用的问题。详见之前的帖子:

      - 米家蓝牙器件接入HA的最佳方案:蓝牙网关+TTL+MQTT,ex榉树锁
            https://bbs.hassbian.com/thread-10055-1-1.html
         注:这个帖子一定要看,硬件连接、来龙去脉、整体思路等等内容这儿就不再重复了。
      - 填坑:killadm大神的LOCK2MQTT代码改造、编译、烧录
            https://bbs.hassbian.com/thread-10218-1-1.html
          注:这个帖子也要看,如何编译、烧写固件等重要内容这儿也不再重复。
      - !ESP Home实现基于蓝牙网关-TTL的智能门锁等蓝牙设备接入
            https://bbs.hassbian.com/thread-10250-1-1.html
         注:这个帖子可以不看,算是一个分支,实验性的,我自己都不用。
      - 我好像找到了ESP8266转发TTL串口发生丢消息问题的根本原因
            https://bbs.hassbian.com/thread-10276-1-1.html
         注:这个也要看,丢消息问题会造成自动化不触发等严重问题。

上面这几个帖子加上本贴,足以把整个事情交代的清清楚楚了。思路理清楚,实际操作才能心中有数。
另外,8楼有硬件连接信息,包括榉树网关和小白万能遥控器声控版。

正式开始:
经过两个月的运行,代码倒是基本稳定,一度造成困扰的丢消息现象也得到了解决。可是这个版本总是有一点不爽:只能适应手上有的这几个蓝牙设备。如果以后增加新的设备,还需要重新修改代码、重新编译升级,其他机油也难以直接拿去使用。

这两天突然想出了一个以不变应万变的方法:尽量简化ESP模块的任务、剩下的全部让HA承担。

具体来说,就是:

- ESP只负责从TTL获取数据、最简单的筛选(挑出含ble_event的行并从中摘出did/eid/edata这3项数据)、最无脑的转发(mqtt topic设为mqttl/did/eid,payload就是edata)。必须强调的是,对于长度超过1个字节的edata,根据格式要求进行逆序调整。
这样,不管是什么类型的蓝牙设备,只要可以连接蓝牙网关,就直接可以适应,不需要在ESP这边做任何适配工作。

- HA侧基于mqtt topic设置传感器,利用强大的template完成数据适配工作,包括edata串的截取、十六进制转换、时间戳转换等。

ESP侧核心代码:
    //提取did/eid/edata
String did = params["dev"]["did"];
int eid = params["evt"]["eid"];
String edata = params["evt"]["edata"];
if (edata.length() > 2) edata = revstr(edata);//凡长度超过2的edata一律调整逆序
String topic = "mqttl/"+did+"/";
topic += eid; //核心语句
mqtt_client.publish( topic.c_str(),edata.c_str(),false);HA侧,根据自己的需要和相应设备的消息格式,在yaml里完成所有的适配工作,比如榉树门锁的状态报告和开锁事件的4个传感器:
sensor:
- platform: mqtt
    name: LockStatus
    icon: 'mdi:door-closed-lock'
    state_topic: 'mqttl/设备did/4110' #替换成正确的did和eid
    value_template: >-
   {% if value == '00' %}
      门未关!
      {% elif value == '01' %}
      已关,未闩
      {% elif value == '02' %}
      已上闩
      {% endif %}
- platform: mqtt
    name: LockOpera
    icon: 'mdi:lock-smart'
    state_topic: 'mqttl/设备did/5' #替换成正确的did和eid
    value_template: >-
       {% if value == '0200' %}
         指纹
       {% elif value == '0100' %}
         密码
       {% elif value == '0000' %}
         蓝牙
       {% endif %}
- platform: mqtt
    name: KeyID
    icon: 'mdi:human-handsdown'
    state_topic: 'mqttl/设备did/5' #替换成正确的did和eid
    value_template: "{{ value }}"
- platform: mqtt
    name: OpTime
    icon: 'mdi:clock-in'
    state_topic: 'mqttl/设备did/5' #替换成正确的did和eid
    value_template: "{{value|int(0,16)|timestamp_local }}"4个传感器分别为门锁状态、开锁方式、keyid、开锁时间。

完整的源码(WiFi、MQTT硬编码,需要自己编辑、编译):

第12~16以及22~25行,为wifi和mqtt相关配置参数,根据自己的情况修改即可

注:更新的通用版在本贴最后

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20200717补充:
免编译通用版固件(含源码),直接在killadm最新版源码基础修改,保留配网功能。懒得自己编译的,可以直接刷入bin文件、配网(设置wifi名称密码和mqtt服务器参数)后即可使用。如果原固件支持OTA,也可以OTA刷入。

配网方法:
如果没有配置wifi,模块就会启动热点,名称为 mqttl_xxxx,密码为 mqttlpassword 。

用手机等任何设备连接此热点就会自动进入配网页面,选择ssid,输入wifi密码、mqtt服务器地址端口号、用户名密码(如果有的话),保存。

保存后模块会重启,以后就都会以刚才保存的这套参数工作,直到重新刷。

之所以设置密码,是防止周围闲的蛋疼的人瞎连

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20200718补充:

免编译通用版固件(含源码)更新,参阅18楼dscao朋友的说明,进一步提高适应性,根据模块序列号自动生成主机名(用作mqtt客户端id,和配网时自动生成的ssid名称一样,mqttl_xxxx),避免了多个模块使用同一个clientid连接至同一个mqtt服务器造成冲突的问题。这样,家里有多个蓝牙网关的,可以放心大胆地给每一个蓝牙网关接一个esp8266模块同时使用了。


同样,压缩包里有源码和编译好的固件,懒得自己编译的可以直接刷。
可能有人还不知道,这个系列的固件(从killadm的代码开始)都是支持OTA的,通过http://ip地址/update访问、输入用户名和密码(默认都是admin)就可以上传升级固件了(上传后会自动用新的固件重启)。

~~~~~~~~~~~~~~~~~~分割线也升级了~~~~~~~~~~~~~~~~~~
20200719补充:

小修改,倒数第二行,主循环最后的delay(100)修改为dely(1)。

100可能延时偏大,造成了消息丢失现象(很可能是、也可能不是这个原因)。

12个小时里丢失7条,已经达到无法忍受的程度了!

之前用10,几天偶尔可见一次丢失,一直不确定是不是延时造成的。

改成1观察了一段时间,效果非常好,连续几天没有发现丢消息的问题,运行很稳定(我一直把网关敞着盖、ESP-01S模块露在外面)。

同样,源码和编译好的固件都在包里,直接OTA即可


没有特别原因的话,这个版本基本不需要再做修改,可以长期使用了。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
剩下的事情才是最重要的:兼容所有米家蓝牙设备!
ESP这边的工作没问题了,我们需要在HA侧针对每种设备定制yaml。我在3楼放上了我自己根据实际收集到的消息和小米文档定制的榉树门锁、花花草草监测仪和蓝牙温湿度2的配套yaml,同时我把看到的其他坛友提供的配套yaml信息也都放在3楼,大家多多沟通。

接下来,我有个提议:如果你用的是其他坛友未提及的种类的蓝牙设备,请上传你的yaml(可以把did隐去)。

或者你不知道如何定制yaml的话,可以把收集到的消息发出来,我们一起讨论如何编辑yaml(3楼有小米官方文档链接)。

相信经过大家的共同积累,用不了多久,这个程序一定可以纳入全部米家蓝牙设备、给更多的人带来更大的便利。



余歌唱晚 发表于 2020-7-16 18:46:59

沙发坐一坐,未拆封小白遥控的设备终于用得上了。。。

XCray 发表于 2020-7-16 19:15:03

本帖最后由 XCray 于 2020-9-1 06:41 编辑

那么问题来了:消息格式未知、did未知的设备如何加入呢?
当然,首先要做的是把设备的did、所有的eid和edata格式弄清楚。一是小米官网的文档(https://iot.mi.com/new/doc/embedded-development/ble/object-definition),更重要的是收集设备产生的数据。

以ha 0.112.3版本为例,侧边栏选“配置”,然后到“集成、MQTT、配置”,订阅主题那儿输入“mqttl/#”,然后点“开始监听”就可以收集数据了,然后就可以根据收集到的数据编辑yaml文件进行适配了。当然,先要完成编辑、编译代码(就是压缩包里的ino文件)、烧写或OTA、正确连线等准备工作。

如果碰到了有数据但不知道如何编辑yaml的问题,可以提出来讨论,这几天有些收获。
其实,就我个人的感受来说,难度更大的不是esp上的代码,而是ha中的yaml配置,尤其是template!强大是真强大,但搞明白它独有的逻辑和玩法,还是有些费脑筋的。

这是我已经适配好的3种蓝牙设备的yaml,分别是榉树智能锁、花花草草监测仪、蓝牙温湿度2;其中花花草草有两个。其他如果一种设备有多个,可以参考办理。
如果你也有这3种当中的任何一个,可以直接用,只需要把文件中的“设备did”替换成自己的did即可。


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
接下来,我有个提议:如果你用的是其他坛友未提及的种类的蓝牙设备,请上传你的yaml(可以把did隐去)。

或者你不知道如何定制yaml的话,可以把收集到的消息发出来,我们一起讨论如何编辑yaml。

相信经过大家的共同积累,用不了多久,这个程序一定可以纳入全部米家蓝牙设备、给更多的人带来更大的便利。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20200806补充:
99楼有sunshine朋友提供的一代蓝牙温湿度计yaml配置。
期待更多的朋友补充更多的yaml样本~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20200808补充:
这里有chenquanhao朋友提供的鹿客Classic 2X的 yaml,以及创米小白万能遥控器声控版的更详细的使用方法:
https://bbs.hassbian.com/thread-10575-1-1.html
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20200815补充:
109楼有ghostist朋友提供的米家智能锁yaml,使用同样型号的坛友有福了!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20200820补充:
142楼有dscao朋友提供的米家感应夜灯蓝牙版的yaml,使用同样型号到的坛友有福了!
另外,dscao提出的代码改进对于经常调整mqtt服务器的朋友也非常有用。他在144楼提供了编译好的固件,感谢dscao,需要的朋友可以直接下载使用。

等有空了我合入到主贴的固件里~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20200901补充:
149楼以及下面这个链接有dscao朋友提供的小米门窗传感器2的yaml,适配的硬件又多了一种!感谢dscao!
https://bbs.hassbian.com/thread-10725-1-1.html


dscao 发表于 2020-7-16 19:24:33

本帖最后由 dscao 于 2020-7-16 19:35 编辑

这个非常好,就是要一个通用的固件,免得经常刷固件。楼主辛苦了!
又有东西继续折腾了

dscao 发表于 2020-7-16 19:53:00

LOCK2MQTT中用“method”数据更全面
//获取串口数据中含有method字符的json,基本上涵盖了网关状态、红外收发编码、蓝牙事件、指示灯状态等信息
//我手里没有别的蓝牙设备,没办法抓数据,猜测如果单纯作为蓝牙网关的话只匹配ble_event就够了
    if (parse_result.Match("\{.*method.*\}") == REGEXP_MATCHED) {

看了你的代码还是这个:
//获取串口数据中含有ble_event字符的json
if (parse_result.Match("\{.*ble_event.*\}") == REGEXP_MATCHED) {

建议为了支持更全面的设备修改为:
if (parse_result.Match("\{.*method.*}") == REGEXP_MATCHED) {

比如这种消息也能收到:

下午5:27 收到关于 LOCK2MQTT/json 的消息[ 6 ]
{
    "id": 1688666117,
    "method": "event.miio_mode",
    "params": [
      2
    ],
    "retry": 0,
    "timestamp": 8,
    "tick": 8240
}
QoS: 0 - Retain: false

XCray 发表于 2020-7-16 20:03:02

本帖最后由 XCray 于 2020-7-16 20:08 编辑

dscao 发表于 2020-7-16 19:53
LOCK2MQTT中用“method”数据更全面
//获取串口数据中含有method字符的json,基本上涵盖了网关状态、红外收 ...
需要的话,当然可以改了。

问题是这条消息有啥用呢?

我的情况是只有ble_event的消息有意义,所以就用这个筛选了(我用的是榉树锁附送的网关,没有红外)。

网关状态、指示灯状态对应的消息是啥?我专门收集过没有ble_event的消息,没看到有实用价值的

dscao 发表于 2020-7-16 21:42:39

XCray 发表于 2020-7-16 20:03
需要的话,当然可以改了。

问题是这条消息有啥用呢?


也是,好像没什么实际作用。我用小白遥控的。遥控方面,miio已经支持了。

另外killadm大神的LOCK2MQTT原版中的热点配置网络,个人感觉还是值得保留的。配置方便,下载固件刷机就好,不用再去安装编译环境(第一次还是有点折腾)。安全性方面也没什么问题,局域网才能ota,配置正常联网后热点不启用。关键是方便通用。

XCray 发表于 2020-7-17 07:45:12

硬件连接信息汇总

本帖最后由 XCray 于 2020-9-9 07:27 编辑

这个玩法只需要连接3根线,分别为:
蓝牙网关端ESP端      作用
GND         GND       公共地
TX               RX          网关至ESP串口
VCC/VDD   3V3/5V   电源



其中最需要注意的是电源!


ESP模块,大部分使用3.3V的工作电压,接5V必烧!!!也有一部分尤其是开发板,使用5V(板载转3.3V的电路,因为芯片自身用的就是3.3V)。


3.3V的针脚,一般在电路板上会标成“3V3”。


蓝牙网关,一般都会有针脚或焊点可以对外提供电源,有5V的,也有3.3V的。具体是哪个,需要用万用表测量或者参考别的机油共享的信息。


具体来说,我用的榉树网关提供的就是3.3V,就是下图中的“VDD”,详细信息:
https://bbs.hassbian.com/thread-10055-1-1.html
https://bbs.hassbian.com/data/attachment/forum/202005/23/185103jfazdbkobanifv02.jpg

还有一种很多人使用的网关,就是小白万能遥控器声控版,板子上5V的和3.3V的供电都有。
chenquanhao机油在这个帖子里提供了详细信息,并给出了3.3V焊点的清晰照片:
https://bbs.hassbian.com/thread-10575-1-1.html
https://bbs.hassbian.com/data/attachment/forum/202008/08/024751g0y0zcvztjcvjibv.png
另外,还有一个焊点标注的是VBUS,提供的5V电压,这篇文章里有照片,虽然不是特别清楚:
https://post.smzdm.com/p/a4wmp04x/
https://qnam.smzdm.com/202005/22/5ec7b6da627ab485.jpg_e680.jpg

再次提醒:5V和3.3V一定要注意区分,3.3V的ESP模块接5V必烧!

ghostist 发表于 2020-7-17 09:11:30

准备出掉小爱闹钟 换小白网关+小爱play了

XCray 发表于 2020-7-17 09:27:30

本帖最后由 XCray 于 2020-7-17 17:29 编辑

dscao 发表于 2020-7-16 19:24
这个非常好,就是要一个通用的固件,免得经常刷固件。楼主辛苦了!
又有东西继续折腾了


没错,这个思路就是要打造一个通用的固件。

主贴最后加入了通用版固件,懒得安装arduino ide自己编译的,可以直接刷入(线刷或OTA均可)、配网后即可使用。

顺便说一句:之所以把逆序调整放在esp代码里完成,是因为我实在想不出如何在ha里实现。或者即使可以实现,也更复杂、远不如直接在esp里实现更简单。
如果哪天找到了ha里进行逆序调整的更简便的方法,毫无疑问,esp就可以再进一步简化了。
页: [1] 2 3 4 5 6 7 8 9 10
查看完整版本: (多个)蓝牙网关 TTL->MQTT,支持任意米家蓝牙设备接入HA/NR