0x00 序言
离开学校,进入社会,笔者变成了打工人。在感慨时光流逝的同时,也庆幸于住宿条件变好了,有了更多的空间来做自己的爱好。原先难以部署的 3D 打印机等设备,由于有了单人宿舍,现在也可以提上日程。
笔者的宿舍并不很大,类似于酒店单间:使用面积大约 30 余平米,有一个卧室,带卫生间,门口有厨房区域。在过去的两周里,笔者忙里偷闲,对宿舍进行了一系列智能家居改造,故以本文记录下来。
在智能家居方面,笔者也不算是新手。本科四年级时,笔者在校外租住了一年,当时用小爱音箱和蓝牙 mesh 灯泡组装了一套极简版的智能家居,能用语音关掉卧室里的灯,这样就不必下床去摸开关了。然而,今次笔者要组装的系统远比当时复杂,在做完之后,很有一种成就感。若读者亲身实践一次,相信也会有类似的感受。
简而言之,笔者最终实现了:
- 用手机 / 平板控制全部灯具(卫生间除外);
- 按照笔者的作息规律,定时开关电热水器和空调;
- 推开门之后,自动开灯;
- 接入 Apple HomeKit 以便在 iPhone 和 iPad 上控制家居设备。
笔者采用了米家方案。借助网关,所有设备都可以远程控制(外出时也能控制宿舍里的设备)。
0x01 架设网络
智能家居的核心是网络。笔者用到的 iot 设备要么是 wifi 的,要么是蓝牙 mesh 的。在没有网关的情况下:
- wifi 设备通过 internet 通讯,所以用户无论在哪里,都能控制设备。缺点在于功耗比蓝牙设备大。
- 蓝牙 mesh 设备通过蓝牙 BLE 通讯,优点在于低功耗。用户在家时,可以用手机连接 iot 设备,但一出门便失去控制。解决方案是在家部署蓝牙网关。
有传言称蓝牙 mesh 的可靠性不如 zigbee,但笔者在使用过程中,没有发现显著问题。
公寓的网络提供商是中国电信的二道贩子,笔者从他们那里买来了宽带。他们提供了一台 H3C Magic R2+ 路由器,这台路由器无线速率很低,因此笔者让它仅负责拨号,关闭 wifi;另购了一台中兴巡天 BE5100 路由器(支持 WiFi-7)作为 AP。幸运的是,墙壁上有网线端口与弱电箱相通,因此笔者无需在房间中到处布线。网络结构设计如下:
关于 nas。它是一台 R5 5600G 电脑,运行 win10 系统。除了当 nas 之外,还承担了虚拟化平台的功能。笔者使用 Hyper-V 方案,运行了若干个 vm,接入主网络(网络结构类似于 ESXi 的虚拟交换机)。所以逻辑上说,各个虚拟机都是直接挂在 192.168.10.0/24 下的主机。
关于打印机。笔者的打印机型号是 brother DCP-1608,它本身只有 usb 接口,不像网络打印机那样可以直接联机使用。不过,我们可以将它连接到 nas,使用 windows 的「共享」功能,让局域网中的其他 windows 电脑也能打印。
关于蓝牙网关。笔者用「小爱音箱 Play 增强版」作为蓝牙 mesh 网关,它还自带一个红外发射器,可以用来控制空调。
本文网络中的服务全部使用静态 IP。即使 DHCP 路由器宕机,也能依靠下级路由器和交换机完成基本的数据传输。
树莓派可以通过
nmtui
程序配置网络,用 nmcli con reload
使新配置生效。费了九牛二虎之力,终于把光猫、拨号路由器(扯断天线)和树莓派都塞进了弱电箱:
至此,我们的网络环境已经搭好,只待接入 iot 设备。
0x02 灯光智能化
在搭建智能家居之前,笔者每天睡觉前都得手动关灯,这是智能化改造所需解决的最紧迫的问题。卧室的灯是传统的 LED 环形灯管,不支持智能控制,因此笔者一方面采购其他光源,一方面调研控制这种灯管的方法。
首先来添加灯具。笔者从宜家购买了工作台灯(焊接时使用)、上照灯(放在靠窗的小吧台)、落地灯(放在台式机旁边)。台灯是 E14 灯泡接口(宜家有售智能灯泡,能接入米家),其他两盏灯是 E27 接口(小米有售蓝牙 mesh 灯泡)。这里提到的灯泡都支持 2700K-6500K 色温调节,可以为工作和休闲提供不同的灯光氛围。
摆上这些灯之后,即使不开顶灯,室内也足够亮了,因此晚上睡觉前可以不再使用顶灯。但这几个分布式的光源毕竟没法照到房间的每个角落,我们迟早还得解决顶灯控制的问题。
最容易想到的方案是改开关面板:拆掉原来的非智能开关,装一个智能开关上去。然而,iot 设备肯定是要持续耗电的,如果开关面板的 86 盒里面没有零线,则无法构成回路,也就无法给 iot 设备供电了。很不幸,笔者拆了开关面板之后,发现它是一个单火开关。
市场上也存在单火开关的改造方案。它的思路是在「火线 - 控制器 - 灯 - 零线」的回路中长期维持微小的电流,以供控制器运行;当用户需要开灯时,则提供能让灯正常工作的电流。这个方案极度不雅:微小的电流也可能让小功率灯泡发出一些光(俗称「鬼火」)。可以参考一篇讨论文章。
既然改造开关面板的方向走不通,我们来考虑改造灯具本身。至少有三种方案:
- 把灯管换成智能灯管。不过,笔者没有找到满意的智能环形灯管(淘宝上能搜到的产品都是不知名小厂家做的),所以放弃此方案。读者若有推荐,可在评论区留言。
- 拆掉整个灯具,换成智能吸顶灯。这方面的产品很多(当然,溢价也高,厂家也是无利不起早)。这个方案的问题在于要重新打孔,比较麻烦。
- 使用通断器。这是笔者最终采用的方案。
首先解释一下通断器方案的原理。让开关保持在打开的状态,这样顶灯位置的火线和零线之间始终有电压。我们便在那里放一个智能控制的断路器,需要开灯时给灯管通电即可。由于通断器体积很小,它可以塞进灯罩。安装方法如下:
现在,宿舍里还剩下厨房区的两盏筒灯、以及卫生间灯没有智能化。筒灯直接换成小米的产品即可,在米家 app 中绑定成灯组,以便一次性控制所有筒灯。至于卫生间灯,似乎没有智能化改造的必要,毕竟开关位于如厕的必经之路上。当然,如果想要改造,我们可以使用通断器。
0x03 空调和热水器
某天,笔者听同事谈起热水器过于耗电,于是决定将热水器也智能化。本文把空调和热水器合在一起讨论,因为这两种电器都是人在家时需要开启、人离家后可以关闭。
控制空调是简单的,笔者的音箱即可发出遥控信号。至于热水器,笔者选择使用智能插座,它不仅可以控制电热水器的开关,还能监控其功率和耗电量。
现在讨论如何实现「人来通电,人走断电」。由于热水器和空调都不是即时见效的(大致需要提前 30min 打开),我们需要根据自己的作息规律,调整其开启时间。具体而言,笔者的设置是:
- 当用户离开家 1km 后,关闭空调和热水器
- 下班前 30min 打开空调和热水器
- 01:30 关闭热水器,05:00 打开热水器
0x04 门窗传感器
接下来实现「开门后自动开灯」的功能。这个功能依赖门窗传感器,它是蓝牙 mesh 设备,由纽扣电池供电,一半装在门上,一半装在门框上。实践发现它的信号似乎比其他持续供电的 mesh 设备弱一些,建议把音箱摆放在靠近门窗传感器的位置。
门窗传感器上自带了环境光传感器,可以检测「环境光亮 / 环境光暗」。因此,我们可以设计这样的自动化逻辑:「当门打开,且环境光暗时,自动打开一些灯具」。
要解决这个问题,可以采用人体传感器;或者像笔者一样,设置一个「离家 500m 后自动关灯」的自动化逻辑。考虑到传感器误差,后者应该更实用,代价无非是稍微浪费几分钟电。
0x05 通过 Home Assistant 接入 HomeKit
迄今为止,所有的控制都是在米家 app 上完成的。这样的交互方式不太方便。即便使用小组件,也需要先把手机划到主屏,然后划到组件屏,找到「米家智能场景」和「米家快捷操作」。
因此,我们接下来把这些智能家居设备都接入 ios 原生的「家庭」应用中。它至少给我们带来了以下好处:
- 在控制中心(即从屏幕右上角下拉的菜单)中,我们能直接操控设备,即使是锁屏状态也可以使用。
- 多端同步,无需在 iPad 上重新设置。
- 可以用 Siri 控制设备,它远比小爱音箱聪明,语音识别也更准确。
我们可以通过 Home Assistant 或 Homebridge 将米家设备接入 HomeKit。由于笔者打算以后使用 ESP32 自行开发一些智能设备,故选用 Home Assistant(以下简称 HA)。接下来的步骤主要参考了 Wulu 的文章。
首先是在树莓派 4B 上安装 HA。笔者不建议使用 Home Assistant OS,因为它的初始化阶段非常黑盒:必须连接以太网(且必须是 DHCP)、在初始化时从 github 下载数百 MB 的文件,而当这一切发生时,我们甚至无法介入。
现在使用 docker compose 部署 HA。使用官方模板:
services:
homeassistant:
container_name: homeassistant
image: "ghcr.io/home-assistant/home-assistant:stable"
volumes:
- /PATH_TO_YOUR_CONFIG:/config
- /etc/localtime:/etc/localtime:ro
- /run/dbus:/run/dbus:ro
restart: unless-stopped
privileged: true
network_mode: host
启动:
docker-compose up -d
至此,我们已经搭建好了 HA。接下来,我们需要把米家设备接入 HA,这个功能由 hass-xiaomi-miot 项目提供,文档建议使用 HACS 包管理器安装。
按照指引,安装 HACS:
docker-compose exec homeassistant bash
wget -O - https://get.hacs.xyz | bash -
# Connecting to get.hacs.xyz (104.26.6.112:443)
# Connecting to raw.githubusercontent.com (185.199.110.133:443)
# writing to stdout
# - 100% |************************************************************************| 4525 0:00:00 ETA
# written to stdout
# INFO: Trying to find the correct directory...
# INFO: Found Home Assistant configuration directory at '/config'
# INFO: Creating custom_components directory...
# INFO: Changing to the custom_components directory...
# INFO: Downloading HACS
# Connecting to github.com (140.82.116.4:443)
# Connecting to github.com (140.82.116.4:443)
# Connecting to objects.githubusercontent.com (185.199.111.133:443)
# saving to 'hacs.zip'
# hacs.zip 100% # |************************************************************************| 15.9M 0:00:00 ETA
# 'hacs.zip' saved
# INFO: Creating HACS directory...
# INFO: Unpacking HACS...
#
# INFO: Verifying versions
# INFO: Current version is 2024.8.2, minimum version is 2024.4.1
#
# INFO: Removing HACS zip file...
# INFO: Installation complete.
#
# INFO: Remember to restart Home Assistant before you configure it
# 重启 HA
docker-compose restart homeassistant
在 HA 界面中操作:
接下来在 HACS 中安装 hass-xiaomi-miot:
再次重启 HA:
docker-compose restart homeassistant
接下来,在 HA 中添加设备,选择使用「账号集成」,并提供小米 ID 和密码。于是能找到我们所有的设备了:
添加完成之后,在「实体」页可以看到一大群设备:
现在,HA 可以操控灯泡了:
按照 Wulu 博客中的指引,禁用一些不需要由 HA 控制的设备:
在多次实验之后,笔者的操作是:
- 禁用热水器智能开关的指示灯;
- 禁用音箱;
- 由于厨房的两个筒灯只需要一同控制,所以分别禁用两个筒灯,保留灯组。
最后,把 Home Assistant 连接到 HomeKit:
接下来,在「通知」中找到二维码:
扫描后可以在「家庭」应用中导入桥接设备。逐一分配 iot 设备的房间、名称:
现在,我们在控制中心即可操纵灯泡:
对 Siri 说「打开厨房灯」,可以正常控制。至此,我们实现了所有需求。