标签 Home Assistant 下的文章

我的智能设备都是在Home Assistant下控制的,小米设备控制插件用的是Xiaomi Miot For HomeAssistant

这个插件很棒,也是之前唯一可用的小米LOT插件,好多年了al-one一直在全力更新,最近更是更新了一个大的1.X版本。不过大版本略有些小问题。

周中小米官方突然更新了一个Xiaomi Home Integration for Home Assistant,很快star就达到了10K+。

今天新装了一个HA,跑了一下ha_xiaomi_home,对于我来说两者使用功能上差距不大。

小米的可控实体更多一些,一些触发型设备(如按键开关)也有了(触发是不可以的),网关的控制也有了一些,看到了虚拟事件实体(还不知道是否可用)。

两个插件实现逻辑不同,一个是推,一个是拉。Xiaomi Miot使用的是轮询的方法,每分钟查询一次数据,属于拉数据;xiaomi_home用推数据,时效性上更有保证。

因为我基本上都是用的脚本查询设备状态、控制设备状态。脚本本身cron的周期是1分钟,所以对于我来说,两者使用上没啥区别。

小米官方给的逻辑图:
1.jpg

我已经把我的家居控制脚本改为了官方插件版,简单测试了一下基本都正常。持续观察一下。

现状

我的米家设备几乎全是通过home assistant api控制的,设备按照策略自动执行,很少人工干预。我只需要开/关这些策略就可以了。

米家app&home assistant之间的通信,主要靠设备的状态指示灯,把指示灯作为寄存器来传递状态,这好像是一个通行办法,比如空气净化器的状态指示灯。貌似也没有什么其他更好的办法了。

问题

我有一个策略是出差长期离家后所有的环境设备就不用再工作了,我用一个空气净化器的状态指示灯来控制策略的ON/OFF。
然而当我一段时间不出差之后,我就再也想不起来是用哪一个设备的状态指示灯来控制这个策略的了。

解决

我买了一个4路继电器模块充当寄存器,用继电器的开关状态来作为策略开关。
这个板子很便宜,27元,质量一般般,用的小米的蓝牙通讯模块。
1.png

看看长啥样子
2.jpg
3.jpg
4.jpg
5.jpg

继电器看起来是二手的,用的二手元器件?
6.jpg

小米的蓝牙通讯模块
7.jpg

使用上是非常的方便,完全满足我的需求,
8.jpg

最后

这个板子质量一般般,没有外壳,用作强电控制的话,非常危险。
可以自己3D打印一个外壳。

WLED

项目地址

WLED Project: https://kno.wled.ge/
GITHUB: https://github.com/Aircoookie/WLED

WLED 是什么?

WLED是用ESP8266/ESP32模块控制NeoPixel的项目。

  • 支持各种灯带,灯环,灯板,
  • 有非常多的特效,支持各种参数的控制;
  • 支持各种控制方法,Serial、MQTT、HTTP、Websocket等等;
  • 有电脑端,移动端的WEB控制界面;
  • 支持 home sassistant 集成;
  • 浏览器直接刷写固件;

总之WLED几乎就是玩LED界的天花板。

WLED & home assistant

home assistant 自带 wled 集成,wled上线后,home assistant能自动识别到wled,简单添加即可。

米家的智障设备

米家的智能设备只能定时、条件触发这两个最简单的操作,说白了就是一个定时自动开关,复杂一些的场景就无能为力了。
单靠米家这点功能,想要智能门都没有,只有自己控制设备,实现智能化。

按照这个思路开始折腾

方案1,ZigBee

我有一个最老款的米家ZigBee一代网关,以前写过ZigBee控制协议,Server端可以接收到网关下所有子设备的通讯数据(组播收),Client端可以模拟子设备发送数据,模拟心跳、 模拟传感器、模拟无线开关都没有问题,做联动触发也都正常(单播发),

ZigBee虽然能控制的设备有限,只要能控制网关下子设备的触发,再结合米家的场景,组合起来应该也将就够用了,跑了一下程序,发现Server可以运行,Client端无法运行了,只可以接收数据,不能发送数据了,搜索一下发现是一代网关插件升级之后不允许局域网通讯了,插件还无法降版,这条路断了,

PS:即使这条路没断这也不是一个好的方案,
1,一代网关太老了,缺乏新的支持,产品已经停产,新的网关更不支持局域网接入,
2,小米自家也在慢慢的淘汰ZigBee换用蓝牙

方案2,Home Assistant

自己写程序控制设备,Home Assistant应该是天选的,HA有原生的REST API,很灵活很方便,简单易用、坚固稳定。
其实HA应该是第一选择,但HA装系统、配置、导入设备,都比较麻烦,实在有点太折腾了。

