破解我的云控吊扇的射频遥控
摘要
一位开发者对Dreo云控吊扇的射频遥控器进行逆向工程,以实现通过Home Assistant的本地控制,从而绕过云依赖,并记录了解码和重放命令的过程。
暂无内容
查看缓存全文
缓存时间: 2026/06/30 21:39
# RF破解我的云控吊扇 · Sam Wilkinson
来源:https://samwilkinson.io/posts/2026-06-24-rf-hacking-dreo
## RF破解我的云控吊扇
2026年6月24日 · 8分钟阅读
搬进现在的住处后,我们很快就想换掉卧室的吊扇。那家伙几乎占了天花板四分之一,晃得厉害,而且我根本搞不清那三根(!)拉绳分别控制什么。必须换掉。
一番搜索后,Dreo 的这款吊扇(型号 CLF513S)看起来不错。价格合理,外观漂亮,最重要的是尺寸正常。
过去几年我一直热衷于智能家居,以 Home Assistant 为核心平台,所以希望能把新风扇加入我的系统。遗憾的是,Dreo 的智能家居集成默认仅支持云端。不过,他们维护了一个官方的 Home Assistant 集成,这点值得加分。
我尽可能避免使用基于云的智能家居控制,原因如下:
- 网络中断会导致设备无法工作。
- 你常常会被锁定在充满广告的专用应用中,而绕过这些应用的集成可能不稳定。
- 让外部服务器控制家里的实物,感觉总有点不对劲。
风扇外观时尚且价格实惠,我忍了忍还是买下了,希望安装后能找到本地控制的方法。
## 选择本地控制的路径
在探索本地控制的选项时,我发现了 GitHub 上 `ouaibe` 的出色项目,他们通过令人印象深刻的固件逆向工程,在另一款 Dreo 风扇上成功运行了 ESPHome。
虽然我可以尝试跟着他们的步骤,在我的吊扇上复制他们的方法,但一想到可能把直连在天花板上的东西变砖,就打了退堂鼓。
风扇唯一的本地控制方式就是遥控器,所以我打算走“万能遥控器”路线:解码遥控器的指令并重放它们。万能遥控器是出了名的可靠产品,显然我没走错路。
Dreo 遥控器
遥控器不需要视线对准,所以不像电视遥控器那样使用红外线。查阅背面标注的 FCC ID 后确认它是一个射频发射器。
为了实现通过 Home Assistant 进行本地控制,我需要完成三步:
1. 解码遥控器的 RF 指令。
2. 构建一个能重放这些指令的设备。
3. 让 Home Assistant 触发这些重放。
确定了方法后,第一步是弄清楚遥控器到底发送了什么信号。
## 解码指令
要解码一个(简单的)RF 控制方案,你需要确定三件事:
1. **载波频率**:用于通信的基础频率。
2. **调制方式**:如何通过载波频率传输 1 和 0。
3. **有效载荷**:遥控器发送的实际 1 和 0 比特序列。
根据制造商 FCC 文档找到载波频率(433.92 MHz,遥控器常用频率)后,下一步是弄清楚调制方式。
遥控器常用的两种数字调制方式是:
- **幅移键控 (ASK)**:发射机通过升高和降低载波振幅来表示 1 和 0。一种简单形式是**开关键控 (OOK)**,即载波直接打开和关闭。
- **频移键控 (FSK)**:发射机将信号频率略微高于和低于载波频率,以表示 1 和 0。
这跟 AM 与 FM 收音机的基本概念相同,但处理的是数字信号而非模拟音频。FCC 文档 *声称* 遥控器使用 FSK,但我想实际验证信号,而不是盲目相信文档。通常这些文档会使用通用值,所以它们并不是最可靠的来源。
我使用 RTL-SDR(配合 gqrx)在按下遥控器按钮时捕获 RF 频谱数据。结果清楚地表明遥控器使用的是 ASK(具体来说是 OOK):在载波频率上出现高振幅脉冲,中间是静默。下面是水平旋转的水声图,显示了按下风扇开/关按钮两次时捕获的频谱。
水声图
通过下方的图表更详细地查看捕获数据,信号似乎使用短脉冲和长脉冲的振幅变化,有点像摩斯电码的点与划。
OOK 比特
放大一次按钮按下,我发现一个特定模式在快速连续重复五次。下面的图表显示了一次重复,然后我可以将其解码为逻辑 1 和 0。对每个我想复制的按钮(风扇开/关、风扇速度预设、灯光开/关、亮度升/降)重复这个过程。
开/关指令解码
每个指令的结构相同,单个数据包重复五次,重复间隔为 8.8 毫秒:
- **前导码**:8 个逻辑 0。
- 共享的 **20 位同步** 短语。
- 唯一的 **13 位有效载荷**,指定指令。
例如,风扇开/关按钮的有效载荷是:
`0111110010000`
如上所述,逻辑位被编码为短的 OOK 脉冲模式,其中 `1000` 代表逻辑 `0`,`1110` 代表逻辑 `1`。这些模式中的每个脉冲持续 300 微秒,因此每个逻辑位(四个脉冲)需要 1.2 毫秒传输。
这意味着上面的风扇开/关有效载荷被传输为:
`1000 1110 1110 1110 1110 1110 1000 1000 1110 1000 1000 1000 1000`
所有解码后的指令都可以在项目的仓库中找到。
## 重放指令
为了重放这些指令,我将 Xiao ESP32-C6 板连接到 RFM69HCW 433 MHz RF 收发器。我最近经常使用 Seeed Studio 的 Xiao 板,它们非常小巧,非常适合保持项目紧凑。ESP32 完全被收发器分线板覆盖。
开放式外壳中的 RFAN 电路
据我所知,我解码的数据包结构是专有的,不受 RadioHead 等现有库支持。我没有让射频库来理解协议,而是使用收发器的原始发送模式,并手动根据从原始遥控器解码的脉冲时序切换其数据引脚。
要重放指令,微控制器需要:
1. 通过 SPI 配置射频模块:频率、调制方式、功率设置等。
2. 将射频模块置于发送模式。
3. 根据指令的脉冲时序切换射频模块的数据引脚。
4. 将射频模块恢复至休眠状态,直到再次需要。
这里 RTL-SDR 再次发挥了作用。没有它,调试主要就是刷固件、走进卧室看看风扇有没有反应。有了 SDR,我可以实际比较生成的信号和原始遥控器捕获的信号。
最烦人的问题是时序。风扇相当挑剔:一个在代码中看起来正确的指令,如果脉冲时序或数据包间间隔稍有偏差,就可能被忽略。
最后一个障碍是我在射频/SPI 处理中引入的一个 bug,导致 ESP32 断开 Wi-Fi 连接。修复后,经过多次在办公室和卧室之间来回测试命令,ESP32 终于能够可靠地重放与原始遥控器相同的指令了!
## 连接到 Home Assistant
现在我已经能够重放想要的指令,我需要一种从 Home Assistant 触发它们的方法。一个简单的解决方案是 MQTT,这是一种轻量级的消息协议,广泛应用于智能家居设备。MQTT 的工作原理是:设备向命名主题发布消息,而其他设备订阅这些主题,并在消息到达时做出响应。
MQTT 图示
我将 ESP32 配置为订阅一组 MQTT 主题,每个主题对应一个特定的风扇或灯光指令。Home Assistant 可以在用户操作仪表板上的风扇控制时,向这些主题发布消息。当 ESP32 收到消息时,它会重放相应的 RF 指令。
由于风扇不会向发射器发送任何反馈,ESP32 无法知道风扇的实际状态。为解决这个问题,设备首次通电时会假设一个默认状态:灯光关闭、中等亮度、风扇关闭。当它发送指令时,会相应地更新这个内部状态。状态会保存到持久存储中,因此默认状态仅在首次启动时需要。
偶尔状态会与风扇不同步,例如在墙壁开关关闭风扇时发送指令。发生这种情况时,我只需使用遥控器将风扇恢复到 Home Assistant 期望的状态即可。
## 总结
外壳中的 RFAN
为发射器打印了一个小外壳,并给天线添上标志性的强调色后,终于可以投入使用了。
这种项目成功的最好标志就是没人再需要想着它。这个小发射器在我的办公室架子上放了将近一年,我和伴侣每天都用 Siri 愉快地控制我们的风扇。
如果你有兴趣复现这个方法,请查看项目的仓库。
相似文章
一款由iroh驱动的智能风扇
本文演示了如何使用ESP32微控制器和iroh网络库构建智能风扇,实现无需云服务的点对点控制。
QuadRF 可以探测无人机并透过墙壁看到 WiFi 信号
QuadRF 是一款基于 Raspberry Pi 5 的相控阵无线电,能够探测无人机并透过墙壁可视化 WiFi 信号,并配有用于高级信号处理的开源软件。
逆向工程如今变得廉价
本文讨论了编程代理如何大幅降低逆向工程家用设备的成本和精力,使自动化项目更易实现且风险更低。
无需触碰,通过音箱入侵你的电脑
一位安全研究人员对 Creative Sound Blaster Katana V2X 的固件进行了逆向工程,发现了漏洞,攻击者可在15米范围内将音箱变成隐蔽的窃听工具和无需物理接触的 Rubber Ducky。
逆向工程Creative Katana音箱以从Linux控制
一位开发者逆向工程了专有的Creative Sound Blaster Katana V2X音箱的USB协议,以便从Linux控制它,记录了捕获流量、去混淆固件和分析命令的过程。