dgebbink/duuxventilator

GitHub: dgebbink/duuxventilator

通过 DNS 覆盖拦截 DUUX 风扇的云端 MQTT 连接并重定向到本地 broker,实现完全脱离云端、经由 Home Assistant 接入 Apple Home 的本地化控制方案。

Stars: 0 | Forks: 0

# DUUX 风扇 — 通过 Home Assistant 将本地 MQTT 接入 Apple Home 拦截 DUUX Whisper Flex 风扇的云端 MQTT 连接并将其重定向到本地 Mosquitto broker,使风扇可以通过 Home Assistant 和 Apple Home 进行控制 —— 无需任何云端依赖。 ## 工作原理 ``` Fan ──MQTTS:443──► Mosquitto (local) ──► state-keeper ──► retained topics ──► Home Assistant ──► Apple Home ▲ DNS override collector3.cloudgarden.nl → 192.168.2.27 ``` 1. 风扇通过 MQTTS 连接到 `collector3.cloudgarden.nl:443` 2. 本地 DNS 覆盖将该主机名指向 Mosquitto 主机 3. Mosquitto 提供自签名的 TLS 证书(风扇不会验证证书链) 4. `duux-state-keeper` 订阅原始风扇 topic,并使用 `retain=True` 重新发布提取出的状态 5. Home Assistant 读取保留的 state topic —— 在任何 HA 重启后都能立即恢复状态 ## 硬件 - **风扇:** DUUX Whisper Flex(固件 14.3.10) - **Broker 主机:** 运行 Docker 的 Raspberry Pi(192.168.2.27,macvlan) - **Home Assistant:** 192.168.2.26 ## MQTT Topic ### 原始风扇 topic(由风扇发布) | Topic | 方向 | 内容 | |-------|-----------|---------| | `sensor/e0:5a:1b:76:ef:60/in` | 风扇 → broker | JSON 状态(电源、速度、模式等) | | `sensor/e0:5a:1b:76:ef:60/command` | broker → 风扇 | 纯文本命令,例如 `tune set power 1` | | `sensor/e0:5a:1b:76:ef:60/online` | 风扇 → broker | `{"online":true,"connectionType":"mqtt"}` | ### 保留的状态 topic(由 duux-state-keeper 发布,v1.1) | Topic | 内容 | 值 | |-------|---------|--------| | `duux/e0:5a:1b:76:ef:60/power` | 电源状态 | `"1"` 或 `"0"` | | `duux/e0:5a:1b:76:ef:60/speed` | 设备原始速度 | `"1"` – `"26"` | | `duux/e0:5a:1b:76:ef:60/available` | 可用性 | `"online"` 或 `"offline"` | State payload 示例: ``` {"sub":{"Tune":[{"uid":"dune79w7bsu6dg3e","id":1,"power":0,"mode":0,"speed":8,"swing":0,"tilt":0,"timer":0}]}} ``` - `power`:`0` = 关闭,`1` = 开启 - `speed`:`1–26`(Whisper Flex 1 的范围) ## 设置说明 ### 1. 生成 TLS 证书 ``` bash certs/generate-certs.sh ``` 为 `collector3.cloudgarden.nl` 生成自签名证书。 ### 2. 启动 Mosquitto + state-keeper 将 `docker-compose-additions.yml` 合并到你现有的 compose 技术栈中: ``` docker compose -f docker-compose.yml -f docker-compose-additions.yml up -d mosquitto duux-state-keeper ``` ### 3. DNS 覆盖 在你的本地 DNS(例如 Pi-hole)中,将 `collector3.cloudgarden.nl`(以及 `collector.cloudgarden.nl`)指向你的 Mosquitto 主机(192.168.2.27)。 ### 4. 验证 重新插拔风扇电源,然后检查原始 topic: ``` mosquitto_sub -h 192.168.2.27 -p 1883 -t 'sensor/#' -v ``` 并验证是否出现了保留的 state topic: ``` mosquitto_sub -h 192.168.2.27 -p 1883 -t 'duux/#' -v ``` ### 5. Home Assistant 将 `homeassistant/fan.yaml` 复制到 `/mqtt/fan.yaml`,并确保你的 `configuration.yaml` 包含以下内容: ``` mqtt: fan: !include_dir_merge_list mqtt/ ``` 重启 Home Assistant。该风扇将作为一个 fan 实体(`fan.duux_whisper_flex`)出现,支持开/关和速度(百分比)控制。在第一次风扇事件后,状态将被保留,并在 HA 重启后依然存在。 ### 6. Apple Home 在 Home Assistant 中启用内置的 **HomeKit Bridge** 集成(设置 → 集成),添加该 fan 实体,然后在 Apple Home 应用中扫描二维码即可。 ## 文件 | 文件 | 用途 | |------|---------| | `certs/generate-certs.sh` | 生成自签名 TLS 证书 | | `mosquitto/duux-fan-tls.conf` | Mosquitto TLS 监听器配置 | | `docker-compose-additions.yml` | 用于端口 443、volumes 和 state-keeper 的 compose 覆盖配置 | | `capture-credentials.sh` | 调试助手:捕获原始 MQTT CONNECT 数据包 | | `homeassistant/fan.yaml` | 用于 Home Assistant 的 MQTT fan 实体 | | `homeassistant/configuration.yaml` | HA 配置片段 | | `state-keeper/state_keeper.py` | State keeper 服务 (v1.1) | | `state-keeper/Dockerfile` | 用于 state-keeper 的 Docker 镜像 | | `state-keeper/requirements.txt` | Python 依赖 | ## 更新日志 ### v1.1 - 添加了 `duux-state-keeper` Docker 服务,该服务订阅原始风扇 topic,并使用 `retain=True` 将提取的状态重新发布到 `duux//power`、`duux//speed` 和 `duux//available` - 更新了 `homeassistant/fan.yaml` 以从保留的 state topic 中读取数据 —— Home Assistant 现在可以在重启时立即恢复上次已知的 fan 状态 ### v1.0 - 初始设置:DNS 拦截、Mosquitto TLS 监听器、读取原始风扇 topic 的 HA fan 实体
标签:DNS劫持, Home Assistant, 底层编程, 智能家居, 本地化, 版权保护, 物联网, 请求拦截, 逆向工具