ShadowZZP/esphome-panasonic-erv

GitHub: ShadowZZP/esphome-panasonic-erv

用 ESP32 直接对接松下新风 ERV 的 CN12 私有协议,实现完全本地化的 Home Assistant 与 HomeKit 控制,彻底替代原厂云模块。

Stars: 6 | Forks: 0

**English** · [简体中文](README.zh-CN.md) # esphome-panasonic-erv 为 Panasonic 新风热交换器提供本地化的 Home Assistant 和 Apple HomeKit 控制——这是一种能量 / 热回收新风交换器 (ERV / HRV / 新风 / 全热交换器)。无需专有模块,无需云端,无需 订阅:仅需一个 **约 5 美元的 ESP32** 即可替代 OEM 模块并直接与设备通信。 ![License: MIT](https://img.shields.io/badge/license-MIT-blue) ![ESPHome](https://img.shields.io/badge/ESPHome-external_component-black) ![No cloud](https://img.shields.io/badge/cloud-not_required-success) ![Cost](https://img.shields.io/badge/hardware-~%245_ESP32-success) ![Verified on hardware](https://img.shields.io/badge/status-verified_on_FY--25ZDP1C-success) 松下为这些设备销售两款可选的附加模块,一个是 Wi-Fi 模块(APP + 云端),另一个是 RS485 模块(用于楼宇自动化的 Modbus),两者都插入同一个 **CN12** 端口。本 项目**两者都不需要**。一个运行着 [ESPHome](https://esphome.io) 的 ESP32-S3 占用该插槽并 直接与主板进行其私有的 CN12 协议通信,因此一切操作都在您的局域网内完成。 与替代方案相比——无论是连接简单的继电器(仅支持开/关和强风模式),还是保留 RS485 模块并添加一个 Modbus/TCP 网关——本项目原生支持该协议,因此您只需 ESP 即可获得完整的 风量 / 模式 / 风扇控制权。 **亮点** - 💸 **低成本** — 整个构建过程只需一个 ESP32(约 **¥30 / US$5**)和几根跳线。 OEM 的 Wi-Fi 和 RS485 模块成本要高出数倍,并且会将您锁定在云端或某个楼宇系统中。 - 🔌 **无需 OEM 模块** — ESP 取代了 Wi-Fi *或* RS485 模块,直接与设备通信。 - ☁️ **无云端,无 APP** — 控制操作永远不会离开您的本地网络。 - 🔄 **双向状态** — 在墙壁控制面板上的更改会在约一秒钟内同步显示在 Home Assistant 中。 - 🍎 **HomeKit 就绪** — 一个 Home Assistant 套件即可将其变为具有多种风速和模式的 Apple Home 风扇。

Apple HomeKit     Home Assistant device page
Same unit in Apple Home (left) and Home Assistant (right).