ZigBee的路不通,没办法只能走HA这条路了,虚拟机装好HA,MIIot装好,设备绑定好,API调试好,问题又来了,HA对米家的设备支持不全,触发设备全都不能控制,支持的设备还有很多功能缺失,比如,浴霸只能开关灯,通风,排风,暖风这些功能全都缺失了,触发设备不支持,控制触发设备结合米家场景的方法也都行不通了,

两条大腿都断了,准备放弃这个事了。不死心,又盘了盘,Github看了看,发现有抓包模拟协议控制设备的,协议控制一般是我的首选,很久之前我就尝试过抓包,发现双向都是加密的,看了看也就放弃了,当时也没有硬需求,之后也就没多做研究,现在已经没有其他办法了,不死心,硬着头皮上,再抓包试试...

方案3,协议控制

协议控制的好处是可以一次性解决所有的问题,指令直接发送到小米云端和设备无关和系统无关,丢数据到api.io.mi.com,由小米云端下发设备控制,高效稳定,梳理协议是最复杂难度最高的,无法解密的概率是很高的,当然解密了收益是最大的,有两个关键问题,

1,RC4密匙的算法
sha256(ssecurity + _nonce)

2,请求签名加密方法
反正也不知道sign的具体格式到底是啥 各种调 各种尝试 结果如下:
uri . key _nonce . data

提交数据有两种方式
1,加密方式,RC4加密,以后可能都要RC4加密
2,明文,目前可用,可能是在兼容老设备?

构建请求JSON
构建请求JSON必须解密RC4,按照原数据结构再构建请求数据,数据结果详细说明可以通过https://home.miot-spec.com/查询,读两遍别人的代码,把代码删减一下,Python跑通,用更简单的PHP重新写一遍,方便网页控制10几行代码DEMO测试通过... 前前后后折腾了一个礼拜,备忘,

参考:
https://www.xiaoweigod.com/network/2235.html
https://kero.ink/posts/mihome-app-api.html
https://github.com/PiotrMachowski/Xiaomi-cloud-tokens-extractor/blob/master/token_extractor.py

发现问题:
稳定运行1个多月之后发现抓包获取到的授权过期了,原来这个授权是会过期的,生命周期并不很长!总不至于每个月抓一次吧授权吧。

解决方法:
跑脚本,模拟一遍登录流程,抓取登录后的cookie,保存到本地,定期获取一下,周期暂时先放到1个月试试。

更新

今天我更新了一下Xiaomi Miot Auto发现多了一个可选项,

禁用米家APP通知消息实体 这个虚拟传感器以前就有 但我没有使用过
禁用米家场景历史实体 这个是新增加的 正好两个一起研究一下

