Tasmota 开发者指南:从事件驱动架构到传感器驱动开发全解析
2026/9/12 17:32:23 网站建设 项目流程

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

本篇技术指南以 Tasmota 固件的开发者文档(.doc_for_ai/FOR_DEVELOPERS.md)为骨架,系统梳理其事件驱动的模块化架构、编译期配置覆盖机制、命令系统、GPIO 管理,以及从零编写驱动/传感器模块的完整套路(回调分发、XdrvMailbox命令上下文、TSettings持久化存储、I2C 辅助 API)。读完本文,你将能直接在本仓库源码中定位关键实现,并具备为 Tasmota 新增一个传感器或驱动模块的完整工程能力。

一、Tasmota 整体架构:事件驱动 + 模块化

1. 核心设计原则

Tasmota 是运行在ESP8266/ESP8285 与 ESP32 系列微控制器上的模块化替代固件,其架构遵循三条基本原则:

  1. 事件驱动:主循环通过"回调 ID"把事件分发给驱动(driver)、传感器(sensor)、能量监测(energy)与灯光(light)模块。这些回调 ID 定义在enum XsnsFunctions中,见 tasmota/include/tasmota.h。
  2. 模块化:Wi-Fi、MQTT、Web 界面等核心功能常驻固件;可选功能通过编译期#define USE_xxx指令条件编译;驱动、传感器、显示、灯光、能量模块按编号组织。
  3. 非阻塞:所有回调都必须是非阻塞操作,否则会拖垮主循环的响应性。周期性回调按50 ms、100 ms、200 ms、250 ms、1 s的固定间隔调度。

2. 通信通道

通道用途
MQTT自动化系统的主要协议
HTTPWeb 界面 + REST 风格命令端点/cm
串口 Serial调试与配置的 console 访问
WebSocket标准 UI 不使用;Web 界面基于 chunked HTTP + 周期轮询

3. 固件源码布局

tasmota/ ├── tasmota.ino # 主固件入口 ├── my_user_config.h # 主编译期配置(勿直接编辑) ├── user_config_override.h # 用户覆盖配置 ├── user_config_override_sample.h # 覆盖配置模板 ├── tasmota_xdrv_driver/ # 驱动模块 (xdrv_##_*.ino) ├── tasmota_xsns_sensor/ # 传感器模块 (xsns_##_*.ino) ├── tasmota_xdsp_display/ # 显示模块 (xdsp_##_*.ino) ├── tasmota_xlgt_light/ # 灯光控制器模块 (xlgt_##_*.ino) ├── tasmota_xnrg_energy/ # 能量监测模块 (xnrg_##_*.ino) ├── tasmota_xx2c_global/ # 跨模块共享代码(各 *_interface.ino 调度器) ├── tasmota_support/ # 核心支撑代码(settings、命令解析、I2C 等) ├── include/ # 公共头文件 (tasmota.h, tasmota_types.h, i18n.h ...) ├── berry/ # Berry VM 与随固件分发的 Berry 脚本 ├── language/ # 多语言本地化头文件 └── html_uncompressed/, html_compressed/ # Web UI HTML/JS 源码

每个目录下的文件数量会随新驱动不断变化,不要依赖硬编码的文件数量

4. 调度器的实现证据

所谓"主循环分发事件",在源码层面的落点就是各*_interface.ino中的调度函数。例如传感器侧,tasmota/tasmota_xx2c_global/xsns_interface.ino 用一个函数指针数组把XSNS_01XSNS_xx映射到Xsns01()Xsnsxx()XsnsCall(uint32_t function)(见 xsns_interface.ino)再遍历已启用的传感器逐一分发事件,并且支持运行时禁用某个传感器(XsnsEnabled检查)。驱动、显示、灯光、能量模块的xdrv_interface.inoxdsp_interface.inoxlgt_interface.inoxnrg_interface.ino结构完全一致。

