6435067-spec/tuya-local-esp32

GitHub: 6435067-spec/tuya-local-esp32

两个单头文件的 ESP32 编解码器,支持在局域网内直接控制 Tuya 协议 3.4/3.5 设备,无需云端。

Stars: 0 | Forks: 0

# Tuya Local for ESP32 — 协议 3.4 与 3.5 **English** · [Русский](README.ru.md) · [עברית](README.he.md) · [Español](README.es.md) 两个独立的单头文件 codec,可直接与 Tuya Wi-Fi 设备通信——例如继电器、 插座、电能表——**直接在你的 LAN 上进行,无需 cloud**。只需提供一个 IP、 一个 16 字节的 local key 和一个 datapoint,即可通过 TCP 读取状态或切换继电器。 * **[Tuya34.h](Tuya34.h)** — 协议 **3.4**:`0x55AA` 帧,AES-ECB payload + HMAC-SHA256。 * **[Tuya35.h](Tuya35.h)** — 协议 **3.5**:`0x6699` 帧,AES-GCM (IV + tag)。 相同的握手,相同的 API —— 你只需切换头文件和类型,其他都不用改。仅依赖于 ESP32 Arduino core (`WiFi` + 内置 mbedtls) 和 ArduinoJson v7。 ## 为什么会有这个项目 公开的 ESP32 Tuya **3.5** LAN 协议实现非常稀少 —— 大多数 库仅停留在 3.3/3.4。此处的 3.4 codec 已经在一个锅炉房运行了多年, 驱动着三个泵/加热器继电器;而 3.5 codec 是通过逆向 [tinytuya](https://github.com/jasonacox/tinytuya) 的帧结构开发的,并且已在真实 硬件上验证(ESP32-D0WD-V3 对接 Tuya 3.5 加热器继电器):握手、状态读取 (`0x10` 和 `0x0A`) 以及控制功能均正常工作。 这两个头文件是从生产环境的固件中提取出来的,并且是与设备无关、 与项目无关的代码块 —— 设备以 struct 的形式传入,没有任何硬编码内容。 ## 用法 ``` #include "Tuya35.h" // or "Tuya34.h" for a 3.4 device Tuya35Device dev = { "192.168.1.50", { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' }, // local key, 16 bytes "1", // relay DP (often "1"; sockets sometimes "switch_1") 6668 // local Tuya port }; Tuya35 tuya(dev); bool on; float watts; String raw; tuya.read(0x10, &on, &watts, &raw); // read status (0x10 = DP_QUERY_NEW, 0x0A = fallback) tuya.setRelay(true, &watts, &raw); // switch on, then read back power if the device meters it ``` 对于 3.4 设备,用法完全相同,只是去掉了查询命令参数: `tuya.read(&on, &watts, &raw)`。 设置 `Tuya35::DBG = true;`(或 `Tuya34::DBG`)可以在 Serial 中输出每一帧的完整十六进制转储 —— 它能帮你区分“非 0x6699 帧”错误和“GCM auth FAIL” (key 错误),这是调试 Tuya 连接时最常见的操作。 ## 获取 local key 该 key 由 Tuya cloud 按设备发放一次: 1. 在 Tuya / Smart Life app 中配对设备。 2. 将该 app 关联到一个 [Tuya IoT](https://iot.tuya.com/) cloud 项目。 3. 运行 [`tinytuya wizard`](https://github.com/jasonacox/tinytuya)(或 `tuya-cli`) —— 它会打印出每个设备的 16 字符 local key 和 datapoint 映射。 在你的路由器中将设备的 DHCP 地址固定下来,以免其 IP 发生变动。 **切勿将真实的 key 提交到公开的代码库中。** ## 示例 | Sketch | 说明 | |---|---| | [RelayControl](examples/RelayControl/RelayControl.ino) | 最简示例:包含一个头文件,读取状态,切换继电器。通过一个 `#define` 即可在 3.4 和 3.5 之间切换。 | | [Tuya35_TestBench](examples/Tuya35_TestBench/Tuya35_TestBench.ino) | 3.5 codec 的独立交互式调试台:提供 Serial 菜单,可针对单个设备执行握手 / 读取 / 开 / 关操作,并带有十六进制日志记录。 | 两者均可在 `arduino-cli` 中针对 `esp32:esp32:esp32` 顺利通过编译检查。 ## 协议工作原理 (3.5) ``` frame: PREFIX(0x00006699) | 00 00 | seq(4) | cmd(4) | len(4) | IV(12) | ciphertext | TAG(16) | SUFFIX(0x00009966) ``` * Payload 为 AES-GCM;**AAD 为前缀之后的 14 个头部字节** (`unknown + seq + cmd + len`),tag 用于对它们进行身份验证。 * 握手 `NEG_START → NEG_RESP → NEG_FINISH`:设备返回一个 remote nonce 以及 `HMAC(local_key, local_nonce)`;session key 为 `AES-GCM(local_key, iv = nonce[:12], data = local_nonce ⊕ remote_nonce)` —— 仅取 ciphertext,丢弃 tag。 * `CONTROL_NEW` 在 JSON 之前需要一个 15 字节的版本头 `"3.5" + 12×00`。 3.4 的结构相同,但使用 `0x55AA` 组帧和 AES-ECB + HMAC 来代替 GCM; 握手和命令代码是共享的。组帧参考: [tinytuya](https://github.com/jasonacox/tinytuya) (`core/header.py`, `message_helper.py`, `XenonDevice.py`)。 ## 安装 将 `Tuya34.h` / `Tuya35.h` 放在你的 sketch 旁边,或者将此代码库克隆到你的 Arduino `libraries/` 文件夹中(它自带了 `library.properties`,因此示例会显示在 File → Examples 下)。从 Library Manager 安装 ArduinoJson (v7)。 ## 许可证 MIT — 查看 [LICENSE](LICENSE)。
标签:C++, ESP32, 嵌入式开发, 数据擦除, 智能家居, 涂鸦协议, 物联网