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, 客户端加密, 嵌入式固件, 应用安全, 智能家居, 物联网, 请求拦截