二、编译期配置覆盖:user_config_override.h

Tasmota 的构建定制遵循永不直接编辑my_user_config.h的原则——它是随每个 release 分发的"主配置"。正确做法是:

  1. 把 tasmota/user_config_override_sample.h 复制为tasmota/user_config_override.h
  2. 在其中加入自己的#define/#undef指令。
#ifndef _USER_CONFIG_OVERRIDE_H_ #define _USER_CONFIG_OVERRIDE_H_ // 启用可选功能 #define USE_BERRY_DEBUG // 关闭无用功能以节省 flash 空间 #undef USE_DOMOTICZ #undef USE_KNX #endif // _USER_CONFIG_OVERRIDE_H_

该文件对所有#ifdef USE_xxx条件编译的模块生效:每个驱动/传感器模块的.ino文件整体被#ifdef USE_<feature>包裹,未定义对应宏时整个模块不会参与编译,这正是"可选功能裁剪"机制的根基。此外平台级配置(如 flash 分区、编译环境)可参考 platformio_tasmota_env.ini 与 platformio_tasmota_env32.ini。

三、统一命令系统

Tasmota 的全部功能都收敛到一个统一的命令系统:

  • 命令可通过MQTT、HTTP(/cm?cmnd=...)、串口或 Web Console发送;
  • 格式为Command [parameter],命令名大小写不敏感
  • 响应通常是 JSON;
  • 多条命令可用Backlog cmd1; cmd2; cmd3链式执行。

命令解析最终会落到各模块的FUNC_COMMAND/FUNC_COMMAND_SENSOR/FUNC_COMMAND_DRIVER回调中,参数与上下文通过全局结构XdrvMailbox传递(详见下文第五节)。

四、GPIO 运行时管理

Tasmota 在运行时把逻辑功能("组件")映射到物理 GPIO,因此更换引脚映射无需重新编译

  1. 模块(Module):预置的硬件基座配置,用Module命令切换;
  2. 模板(Template):JSON 描述符,可覆盖模块默认的 GPIO 分配,用Template命令应用;
  3. GPIO 命令GPIO<x> <component>把某个组件单独指派到指定引脚。

模板数据与模块定义集中在 tasmota/include/tasmota_template.h 与 tasmota/include/tasmota_template_legacy.h;官方模板仓库索引见仓库根目录 TEMPLATES.md。

五、驱动与传感器开发规范

1. 命名约定与回调入口

每个模块拥有唯一编号,并导出一个统一签名的回调函数:

模块类型存放目录回调函数编译开关示例
驱动tasmota_xdrv_driver/xdrv_XX_<name>.inobool XdrvXX(uint32_t function)#define USE_<feature>
传感器tasmota_xsns_sensor/xsns_XX_<name>.inobool XsnsXX(uint32_t function)#define XSNS_XX XX
能量tasmota_xnrg_energy/xnrg_XX_<name>.inobool XnrgXX(uint32_t function)#define XNRG_XX XX
灯光tasmota_xlgt_light/xlgt_XX_<name>.inobool XlgtXX(uint32_t function)#define XLGT_XX XX
显示tasmota_xdsp_display/xdsp_XX_<name>.inobool XdspXX(uint32_t function)#define XDSP_XX XX

模块在编译期通过#define USE_<feature>启用,并用#define XSNS_XX XX(或对应前缀)声明自己的 ID。以传感器为例,tasmota/tasmota_xsns_sensor/xsns_05_ds18x20.ino 声明XSNS_05xdrv_01_9_webserver.inoxdrv_02_9_mqtt.ino等驱动则对应XDRV_前缀。

2. 传感器驱动骨架(可直接套用)

