Please enable Javascript to view the contents

HA + 小米智能家居 = 失业宅心灵鸡汤

 ·  ☕ 5 分钟

logo

本文介绍如何使用 Home Assistant (HA) 集成小米米家智能家居设备,实现基于 Prometheus Alertmanager 的自动化米家开关控制。并结合 HomeKit Bridge,实现 iPhone 位置感知驱动的自动化。

缘起

缘起:这节写得有点冗长,不喜可跳过。

要问原始石器时代的程序员,为什么选择这个爱好或行当,多数的回答是:在软件世界里,找回现实世界中失去的自由。现实世界中,无数说不清、道不明的东西,很多甚至不能用逻辑、用理性去理解。每天都可以见到 The Emperor’s New Clothes 上演。但在软件世界里,这些东西得到了最少化。

智能家居可视为物联网(IoT)的一种应用,而物联网(IoT)的美,在于它的开放性。没人想被封闭在某个厂商的生态系统里。相反,每个 IoT 厂商都想把你锁定在自己的生态系统中。于是,智能家居的 DIY 爱好者们,就开始了对抗封闭生态系统的折腾。现在世界实现不了的东西,可以在数字世界里补偿一点。

小米作为一个典型的 IoT 厂商,是智能家居 DIY 爱好者的常用选择。但小米米家生态系统的封闭性也很强。很多时候,你想让你的智能家居设备和其他厂商的设备联动,或和你自己的自定义程序联动,是很难做到的。好在,Home Assistant 作为一个开放的智能家居中枢软件,可以很好地整合各种厂商的设备,并且提供开放的 API 供用户自定义自动化逻辑。

动机

2021 年算是背上一身债,花光身家去置了新家(别在意现在价值腰斩了多少,感谢仁慈)。入住时就打算玩玩智能家居,在价格能承受的情况下,能上智能家居的电器,都上了智能家居(除了一些明显智商税的设备)。正如 我的智能家居设计 —— 说说好像过时的 IOT 中写的,我用的是小米生态设备,即使使用上了 小米中枢网关,可以 DIY 编程折腾的空间还是有限。连一个 webhook 的设备事件通知,或通过 push URL 控制设备都做不到。当时已经知道 Home Assistant 可以整合小米。那时只有 非官方的 hass-xiaomi-miot 插件可以用,但安装配置比较麻烦。加上当时 Home Assistant 的文档和社区都不够完善,折腾的热情也就没有持续下去。直到最近有时间,看到米家官方已经推出了 ha_xiaomi_home Home Assistant 插件,安装配置比较方便,未来维护也可期。于是就开始折腾 Home Assistant 了。

2024 年,我写过一篇文章 我的智能家居设计 —— 说说好像过时的 IOT,介绍了我用小米米家全家桶做的智能家居设计和实践,顺便吐槽了一下 DOS WPS。2025 年下半年,失业在家。专业知识充电和面试简历准备、各种投简历渠道当然不能少。但市场、年纪注定还是要等待。生活还是要有点“不良爱好”,不然等待的日子会很难熬。我的“不良爱好”之一,就是折腾 self-hosted 和智能家居。

如果能让开放的智能家居接入 LLM,实现一些实用的 AI 功能,顺路学习一些 AI 应用,就更兼顾新技术学习和应用了。

需求分析

现状

家中 Home Lab 其中一个 Raspberry Pi,跑了一堆 self-hosted 服务。安装了 Prometheus 和 Alertmanager 来监控 Pi 的温度,时常收到 80 度报警。我不想为 Pi 安装散热器和风扇,所以就想到了智能家居的自动化,能不能让 Prometheus Alert 驱动打开插上风扇的小米开关?但现在的配置下,Prometheus 的 Alertmanager 与米家开关的控制没法集成。原因是米家没有本地简单的 web API 可用。于是就想到了 Home Assistant 这个开放 API 的智能家居中枢软件,能不能集成米家设备?

目标

  1. 通过 Home Assistant 集成小米米家智能家居设备,提供开放的接口。
  2. 基于开放的接口(包括米家数据源和非米家数据源),实现一些智能自动化,如:
    • Prometheus Alertmanager 告警时,自动打开或关闭小米智能开关,从而控制风扇的开启和关闭。
    • 人离家作为一个事件源或状态,供自动化使用,如离家后才打开大门的监控消息推送。
    • 人的地理位置作为一个事件源或状态,供自动化使用,如到家 15 分钟前,提前自动打开空气净化器。

方案设计

Home Assistant 集成 Xiaomi & Apple HomeKit Bridge
如上图排版有问题,请点这里用 Draw.io 打开

实现

Prometheus 告警控制小米开关风扇

