dzerik/zs3l-ncp-flash-over-network
GitHub: dzerik/zs3l-ncp-flash-over-network
通过 WiFi 远程将封闭的涂鸦 ZS3L Zigbee 网关刷写为开源 Zigbee 协调器,无需 SWD 或焊接。
Stars: 0 | Forks: 0
# 通过网络刷写 ZS3L Zigbee NCP —— 无需 SWD,无需焊接
将一个 **WBRG1 + ZS3L** Tuya Zigbee 网关——一款以智能家居品牌名义销售的封闭固件集线器——变成 Home Assistant 的开源 **Zigbee coordinator**——完全通过 WiFi 刷写 Silicon Labs **EFR32MG21 (Tuya ZS3L)** NCP,经由网关 Realtek **RTL8721CSM (WBRG1)** 模块上的 OpenBeken 桥接进行。不需要 J-Link,不需要 SWD,也不需要焊接 Zigbee 芯片。
## 原理
Zigbee 芯片 (EFR32) 无法直接访问——它连接在 RTL8721 的 UART 上。一旦 RTL8721 运行了带有 `uarttcp` 桥接的 [OpenBeken](https://github.com/openshwprojects/OpenBK7231T_App),你就可以通过 TCP 访问 EFR32。但是,正在运行的 NCP 应用无法被指示跳转到其 bootloader,而且 TCP socket 上也没有 DTR/RTS。
原厂网关固件通过驱动两个 RTL8721 GPIO 来更新 NCP:一个 **boot-select strap** 和 **EFR32 reset** 线。我们完全复现了这一操作,只是改为从 OpenBeken 通过 WiFi 进行:将 strap 保持为 HIGH,向 EFR32 reset 发送脉冲,芯片就会进入其 **Gecko bootloader**。然后我们使用一个内置的微型 **XMODEM-CRC** 发送器 (`flasher/flash_zs3l.py`) 上传 `.gbl` 固件。
有两个耗费了数小时的坑(已记录在 [docs/investigation.md](docs/investigation.md) 中):
- **硬件流控制。** NCP 构建版本是启用了*硬件流控制*的镜像,因此**除非 OpenBeken 桥接开启了流控制** (`startDriver uarttcp 115200 512 1 1`),否则正在运行的应用程序将**毫无反应**。bootloader 本身不使用流控制,因此刷写工具会将桥接切换为 `flow=0` 以进行刷写,并在运行时切换回 `flow=1`。
- **reset 引脚与其他指南所述不同。** 在此设备上它是 **PB13** (OpenBeken 引脚索引 **45**),而不是 PA28。请使用 `scan-reset` 来查找你设备的对应引脚。
## 引脚映射(我测试的网关——请自行验证)
OpenBeken 平铺引脚索引 = `port*32 + pin` (PA0..31 = 0..31, PB0..31 = 32..63)。
| 信号 | RTL8721 引脚 | OpenBeken 索引 | 驱动方式 |
|---|---|---|---|
| Zigbee boot-select strap | PB4 | **36** | HIGH 以进入 bootloader |
| EFR32 reset (`nRESET`) | PB13 | **45** | 低电平有效脉冲 (active-LOW pulse) |
| UART0 桥接 (请勿改动) | PA16/17/18/19 | 16/17/18/19 | RTS0/CTS0/TX0/RX0 |
## 前置条件
1. WBRG1 已经刷入 **OpenBeken** (`OpenRTL8720D`),可在你的局域网内访问,并且桥接正在运行:`startDriver uarttcp 115200 512 1 1`。
2. 一个 ZS3L NCP 固件 `.gbl`。可用的固件位于 [`config/zs3l_zigbee_ncp_8.2.2.0_115200.gbl`](config/) (EmberZNet 8.2.2.0,使用 [`silabs-firmware-builder`](https://github.com/NabuCasa/silabs-firmware-builder) 构建——如果你自行构建,请参阅 [Dockerfile 说明](config/Dockerfile-libdbus.md))。
3. Python 3,以及用于验证的 [`bellows`](https://github.com/zigpy/bellows)
(请在 **Python 3.12** 下安装——CLI 在 3.14 上会出错)。
## 开始刷写
```
# (可选) 在你的 gateway 上找到 reset pin
python3 flasher/flash_zs3l.py --host 192.168.1.68 scan-reset
# 强制 bootloader + 上传 firmware
python3 flasher/flash_zs3l.py --host 192.168.1.68 \
flash --gbl config/zs3l_zigbee_ncp_8.2.2.0_115200.gbl
# 断电重启整个 hub(软件重启不会重置 EFR32!)
# 验证(需要在 Python 3.12 上安装 bellows;bridge 必须处于 flow=1)
bellows -d socket://192.168.1.68:8888 info
# -> EmberZNet version: 8.2.2.0 build 436 ; EmberNodeType.COORDINATOR
```
## 在 Home Assistant 中使用它
将其作为**辅助 coordinator** 与你现有的设置一起运行。
**ZHA(最简单——HA 内置):** 设置 → 设备与服务 → 添加集成 →
*Zigbee Home Automation* → 手动输入 → radio 类型 **EZSP** → 设备路径
`socket://192.168.1.68:8888`。
**Zigbee2MQTT(独立实例):**
```
serial:
port: tcp://192.168.1.68:8888
adapter: ember
baudrate: 115200
```
流控制由 OpenBeken 桥接处理 (`flow=1`);对于 TCP 端口,HA 端不需要任何额外配置。
## 文件
- `flasher/flash_zs3l.py` —— bootloader 强制进入 + XMODEM 刷写工具 (`enter` / `scan-reset` / `flash` / `run`)。
- `flasher/verify.sh` —— 基于 bellows 的验证脚本。
- `config/` —— 一个可用的 `.gbl`,OpenBeken `autoexec.bat` 变体,以及 Dockerfile 修复。
- `docs/investigation.md` —— 记录了研究过程及走过的死胡同。
- `CREDITS.md` —— 本项目是建立在大量社区工作的基础之上的。
## 许可证
MIT —— 详见 [LICENSE](LICENSE)。固件 `.gbl` 是通过社区的 `silabs-firmware-builder` 从 Silicon Labs 的 SDK 构建的;其许可遵循 Silicon Labs 的条款。
标签:Home Assistant, OpenBeken, Zigbee, 固件刷写, 智能家居, 物联网, 请求拦截, 逆向工具