v0.7.14 的更新,add scene history sensor (#1361)
https://github.com/al-one/hass-xiaomi-miot/releases/tag/v0.7.14

打印一下传感器信息:

sensor.mi_345123456_message

Array (
    [entity_id] => sensor.mi_345123456_message
    [state] => 摄像机: 用户345123456于23:42在带屏音箱上观看摄像机 储藏室直播视频.
    [attributes] => Array
        (
            [entity_class] => MihomeMessageSensor
            [filter_homes] => Array
                (
                )

            [exclude_types] => Array
                (
                    [0] => 13
                )

            [msg_id] => 17344867324567850112
            [is_new] => 1
            [type] => 6
            [title] => 用户345123456于23:42在带屏音箱上观看摄像机直播视频.
            [content] => 摄像机
            [user_id] => 345123456
            [ctime] => 1703173364
            [timestamp] => 2023-12-21T15:42:44+00:00
            [model] => isa.camera.hlc6
            [device_id] => 345123456
            [home_name] => 大楼
            [room_name] => 一楼
            [event] => stream
            [event_data] => 
            [prev_message] => 小米智能摄像机: 用户345123456于23:09在带屏音箱上观看小米智能摄像机直播视频.
            [icon] => mdi:message
            [friendly_name] => Xiaomi 345123456 message
        )

    [last_changed] => 2023-12-21 23:42:56
    [last_updated] => 2023-12-21 23:42:56
    [context] => Array
        (
            [id] => 01HJ6ASDFARTEGWT083FPEH
            [parent_id] => 
            [user_id] => 
        )
)

sensor.mi_666666666_66660166660575_scene_history

Array (
    [entity_id] => sensor.mi_345123456_884885886887_scene_history
    [state] => 旅行
    [attributes] => Array
        (
            [entity_class] => MihomeSceneHistorySensor
            [from] => user
            [name] => 旅行
            [ts] => 1703173662
            [timestamp] => 2023-12-21T15:47:42+00:00
            [scene_id] => 1731231401335251234
            [targets] => Array
                (
                    [0] => Array
                        (
                            [at] => phone
                            [error] => 0
                            [note] => 
                            [origCode] => 0
                            [origErr] => 
                            [t] => 1
                        )

                )

            [prev_value] => 有人移动-米家智能充电台灯开灯并设置灯光
            [prev_scene_id] => 1721231066712417412
            [icon] => mdi:message
            [friendly_name] => Xiaomi 345123456_884885886887 Scene History
        )

    [last_changed] => 2023-12-21 23:47:57
    [last_updated] => 2023-12-21 23:47:57
    [context] => Array
        (
            [id] => 01HJ6XXXXXXXXXXJQKQM2DFM5Q
            [parent_id] => 
            [user_id] => 
        )
)

作用

一个是记录米家的通知消息,一个是记录米家的场景消息,通过这两个虚拟传感器,就可以捕捉到米家智能化都做了些什么。但home assistant是通过轮询来工作的,所以消息不是实时的。

但是不管怎么说,这都为米家 & home assistant 通讯提供了另一条途径。

问题

  • 这两个传感器都只保留最后两条消息,(当然可以通过读取日志获取更多的历史消息)
  • 读取的消息不是实时的,轮训的周期应该是30秒,当然可以自定义
  • 每次读取最后一条消息,如果瞬间触发了5个场景事件,生成5条消息,那么除了最后一条,其余4条就都被MISS了,

使用

未完....

Home Assistant

Home Assistant是一个IoT设备的集中管理平台,他可以解决各家产品相互不兼容的问题。

我用的最多的设备是米家,其次是易微联,还有少量的其他品牌的产品,另外还有一些自己DIY的设备,比如WLED,ESP8266的继电器等等。

这些品牌都互不兼容,或者蹩脚兼容。好在这些品牌几乎都能被Home Assistant所支持,或者说大家都符合相关IoT标准。

丢弃米家接口

我一直都是通过对https://api.io.mi.com/app接口进行抓包,而后将数据rc4加解密,直接对米家APP的接口进行读写操作。这套流程很麻烦,涉及到抓包,签名,授权,数据加解密等各个环节。

[抓包米家app文章] 米家"智能"设备折腾 模拟米家协议

麻烦是麻烦些,因为是直接操作的米家APP接口,好处是相当稳定。随着手机抓包的越来越难,加之有个别新的设备抓包数据莫名其妙的无法解密,比如最新的人体传感器2S,所以我决定弃用解密米家APP的方案。

即使数据可以解密,这个方法也不是长久之计,说不定哪天一更新就不能用了,所以我决定扔掉用了几年的米家接口。

请勿索要米家APP接口协议,因为这涉及加解密,其实GITHUB上有,我就是参考的别人的代码,也可已参考上文完整的思路已经给出了

Home Assistant REST API

REST API是Home Assistant另外一个非常大的特点,别的品牌也有开放接口给开发者的,但是这些接口更多的是给产品、给厂商,并不是给普通用户的。

Home Assistant的API是面向用户的,你只需要会一点点基础编程就可以使用,最少也就3-4行代码就可以解决问题了。

比如,要把灯打开:

// php
$token = "xxxxxxxxxx"; // token
$id = "xxxxxxxxxx"; // 设备id
$url = "http://192.168.1.15:8123/api/services/light/turn_on"; // hass 服务器地址
$opts = ["http" => ["method" => "POST", "content" => json_encode(['entity_id' => $id], 320), "header" => "Authorization: Bearer {$token}"]];
file_get_contents($url, false, stream_context_create($opts));

加上一个cron就可以做一些自定义的控制了。

Home Assistant REST API 官方文档:

HA的API几乎可以做所有的操作,官方文档有详细实例。
https://developers.home-assistant.io/docs/api/rest/

开启Home Assistant接口功能

API功能是Home Assistant系统默认就带的,只需在菜单administrator中开启高级模式,再在长期访问令牌中添加一个TOKEN就可以了。

注意生成了TOKEN要及时复制保存,关闭了alert就再也看不到了。

除了灯和开关 为什么找不到其他的控制方法?

灯和开关都可以找到demo,一搜一大堆。除了这两个方法之外就几乎再也找不别的方法实例了,github和官方文档都没有,难道所有人只操作灯和开关?

官方文档services方法这样写:

Returns an array of service objects. Each object contains the domain and which services it contains.

看了几遍我都没有明白,直到我把自己的services全部打印出来,里面把所有的域名,方法,属性全部列了出来。
只要按照里面的数据,构建自己的请求就可以了。

我做了4个方法:

  • light 控制灯
  • switch 控制开关
  • cover 控制电机(窗帘等)
  • text 控制小爱语音

如果有小爱,是有一个偷懒的办法的,只要一个text就够了,所有的操作都让小爱去干就可以了,比如关闭4个灯:
light(灯0, off),light(灯1, off),light(灯2, off),light(灯3, off)

text(小爱同学,关闭所有的灯。)