你知道这世界最不缺什么吗?那些说"总有一天会去做"的人。空想家们坐在那里无所事事,等待完美的时机、完美的配置、完美的什么东西。与此同时,生活不停地在走。
"我再次感受到幸福是多么简单而朴素的东西:一杯酒、一颗烤栗子、一个破旧的小火炉、大海的声音。就这些了。" 尼科斯·卡赞扎基斯,《希腊人佐尔巴》
佐尔巴没有等待。佐尔巴跳舞了。佐尔巴失败得惊天动地,然后大笑着面对。当他宏大的采矿工程坍塌了,真的坍塌了,他抓起一瓶酒,在海滩上跳起了舞。与其坐以待毙,不如像佐尔巴一样失败。
所以今天,我和儿子要行动了。计划已经制定。硬件已经准备好。大部分已经单独测试过了:自动化能运行,传感器能检测,代码能编译。现在看看它们能不能一起工作。会出问题吗?大概率会。我们准备好迎接挑战了吗?当然。这才是有趣的部分。
**没有计划,就没有前进的路。**只有自说自话的人。只有空想。这不是空想。这是执行简报。
任务
今晚我们烤肉吃晚餐的时候,这个家将会:
- 在你进入的房间自动开灯,离开时灯光在身后渐渐熄灭
- 床感应到我们入睡时锁上所有的门
- 我们(又)忘记关的时候自动关闭车库
- 根据哪些房间真正有人来调节温控
- 生成WiFi噪音,让外面的人无法用同样的感应技术来监测我们
亚马逊什么都不会知道。一切都在本地运行。没有云端。没有订阅。没有数据采集。
武器库(已就位)
大脑:Raspberry Pi 5 - 准备就绪
这个家伙已经在我桌上放了两周,完全配置好了,就等今天。Pi 5对于基本的家庭自动化来说性能过剩。我就喜欢性能过剩。上面运行着Raspberry Pi OS Lite,Docker已安装,Portainer在运行。我只需要把它接到它要待的地方就行了。
我选了Argon ONE V3 M.2 NVME PCIE 外壳套装。已经组装好:
- M.2 SSD已刷入操作系统(再也不用担心SD卡故障)
- Docker + Portainer安装并测试完毕
- Home Assistant容器随时可以部署
- 网络上已分配静态IP
起飞前检查清单 - 完成
- ☑ Raspberry Pi OS Lite已刷入SSD
- ☑ SSH已启用,凭证已设置
- ☑ 网络已配置静态IP
- ☑ Docker + Portainer运行中
- ☑ Home Assistant配置文件已准备好
传感器:ESP32开发板 - 已刷写并测试
这些小小的ESP32开发板是最有意思的部分。上周末我和儿子一起刷写它们,看着WiFi信号数据不断涌入。确认可以工作。
- WiFi感应单元 - 通过测量WiFi信号扰动来检测运动。在客厅走动测试过,能穿墙检测运动,范围大约4.5到6米。
- WiFi迷雾单元 - 生成噪音来干扰任何外部WiFi感应。在隔离环境中运行,在信号空间中制造出漂亮的混沌。
今天我们将它们整合到Home Assistant中,看看自动化能否正确触发。代码在测试中能跑。问题是:全部连接后还能不能跑?
(如果你想了解为什么这很重要,可以读我关于WiFi感应和WiFi对抗措施的文章。)
现有基础设施 - 已就位
我们不是从零开始。房子里已经有智能设备了,只是它们在各自独立的应用里运行,像一堆互不相连的孤岛。今天我们统一王国:
- 飞利浦Hue灯泡 - 已在整个房子安装。目前由Hue应用控制。今天:Home Assistant接管。
- Ecobee温控器 - 通过自身传感器已经知道哪些房间有人。今天:我们整合这些数据。
- Eight Sleep智能床 - 已在追踪我什么时候睡着。今天:它触发锁定自动化。
- Kwikset门锁(Z-Wave) - 已在门上。今天:它们学会自动锁门。
- MyQ车库 - 已安装。今天:再也不用因为忘关车库而开车回家了。
**重点是:**你可能已经拥有比你以为的更多的智能家居设备。它们只是还没有互相交流而已。
第一阶段:基础设施(已完成)
这是上周末的工作。如果你之后想跟着做,这是我们做了什么。如果你读过我的Docker文章,你就知道我们为什么把所有东西都容器化了。
bash# Docker + Portainer - Already running
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
docker volume create portainer_data
docker run -d -p 9000:9000 --name portainer \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-cePortainer在http://raspberrypi.local:9000上运行。漂亮的容器管理界面。确认完毕。
第二阶段:Home Assistant(今天的第一个任务)
docker-compose文件已经写好。配置目录已经准备好。今天我们正式启动,开始连接设备。
yaml# docker-compose.yml - ready to deploy
version: '3'
services:
homeassistant:
container_name: homeassistant
image: ghcr.io/home-assistant/home-assistant:stable
volumes:
- /home/pi/homeassistant:/config
- /etc/localtime:/etc/localtime:ro
restart: unless-stopped
privileged: true
network_mode: host**计划:**运行docker-compose up -d,打开设置向导,然后逐一连接这些集成:
- 飞利浦Hue - 应该在网络上自动发现
- Ecobee - OAuth流程,需要手边有应用
- Eight Sleep - API集成,凭证已准备
- Z-Wave - 这个可能会有点刺激,门锁可能会闹脾气
- MyQ - 简单直接,以前做过
- ESPHome - 用于上周末刷写的ESP32设备
**预期挑战:**Z-Wave。门锁总是有脾气。走着看吧。
第三阶段:WiFi感应整合(今天最好玩的部分)
感应单元 - 准备连接
上周末,我儿子看着串口监视器,这个东西检测到了我在客厅走动。他的原话:"爸,这又恐怖又酷。"
ESP32已经刷入了ESPHome。已经能通过WiFi CSI(信道状态信息)检测运动了。今天我们把它接入Home Assistant并给它取个名字:binary_sensor.living_room_occupied
**测试:**走进客厅。Home Assistant能检测到吗?如果能,我们就成了。
迷雾单元 - 隐私层准备就绪
第二块ESP32运行的是我对抗措施文章里的噪音生成器。它已经在我的工作台上运行了一周,在WiFi频谱中制造漂亮的混沌。
没错,我们一边用WiFi感应做自己的自动化,一边防止别人对我们做同样的事。这不是虚伪。这是操作安全。而且我儿子觉得这是世界上最酷的东西。
未来扩展:3+3
今天的目标是用一个传感器和一个迷雾设备证明概念。一旦有信心:
- **3个感应设备:**客厅、厨房、卧室
- **3个迷雾设备:**分布在全屋实现完整覆盖
大约50美元的ESP32开发板就能升级整个房子。不过首先,让我们确保今天能成功。
第四阶段:自动化(真正的目的)
一切都是为此而来。这些YAML文件已经写好,在脑子里测试了上百遍,随时可以粘贴。第一次就能成功吗?试试看。
自动化1:跟随照明(重头戏)
**愿景:**走进一个房间,灯光升起迎接你。离开,灯光在你身后渐渐熄灭,像一个有礼貌的管家。托尼·斯塔克的家。这就是目标。
**细节:**如果你手动开了灯,系统不会干涉。你的选择被尊重。我们用input_boolean辅助器来追踪这一点。因为没有什么比跟你对着干的自动化更糟糕的了。
yaml# configuration.yaml additions
input_text:
last_occupied_room:
name: "Last Occupied Room"
initial: "none"
input_boolean:
living_room_auto_triggered:
name: "Living Room Auto Triggered"
kitchen_auto_triggered:
name: "Kitchen Auto Triggered"
bedroom_auto_triggered:
name: "Bedroom Auto Triggered"接下来是自动化:
yaml# automations.yaml
- alias: "Follow Me - Living Room Entry"
trigger:
- platform: state
entity_id: binary_sensor.living_room_occupied
to: "on"
condition:
- condition: state
entity_id: light.living_room
state: "off"
action:
# Dim the previous room if it was auto-triggered
- choose:
- conditions:
- condition: template
value_template: "{{ states('input_text.last_occupied_room') == 'kitchen' }}"
- condition: state
entity_id: input_boolean.kitchen_auto_triggered
state: "on"
sequence:
- service: light.turn_on
target:
entity_id: light.kitchen
data:
brightness_pct: 20
transition: 3
# Turn on current room
- service: light.turn_on
target:
entity_id: light.living_room
data:
brightness_pct: 100
- service: input_boolean.turn_on
target:
entity_id: input_boolean.living_room_auto_triggered
- service: input_text.set_value
target:
entity_id: input_text.last_occupied_room
data:
value: "living_room"
- alias: "Follow Me - Living Room Vacancy"
trigger:
- platform: state
entity_id: binary_sensor.living_room_occupied
to: "off"
for:
minutes: 2
condition:
- condition: state
entity_id: input_boolean.living_room_auto_triggered
state: "on"
action:
- service: light.turn_off
target:
entity_id: light.living_room
data:
transition: 5
- service: input_boolean.turn_off
target:
entity_id: input_boolean.living_room_auto_triggered**测试:**部署完成后,我和儿子会在房子里走来走去,看灯是不是跟着我们。如果成功,我们会觉得自己像在电影里。如果失败,我们就一边吃披萨一边调试。
自动化2:睡前锁定(安心保障)
**场景:**晚上10点。我上床了。五分钟后,Eight Sleep确认我确实睡着了(不只是躺着刷手机)。房子做出响应:所有门上锁,如果我忘了车库会自动关闭(又来了),温控器切换到睡眠模式,自动点亮的灯渐渐熄灭。
yaml- alias: "Bedtime - Eight Sleep Triggered Lockdown"
trigger:
- platform: state
entity_id: binary_sensor.eight_sleep_bed_presence
to: "on"
for:
minutes: 5
condition:
- condition: time
after: "21:00:00"
before: "06:00:00"
action:
# Lock all doors
- service: lock.lock
target:
entity_id:
- lock.front_door
- lock.back_door
# Close garage if open
- service: cover.close_cover
target:
entity_id: cover.garage_door
# Set Ecobee to sleep mode
- service: climate.set_preset_mode
target:
entity_id: climate.ecobee
data:
preset_mode: "Sleep"
# Turn off auto-triggered lights
- service: light.turn_off
target:
entity_id:
- light.living_room
- light.kitchen
data:
transition: 5**没有Eight Sleep?**可以用基于时间的触发器(晚上10:30)或手机充电检测来代替。逻辑是一样的。
自动化3:车库自动关闭(婚姻的救星)
问题:"你关车库了吗?"这个家每周被问3次的问题。再也不用了。开着超过10分钟,它自己关上并通知我。
yaml- alias: "Garage - Auto Close After 10 Minutes"
trigger:
- platform: state
entity_id: cover.garage_door
to: "open"
for:
minutes: 10
action:
- service: cover.close_cover
target:
entity_id: cover.garage_door
- service: notify.mobile_app_your_phone
data:
title: "Garage Secured"
message: "Garage was open for 10 minutes. Auto-closed."
data:
tag: "garage-closed"自动化4:智能温控(节能利器)
**逻辑:**为什么要给空房子供暖?当WiFi传感器说30分钟内没人在家,Ecobee切换到离家模式。有人进来时,它自动恢复。
yaml- alias: "Ecobee - Away When House Empty"
trigger:
- platform: state
entity_id: binary_sensor.home_occupied
to: "off"
for:
minutes: 30
action:
- service: climate.set_preset_mode
target:
entity_id: climate.ecobee
data:
preset_mode: "Away"
- alias: "Ecobee - Home When Occupied"
trigger:
- platform: state
entity_id: binary_sensor.home_occupied
to: "on"
condition:
- condition: state
entity_id: climate.ecobee
attribute: preset_mode
state: "Away"
action:
- service: climate.set_preset_mode
target:
entity_id: climate.ecobee
data:
preset_mode: "Home"创建聚合传感器
binary_sensor.home_occupied是一个模板传感器,组合了所有房间的传感器:
yamltemplate:
- binary_sensor:
- name: "Home Occupied"
state: >
{{ is_state('binary_sensor.living_room_occupied', 'on')
or is_state('binary_sensor.kitchen_occupied', 'on')
or is_state('binary_sensor.bedroom_occupied', 'on') }}可能出什么问题?(有趣的部分)
事情是这样的:今天一定会有什么出问题。这不是悲观,这是现实。没关系。这才是核心。
今天冒险的可能候选项:
- Z-Wave门锁 - 这些东西有脾气。配对可能需要多次尝试。
- WiFi传感器校准 - 在工作台上能用,但安装到位后呢?
- 自动化的边界情况 - 如果有人2秒内穿过房间会怎样?
- "昨天还好用呢"问题 - 技术最爱讲的笑话。
但这正是我们一起做的原因。父子俩,排除故障、学习、大概率还会争论为什么YAML解析不了。这才是真正学习的方式:造一个真东西,看它坏掉,然后修好。
佐尔巴的矿塌了。他的反应?在海滩上跳舞。今天不管什么坏了,我们都会搞定。搞不定的话,晚饭时也有个好故事讲。
哲学
这就是行动者和空想者之间的区别:
空想者研究好几个月。读每一篇文章。等"对的"硬件。把计划优化到完美。永远不开始。
行动者写下计划,收集所需的东西,然后执行。他们预期挑战。随机应变。在失败中前进。
没有计划,就没有前进的路。只有自说自话的人。但没有执行的计划,只是多了几个步骤的空想而已。
今天的成功标准
- ☐ Home Assistant运行中,所有设备已连接
- ☐ WiFi传感器在客厅检测到运动
- ☐ 跟随照明至少在一个房间工作
- ☐ 睡前锁定自动化已启用
- ☐ 我儿子说"这就像托尼·斯塔克的家"
接下来(今天成功之后)
假设我们会成功,而且我们一定会成功,即使花的时间比预期长:
- ESP32完整3+3部署 - 每个主要房间都有感应,迷雾覆盖全屋
- 壁挂式平板仪表盘 - 走廊里常亮的控制面板
- 本地语音控制 - Wyoming/Piper实现不出家门的语音命令
- 漏水传感器 - 每个水槽下面和热水器旁边
但首先:今天。首先:执行。首先:证明这些计划确实能用。
"生活就是当你忙着做其他计划时发生的事。" 约翰·列侬
错了。生活是当你停止计划开始行动时发生的事。另一边见。 是时候去造点什么了。