#ifdef USE_MY_SENSOR #define XSNS_99 99 // 唯一传感器 ID #define XI2C_99 99 // I2C 驱动索引(仅当使用 I2C 并注册时) bool MySensorDetected = false; void MySensorInit(void) { // ... 探测设备,成功后置 MySensorDetected = true } void MySensorEverySecond(void) { // ... 读取传感器数据 } void MySensorShow(bool json) { if (json) { ResponseAppend_P(PSTR(",\"MySensor\":{\"Temperature\":%d}"), temperature); #ifdef USE_WEBSERVER } else { WSContentSend_PD(HTTP_SNS_F_TEMP, "MySensor", Settings->flag2.temperature_resolution, // flag2 为 SysMBitfield1 类型 &temperature, TempUnit()); #endif // USE_WEBSERVER } } bool Xsns99(uint32_t function) { if (!I2cEnabled(XI2C_99)) { return false; } // 以 I2C 注册状态作为门控 bool result = false; if (FUNC_INIT == function) { MySensorInit(); } else if (MySensorDetected) { switch (function) { case FUNC_EVERY_SECOND: MySensorEverySecond(); break; case FUNC_JSON_APPEND: MySensorShow(true); break; #ifdef USE_WEBSERVER case FUNC_WEB_SENSOR: MySensorShow(false); break; #endif } } return result; } #endif // USE_MY_SENSOR

三个关键注意点:

  • 旧的i2c_flg全局变量已不存在。应改用I2cEnabled(XI2C_xx)I2cSetActiveFound()与 I2C 驱动注册表集成,实现见 tasmota/tasmota_support/support_a_i2c.ino;
  • Web 传感器显示字符串(如HTTP_SNS_F_TEMPHTTP_SNS_HUMHTTP_SNS_F_DISTANCE_CM)声明在 tasmota/include/i18n.h,能复用就复用,不要自造新字符串;
  • Settings->flag2类型为SysMBitfield1(定义在 tasmota/include/tasmota_types.h),内含temperature_resolutionhumidity_resolution等分辨率位域。