Prometheus Alertmanager 配置脚本:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
groups:
- name: node_exporter_alerts
  rules:
  - alert: HostPhysicalComponentTooHot
    expr: node_hwmon_temp_celsius * on(chip,instance,job) group_left(chip_name) node_hwmon_chip_names > 70
    for: 2m
    labels:
      severity: warning
    annotations:
      summary: Host physical component too hot (instance {{ $labels.instance }})
      description: 🔥 Physical hardware {{ $labels.instance }}/{{ $labels.chip_name }}/{{ $labels.sensor }} too hot {{ $value }}°C

Prometheus Alertmanager 发出的 alert webhook 报文示例数据:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
{
  "receiver": "webhook_receiver",
  "status": "firing",
  "alerts": [
...
  ],
  "groupLabels": {},
  "commonLabels": {
    "alertname": "HostPhysicalComponentTooHot",
    "instance": "192.168.1.68:9100",
    "job": "192.168.16.130",
    "severity": "warning"
  },
  "commonAnnotations": {...},
}

Home Assistant 的自动化配置 UI:

ha auto

Home Assistant 的自动化配置 script:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
alias: Toggle Switch When Alert Firing/Resolved
description: Handle Prometheus Alertmanager webhook
triggers:
  - webhook_id: prometheus_alert
    allowed_methods:
      - POST
    local_only: true
    trigger: webhook
conditions: []
actions:
  - variables:
      alert_status: "{{ trigger.json.status }}"
      alert_name: "{{ trigger.json.commonLabels.alertname }}"
      alert_instance: "{{ trigger.json.commonLabels.instance }}"
  - choose:
      - conditions:
          - condition: template
            value_template: "{{ alert_name == 'HostPhysicalComponentTooHot' }}"
          - condition: template
            value_template: "{{ alert_instance == '192.168.1.68:9100' }}"
        sequence:
          - choose:
              - conditions:
                  - condition: template
                    value_template: "{{ alert_status == 'firing' }}"
                sequence:
                  - target:
                      entity_id: switch.qmi_cn_9083433944_psv3_on_p_2_1
                    action: switch.turn_on
              - conditions:
                  - condition: template
                    value_template: "{{ alert_status == 'resolved' }}"
                sequence:
                  - target:
                      entity_id: switch.qmi_cn_9083433944_psv3_on_p_2_1
                    action: switch.turn_off
mode: single

手机地理位置驱动的自动化

有几个实用的场景:

  • 人离家作为一个事件源或状态,供自动化使用,如离家后才打开大门的监控消息推送。
  • 人的地理位置作为一个事件源或状态,供自动化使用,如到家 15 分钟前,提前自动打开空气净化器。

在手机安装了 Home Assistant App,连接到 self-hosted 的 HA Server 后,手机就是一个 sensor 设备了。它可以传感:

  • 手机连接的 Wi‑Fi 热点名(SSID)
  • 手机位置
  • 等等

以下可以作个 Demo。

ssid auto

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
alias: SSID
description: ""
triggers:
  - trigger: state
    entity_id:
      - sensor.markiphone_ssid
    from:
      - MY_WIFI_SSID_Name
    to: null
    for:
      hours: 0
      minutes: 0
      seconds: 10
conditions: []
actions:
  - device_id: 01538aafdaf38599d12dd5c039aabb6b
    domain: mobile_app
    type: notify
    message: SSID Updated 1
    title: SSID Updated 2
mode: single

phone-ssid-update-nft

米家接入 Apple HomeKit 让 iPhone Siri 控制家电

Home Assistant 安装了 HomeKit Bridge 集成后,就可以用 iPhone 或 Siri 控制家电了。我终于可以用心爱的粤语去问候米家家电了。小爱同学 ByeBye。

homekit-siri.png

结语

以前,智能家居是智商税式的时髦,多少有点华而不实。而发展到现在,我认为已经有不错的实用性。我不知道未来 AI + 智能家居会有什么发展。对于一个记忆容易过载的人来说,如果 AI 可以帮我记住使用频率极低的小电子玩意、小工具放在哪儿,或者在发现我和女儿吵架、说她没有履行昨天在家说的家务承诺时,跳出来作证昨天大家都说了什么——这大概有点意思。更多的感情连结、更强的感知能力,或许是未来 AI 家居的一个方向。但我对平台开放性并不抱太大希望。米家官方出的 Home Assistant 集成,或许是一个特例。

最后,感谢我的家人和朋友。在失业这段时间,给了我很多支持和鼓励。这编文章我计划两小时写完。结果写了一天。正经的找工作事没做,居然没有人责怪一个 40 岁的男人在失业时还不务正业,不去充电,只顾折腾自个儿的兴趣爱好。

分享

Mark Zhu
作者
Mark Zhu
我在找工作 | I'm open to work