家里虽然购买了许多可以连网的智能设备,但是设备联动,自动化却并没有怎么弄。最复杂的一个地方也就是家里的次卫。

利用米家的人体传感器2与门窗传感器2还有智能浴霸Pro,实现了一个简单的自动化。可以在开门的同时根据次卫的环境光亮度决定是否开灯,并且可以在没有人的情况下自动关灯。不过受限于小米没有区分动作和状态,且浴霸灯的开/关无法被当作事件来触发,一直没法完整的覆盖所有的使用情况。

当时去论坛查找解决方法的时候,就有人提到过可以利用 Home Assistant 来解决问题。但是需要额外购买硬件,一直没有去尝试。在去年家里买了一台 NAS 之后,家里具备了部署 Home Assistant 的条件,然而那段时间觉得接入设备麻烦,就没有弄。

最近突然看到一个仓库 xiaomi_miot_raw,可以将小米设备自动的接入 Home Assistant。看到能这么容易接入小米设备,便动起去尝试一下的心思。稍微搜索一下,发现米家与 Home Assistant 是可以共存的。这样就算我没有成功解决问题,也不会影响到现在的智能家居使用体验。

安装

通过上网搜索,没想到安装 Home Assistant 异常方便。

首先在 NAS 上安装 Virtual Machine Manager,根据提示设置好软件后,再导入从 官网 下载的 ova 文件。除了记得固件选择 UEFI 外,其他均可一直下一步,待设置完成之后直接启动即可。

不过从现在开始,你就需要等待一段时间(20 分钟以上),因为会从 ghcr.io 上下载镜像,而国内访问速度感人。

反向代理

因为我域名开启了 HSTS,必须使用 HTTPS 访问,所以需要在 NAS 上设置反向代理到 Home Assistant 网站。但我发现发送到 Home Assistant 的请求总是被拒绝。

通过查询 文档,还需要在配置中添加以下设置才能正常访问。

http:
  use_x_forwarded_for: true
  trusted_proxies:
    - 10.0.0.200      # NAS 的 IP 地址

VSCode

安装好 Home Assistant 之后,我第一时间安装了 VSCode 加载项。因为想到之前看过的 Open Source Home Automation - Home Assistant - Open Source Friday 中,介绍过利用 VSCode 来编辑配置。

Node-RED

启动前设置好 credential_secret,并关闭 ssl,不然会报错。

ESPHome

在 VSCode 中的 ESPHome 插件无法访问到 ESPHome Dashboard。

Cannot connect to ESPHome dashboard. Make sure you can access 'http://15ef4d2f-esphome.local.hass.io:6052/' and have set the option 'leave_front_door_open': true

根据论坛的 回复,我进行了设置,依然会报错。最后我发现是主机名称的问题,在我这里显示的主机名为 a0d7b954-esphome,当我将设置里的 15ef4d2f-esphome 改成我所显示的,一切都恢复正常。

HACS

直接通过 VSCode,在命令行中输入 wget -O - https://get.hacs.xyz | bash -,即可完成安装。根据提示完成配置即可。

通过 HACS,就可以下载 Xiaomi MIoT 及其他自定义集成。

设备接入

次卫的自动化,需要三个设备,智能浴霸Pro(WiFi 连接),人体传感器2与门窗传感器2(蓝牙网关连接)。

小米

通过 xiaomi_miot_raw 可以方便的将设备接入,不过均是通过云端接入。

我首先尝试将自动化所需的门窗传感器,人体传感器还有浴霸都接入进来。结果发现这个集成其实并不适合我想要的自动化。因为云端接入的延迟太高,我开门之后 2 秒以上,门窗传感器的状态才会更新。其他传感器也有不小的延迟。为了实现自动化的及时响应,看来必须要把设备通过本地接入。

蓝牙设备

我看到 ESPHome 支持接入小米的蓝牙设备 Xiaomi Mijia BLE Sensors。可以直接利用 ESP32 充当蓝牙网关获取蓝牙设备的数据,

还好家里有一个之前玩单片机时买的 ESP32。不过 ESPHome 官方并没有支持小米门窗传感器2,还好有人提供了支持。MCCGQ02HL 这个型号,也就是小米门窗传感器2。

在测试过程中,我发现会经常丢失数据包,明明已经关门了,但是 Home Assistant 上的状态还是开门。根据 文章 里提到,默认的 window 太小,所以需要调整 scan_parameters,才能保证接收到的数据包完整。

人体传感器2 miot_rtcgq02lm,我也尝试了一下,结果发现触发之后无法恢复至未触发,不知道是什么原因。上面设置参数之后也没有效果,似乎不是丢失数据包的问题。因为我对具体的代码并不了解,只能凑合继续使用云端接入。

WiFi 设备本地接入

智能浴霸Pro 可以通过 miio_yeelink 本地接入 Home Assistant。

默认情况下 30 秒才更新一次状态,这样间隔太长了,无法作为自动化的条件。所以需要手动通过修改 configuration.yaml 设置 scan_interval。参考:Entity integration platform options

light:
  - platform: miio_yeelink
    name: Mi Smart Bathroom Heater Pro
    host: !secret xiaomi_mi_smart_bathroom_heater_pro_host
    token: !secret xiaomi_mi_smart_bathroom_heater_pro_token
    model: yeelink.bhf_light.v5
    scan_interval: 1