``` ┌────────────┐ CN12 ┌──────────┐ Wi-Fi ┌────────────────┐ ┌──────────┐ │ ERV main │ 9600 8N1 │ ESP32-S3 │ native │ Home Assistant │ │ Apple │ │ board │◄═══════════►│ ESPHome │◄══════════►│ │◄═══►│ HomeKit │ └────────────┘ └──────────┘ API └────────────────┘ └──────────┘ ▲ the ESP sits where the OEM Wi-Fi / RS485 module used to, and talks to the board directly ``` CN12 协议是未公开的;它是通过逻辑分析仪逆向工程并在真实的 **FY-25ZDP1C** 上验证得来的。如果您只想让它正常工作,请按照下面的指南操作。如果您想知道它是 如何运作的,请跳转至文末的 [工作原理](#how-it-works) 和 [逆向工程过程](#how-it-was-reverse-engineered)。 ## 目录 - [仓库结构](#repository-layout) - [所需材料](#what-you-need) - [兼容性](#compatibility) - [安装与接线](#install-and-wire-it-up) - [Home Assistant 与 HomeKit](#home-assistant-and-homekit) - [实体](#entities) - [配置](#configuration) - [故障排除](#troubleshooting) - [工作原理](#how-it-works) - [逆向工程过程](#how-it-was-reverse-engineered) - [状态同步与效率](#state-sync-and-efficiency) - [贡献与反馈](#contributing-and-feedback) - [致谢](#credits) - [许可证](#license) ## 仓库结构 | 路径 | 文件说明 | 何时使用 | |------|-----------|-----------------| | [`panasonic-erv.yaml`](panasonic-erv.yaml) | ESPHome 设备配置(实体、UART、引脚) | 将其**烧录**到您的 ESP32 | | [`components/panasonic_erv/`](components/panasonic_erv) | 驱动程序 — C++ 协议 + Python 代码生成 | 由配置文件引入;编辑以扩展协议 | | [`homeassistant/packages/panasonic_erv.yaml`](homeassistant/packages/panasonic_erv.yaml) | Home Assistant template-fan 套件 | **复制到 HA** `config/packages/` 用于 HomeKit | | [`tools/decode.py`](tools/decode.py) | CN12 帧 decoder + command 构建器(纯 Python) | 在适配变体时 decode 捕获的数据或构建测试命令 | | [`secrets.yaml.example`](secrets.yaml.example) | 密钥模板 | 复制到 `secrets.yaml`,填写 Wi-Fi + 密钥 | | [`docs/PROTOCOL.md`](docs/PROTOCOL.md) · [中文](docs/PROTOCOL.zh-CN.md) | 逆向工程的协议 + 官方寄存器映射表 | 用于理解或扩展协议 | | [`docs/WIRING.md`](docs/WIRING.md) · [中文](docs/WIRING.zh-CN.md) | 接线 + 供电指南 | 将 ESP 连接到 CN12 时使用 | ## 所需材料 完整的物料清单: - **1 × ESP32-S3 开发板** — 示例针对常见的 `esp32-s3-devkitc-1`。约 **¥30 / US$5**。 - **几根跳线** — 母对母杜邦线最容易连接到 CN12 插针。 - **一根 USB-C 数据线** — 仅用于首次烧录。 - **一台电脑** — 运行 [ESPHome](https://esphome.io) 命令行,或 Home Assistant 的 ESPHome add-on。 这就是全部成本。不需要 Panasonic Wi-Fi 或 RS485 模块,不需要网关,不需要账户,不需要订阅。 只有当您以后想利用设备自带的 5V 电源供电,而不是一直插着 USB 线时,才需要用到电烙铁。 ## 兼容性 已在 **Panasonic FY-25ZDP1C** 上验证。Wi-Fi 模块 (FY-WF15ZDP1C) 和 RS485 模块 (FY-RS15ZDP2C) 都插入同一个 CN12 端口,并且松下的手册在整个 ERV 系列中都列出了该模块, 因此无论您出厂时自带哪种模块,这都应该适用于以下任何设备。只有 FY-25ZDP1C 经过 了物理测试;请将其余型号视为“应该可用,但未经测试”。可用的模式因型号类别而异 (薄型家用设备的模式 `0x05` 是排气;而在寒冷地区设备上,相同的值是严寒模式,参见 [`docs/PROTOCOL.md`](docs/PROTOCOL.md))。此组件实现了 薄型家用设备的电源/模式/风扇控制;更大的设备暴露了它尚未触及的额外功能。 | 类别 | 型号 | |-------|--------| | **薄型家用** | FY-15ZDP1C, **FY-25ZDP1C** ✅, FY-35ZDP1C, FY-50ZDP1C, FY-15GZD1, FY-25GZD1, FY-35GZD1, FY-50GZD1, FY-RZ18DP1, FY-RZ28DP1, FY-RZ38DP1 | | **薄型家用,严寒地区** | FY-15ZDP1CX, FY-25ZDP1CX, FY-35ZDP1CX | | **DC 电机** | FY-15ZJD2C, FY-25ZJD2C, FY-35ZJD2C, FY-15GZJP2, FY-25GZJP2, FY-35GZJP2, FY-15ZJP2C, FY-25ZJP2C, FY-35ZJP2C | | **商用** | FY-15ZY1C, FY-25ZY1C, FY-35ZY1C, FY-50ZY1C, FY-65ZY1C, FY-80ZY1C, FY-1KZY1C, FY-1HZY1C, FY-2KZY1C | | **柜式** | FY-50ZR1C, FY-70ZR1C | 如果您尝试了非 FY-25ZDP1C 的型号,请提交一个 issue 并附上结果——这对大家都有帮助。 ## 安装与接线 您可以先在桌面上完成整个软件部分,然后再将其接入设备。按步骤操作: **1. 安装 ESPHome。** ``` pip install esphome # or use the ESPHome add-on inside Home Assistant ``` **2. 获取配置并设置您的密钥。** ``` git clone https://github.com/shadowzzp/esphome-panasonic-erv cd esphome-panasonic-erv cp secrets.yaml.example secrets.yaml # then edit your Wi-Fi SSID and password openssl rand -base64 32 # paste the output as panasonic_erv_api_key openssl rand -base64 32 # paste the output as panasonic_erv_ota_password ``` 包含的 [`panasonic-erv.yaml`](panasonic-erv.yaml) 已经指向了本地的 `components/` 文件夹,因此可以直接编译。 **3. 通过 USB 烧录。** 将 ESP32 插入您的电脑并运行: ``` esphome run panasonic-erv.yaml --device /dev/ttyACM0 ``` 随后的每次更新都可以通过 Wi-Fi 进行——无需数据线,也无需打开机壳: ``` esphome run panasonic-erv.yaml --device ``` **4. 将其连接到设备。** 在断路器处关闭 ERV 的电源,并从 CN12 拔下 OEM 模块。 连接三根线(完整指南和接线图请见 [`docs/WIRING.md`](docs/WIRING.md)): | ESP32-S3 | | CN12 | |----------|---|------| | `GPIO18` | ← | A 线(主板 TX) | | `GPIO17` | → | B 线(主板 RX) | | `GND` | — | `GND` | CN12 的两条线在主板侧均为 3.3V,因此 ESP 可直接连接——无需电平转换器。 **切勿在插入 ESP 的同时保留插入的 OEM 模块。**

ESP32 wired into the ERV's CN12 in the ceiling
The ESP32-S3 (lower left) wired into the ERV's CN12 in place of the OEM module.

**5. 上电。** 示例默认配置了 `tx_enable_at_boot: true`,因此 ESP 会在 启动时将自身注册为模块,面板上的 `F02` 错误也会随之消除。现在您已经可以完全控制它了。 ## Home Assistant 与 HomeKit 几分钟后,该设备就会通过 ESPHome native API 出现在 Home Assistant 中(设置 → 设备与服务)。确认添加,并在提示时粘贴 `panasonic_erv_api_key`。您将获得一个**电源** 开关以及**模式** / **风扇**选择器,外加一些诊断实体。 对于 Apple Home,只需添加一个文件。将 [`homeassistant/packages/panasonic_erv.yaml`](homeassistant/packages/panasonic_erv.yaml) 复制到您的 HA `config/packages/` 文件夹中,确保 `configuration.yaml` 包含: ``` homeassistant: packages: !include_dir_named packages ``` 然后重新加载(开发者工具 → YAML → Template 实体,或重启)。它将开关和两个 选择器合并为一个 `fan.panasonic_erv`,HomeKit Bridge 会将其作为一个具有开/关、三档 风速以及模式预设的风扇公开——并保持双向同步。**请务必保留文件名中的下划线**:HA 会静默忽略名称中包含连字符的包文件。 ## 实体 | 实体 | 类型 | 说明 | |--------|------|-------| | `switch.panasonic_erv_power` | switch | 开 / 关 | | `select.panasonic_erv_mode` | select | 热交换 / 内循环 / 外循环 (heat-exchange / recirculate / exhaust) | | `select.panasonic_erv_fan` | select | 1 / 2 / 3 | | `fan.panasonic_erv` | fan | 来自 HA 包的统一实体,用于 HomeKit | | `switch.panasonic_erv_tx_enable` | switch (config) | 主总线切断开关;重新插入 OEM 模块前请关闭 | | `switch.panasonic_erv_auto_keepalive` | switch (config) | 注册与 keepalive 循环 | | `button.panasonic_erv_send_registration` | button (diag) | 重放开机握手 | | `button.panasonic_erv_restart` / `…_safe_mode_ota_recovery` / `…_send_poll` | button (diag) | 远程恢复 | | `text.panasonic_erv_raw_tx_hex` | text (config) | 为协议开发注入任意 frame | | `number.panasonic_erv_cksum_base` | number (config) | 针对不同变体实时调整 checksum base | | `sensor.panasonic_erv_*` | sensor (diag) | Wi-Fi 信号、正常运行时间、RX/TX 帧计数器 | ## 配置 ``` panasonic_erv: id: erv uart_id: erv_uart tx_enable_at_boot: true # default false. true = register + keepalive on boot (OEM module removed) cksum_base: 0xC0BA # checksum base (Σ payload + base); default verified on FY-25ZDP1C ``` `tx_enable_at_boot` 默认设置为 `false`,因此组件在您主动开启前处于仅监听状态,这在 仍插有 OEM 模块且您正在嗅探总线时是最安全的。 ## 故障排除 **面板显示 `F02`。** 主板未检测到已注册的模块。请检查 `tx_enable_at_boot` 是否为 `true`(或开启 *TX Enable*),OEM 模块是否已拔出,以及 TX/RX 是否接反。按下 *Send Registration*。 **设备关闭时,风扇或模式更改被忽略。** 这是预期行为。在断电,主板不会更改风速或 模式。请先打开电源;HomeKit 风扇会自动执行此操作。 **无状态 / 总线上无数据。** 请确认是否共地,并检查 `rx_pin` 是否接在 A 线(主板 TX)上。 **大量快速指令后面板空白。** 这是暂时性的;给设备断电重启或按一下面板上的按钮即可。 固件中的命令合并机制就是为了防止这种情况。 以下内容是为好奇者准备的。如果您的风扇已经正常工作,可以跳过。 ## 工作原理 OEM 模块和主板通过 CN12 以 9600 8N1 的波特率交换由 `A5 A5 5A 5A` 框定的数据包。 ESPHome 组件取代了模块的位置并扮演其角色: 1. **注册。** 在启动时,它会重放模块的上电握手,然后通过大约每 2 秒一次的轮询和 每 6 秒一次的心跳来保持连接活跃。如果没有此步骤,面板会显示 `F02`。 2. **读取状态。** 它将主板的状态帧 (`03 0B … RUN MODE FAN`) 解析为电源、模式 和风速,因此在墙壁面板上所做的更改也会显示在 Home Assistant 中。 3. **发送指令。** 它使用正确的 checksum 构建 66 字节的指令帧 (`02 0B`),并利用 掩码写入,从而在更改一个字段时不干扰其他字段。 包括官方 Modbus 寄存器映射表在内的完整逐帧规范,位于 [`docs/PROTOCOL.md`](docs/PROTOCOL.md)。 ## 逆向工程过程 CN12 协议并未公开,因此它是通过逻辑分析仪在桌面上从头开始解析出来的。简述如下: 1. **寻找总线。** 拔下 OEM Wi-Fi 模块会使面板显示 `F02`(设备连接 错误)。这证实了承载控制信号的正是模块↔主板之间的连接,而 CN12 就是那条链路。 2. **监听。** 将逻辑分析仪接在 A 线上——这是主板的 3.3V 发送线,只读且安全—— 显示了由 `A5 A5 5A 5A` 框定的 9600 8N1 通信流量。 3. **映射字段。** 按下墙壁面板上的电源 / 模式 / 风扇键,并观察哪些字节发生了变化, 从而在 `36 00 00 00 …` payload 中确定了 RUN、MODE 和 FAN。 4. **破解 checksum。** 每条命令都带有一个 16 位的 `b5 b6` 字段。其中一部分在每次 启动时看起来都是随机的——这是一个干扰项,后来证明那是主板自身的状态序列。而*命令* 的 checksum 是确定性的:`(Σ payload + 0xC0BA) & 0xFFFF`,这在捕获到的三条 命令中都是一致的。利用该 checksum 合成一条开机命令并发送,使得设备 在物理上启动了——这就是一切豁然开朗的时刻。 5. **伪装成模块。** 重放模块的开机握手和 keepalive 节奏,使主板 接受 ESP 作为真正的模块,因此面板永远不会回退到 `F02`。

Logic analyzer tapping the CN12 bus on the bench
Bench setup: tapping the CN12 bus to capture and decode the protocol.

完整规范请见 [`docs/PROTOCOL.md`](docs/PROTOCOL.md)。 ## 状态同步与效率 两个设计选择使得控制变得迅速,而不会淹没网络或缓慢的 9600 波特率总线。 **滑块连发。** 拖动 HomeKit 的风速滑块会触发一连串的设置百分比调用。 固件将它们合并,并且只发送最终确定的值,因此总线和设备的面板 永远不会看到中间的步骤。 **空闲流量。** ESPHome 的 `select` 不会对状态进行去重,因此轮询会 在每个时间间隔向 HA 重新发布数据,无论是否有更改。相反,这里的选择器是乐观的 (点击时提供即时反馈),并且一个小型的 `interval` lambda 只在主板状态实际发生 变化时,且仅在正在进行的命令执行完毕后,才将主板的真实状态推送回去。其结果是 即时的 UI 反馈,在墙壁面板发生某些变化时大约一秒钟的同步时间,以及在空闲时 几乎没有流量。logger 运行在 `INFO` 级别,并且逐帧的十六进制格式化会在编译时 被剔除,除非您将其提高到 `DEBUG` 级别,因此对于已安装封闭的设备,依然可以在 不带来平时性能损耗的情况下通过无线方式进行深度调试。 ## 致谢 “模拟模块”的方法是由 [DomiStyle/esphome-panasonic-ac](https://github.com/DomiStyle/esphome-panasonic-ac) 证明的,该项目对松下空调(CN-CNT / CZ-TACG1 协议)做了同样的事情。ERV 的 CN12 帧规范是不同的,因此该协议是从头开始逆向的,但那个项目表明这是 值得做的。基于 [ESPHome](https://esphome.io) 构建。 ## 许可证 [MIT](LICENSE)
标签:ESPHome, Home Assistant, HomeKit, 新风系统, 智能家居, 物联网, 硬件DIY, 逆向工具