jnilo1/rtl8196e-gateway
GitHub: jnilo1/rtl8196e-gateway
该项目为 RTL8196E 智能家居网关提供开源 Linux 固件,将其从云端依赖设备转变为完全本地化运行的 Zigbee 协调器或 Thread 边界路由器。
Stars: 184 | Forks: 24
# RTL8196E 网关 — 适用于智能家居 Hub 的开源 Linux 固件
## 您可以用它做什么?
**Lidl Silvercrest Zigbee 网关** 通常被锁定在 Tuya 云端。
本项目替换了其固件,将其变成一个**完全本地化、开源的智能家居 hub** — Zigbee 协调器、Thread 边界路由器或 Zigbee 路由器:
- **Zigbee 协调器** — 配合 Zigbee2MQTT 或 ZHA 对接和控制任何 Zigbee 设备,无需云端
- **在 Series-1 芯片上运行现代 Zigbee 协议栈** — 运行 **EmberZNet 8.2** 主机端
(cpcd + zigbeed),或将整个协议栈交给 Zigbee2MQTT 的 **ZigBee-on-Host**
(`zoh`) 适配器 — 您不再受限于该芯片最后一次片上 NCP 发布版本 (7.5.1)
- **Thread 边界路由器** — 在网关上原生运行 otbr-agent,兼容 Home Assistant
- **Zigbee 路由器** — 作为独立的 3.0 路由器扩展您的 Zigbee mesh 网络
- **SSH 访问** — 在网关上获得完整的 Linux shell (BusyBox + Dropbear)
- **OTA 固件更新** — 通过网络刷入 Zigbee/Thread 无线电,无需 SWD
该网关包含两块芯片:一块是运行 Linux 的 **Realtek RTL8196E**,另一块是
通过 UART 连接的 **Silabs EFR32MG1B** Zigbee/Thread 无线电芯片。本项目为两者均提供了固件。
而且不仅仅是这款网关:RTL8196E 被广泛应用于那个时代的许多廉价 Zigbee hub 中,
从 v3.10.0 版本开始,所有特定于开发板的内容(引脚、接线、内存大小)
都被放置在设备树中,支持针对各开发板的内核构建
(`BOARD= ./build_kernel.sh`) 并提供了添加新开发板的文档化指南。如果
您拥有其他基于 RTL8196E 的网关,移植此固件只需遵循指南即可,
无需重新 fork — 社区正在推进向 **Sengled Smart Hub G4** 的移植工作
([#119](https://github.com/jnilo1/rtl8196e-gateway/discussions/119))。
## 快速开始
### 准备工作
- 一台 Lidl Silvercrest Zigbee 网关
- USB 转串口适配器(3.3V,38400 8N1)— 仅在首次刷写时需要
- 连接到网关的以太网连接
- **网关的 SSH 访问权限**(仅用于升级和 `flash_efr32.sh`):
- **SSH 密钥**(推荐):使用 `ssh-copy-id root@` 一次性复制您的公钥,
之后每次脚本调用都将静默运行。
- 不带 `ssh-agent` 的**加密密钥**,或仅有 **root 密码**:同样
可行。每个脚本中的第一次 SSH 调用会提示您输入一次
(密码短语或密码);后续命令将复用同一多路复用
通道 — 无需重复提示。
- **带有密码的非交互式(CI / 自动化)**:在环境中设置
`SSH_PASSWORD=`。脚本将使用
`sshpass` 将密码提供给第一次 ssh 调用(因此在这种情况下请安装
`sshpass`:`sudo apt install sshpass`);后续调用
将复用多路复用通道,无需进一步输入。
全新安装的默认密码为 `root` — 请在网关启动后尽快修改。
`S90checkpasswd` 在您修改之前会在每次登录时发出警告。
### 第 1 步:克隆并刷入 Linux 系统
```
git clone https://github.com/jnilo1/rtl8196e-gateway.git
cd rtl8196e-gateway
# 首次刷写 — 网关必须处于 bootloader 模式(通过串口 ESC 进入 提示符):
./flash_install_rtl8196e.sh
# 升级 — 网关运行 Linux(自动保存配置):
./flash_install_rtl8196e.sh 192.168.1.88
# 全自动升级(固件 >= v2.0.0,无提示):
./flash_install_rtl8196e.sh -y 192.168.1.88
```
该脚本会构建一个完整的 16 MiB flash 镜像,并通过 TFTP 上传。
- **首次刷写**(无参数):网关必须已处于 bootloader 模式
(通过串口控制台 + 开机时按 ESC)。用户配置无法保存 — 系统
会提示您进行网络和无线电设置。
- **升级**(带 `LINUX_IP` 参数):通过 SSH 连接,保存用户配置(网络、
密码、SSH 密钥、无线电模式),触发 boothold + 重启,然后进行刷写。
在固件版本 >= v2.0.0 时,`-y` 标志可实现完全无人值守操作。
- 对于旧版 bootloader (Tuya/V1.2),脚本会引导您在串口控制台上执行 FLW
命令。
详情请参阅 [35-Migration](./3-Main-SoC-Realtek-RTL8196E/35-Migration/README.md)。
### 第 2 步:刷入 Zigbee 无线电固件
一旦网关启动运行(通过端口 22 进行 SSH 访问):
```
./flash_efr32.sh -y ncp # default IP 192.168.1.88
./flash_efr32.sh -y ncp 460800 # NCP at 460800 baud
./flash_efr32.sh -y -g 10.0.0.5 otrcp # custom IP, OT-RCP
./flash_efr32.sh --help # full CLI reference
```
根据您的使用场景选择固件(别名 = `bootloader`、`ncp`、`rcp`、
`otrcp`、`router` — 也接受数字 `1`-`5`):
| 选项 | 固件 | 配合使用 |
|--------|----------|----------|
| **NCP-UART-HW** | EmberZNet 7.5.1 (EZSP) | zigbee2mqtt、ZHA — 最简单的设置 |
| **RCP-UART-HW** | 802.15.4 RCP (CPC) | 配合 zigbee2mqtt 运行主机端的 **EmberZNet 8.2** (cpcd + zigbeed) — 该 Series-1 芯片上最新的 Zigbee 协议栈 |
| **OT-RCP** | OpenThread RCP | otbr-agent (Thread 边界路由器),或 zigbee2mqtt 的 **ZigBee-on-Host** (`zoh` 适配器) |
### 第 3 步:连接 Zigbee2MQTT
在您的 zigbee2mqtt `configuration.yaml` 中:
```
serial:
port: tcp://:8888
adapter: ember
```
打开 `http://localhost:8080` 的 Web UI 并开始配对设备。
## 仓库结构
| 目录 | 内容 |
|-----------|----------|
| [0-Hardware](./0-Hardware/README.md) | PCB 照片、引脚定义、芯片规格 |
| [1-Build-Environment](./1-Build-Environment/README.md) | 工具链 (Lexra MIPS + ARM GCC + Silabs slc-cli) |
| [2-Zigbee-Radio-Silabs-EFR32](./2-Zigbee-Radio-Silabs-EFR32/README.md) | EFR32 固件:bootloader、NCP、RCP、OT-RCP、路由器 |
| [3-Main-SoC-Realtek-RTL8196E](./3-Main-SoC-Realtek-RTL8196E/README.md) | Linux 系统:bootloader、kernel、rootfs、userdata |
### 脚本
**安装、备份与刷写**(仓库根目录):
| 脚本 | 描述 |
|--------|-------------|
| [`flash_install_rtl8196e.sh`](https://github.com/jnilo1/rtl8196e-gateway/blob/main/flash_install_rtl8196e.sh) | **安装自定义固件** — 首次刷写(无参数,bootloader 模式)或升级(`LINUX_IP`,保存配置)。`-y` 用于无人值守升级 (>= v2.0.0) |
| [`build_fullflash.sh`](https://github.com/jnilo1/rtl8196e-gateway/blob/main/build_fullflash.sh) | 将所有 4 个分区构建为完整的 16 MiB flash 镜像 |
| [`backup_gateway.sh`](https://github.com/jnilo1/rtl8196e-gateway/blob/main/backup_gateway.sh) | 备份整个 flash — 自动检测网关状态(SSH 或 bootloader) |
| [`restore_gateway.sh`](https://github.com/jnilo1/rtl8196e-gateway/blob/main/restore_gateway.sh) | 恢复 fullflash.bin 备份 — 引导您完成 TFTP + FLW 流程 |
| [`flash_efr32.sh`](https://github.com/jnilo1/rtl8196e-gateway/blob/main/flash_efr32.sh) | 通过 SSH 刷入 Zigbee/Thread 无线电固件(通过 universal-silabs-flasher 进行 OTA) |
**组件级构建与刷写**(位于 `3-Main-SoC-Realtek-RTL8196E/`):
| 脚本 | 描述 |
|--------|-------------|
| [`31-Bootloader/build_bootloader.sh`](https://github.com/jnilo1/rtl8196e-gateway/blob/main/3-Main-SoC-Realtek-RTL8196E/31-Bootloader/build_bootloader.sh) | 构建 RTL8196E bootloader |
| [`31-Bootloader/flash_bootloader.sh`](https://github.com/jnilo1/rtl8196e-gateway/blob/main/3-Main-SoC-Realtek-RTL8196E/31-Bootloader/flash_bootloader.sh) | 仅刷写 bootloader — 网关必须处于 bootloader 模式 |
| [`32-Kernel/build_kernel.sh`](https://github.com/jnilo1/rtl8196e-gateway/blob/main/3-Main-SoC-Realtek-RTL8196E/32-Kernel/build_kernel.sh) | 构建 Linux kernel |
| [`32-Kernel/flash_kernel.sh`](https://github.com/jnilo1/rtl8196e-gateway/blob/main/3-Main-SoC-Realtek-RTL8196E/32-Kernel/flash_kernel.sh) | 仅刷写 kernel — 网关必须处于 bootloader 模式 |
| [`33-Rootfs/build_rootfs.sh`](https://github.com/jnilo1/rtl8196e-gateway/blob/main/3-Main-SoC-Realtek-RTL8196E/33-Rootfs/build_rootfs.sh) | 构建 root 文件系统 |
| [`33-Rootfs/flash_rootfs.sh`](https://github.com/jnilo1/rtl8196e-gateway/blob/main/3-Main-SoC-Realtek-RTL8196E/33-Rootfs/flash_rootfs.sh) | 仅刷写 rootfs — 网关必须处于 bootloader 模式 |
| [`34-Userdata/build_userdata.sh`](https://github.com/jnilo1/rtl8196e-gateway/blob/main/3-Main-SoC-Realtek-RTL8196E/34-Userdata/build_userdata.sh) | 构建 JFFS2 userdata 分区 |
| [`34-Userdata/flash_userdata.sh`](https://github.com/jnilo1/rtl8196e-gateway/blob/main/3-Main-SoC-Realtek-RTL8196E/34-Userdata/flash_userdata.sh) | 仅刷写 userdata — 网关必须处于 bootloader 模式 |
| [`flash_remote.sh`](https://github.com/jnilo1/rtl8196e-gateway/blob/main/3-Main-SoC-Realtek-RTL8196E/flash_remote.sh) | 通过 SSH 登录运行中的网关,执行 boothold,然后刷入单个分区(无需串口)。对于 userdata,会保留用户配置(网络、密码、SSH 密钥等) |
**备份工具**(位于 `30-Backup-Restore/`):
| 脚本 | 描述 |
|--------|-------------|
| [`split_flash.sh`](https://github.com/jnilo1/rtl8196e-gateway/blob/main/3-Main-SoC-Realtek-RTL8196E/30-Backup-Restore/split_flash.sh) | 将 16 MB 完整 flash 拆分为单个分区文件 |
| [`restore_mtd_via_ssh.sh`](https://github.com/jnilo1/rtl8196e-gateway/blob/main/3-Main-SoC-Realtek-RTL8196E/30-Backup-Restore/scripts/restore_mtd_via_ssh.sh) | 通过 SSH 恢复分区(仅限原始 Tuya 固件) |
## 从源码构建
仓库中已包含预构建镜像。如果您想进行自定义:
**原生环境 (Ubuntu 22.04 / WSL2):**
```
cd 1-Build-Environment && sudo ./install_deps.sh
```
**Docker(任何操作系统):**
```
cd 1-Build-Environment && docker build -t lidl-gateway-builder .
docker run -it --rm -v $(pwd)/..:/workspace lidl-gateway-builder
```
然后进行构建和刷写:
```
# 构建 Linux 系统
cd 3-Main-SoC-Realtek-RTL8196E/32-Kernel && ./build_kernel.sh
cd ../33-Rootfs && ./build_rootfs.sh
cd ../.. && ./flash_install_rtl8196e.sh
# 构建并刷写 Zigbee 固件
cd 2-Zigbee-Radio-Silabs-EFR32/24-NCP-UART-HW && ./build_ncp.sh 460800
cd ../.. && ./flash_efr32.sh -y -g ncp 460800
```
详情请参阅 [1-Build-Environment](./1-Build-Environment/README.md)。
## 故障排除
### EFR32 Zigbee/Thread 无线电无响应
如果您在 **v3.1.x 或 v3.2.x** 版本上,以 460800 波特率运行约 1 小时后在 `otbr-agent` 日志中看到反复的 `HandleRcpTimeout()` / `Failed to communicate
with RCP` 错误(问题
[#89](https://github.com/jnilo1/rtl8196e-gateway/issues/89)),
请升级到 **v3.3.0+** — 根本原因是 `S70otbr` 没有在 spinel 链接上启用硬件 UART 流控制;
如果没有流控制,RX FIFO 在突发的 Spinel 流量下可能会溢出。v3.3.0
将 `&uart-flow-control=true` 添加到 spinel 无线电 URL 中(并在 kernel 侧增加了防御层),从而消除了这种故障情况。
如果无线电芯片卡死(Z2M / ZHA / OTBR 无法再与其通信,但网关上的
Linux / SSH 正常),可以使用三种逐步升级的恢复手段 —
请按顺序尝试:
1. **长按前面板按钮(5 秒钟)** — 网关的外壳按钮(Tuya 用于 App 配对的
按钮)已通过 `S40button` 连接,可向 EFR32 的 `nRST` 引脚发送
脉冲信号。长按时状态指示灯会闪烁
以提供视觉反馈。此操作可将 EFR32 从任何死锁状态中释放并
重启无线电 daemon。**无需 SSH 或网络。**
2. **`ssh root@ recover_efr32`** — 效果相同,可脚本化,适用于
网络正常但无线电异常的情况。
3. **`ssh root@ reboot`** — 完整 SoC 重启。作为副作用也会重置 EFR32
(SoC 的 pin-mux 寄存器默认值会短暂拉低无线电的 `nRST`)。如果
恢复手段 1 和 2 没有让无线电恢复,或者您确实需要
Linux 端重置,请使用此方法。
如果这些都不起作用,说明无线电固件本身已无法从
软件层面恢复(例如,用户刷入不兼容任何已知协议的非 Zigbee 固件)。请对网关进行电源循环,然后通过
`flash_efr32.sh` 重新刷写。完整的设计原理、为何采用这种
架构,以及要实现更激进的恢复方案需要做哪些修改,均记录在
[2-Zigbee-Radio-Silabs-EFR32/POST-MORTEM-bootloader-recovery.md](./2-Zigbee-Radio-Silabs-EFR32/POST-MORTEM-bootloader-recovery.md) 中。
## 致谢
本项目基于 [Paul Banks](https://paulbanks.org/projects/lidl-zigbee/) 的初步研究。
无需破解 root 密码 — 只要能访问 Realtek bootloader 提示符
(串口控制台,开机时按 ESC),您就可以刷写网关。
## 许可证
MIT License — 详情请参阅 [LICENSE]( )。
标签:Thread边界路由器, Zigbee, 客户端加密, 嵌入式固件, 应用安全, 智能家居, 物联网, 请求拦截