六、回调 ID 全参考(enum XsnsFunctions

完整回调 ID 定义在 tasmota/include/tasmota.h。enum XsnsFunctions被哨兵值FUNC_return_result = 200分为两段:

  • FUNC_return_result之前fire and forget,分发器忽略返回值;
  • FUNC_return_result之后:回调须返回bool表示是否"消费"了该事件(true在适用场景下会终止后续分发)。

1. 无返回值回调(节选)

函数用途
FUNC_SETTINGS_OVERRIDE在设置加载前调整默认值
FUNC_SETUP_RING1/RING2早期 setup 阶段
FUNC_PRE_INITGPIO 建立完成后
FUNC_INIT初始化结束
FUNC_ACTIVE驱动存在性查询
FUNC_ABOUT_TO_RESTART触发重启前
FUNC_LOOP/FUNC_SLEEP_LOOP主循环 tick
FUNC_EVERY_50_MSECOND每 50 ms
FUNC_EVERY_100_MSECOND每 100 ms
FUNC_EVERY_200_MSECOND每 200 ms(仅能量槽位)
FUNC_EVERY_250_MSECOND每 250 ms
FUNC_EVERY_SECOND每秒
FUNC_RESET_SETTINGS/FUNC_RESTORE_SETTINGS/FUNC_SAVE_SETTINGS设置重置 / 恢复 / 保存
FUNC_SAVE_AT_MIDNIGHT每日 00:00 例行维护
FUNC_SAVE_BEFORE_RESTART计划重启前持久化数据
FUNC_INTERRUPT_STOP/START临界区前后禁用/启用中断
FUNC_AFTER_TELEPERIODteleperiod 发布之后
FUNC_JSON_APPEND向 teleperiod 载荷追加 JSON
FUNC_WEB_SENSOR/FUNC_WEB_COL_SENSOR向主页面传感器区块追加 HTML 行 / 列格式 HTML
FUNC_MQTT_SUBSCRIBE连接时追加 MQTT 订阅
FUNC_MQTT_INITMQTT(重)连接结束时执行一次
FUNC_SET_POWER继电器变化前通知
FUNC_SHOW_SENSORFUNC_JSON_APPEND完成后
FUNC_ANY_KEY任意按键/开关交互
FUNC_LED_LINK链路/状态 LED 控制
FUNC_ENERGY_EVERY_SECOND/FUNC_ENERGY_RESET能量驱动 tick / 计数器复位
FUNC_TELEPERIOD_RULES_PROCESS与 teleperiod 绑定的规则处理
FUNC_FREE_MEM诊断内存转储请求
FUNC_WEB_ADD_BUTTON/FUNC_WEB_ADD_CONSOLE_BUTTON/FUNC_WEB_ADD_MANAGEMENT_BUTTON/FUNC_WEB_ADD_MAIN_BUTTON向配置页 / 控制台页 / 管理页 / 主页添加按钮
FUNC_WEB_GET_ARG自定义 HTTP 参数处理
FUNC_WEB_ADD_HANDLER注册额外 URL handler
FUNC_SET_SCHEME灯光方案变更(灯光槽位)
FUNC_HOTPLUG_SCAN周期性热插拔设备扫描
FUNC_TIME_SYNCEDNTP 同步完成
FUNC_DEVICE_GROUP_ITEM设备组条目处理
FUNC_NETWORK_UP/DOWN网络连通性变化
FUNC_WEB_STATUS_LEFT/RIGHT状态页左右列

2. 带返回值回调(ID ≥ 200)

函数用途
FUNC_PIN_STATE配置期覆盖 GPIO 状态
FUNC_MODULE_INIT模块专属初始化
FUNC_ADD_BUTTON/FUNC_ADD_SWITCH注册自定义按键 / 开关 handler
FUNC_BUTTON_PRESSED/FUNC_BUTTON_MULTI_PRESSED处理单次按压 / 多次按压手势
FUNC_SET_DEVICE_POWER驱动设备专属继电器
FUNC_MQTT_DATA检查/处理原始 MQTT 载荷
FUNC_SERIAL处理主串口收到的字节
FUNC_COMMAND通用命令分发(驱动自定义命令)
FUNC_COMMAND_SENSOR处理Sensor<id>命令
FUNC_COMMAND_DRIVER处理Driver<id>命令
FUNC_RULES_PROCESS自定义规则展开
FUNC_SET_CHANNELS灯光通道更新

显示驱动还有一套独立的FUNC_DISPLAY_*回调;哪个驱动/传感器/显示/能量/灯光槽位收到哪个回调、按什么顺序分发的权威表见 docs/API.md(仓库根目录 API.md 亦可供参考)。

七、命令上下文:XdrvMailbox

自定义命令 handler(FUNC_COMMANDFUNC_COMMAND_SENSORFUNC_COMMAND_DRIVER)从全局结构XdrvMailbox读取输入,其定义位于 tasmota/tasmota.ino:

struct XDRVMAILBOX { bool grpflg; // 命令是否来自 group topic bool usridx; // 命令名是否带用户提供的数字后缀 uint16_t command_code; // 命令表索引 uint32_t index; // 命令的数字后缀(如 Power2 的 2),默认 1 uint32_t data_len; // data 的长度 int32_t payload; // 第一个参数的数值,非数值时为 -99 char *topic; // 命令来源的 MQTT topic(或 nullptr) char *data; // 原始参数字符串(可写) char *command; // 解析出的命令名 } XdrvMailbox;

注意:docs/Sensor-API.md展示的是该结构的旧版本,请以tasmota.ino中的当前定义为准。

用于构建 JSON 响应的辅助函数声明在 tasmota/tasmota_support/support_command.ino(实现见 support_command.ino):

  • void ResponseCmnd(void)— 开始{"<Command>":...响应;
  • void ResponseCmndDone(void)— 输出{"<Command>":"Done"}
  • void ResponseCmndNumber(int value)— 输出{"<Command>":<value>}
  • void ResponseCmndIdxNumber(int value)— 输出{"<Command><index>":<value>}
  • void ResponseCmndFloat(float value, uint32_t decimals)ResponseCmndIdxFloat(...)— 浮点版本;
  • int Response_P(const char* format, ...)— 替换响应缓冲区(位于 tasmota/tasmota_support/support.ino);
  • int ResponseAppend_P(const char* format, ...)— 追加到响应缓冲区。

若要把缓冲区作为传感器遥测载荷发布:

void MqttPublishTeleSensor(void); // 发布 tele/<topic>/SENSOR

八、持久化设置存储:TSettings

持久化设置保存在 flash 中,结构体为TSettings,定义于 tasmota/include/tasmota_types.h,全局实例通过指针Settings访问(声明于 tasmota/tasmota.ino):

extern TSettings* Settings; // 见 tasmota.ino

几个关键设计点:

  • 大多数字符串字段(Wi-Fi SSID/密码、MQTT host/user/password/topic、hostname、friendly name、NTP 服务器等)不是结构体直接成员,而是存于单一text_pool[]中,通过索引经SettingsText()/SettingsUpdateText()访问(实现见 tasmota/tasmota_support/settings.ino);
  • 合法索引集合为enum SettingsTextIndex(见 tasmota/include/tasmota.h),例如SET_OTAURLSET_MQTT_HOSTSET_HOSTNAMESET_DEVICENAME等;
  • SetOption32..SetOption49存储在Settings->param[PARAM8_SIZE]
  • 大量标志位分布在Settings->flagSettings->flag2(类型SysMBitfield1)等位域中(typedef 见tasmota_types.h)。

读写访问模式:

const char* host = SettingsText(SET_MQTT_HOST); SettingsUpdateText(SET_MQTT_HOST, "broker.example.com"); uint16_t period = Settings->tele_period; Settings->tele_period = 300;

不要凭旧版本固件的记忆臆造字段名——始终以tasmota_types.hSettingsTextIndex枚举为准。

九、日志系统

日志级别定义在 tasmota/include/tasmota.h 的enum LoggingLevels

enum LoggingLevels { LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE };

主日志函数(位于 tasmota/tasmota_support/support.ino):

void AddLog(uint32_t loglevel, PGM_P formatP, ...);

格式串要求来自 PROGMEM,通常用PSTR(...)包裹:

AddLog(LOG_LEVEL_INFO, PSTR("MyDriver: value=%d"), value);

不存在AddLog_P/AddLog_P2——直接调用AddLog即可。

条件调试宏

定义于 tasmota/include/tasmota_globals.h,由编译期#define门控:

#ifdef DEBUG_TASMOTA_CORE #define DEBUG_CORE_LOG(...) AddLog(LOG_LEVEL_DEBUG, __VA_ARGS__) #else #define DEBUG_CORE_LOG(...) #endif #ifdef DEBUG_TASMOTA_DRIVER #define DEBUG_DRIVER_LOG(...) AddLog(LOG_LEVEL_DEBUG, __VA_ARGS__) #else #define DEBUG_DRIVER_LOG(...) #endif #ifdef DEBUG_TASMOTA_SENSOR #define DEBUG_SENSOR_LOG(...) AddLog(LOG_LEVEL_DEBUG, __VA_ARGS__) #else #define DEBUG_SENSOR_LOG(...) #endif #ifdef DEBUG_TASMOTA_TRACE #define DEBUG_TRACE_LOG(...) AddLog(LOG_LEVEL_DEBUG, __VA_ARGS__) #else #define DEBUG_TRACE_LOG(...) #endif #ifdef USE_DEBUG_DRIVER #define SHOW_FREE_MEM(WHERE) ShowFreeMem(WHERE); #else #define SHOW_FREE_MEM(WHERE) #endif

user_config_override.h中定义对应的DEBUG_TASMOTA_*符号即可启用。没有CHECK_OOM

堆内存诊断

自由堆可从标准 ESP 封装获取:

uint32_t free = ESP.getFreeHeap(); AddLog(LOG_LEVEL_DEBUG, PSTR("Free heap: %u"), free);

Tasmota 另在 tasmota/tasmota_support/support_esp32.ino(ESP8266 侧为 support_esp8266.ino)提供自有辅助函数(如ESP_getFreeHeap()ESP_getMaxAllocHeap()),具体集合请以所在分支的该文件为准。

十、I2C 辅助 API

定义于 tasmota/tasmota_support/support_a_i2c.ino。所有读写辅助函数都带可选bus参数(默认0);双 I2C 总线设备上,次总线传1

1. 总线管理

bool I2cBegin(int sda, int scl, uint32_t bus = 0, uint32_t frequency = 100000); bool I2cSetClock(uint32_t frequency = 0, uint32_t bus = 0); bool I2cReset(uint32_t bus = 0); void I2cScan(uint8_t bus = 0); // 把发现的地址打印到响应缓冲区

2. 读操作(成功返回true

bool I2cValidRead (uint8_t addr, uint8_t reg, uint8_t size, uint8_t bus = 0, bool sendStop = false); bool I2cValidRead8 (uint8_t *data, uint8_t addr, uint8_t reg, uint8_t bus = 0); bool I2cValidRead16 (uint16_t *data, uint8_t addr, uint8_t reg, uint8_t bus = 0); bool I2cValidReadS16(int16_t *data, uint8_t addr, uint8_t reg, uint8_t bus = 0); bool I2cValidRead16LE (uint16_t *data, uint8_t addr, uint8_t reg, uint8_t bus = 0); bool I2cValidReadS16_LE(int16_t *data, uint8_t addr, uint8_t reg, uint8_t bus = 0); bool I2cValidRead24 (int32_t *data, uint8_t addr, uint8_t reg, uint8_t bus = 0);

3. 读操作(直接返回值,无错误指示)

uint8_t I2cRead8 (uint8_t addr, uint8_t reg, uint8_t bus = 0); uint16_t I2cRead16 (uint8_t addr, uint8_t reg, uint8_t bus = 0); int16_t I2cReadS16 (uint8_t addr, uint8_t reg, uint8_t bus = 0); uint16_t I2cRead16LE (uint8_t addr, uint8_t reg, uint8_t bus = 0); int16_t I2cReadS16_LE(uint8_t addr, uint8_t reg, uint8_t bus = 0); int32_t I2cRead24 (uint8_t addr, uint8_t reg, uint8_t bus = 0);

不存在I2cReadS32/I2cReadS32_LE/I2cValidReadS32/I2cValidReadS32_LE——需要 32 位读取时请用I2cReadBuffer自行拼装。

4. 写操作(成功返回true

bool I2cWrite0 (uint8_t addr, uint8_t reg, uint8_t bus = 0); bool I2cWrite8 (uint8_t addr, uint8_t reg, uint32_t val, uint8_t bus = 0); bool I2cWrite16(uint8_t addr, uint8_t reg, uint32_t val, uint8_t bus = 0); bool I2cWrite (uint8_t addr, uint8_t reg, uint32_t val, uint8_t size, uint8_t bus = 0);

没有I2cWrite16LE辅助函数。

5. 缓冲传输(注意:成功返回false、出错返回true,约定相反)

bool I2cReadBuffer (uint8_t addr, int reg, uint8_t *reg_data, uint16_t len, uint8_t bus = 0); bool I2cReadBuffer0(uint8_t addr, uint8_t *reg_data, uint16_t len, uint8_t bus = 0); bool I2cWriteBuffer(uint8_t addr, uint8_t reg, uint8_t *reg_data, uint16_t len, uint8_t bus = 0);

6. 驱动注册表 / 探测

bool I2cActive (uint32_t addr, uint8_t bus = 0); void I2cSetActive (uint32_t addr, uint8_t bus = 0); void I2cResetActive (uint32_t addr, uint8_t bus = 0); void I2cSetActiveFound (uint32_t addr, const char *types, uint8_t bus = 0); bool I2cSetDevice (uint32_t addr, uint8_t bus = 0); bool I2cEnabled (uint32_t i2c_index);

I2cEnabled(XI2C_<n>)是 I2C 传感器回调函数开头的首选门控(替代已废弃的i2c_flg全局变量),其实现位于 tasmota/tasmota_xx2c_global/xx2c_interface.ino。底层地址占用表由I2cActive()/I2cSetDevice()维护(见 support_a_i2c.ino):I2cSetDevice先检查地址是否已被其他驱动认领,未认领才发起总线探测,而I2cSetActiveFound会在成功后登记地址并打印I2C: <types> found at 0x.. on bus<n>日志。

7. 标准探测模式

void MySensorDetect(void) { for (uint32_t bus = 0; bus < MAX_I2C; bus++) { for (uint32_t i = 0; i < MY_SENSOR_ADDR_NUM; i++) { uint8_t addr = MY_SENSOR_BASE_ADDR + i; if (!I2cSetDevice(addr, bus)) { continue; } // 已被其他驱动认领则跳过 uint8_t id; if (I2cValidRead8(&id, addr, MY_SENSOR_ID_REG, bus) && id == MY_SENSOR_ID_VAL) { I2cSetActiveFound(addr, "MySensor", bus); // ... 保存 addr/bus,标记已检测 ... return; } } } }

该模式先在多总线上遍历候选地址,用I2cSetDevice抢占式认领,再读设备 ID 寄存器校验,最后用I2cSetActiveFound登记并记日志——这也是仓库中xsns_118_ags02ma.inoxsns_112_ens210.ino等 I2C 传感器普遍遵循的探测套路。

十一、开发速查:把新传感器接入固件的完整路径

  1. 起名与编号:在tasmota_xsns_sensor/下新建xsns_XX_<name>.ino,取一个尚未占用的编号(仓库现有传感器已用到xsns_127,如 xsns_127_esp32_sensors.ino,新模块请避开已有编号);
  2. 实现回调:按上文骨架导出bool XsnsXX(uint32_t function),在FUNC_INIT中探测、FUNC_EVERY_SECOND中读数、FUNC_JSON_APPEND/FUNC_WEB_SENSOR中上报;
  3. 声明 ID 宏#define XSNS_XX XX,并把&XsnsXX按编号顺序追加进 xsns_interface.ino 的函数指针表;
  4. 配置编译开关:模块整体用#ifdef USE_<feature>包裹,并在 tasmota/user_config_override_sample.h 参考模板中添加对应#define
  5. 本地化字符串:Web 端显示串尽量复用 tasmota/include/i18n.h 中已有的HTTP_SNS_*常量;
  6. 命令与设置:需要自定义命令时在FUNC_COMMAND_SENSOR/FUNC_COMMAND_DRIVER中读XdrvMailbox,用ResponseCmnd*系列函数回包;需要持久化数据时通过Settings/SettingsText读写。

十二、进一步阅读

  • API.md — 驱动/传感器回调 ID 权威参考(docs/API.md的同内容版本亦在仓库中)
  • tasmota/include/tasmota.h — 主要枚举与常量(XsnsFunctionsLoggingLevelsSettingsTextIndex
  • tasmota/include/tasmota_types.h —TSettings结构与其他类型
  • tasmota/include/i18n.h — Web 传感器显示字符串常量
  • tasmota/user_config_override_sample.h — 编译期配置覆盖模板
  • platformio_tasmota_env.ini 与 platformio_tasmota_env32.ini — ESP8266 / ESP32 平台编译环境
  • TEMPLATES.md — GPIO 模板总表

【免费下载链接】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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询