TasmotaClient 串口从设备库完全指南:让 Arduino 成为 Tasmota 的可编程外设
【免费下载链接】TasmotaAlternative firmware for ESP8266 and ESP32 based devices with easy configuration using webUI, OTA updates, automation using timers or rules, expandability and entirely local control over MQTT, HTTP, Serial or KNX. Full documentation at项目地址: https://gitcode.com/GitHub_Trending/ta/Tasmota
导读
TasmotaClient 是一个面向 Arduino 系列微控制器(Uno、Pro Mini 等)的从设备库,让 MCU 通过串口挂接到运行 Tasmota 固件的主设备(ESP8266/ESP32)之下,由 Tasmota 统一调度。本文以仓库 tools/fw_TasmotaClient_arduino/TasmotaClient/README.md 为骨架,结合库源码、5 个官方示例以及 Tasmota 主设备端驱动,完整讲解库 API、串口帧协议、回调机制、主设备端启用流程与固件烧录方式。读完本文,你将能够编写自己的 Arduino 从设备固件,让它接受 Tasmota 的定时回调、向 Tasmota 回传 JSON、收发命令并发布遥测数据。
TasmotaClient 的定位与架构
Tasmota 固件本身运行在 ESP8266/ESP32 上,但在需要更多 GPIO、模拟输入或专用外设时,开发者常希望外接一颗廉价的 Arduino(如 ATmega328P 的 Uno / Pro Mini)作为扩展板。TasmotaClient 正是为这一场景设计的串口从设备协议库:Tasmota 作为主机(master),Arduino 作为从机(slave),两者通过 UART 通信。
从 TasmotaClient.h 的文件头注释可以看到其定位为 “Library for microcontrollers enslaved by Tasmota”(面向被 Tasmota 管辖的微控制器的库),而主设备端对应的驱动位于 xdrv_31_tasmota_client.ino,注释为 “Support for external microcontroller on serial”。
该协议本质上是将 Tasmota 内部的FUNC_JSON_APPEND、FUNC_EVERY_SECOND、FUNC_EVERY_100_MSECOND等事件回调“搬运”到串口对端的从设备上,由从设备决定如何响应。README 特别提示:官方 wiki 上的 TasmotaSlave 文档已过时,仍记录着旧的 TasmotaSlave 命令(2020-11-21 标注),因此本文涉及的命令、宏与行为一律以当前仓库源码为准。
库 API 速览
TasmotaClient类定义于 TasmotaClient.h,公共接口如下:
| 方法 | 作用 |
|---|---|
TasmotaClient(HardwareSerial *device = nullptr) | 构造函数,绑定使用的硬件串口(如&Serial) |
void attach_FUNC_JSON(callbackFunc func) | 注册 JSON 回调,Tasmota 请求数据时调用 |
void attach_FUNC_EVERY_SECOND(callbackFunc func) | 注册每秒回调(无 JSON 响应) |
void attach_FUNC_EVERY_100_MSECOND(callbackFunc func) | 注册每 100ms 回调(无 JSON 响应) |
void attach_FUNC_COMMAND_SEND(callbackFunc1 func) | 注册命令回调,对应 Tasmota 主机的ClientSend命令 |
void sendFeatures(void) | 将本库支持的特性位图发回 Tasmota |
void sendJSON(char *json) | 向 Tasmota 回传一段 JSON 字符串 |
void SendTele(char *data) | 向 Tasmota 发送遥测数据(会触发 MQTT 发布) |
void ExecuteCommand(char *cmnd) | 请求 Tasmota 执行一条控制台命令 |
void loop(void) | 主循环处理函数,需周期性调用 |
回调函数类型有两种:callbackFunc(void (*)(void),无参数)与callbackFunc1(void (*)(char*),携带数据指针),见 TasmotaClient.h。
值得注意的实现细节:调用attach_*系列方法时,库不仅保存函数指针,还会把对应的特性位在内部Settings.features中置 1(见 TasmotaClient.cpp)。随后sendFeatures()把这份“能力声明”发给主机,Tasmota 才能知道该从设备支持哪些回调,并有针对性地调度。因此凡是想用的回调,必须先 attach。
串口帧协议详解
TasmotaClient 的通信协议定义在 TasmotaClient.h,命令码如下:
| 常量 | 值 | 含义 |
|---|---|---|
CMND_START | 0xFC | 命令帧起始字节 |
CMND_END | 0xFD | 命令帧结束字节 |
CMND_FEATURES | 0x01 | 请求从设备上报特性 |
CMND_FUNC_JSON | 0x02 | 请求从设备回传 JSON |
CMND_FUNC_EVERY_SECOND | 0x03 | 触发每秒回调 |
CMND_FUNC_EVERY_100_MSECOND | 0x04 | 触发每 100ms 回调 |
CMND_CLIENT_SEND | 0x05 | 向从设备发送数据(对应ClientSend) |
CMND_PUBLISH_TELE | 0x06 | 从设备请求主机发布遥测 |
CMND_EXECUTE_CMND | 0x07 | 从设备请求主机执行命令 |
PARAM_DATA_START | 0xFE | 参数数据起始字节 |
PARAM_DATA_END | 0xFF | 参数数据结束字节 |
主机 → 从设备的命令帧格式为:0xFC + 4 字节命令结构体 + 0xFD。其中命令结构体COMMAND由command、parameter与两个保留字节构成,且注释要求保持 4 字节对齐(见 TasmotaClient.cpp),这一点在主机端 xdrv_31_tasmota_client.ino 中也有相同的对齐约束说明,保证两端结构布局完全一致。
从设备 → 主机的数据帧格式为:0xFE + 数据字节 + 0xFF(见sendJSON、sendFeatures实现)。特性上报则发送 8 字节:4 字节版本号 + 4 字节特性位图(FEATURES结构体,见 TasmotaClient.cpp)。
从设备侧的接收解析入口是loop():读到0xFC后调用ProcessCommand(),读取 4 字节命令并按command分发(见 TasmotaClient.cpp)。所有串口读取都依赖waitforbytes(num, timeout)带超时等待,避免阻塞死等。
从设备固件编写:5 个官方示例逐个拆解
官方提供了 5 个示例固件,全部位于 examples,串口波特率统一为 57600,编译产物以 hex 形式预置在 ProATmega328P-3V3-8Mhz(3.3V/8MHz 变体)与 ProATmega328P-5V-16MHz(5V/16MHz 变体)目录下。它们的核心骨架完全一致:
#include <Arduino.h> #include <TasmotaClient.h> TasmotaClient client(&Serial); void setup() { Serial.begin(57600); // 必须与 Tasmota 主机配置的波特率一致 client.attach_XXX(your_callback); } void loop() { client.loop(); // 周期性处理串口请求 }1. Blink:每秒回调翻转 LED
Blink.ino 是最小的功能演示:通过attach_FUNC_EVERY_SECOND(user_FUNC_EVERY_SECOND)注册每秒回调,回调内部翻转板载 LED 状态。Tasmota 主机每个周期向从设备发送CMND_FUNC_EVERY_SECOND,从设备收到后执行回调,这等价于把 Tasmota 的秒级心跳扩展到了外部 MCU 上。
2. BlinkSendCommand:反向执行 Tasmota 命令
BlinkSendCommand.ino 在每秒回调翻转 LED 的同时,调用client.ExecuteCommand((char*)"publish tele/mytopic/power on")或off,让 Tasmota 主机代执行一条控制台命令(此处为 MQTT publish)。这展示了从设备反向控制主机的通道:任何 Tasmota 控制台命令都可以通过ExecuteCommand触发。主设备端收到CMND_EXECUTE_CMND后调用ExecuteCommand(inbuf, SRC_TCL)执行(见 xdrv_31_tasmota_client.ino)。
3. ClientSendCommand:接收 ClientSend 并回传 JSON
ClientSendCommand.ino 注册了两个回调:
attach_FUNC_COMMAND_SEND(user_FUNC_RECEIVE):接收主机发来的ClientSend数据,示例中匹配ON/OFF(注意大小写敏感)控制 LED;attach_FUNC_JSON(user_FUNC_JSON):当主机在遥测周期请求 JSON 时,把 A0~A7 八个模拟引脚的读数组装成 JSON 回传:
void user_FUNC_JSON(void) { uint8_t a = 0; char myjson[100]; sprintf(myjson,"{\"A0\":%u,\"A1\":%u,\"A2\":%u,\"A3\":%u,\"A4\":%u,\"A5\":%u,\"A6\":%u,\"A7\":%u}", analogRead(A0), analogRead(A1), analogRead(A2), analogRead(A3), analogRead(A4), analogRead(A5), analogRead(A6), analogRead(A7)); client.sendJSON(myjson); }这段 JSON 在主机侧会被追加到状态/遥测 JSON 中(详见下文“遥测聚合”)。
4. ClientRespondTele:收到命令后回发遥测
ClientRespondTele.ino 与示例 3 类似,但改用client.SendTele(response)回发遥测 JSON(如{"Led":"On"})。主机收到CMND_PUBLISH_TELE后,会将其打包进TasmotaClient字段并经MqttPublishPrefixTopicRulesProcess_P发布到 MQTT,同时可供规则处理(见 xdrv_31_tasmota_client.ino)。
5. AnalogJSON:纯遥测 JSON 上报
AnalogJSON.ino 只演示一个能力:注册FUNC_JSON回调,在主机遥测周期请求时回传 8 路模拟量 JSON。适合做多路 ADC 采集从设备的最小模板。
库内部处理逻辑
从设备收到ClientSend时,ProcessSend()会先按参数长度读取数据,去掉首尾的0xFE/0xFF封装,再以\0结尾后交给FUNC_SEND回调(见 TasmotaClient.cpp),因此回调中拿到的char*是可直接strcasecmp的 C 字符串。
在 Tasmota 主机端启用与接线
编译宏
主设备驱动由USE_TASMOTA_CLIENT宏控制。在 tasmota_configurations.h 中取消注释#define USE_TASMOTA_CLIENT即可启用(注释标注该功能约占 2k3 代码、44 字节内存);该文件后续的多处#undef是针对不同预配置构建的显式关闭,而第 1124 行附近则结合了USE_TASMOTA_SLAVE_FLASH_SPEED/USE_TASMOTA_SLAVE_SERIAL_SPEED进行兼容定义。ESP32 版本在 tasmota_configurations_ESP32.h 中同样支持。对应宏还暴露给 Berry 脚本层(见 be_gpio_defines.h)。
驱动默认串口速度为 57600,可用宏覆盖:
#define USE_TASMOTA_CLIENT_FLASH_SPEED 57600 // 烧录波特率,3.3V 变体通常 57600,5V 变体通常 115200 #define USE_TASMOTA_CLIENT_SERIAL_SPEED 57600 // 与 Uno/Pro Mini 上固件匹配的运行波特率(默认值定义见 xdrv_31_tasmota_client.ino。)
GPIO 配置
从设备挂接需要占用 3~4 个 GPIO(在 Web UI 的 Configure Module 中分配):
TASMOTACLIENT_RXD:串口接收(接 Arduino TX)TASMOTACLIENT_TXD:串口发送(接 Arduino RX)TASMOTACLIENT_RST或TASMOTACLIENT_RST_INV:复位控制(前者低电平复位,后者可配置反相)
驱动初始化要求 RXD、TXD 均已分配,且 RST 或 RST_INV 至少其一(见 xdrv_31_tasmota_client.ino)。
控制台命令
启用后 Tasmota 主机新增两条命令(定义见 xdrv_31_tasmota_client.ino):
ClientReset:复位从设备并强制重新进行特性探测(CmndClientReset,见第 479-485 行)ClientSend <数据>:向从设备发送任意数据,触发其FUNC_COMMAND_SEND回调(CmndClientSend,见第 487-499 行)
特性探测与遥测聚合
主机启动后会以延迟策略(waitstate计数避免阻塞启动流程)向从设备发送CMND_FEATURES,从设备回传 8 字节特性块。主机校验版本号TASMOTA_CLIENT_LIB_VERSION(20191129,与库头文件一致),版本不符会记录 “Version not supported” 日志(见 xdrv_31_tasmota_client.ino)。特性位图中func_json_append、func_every_second、func_every_100_msecond、func_client_send分别对应四类回调能力。
主机在每个秒周期按特性位决定是否发送CMND_FUNC_EVERY_SECOND/CMND_FUNC_EVERY_100_MSECOND;在FUNC_JSON_APPEND事件中,若从设备声明支持 JSON,则发送CMND_GET_JSON并接收回包,追加为"TasmotaClient":{...}字段(TasmotaClient_Show,见第 440-452 行),从而把从设备数据自然融入 Tasmota 的状态 JSON。
通过 Tasmota 直接烧录从设备固件
从源码结构看,xdrv_31_tasmota_client.ino 中的TasmotaClient_Flash()实现了基于 STK500 协议的固件烧录流程:通过复位引脚把从设备拉入 bootloader,依次执行CMND_STK_GET_SYNC同步、CMND_STK_SET_DEVICE(_EXT)配置器件、CMND_STK_ENTER_PROGMODE进入编程模式,再按 128 字节页写入解析后的 Intel HEX 数据。即从设备端只需有 STK500 兼容 bootloader,Tasmota 主机即可完成固件刷新,无需额外 USB 编程器。仓库中预编译的 ProATmega328P-3V3-8Mhz 与 ProATmega328P-5V-16MHz 两个目录下的 hex 文件,即为 5 个示例针对 3.3V/8MHz 与 5V/16MHz Pro Mini 两种典型配置的编译产物,可配合烧录流程直接使用。
版本与变更记录
README 的 Change Log 记录如下(2020-11-21 起文档未再更新,当前仓库中库的版本信息以代码为准):
- 2019-11-29 - v0.0.2(预发布):新增
ExecuteCommand(char *cmnd)支持,即从设备可反向向 Tasmota 发送控制台命令;当前源码中的TASMOTA_CLIENT_LIB_VERSION亦为 20191129,与 library.properties 中的version=0.0.2一致。
快速上手清单
- 将 TasmotaClient 目录作为 Arduino 库安装(
library.properties声明支持 avr、esp8266、esp32 等常见架构)。 - 参考任一示例编写从设备固件,在
setup()中Serial.begin(57600)并 attach 所需回调,在loop()中调用client.loop()。 - 在 Tasmota 源码中开启
USE_TASMOTA_CLIENT并重新编译烧录主机固件。 - 在 Web UI 配置
TASMOTACLIENT_RXD/TASMOTACLIENT_TXD/TASMOTACLIENT_RST[_INV]引脚,并确保主机、从设备波特率一致。 - 上电后从控制台用
ClientSend ON验证双向链路;在遥测周期中检查状态 JSON 中是否出现"TasmotaClient"字段。 - 如需换固件,可利用
ClientReset+ STK500 烧录流程通过 Tasmota 直接刷写从设备。
通过这套协议,Tasmota 主设备与 Arduino 从设备可以组合出“Tasmota 负责网络与 MQTT、Arduino 负责本地采样与控制”的灵活架构,且全部数据流在本地串口上完成,不依赖云端。
【免费下载链接】TasmotaAlternative firmware for ESP8266 and ESP32 based devices with easy configuration using webUI, OTA updates, automation using timers or rules, expandability and entirely local control over MQTT, HTTP, Serial or KNX. Full documentation at项目地址: https://gitcode.com/GitHub_Trending/ta/Tasmota
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考