不过通过 WiFi 接入时,只能通过 local polling 获取状态,过短的请求频率(比如 1 秒),有时候设备无法及时响应。

2021-09-30 15:05:14 WARNING (MainThread) [homeassistant.components.light] Updating miio_yeelink light took longer than the scheduled update interval 0:00:01
2021-09-30 15:05:17 WARNING (MainThread) [homeassistant.components.light] Updating miio_yeelink light took longer than the scheduled update interval 0:00:01
2021-09-30 15:05:18 WARNING (MainThread) [homeassistant.components.light] Updating miio_yeelink light took longer than the scheduled update interval 0:00:01

如果减低请求频率的话,状态更新的延迟会增大,自动化的体验就会打折扣。

自动浇水

之前家里一直在使用的自动浇水,可以通过 ESPHome 完美实现我现在所有功能。

使用 number 可以实现从 Home Assistant 中设置延时的长度。

number:
  - platform: template
    name: "Valve1 Delay"
    id: valve1_delay
    initial_value: 360
    min_value: 0
    max_value: 999
    step: 1
    optimistic: true
    restore_value: true

利用 script 可以实现开启阀门之后的延时关闭。

script:
  - id: valve1_delay_off
    mode: restart
    then:
      - delay: !lambda |-
          return id(valve1_delay).state * 1000;
      - switch.turn_off: valve1
switch:
  - platform: gpio
    pin: D5
    id: valve1
    name: "valve1"
    icon: "mdi:sprinkler-variant"
    on_turn_on:
      - script.execute: valve1_delay_off

在编写过程中,我发现它对中文的支持并不好,所以各种命名还是使用英文。

自动化

我选择 Node-RED 来实现次卫的自动化。因为它提供了可视化编辑环境,并且具有很多实用的组件,比如状态机,函数等。通过将次卫分为几种状态,利用事件来触发状态的改变。并根据状态的转换情况来判断是否开灯,或者关灯。在 Home Assistant 中,我可以获取所有我需要的数据,这样我便能完美的实现我理想中的自动化。

不过体验下来,因为不是通过 local push 来接入设备的,自动化的体验并不稳定,甚至有时候会错乱。最后我还是放弃使用 Home Assistant 来实现次卫的自动化。并且吸取了之前实现自动化中复杂状态转化的一些教训,简化了自动化的实现。

次卫的所有状态,应该分为三个状态,无人中选择中活动中。其中,只要门打开,就应该是 选择中,当 30 秒无人移动(人体传感器2支持的最短时间)且关门的情况下,从 选择中 切换至 无人中。当有人移动且关门的情况下,从 选择中 切换至 活动中。并且在 无人中活动中 时开门,自动切换至 选择中。这样主要是为了避免在厕所中传感器没有感应到人的微小动作而导致明明人还在厕所里却关掉灯的情况发生。

在米家中,我创建了四条自动化。

  • 自动化1: 如果 打开门,就执行 开灯,并关闭自动化1,打开自动化2、3。
  • 自动化2: 如果 关闭门且超时无人移动,就执行 关灯,并关闭自动化2、3,打开自动化1。
  • 自动化3: 如果 关闭门且有人移动,就执行 关闭自动化2、3,打开自动化4。
  • 自动化4: 如果 打开门,就执行 关闭自动化4,打开自动化2,3。

这样虽然没有根据厕所环境亮度来决定是否开关灯,但是极大地简化了自动化的复杂度,能够直接在米家平台上实现。提高了响应时间,也避免了各种状态错乱的情况发生。这也算是一种妥协的产物吧,只能期待以后米家能够支持本地自动化,或者米家平台支持更加复杂的自动化。

或者如果购买人体存在传感器,也能够极大的简化智能的设计,并且获得不错的体验。虽然这个传感器加上网关,我之前看了一下要接近千元。摸了摸了.jpg

结语

通过这几天的折腾,算是入门了 Home Assistant。了解了自动化中各种设备的接入方式,知道了各种接入方式的优劣。Home Assistant 作为一个家庭自动化的平台,真是一个集大成者。提供了各种集成,支持了非常多的接入方式,并且可以实现非常复杂的自动化。但是,它并不能打破产品本来的限制,如果一个产品不支持本地获取数据,那么它没办法强行从设备那里获取数据的。虽然可以迂回模拟用户操作从云端获取数据/控制设备,但是这样会受限制于网络环境,与厂商的限制。

希望以后米家或者类似的平台能够更加开放,这样作为一个消费者,才能真正的把一个设备控制在自己手里,而不会受限制于网络环境。家庭自动化,本就应该是一个以本地为中心,不依赖云端的系统。也希望以后的传感器性能与价格能够更加美好。

不知道 Matter 这样的智能家居开源标准能给用户带来多好的体验,国内厂家又会不会跟进或者弄出自己的一套方案呢。小米的 AIoT-Spec 又能发展到什么程度。

虽然现在家庭自动化还很不完善,但至少已经能够实现一些简单的自动化,并且能够确确实实的感受到自动化的魅力。期待今后的发展,能够将全屋自动化变成人人都能享受的事物。

相关的代码,配置文件均存放在 GitHub。home-assistant-config

标签: Home Assistant, 米家, ESPHome