尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

老幕布秒变智能:ESP8266+ESPHome绕过HA直连HomeKit

老幕布秒变智能:ESP8266+ESPHome绕过HA直连HomeKit 上个月在闲鱼收了一块二手电动幕布成色不错就是控制方式实在太原始——配套一个 433MHz 的射频遥控器每次看电影都得摸黑找遥控。家里主力生态是苹果 HomeKit客厅还放着一个米家音箱我的目标很明确让这块老幕布能被 Siri 一句话唤起顺手的话也能在米家 App 里点一下。翻了一圈教程几乎所有答案都指向同一个方向装 Home Assistant。但为了控制一块幕布专门养一台常开的树莓派或 NAS从电费到折腾成本都有点冤。后来才发现ESP8266 ESPHome 这个组合本身就内置了直连 HomeKit 的能力完全可以把 Home Assistant 绕开。这篇文章就把整套方案完整写出来幕布控制电路的识别与继电器并联改造、ESPHome 里的 cover 配置、无 HA 直通 HomeKit 的配对细节以及米家的两条落地路线。适合家里有老电动幕布、又不想为新生态额外引入一台服务器的人参考。1. 改造前先搞明白你家幕布的控制电路是哪一种1.1 三种常见的控制形态电动幕布的原理其实特别朴素一台交流电容电机加限位开关外面再接一个或几个控制开关。抛开品牌不看控制端基本逃不出下面三种形态先花十分钟定位一下后面改动就轻松了。墙控开关直连型墙上是一个三位或两位开关里面直接走电机的升、降、停信号线有的还带一个低压控制小电路。判断方法拆开开关盒背后就是几根粗线直接进墙大概率是这种。射频接收板型这是老幕布最常见的形式遥控器是 433MHz 或 315MHz接收板一般塞在幕布壳子里或墙盒里板子上有明显的继电器触点。判断方法开关盒里能看到一块小板上面有根像铜丝一样的天线板上还印着几个继电器。红外型少数老型号用红外遥控对着接收窗才有反应。识别很容易用手机摄像头对着遥控器发射管按一下能看到紫光那就是红外。无论哪种形态我们要找的核心都一样找到“升”“降”“停”这三个动作对应的电气触点。用万用表通断档在断电状态下按住原开关逐个量十有八九能量出来按键按下时某两根线之间变成导通松开就恢复断开。这个“导通瞬间”就是我们后面要用继电器去模拟的信号。如果你手头没万用表优先拆射频接收板因为板上一般直接标明继电器触点位置用记号笔标一下就行。我给幕布定位时就是这么干的整个过程不超过二十分钟。1.2 为什么“智能插座断电法”不靠谱很多人第一反应是给幕布配个米家智能插座断电、上电不就能控制了吗实测下来这个思路只对极少数“通电就自动升、断电就停”的幕布勉强成立大多数情况是坑原因有三个。第一方向不可控。插座只能送电和断电电机的升降靠方向信号决定。你通电它就是往默认方向跑如果默认方向是降你就永远只能让幕布降下来。第二限位逻辑容易乱。幕布控制器里有行程开关到位后内部继电器会切掉电机电源。你用插座强断电控制器芯片的状态可能直接乱掉下次上电它不知道幕布在哪个位置容易出现“明明到底了还往下降”的误动作。第三频繁启停伤电机。交流电机的启动电流比运行电流大好几倍直接断电让电机在运动中失去控制对机械结构和电机寿命都不友好。所以正确姿势是在控制端并联一个能模拟按键短接的装置也就是继电器。原开关完全保留我们的 ESP8266 只是在旁边替我们“按按钮”不碰电机主回路。这个思路是整个项目的地基后面所有配置都建立在这个“并联模拟按键”的模型上。2. 硬件改造继电器并联进原有开关三个触点就够2.1 物料清单先给一张我实际用的清单照着买基本不会翻车物品型号/规格作用参考价格开发板Wemos D1 MiniESP8266主控15-25 元继电器模块5V 光耦隔离3 路或 2 路 1 路模拟按键短接10-30 元电源5V 1A USB 充电头给 D1 Mini 供电闲置的就行连接线杜邦线若干、一小段导线接线几块钱辅料热缩管、电工胶布绝缘保护家里都有如果你只需要“升/降”两个动作很多幕布控制器到限位自动停不需要停按钮两路继电器就够。如果原控制器支持中途停止就老老实实上三路。我自己最后是用三个独立的单路模块拼的因为手头有两个双路模块刚好没凑齐三路实际效果没区别就是线要多接几根。2.2 并联不串联这是安全底线这里值得展开说清楚。我们的目标不是把幕布的电源线切断再接继电器而是在原有控制开关的两端并联一组常开触点。等效电路就是原有按键和继电器常开触点并联在控制信号两端按下原按键等于触点闭合继电器吸合也是同一个触点闭合谁触发都一样互不影响。接线时注意几个点继电器模块的 VCC 接 D1 Mini 的 5V 引脚GND 接 GNDIN 接 GPIO。模块自带光耦隔离交流侧和直流侧在板子上不通这就是为什么强调要买“光耦隔离”版本而不是那种便宜的三极管直驱版。D1 Mini 的 GPIO 是 3.3V 逻辑大多数继电器模块的 IN 能直接识别没问题。继电器模块触发极性不一样有的高电平触发有的低电平触发。在 ESPHome 里对应inverted: true/false。接线前先看模块说明或者干脆直接用万用表量一下输入端默认电平。我的经验是优先选高电平触发的模块设定inverted: false因为 ESP8266 上电瞬间 GPIO 处于高阻态高电平触发模块在此时不会误动作更安全。如果手头只有低电平触发模块就设inverted: true但一定要在断电状态下接好线再上电测试。2.3 三种控制电路对应的接线位置墙控开关直连型把墙盒拆开用万用表定位好升、降、停三组触点把继电器的常开端NO和公共端COM分别并联到对应按键两端。不需要剪任何线原开关还能用。射频接收板型接收板上的继电器输出触点就是信号源。你按下遥控器板上继电器闭合对应的升/降/停触点被短接。我们把外接继电器的 NO/COM 并到板上继电器的输出触点上就等于在遥控器旁边多加了一个“遥控器”。如果接收板预留了外接开关的焊盘直接焊上去更干净。红外型红外接收输出的是调制信号不是简单的通断触点用并联继电器的方法不通用。我的建议是要么放弃红外部件直接把控制板换成射频/墙控方案要么用支持红外学习的智能音箱或万能遥控器来接管这条路不在本文范围内但是可行的。3. ESPHome 配置用 cover 把幕布抽象成“卷帘”3.1 最小可用配置硬件接好后剩下的就是软件。下面是我最终在用的完整 YAML去掉注释可以直接用esphome: name: projector-screen platform: ESP8266 board: nodemcuv2 wifi: ssid: 你的WiFi password: 你的密码 logger: homekit: switch: - platform: gpio pin: GPIO5 id: relay_up name: Screen Up inverted: true - platform: gpio pin: GPIO4 id: relay_down name: Screen Down inverted: true - platform: gpio pin: GPIO14 id: relay_stop name: Screen Stop inverted: true cover: - platform: template name: Projector Screen device_class: curtain assumed_state: true open_action: - switch.turn_on: relay_up - delay: 400ms - switch.turn_off: relay_up close_action: - switch.turn_on: relay_down - delay: 400ms - switch.turn_off: relay_down stop_action: - switch.turn_on: relay_stop - delay: 400ms - switch.turn_off: relay_stopWemos D1 Mini 的 GPIO 对应关系要注意一下D1 是 GPIO5D2 是 GPIO4D5 是 GPIO14。inverted: true是因为我用的继电器模块是低电平触发如果你的模块是高电平触发把三处inverted删掉就行。三个 switch 的作用是给继电器一个 400ms 的脉冲先吸合模拟按下按键然后断开模拟松开。这就是并联方案的玩法核心。3.2 为什么用 cover 而不是三个 switch很多人会问直接用三个 switch 不也行吗确实能控制但体验差距很大。HomeKit 里如果暴露三个 switchSiri 就只能识别“打开 Screen Up”“关闭 Screen Down”这种别扭指令你没法说“嘿 Siri 放下幕布”。而 cover 在 HomeKit 里是一个“窗户遮盖物”服务天然有打开、关闭、停止三个动作Siri 的语义正好匹配。device_class: curtain会把设备归类为窗帘这样家庭 App 里的图标和 Siri 的说法都更准确。如果你想让 Siri 说“打开投影幕布”改一下 cover 的 name 就行命名直接影响语音指令建议起一个顺口且不和家里其他设备冲突的名字。3.3 脉冲时长和 assumed_state 的坑400ms 的脉冲时长不是随便拍的。原开关是点动按钮控制器需要一个稳定的低电平或高电平来识别按键太短容易漏判太长又可能在一次动作里让控制器误以为连续按了两次。我实测下来 300ms 到 600ms 都能可靠触发取 400ms 是折中。如果你的幕布控制器比较老建议先从 600ms 开始试确认无误再缩短。assumed_state: true表示我们不知道幕布当前的真实位置。因为电机没有反馈ESP8266 不知道幕布现在是在顶部、底部还是半路只能假设执行了命令后状态发生了变化。这会导致 HomeKit 里幕布的位置显示为“未知”属于正常现象后面第 6 节会具体说怎么应对。4. 绕过 Home Assistant 直连 HomeKit原生 homekit 组件的配对与边界4.1 它为什么不需要 Home Assistant这是整个项目最核心的认知更新。以前想让 ESP8266 进 HomeKit标准做法是 ESPHome 连 Home Assistant再由 HA 的 HomeKit Bridge 桥接出去所以教程一律默认你先装 HA。但 ESPHome 从 2023 年下半年开始内置了homekit组件直接在设备固件里实现了 HomeKit Accessory Protocol设备本身就是一只 HomeKit 配件苹果的“家庭”App 可以直接发现并配对完全不需要中间层。换句话说Home Assistant 在这个场景里的角色只是“桥”现在桥被塞进了 ESP8266 固件内部。省掉 HA 之后少了一个常开设备少了版本升级、备份、插件兼容这些维护成本这就是标题里“另类玩法”的真正价值所在。要注意的几个前提条件首先配对的 iPhone 要和 ESP8266 在同一个局域网其次局域网里要能正常跑 mDNS如果你把智能设备都丢在独立的 IoT VLAN 里记得放行 mDNS 或直接把 D1 Mini 接到和手机同一个网段最后如果你需要在户外远程控制幕布苹果家庭要求有一个家庭中枢也就是 HomePod、Apple TV 或常驻家里的 iPad这和 HA 没关系是 HomeKit 本身的机制。4.2 配对操作扫二维码还是输八位码烧录成功后打开 ESPHome 日志启动过程会打印一个二维码和八位设置码。默认设置码是随机生成的每次烧录可能变。如果你想固定一个码可以在 YAML 里加两行homekit: name: Projector Screen setup_code: 12345678固定码的好处是以后重刷固件不用重新生成家里人或者多台设备再配对时也方便。具体配对步骤iPhone 打开“家庭”App点右上角加号选择“添加配件”然后扫 ESPHome 日志里的二维码。如果扫不出来就选“更多选项”手动输入八位码。配好之后设备的默认房间可能是“默认”你在家庭 App 里把它挪到客厅之类的房间再改一下名称接着就可以用 Siri 试了“嘿 Siri关闭投影幕布。”从发出指令到幕布开始动作实测延迟大概一到两秒属于可以接受的范围。4.3 实验性组件的边界要心里有数homekit组件在 ESPHome 文档里至今标注为实验性所以别对稳定性抱有过高期望。我用的 ESPHome 2024.x 版本里template cover 能正常导出一个窗户遮盖配件但如果你用的版本比较早cover 可能没有被组件导出这时候退一步只让三个 switch 暴露到 HomeKit用“打开 Screen Up”这种指令凑合用。另外升级 ESPHome 版本后配置项可能有微调比如assumed_state在部分版本里改名叫optimistic遇到编译报错先查更新日志别硬套旧配置。还有一个现实问题因为assumed_state: trueHomeKit 拿不到幕布的真实位置自动化里的“当幕布状态发生变化”这类触发条件就不可靠。如果你的自动化只关心“按一下按钮就执行动作”那没问题如果依赖位置反馈就得给电机加位置传感器那是另一个更深的话题了。5. 米家路线伪装 Yeelight 和换 Zigbee 通断器两条路5.1 方案A让 ESP8266 假装自己是一盏 Yeelight 灯泡米家生态不像 HomeKit 那样开放普通 DIY 设备没法直接被米家 App 添加。但有一个漏洞可以钻米家 App 添加 Yeelight 灯具时会在局域网里做 SSDP 搜索发现设备后用 TCP 连它的 55443 端口发 JSON-RPC 指令这套“Yeelight 局域网协议”是官方公开的。思路很简单——让 ESP8266 在局域网里表现得像一盏 Yeelight 灯泡米家 App 就会以为它是一盏灯然后把“开灯、关灯”映射成幕布的升降。映射关系可以这样设计set_power on触发升幕脉冲set_power off触发降幕脉冲。如果用 App 里的亮度调节还能映射成“停”或者别的动作自由度很高。下面这个 Arduino 骨架展示了核心的 TCP 指令处理逻辑#include ESP8266WiFi.h #include ArduinoJson.h WiFiServer yeelightServer(55443); const uint8_t RELAY_UP 5; // GPIO5 对应 D1 const uint8_t RELAY_DOWN 4; // GPIO4 对应 D2 void pulse(uint8_t pin) { digitalWrite(pin, HIGH); delay(400); digitalWrite(pin, LOW); } void setup() { pinMode(RELAY_UP, OUTPUT); pinMode(RELAY_DOWN, OUTPUT); WiFi.begin(你的WiFi, 你的密码); yeelightServer.begin(); // UDP 端口的 SSDP 应答需要额外实现用来让米家发现这个设备 } void loop() { WiFiClient client yeelightServer.available(); if (client) { String line client.readStringUntil(\n); DynamicJsonDocument doc(1024); if (deserializeJson(doc, line) DeserializationError::Ok) { if (strcmp(doc[method], set_power) 0) { if (strcmp(doc[params][0], on) 0) pulse(RELAY_UP); else pulse(RELAY_DOWN); client.print({\id\:1,\result\:[\ok\]}\r\n); } } client.stop(); } }这只是核心逻辑完整的模拟还需要实现 UDP 的 SSDP 应答否则米家搜不到设备。如果你想让这套东西在 ESPHome 里跑思路是写一个 external_components 自定义组件把上面这段 socket 逻辑包成一个Component。但从成本角度我更推荐这条路线单独刷 Arduino 固件ESPHome 留给 HomeKit 那条线两条路互不干扰。这个方案要摆正心态我实测时米家 App 能从“添加设备”里发现这个伪 Yeelight添加时会提示设备不支持云绑定选择“仅局域网使用”后它确实出现在设备列表里点开关也能触发幕布。但小爱音箱的语音控制走的是云端链路大概率无法驱动这种纯局域网设备。所以方案A的定位是一个“在米家 App 里能点一下的玩具”适合尝鲜不适合追求完整的米家体验。5.2 方案B换 Aqara Zigbee 通断器最省心的米家路线如果你要的是稳定、能语音、能远程那别折腾 ESP8266 了直接买米家生态的 Zigbee 通断器。接线思路还是一模一样的并联方案只是把 ESP8266 换成通断器把“脉冲”这个动作交给米家自动化实现。通断器本身是一个保持型继电器通电状态下触点一直闭合这不符合点动按钮的行为。解决方法是配自动化在米家 App 里给每个通断器设置“打开后延时 1 秒自动关闭”这样每次触发都相当于一个脉冲。一个幕布需要三个通断器升、降、停或者用两个双路通断器。这套方案的优点是稳定、有云端链路、小爱音箱直接语音控制缺点是成本比 ESP8266 高而且需要额外配一个 Zigbee 网关。5.3 为什么不建议为了这个场景上 Home Assistant如果你家已经有 NAS、树莓派在常开装个 HA 也就顺手的事。但为了一个幕布单独引入 HA意味着你要维护一套系统、定期备份配置、处理各种插件的兼容问题第一次配置至少搭进去一个周末。Home Assistant 的定位是全家智能中枢适合设备杂、协议多、需要深度自动化的场景。如果你只是想让一块老幕布被 Siri 或米家点一下ESPHome 直连 HomeKit或者方案B的 Zigbee 通断器都更划算。等哪天你发现家里的设备多到需要一个统一中枢时再上 HA也不迟那时候 ESP8266 已经有一个完整的 ESPHome 固件加进来只是几分钟的事。6. 五个踩过的坑与最终体验6.1 上电瞬间继电器误触发第一次上电测试时幕布在 D1 Mini 启动的瞬间抽动了一下吓我一跳。原因有两个一是 ESP8266 启动过程中 GPIO 处于高阻态部分继电器模块的输入端对噪声敏感可能会误判成触发二是如果你的模块是低电平触发而 GPIO 在某个瞬间被拉到低就会误动作。解决方法是给 IN 引脚加一个对地的 10kΩ 下拉电阻让输入在悬空时保持确定的低电平。如果用的是高电平触发模块则改成对 VCC 的上拉电阻。另外选模块时尽量选输入端有明确下拉/上拉的型号很多便宜模块出厂就带了可以省掉这一步。6.2 电机启停导致 ESP8266 重启这个坑藏得比较深。幕布电机启动瞬间电流很大如果 D1 Mini 的供电和幕布控制电路在同一个插排上电压跌落会直接把 ESP8266 拉重启。表现就是你喊 Siri 关幕布幕布刚动一下整个设备就掉线了过几秒又自己连回来。解决方法很简单D1 Mini 用独立的 USB 充电头供电和幕布电机完全分开供电。不要共用一个电源插排的同一个口也不要试图让 ESP8266 和幕布控制器共地保持两边完全隔离最省心。继电器模块的光耦隔离就是为了这个场景存在的。6.3 烧录报错“failed to connect to esp8266: timed out”这个报错几乎是每个玩 ESP8266 的人都会遇到一次。那阵子我刷固件刷到怀疑人生后来总结了几条经验接线没问题的情况下按住板上 FLASH 键不放点烧录等 esptool 输出“Connecting...”字样后再松开。确认用的是数据线不是充电线。很多 USB 线只能充电不能传数据这是最常见的翻车原因。检查串口芯片驱动。Wemos D1 Mini 常见的是 CH340 或 CP2102驱动没装好设备管理器里根本看不到串口。换个电脑 USB 口试试不要用延长线或 USB Hub。手动指定波特率降到 9600 或 57600 往往能救回一些顽固的老板子。如果 esptool 一直连不上还有一个终极大法把板子上的 RST 引脚对 GND 短接一下再断开让板子强制重启一次趁它启动前的那零点几秒点击烧录成功率会高很多。6.4 WiFi 掉线后重连慢ESPHome 默认会自动重连 WiFi但省电模式下偶尔会出现“连上了但响应很慢”的情况。如果你是直接给 D1 Mini 插着 USB 充电头长期供电不在乎那点功耗建议在 wifi 配置里加一行wifi: ssid: 你的WiFi password: 你的密码 power_save_mode: nonepower_save_mode: none关闭 WiFi 省电换来的是更稳定的响应。实测在隔了一堵墙的情况下关闭省电模式后 Siri 响应基本感觉不到延迟。6.5 最终体验很满意但要知道它的边界整套跑通之后的体验是这样的在客厅喊一声“嘿 Siri关闭投影幕布”大约一到两秒后幕布开始缓缓下降到限位自动停住“打开投影幕布”就是上升。原装的 433MHz 遥控器依然能用墙上的物理开关也保留着三条控制通道互不干扰。米家那边App 里能看到一盏“灯”点开是幕布上升点是关就是下降娱乐性质大于实用性质。最后说一点个人体会这个项目最大的收获不是省了一个 Home Assistant而是真正理解了智能家居改造里“并联模拟”这个方法论。大多数老旧设备不能直接智能化的原因不是协议复杂而是你总想着接管它的电源实际只需要在它的控制输入端“插一个会按按钮的机器人”就够了。先搞清楚设备怎么被控制再用最小的方式去模拟这个控制动作这套思路可以复用到老式风扇、电动窗帘、晾衣架、投影仪幕布等等一堆设备上。如果你手头也有一台吃灰的老幕布照着这个思路试一试大概率能成功。
返回列表