news 2026/9/12 20:31:39

Tasmota 集成 LibTeleinfo:基于 Arduino 的法国 Teleinfo(TIC)电表解码库实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Tasmota 集成 LibTeleinfo:基于 Arduino 的法国 Teleinfo(TIC)电表解码库实战指南

Tasmota 集成 LibTeleinfo:基于 Arduino 的法国 Teleinfo(TIC)电表解码库实战指南

【免费下载链接】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

Teleinfo(又称 TIC,Télé-Information Client)是法国电网运营商 Enedis(原 ERDF)在其电表(含 Linky 智能电表)上提供的一种串行遥测数据协议,通过电表端口周期性输出电流、电压、功率、累计用电量、费率档位等计量信息。本指南围绕当前仓库 lib/lib_div/LibTeleinfo 目录中的通用 Teleinfo 解码库展开:它既是一套可在 Arduino、Particle(Spark Core)、ESP8266、ESP32、树莓派等任何可运行 C++ 的环境里独立使用的库,也是 Tasmota 固件中 Teleinfo 电能传感器驱动 xnrg_15_teleinfo.ino 的底层解析引擎。读完本文,你将掌握 Teleinfo 的两种传输模式(Historique 历史模式与 Standard 标准模式)及其帧格式、校验和算法、库的安装方法与回调 API,并能结合 Tasmota 的Teleinfo/EnergyConfig命令完成电表接入、原始数据上报与接收质量统计。

库概述:从通用 C++ 库到 Tasmota 能量驱动

LibTeleinfo 由 Charles-Henri Hallard 编写,仓库中的 library.properties 将其描述为 "Decoder for Teleinfo (aka TIC) from French smart power meters",版本为 1.1.7,类别为 Communication,支持任意架构(architectures=*),并明确可在 Arduino、Particle、ESP8266、树莓派等平台运行;library.json 中的 frameworks 为arduino,平台覆盖espressif8266espressif32,这正是 Tasmota 所面向的两类芯片。

从 LibTeleinfo.h 的版本历史可以看到它与 Tasmota 的深度绑定:

  • V1.00(2015-06-14):首次发布;
  • V2.00(2020-06-11):集成进 Tasmota;
  • V2.01(2020-08-11):合并 LibTeleinfo 官方版与 Tasmota 版,新增对 Linky 智能电表 Standard 模式的支持;
  • V2.02(2021-04-20):为过载回调(ADPS)增加 label 字段。

核心类为TInfo,它对外暴露的 API 分成三类:

  • 初始化与状态机init(_Mode_e mode)process(char c)
  • 回调挂接attachADPS()attachData()attachNewFrame()attachUpdatedFrame()
  • 数据访问valueGet()valueGet_P()getList()valuesDump()labelCount()addCustomValue()listDelete()
  • 统计getChecksumErrorCount()getFrameSizeErrorCount()getFrameFormatErrorCount()getFrameInterruptedCount()clearStats()

在 Tasmota 中,该库被 xnrg_15_teleinfo.ino(XNRG_15能量驱动)直接使用:驱动声明一个全局TInfo tinfo对象,通过TasmotaSerial读取电表串口字节流,再逐字节喂给tinfo.process(c)。因此理解 LibTeleinfo 的帧处理机制,就是理解 Tasmota Teleinfo 功能的前提。

安装:把库放入 Arduino libraries 目录

原文档给出的标准 Arduino 安装步骤(下文已结合本仓库实际目录结构说明):

  1. 将 lib/lib_div/LibTeleinfo 目录整体下载(Arduino 环境下通常下载 zip 解压);
  2. 把解压后的文件夹放入 Arduino 环境的libraries目录,最终应形如your_sketchbook_folder/libraries/LibTeleinfo,且该目录下必须包含.cpp.h源文件以及examples子目录;
  3. 在 Arduino IDE 中通过File > Preferences查看你的 sketchbook 文件夹路径。

注意:本仓库中的 LibTeleinfo 是作为 Tasmota 的依赖库放在lib/lib_div/下的,因此它并不需要(也不应)手动复制到 Arduino libraries 目录——Tasmota 通过 PlatformIO 的 lib 目录机制自动编译它。手工安装方式适用于把该库单独用于你自己的 Arduino 工程(例如文档中列出的各示例 sketch)。仓库内的库结构为:

lib/lib_div/LibTeleinfo/ ├── README.md ├── library.json ├── library.properties └── src/ ├── LibTeleinfo.cpp └── LibTeleinfo.h

可以看到本仓库保留了核心src/源码但未附带examples/子目录(Tasmota 场景下示例被 xnrg_15_teleinfo.ino 所替代),如果你需要示例,请以原库发布包为准。

支持的示例场景(原文档列出的 sketch 清单)

原 README 列举了该库作者围绕不同硬件开发的示例 sketch,虽然它们不在本仓库内(仓库以 Tasmota 集成为准),但这份清单可以帮助你判断库的能力边界与适配硬件:

示例平台功能
Arduino_Softserial_EtiquetteArduino逐条(étiquette/标签)显示收到的遥信信息
Arduino_Softserial_BlinkArduino逐帧显示遥信信息,数据变化时 LED 短/长闪烁
Arduino_Softserial_JSONArduino通过串口以 JSON 格式输出遥信信息
Raspberry_JSON树莓派在 stdout 上以 JSON 格式输出遥信信息
WifinfoESP8266 / ESP32Wi-Fi 遥信:Web + REST + 附加功能
ESP32ESP32WifInfo32(后更名 Denky)基础测试
ESP32_PassthruESP32Denky D4 透传测试,在串口控制台显示数据与统计
ESP8266_DataChangedESP8266监视两帧之间变化的数据,按变化情况闪烁 RGB LED
Teleinfo_DenkyD4ESP32基于 ESP32-Pico-V3-02 的 Denky D4 基础测试与统计
Teleinfo_StatsESP32针对接收质量的测试与统计程序

此外,xnrg_15_teleinfo.ino 文件头部还保留了 Tasmota 场景下的硬件模板:

  • Denky(Teleinfo)ESP32 模板;
  • DenkyD4(ESP32-Pico-V3-02)模板;
  • Denky(WifInfo)ESP8266 模板(多个版本)。

这些模板可直接作为 Tasmota 的模块配置使用,从中也能看出该库在实际硬件方案中的典型应用形态。

Teleinfo 协议基础:两种传输模式与帧格式

Historique(历史)模式 vs Standard(标准)模式

_Mode_e枚举定义了库支持的两种模式(见 LibTeleinfo.h):

enum _Mode_e { TINFO_MODE_HISTORIQUE, // Legacy mode (1200) TINFO_MODE_STANDARD // Standard mode (9600) };
  • Historique(历史/传统)模式:串口波特率 1200,帧中标签与值以空格' '分隔,适用于传统电表;
  • Standard(标准)模式:Linky 智能电表的新格式,波特率 9600,标签、值、时间戳之间以制表符\tTINFO_HT,0x09)分隔,支持可选的时间戳字段(horodatage)。

TInfo::init()会根据模式设置分隔符(见 LibTeleinfo.cpp):

if ( _mode == TINFO_MODE_STANDARD ) { _separator = TINFO_HT; // '\t' 0x09 } else { _separator = ' '; // 0x20 }

帧与组(Frame / Group)的控制字符

头文件中定义了完整的帧控制字符集:

#define TINFO_STX 0x02 // 帧起始 #define TINFO_ETX 0x03 // 帧结束 #define TINFO_EOT 0x04 // 帧中断(End Of Transmission) #define TINFO_HT 0x09 // 制表符(Standard 模式分隔符) #define TINFO_SGR '\n' // 组起始(Start of Group) #define TINFO_EGR '\r' // 组结束(End of Group)

一帧遥信数据由若干"组"(group)组成:每一组是一行标签 值 校验和(Historique)或标签 [时间戳] 值 校验和(Standard),行与行之间以\n(组起始)和\r(组结束)包裹;整帧以 STX(0x02)开始、以 ETX(0x03)结束。当电表需要打断当前帧时,会发送 EOT(0x04)字符。

组格式与校验和算法

calcChecksum()的注释(见 LibTeleinfo.cpp)给出了两种模式的精确组格式:

Historique 模式(校验和不包含末尾空格):

LF etiquette SP donnee SP Chk CR 0A 20 20 0D \____check________/

Standard 模式带时间戳(校验和包含最后一个 HT):

LF etiquette HT horodatage HT donnee HT Chk CR 0A 09 09 09 0D \____________checkum_______________/

Standard 模式无时间戳(校验和包含最后一个 HT):

LF etiquette HT donnee HT Chk CR 0A 09 09 0D \_____checkum________/

校验和的计算方法(见 LibTeleinfo.cpp):

uint8_t sum = (_mode == TINFO_MODE_HISTORIQUE) ? _separator : (2 * _separator); // 对标签、值(以及时间戳)中每个 0x20~0x7E 范围内的字符累加其 ASCII 码 // 时间戳字段必须以 'E'/'H'/'e'/'h' 开头(E=Été 夏季,H=Hiver 冬季),后跟数字 return ( (sum & 0x3f) + ' ' );

即:将所有参与校验的字符 ASCII 码相加(Historique 模式初始为分隔符空格的值,Standard 模式初始为两倍制表符值),取sum & 0x3F后再加上' '(0x20)得到校验字符。校验和用于在checkLine()中逐行验证数据完整性,验证失败会递增_checksumerror计数器(见 LibTeleinfo.cpp)。

库状态机:process() 的逐字符解析

库以有限状态机方式逐字符消化串口字节流,状态定义见 LibTeleinfo.h:

enum _State_e { TINFO_INIT, // 初始化 TINFO_WAIT_STX, // 等待帧起始 STX TINFO_WAIT_ETX, // 已收到 STX,等待帧结束 ETX TINFO_READY // 已收到 STX 和 ETX,可正常接收数据 };

TInfo::process(char c)的完整处理逻辑(见 LibTeleinfo.cpp):

  1. 收到 STX(0x02):清空接收缓冲区,重置_frame_updated标志;若状态为TINFO_INITTINFO_WAIT_STX,则转入TINFO_WAIT_ETX
  2. 收到 EOT(0x04):丢弃未完成的帧,清空缓冲区,_frameinterrupted++,回到TINFO_WAIT_STX(这就是原文档"Addon"一节所说的"EOT 帧中断字符处理");
  3. 收到 ETX(0x03):若当前处于TINFO_READY,则说明一帧接收完毕——若本帧内有数据更新(_frame_updated)则调用_fn_updated_frame回调,否则调用_fn_new_frame回调;随后清除TINFO_FLAGS_ALERT标志(例如 ADPS 过载告警,避免长期驻留链表);同时根据当前状态推进到TINFO_READY或回到TINFO_WAIT_STX
  4. 收到\n(组起始):忽略,实际处理推迟到组结束;
  5. 收到\r(组结束):若状态为TINFO_READY,把当前接收缓冲中的一行交给checkLine()校验并入库,然后清空缓冲区。若缓冲区溢出(_recv_idx >= TINFO_BUFSIZE,缓冲区大小TINFO_BUFSIZE为 128 字节)则递增_framesizeerror
  6. 其他字符:仅在TINFO_READY状态下存入接收缓冲区,溢出时记录日志并清空。

checkLine()(见 LibTeleinfo.cpp)是单行解析的核心:要求一行至少 7 个字符,通过统计分隔符数量判断 Standard 模式是否携带时间戳,分离标签/值/校验和,验证校验和后将值写入以ValueList为节点的单向链表,同时通过标志位区分该值是新增(TINFO_FLAGS_ADDED)、已存在(TINFO_FLAGS_EXIST)、更新(TINFO_FLAGS_UPDATED)还是告警(TINFO_FLAGS_ALERT)。特别地,DATE标签格式特殊,格式错误不计入_frameformaterror

链表数据模型:ValueList 与标志位

所有收到的遥信值存放在以ValueList为节点的链表中(见 LibTeleinfo.h):

typedef struct _ValueList ValueList; struct _ValueList { ValueList *next; // 下一个节点 time_t ts; // 时间戳(如 Standard 模式的 horodatage) uint8_t checksum;// 校验和 uint8_t flags; // 标志位 char * name; // 标签名(LABEL) char * value; // 值 };

标志位定义(见 LibTeleinfo.h):

#define TINFO_FLAGS_NONE 0x00 #define TINFO_FLAGS_NOTHING 0x01 #define TINFO_FLAGS_ADDED 0x02 // 新值 #define TINFO_FLAGS_EXIST 0x04 // 已存在(值未变) #define TINFO_FLAGS_UPDATED 0x08 // 值已更新 #define TINFO_FLAGS_ALERT 0x80 // 告警(如 ADPS 过载)

valueAdd()在写入链表时会计算并比对校验和(校验和不符直接拒绝),并维护节点内存:节点连同名称、值字符串一次性malloc分配(sizeof(ValueList) + lgname + 1 + lgvalue + 1),名称和值字符串内联在节点之后(见 LibTeleinfo.cpp)。如果新值与旧值长度不同,旧节点会被释放重建。

customLabel()(见 LibTeleinfo.cpp)对特定标签做预处理:单相电表的ADPS标签触发相位 0 告警;三相电表的ADIR1/ADIR2/ADIR3分别触发相位 1/2/3 告警,并调用_fn_ADPS回调。这类标签不会被永久保存。

Tasmota 集成实践:从 GPIO 到 MQTT 的完整链路

硬件接线与模板

Tasmota 通过两个 GPIO 功能接入电表(见 tasmota_template.h):

  • GPIO_TELEINFO_RX(Teleinfo 遥测数据接收引脚,即Teleinfo):接电表 TIC 输出的 RX 数据;
  • GPIO_TELEINFO_ENABLE(Teleinfo 使能引脚,即Teleinfo Enable):部分电表/光电头需要拉高此引脚才输出数据,Tasmota 在初始化时将其置为 HIGH,重启前置为 LOW(见TInfoInit()TInfoSaveBeforeRestart())。

在 xnrg_15_teleinfo.ino 头部保留了官方硬件模板示例,例如 DenkyD4 模板与 WifInfo 模板,可作为配置参考。

串口初始化

TInfoInit()(见 xnrg_15_teleinfo.ino)根据模式选择波特率与串口缓冲区大小:

模式波特率串口接收缓冲区
Historique1200512 字节(TELEINFO_SERIAL_BUFFER_HISTORIQUE
Standard96001536 字节(TELEINFO_SERIAL_BUFFER_STANDARD

串口配置为SERIAL_7E1(7 数据位 + 偶校验 + 1 停止位)。ESP8266 上优先尝试硬件串口,失败则回退软件串口;ESP32 使用 UART 硬件串口。初始化完成后调用:

tinfo.init(tinfo_mode); tinfo.attachADPS(ADPSCallback); tinfo.attachData(DataCallback); tinfo.attachNewFrame(NewFrameCallback);

把三个回调挂接到库上:ADPS 过载告警、逐条数据更新、整帧接收完成。

数据消费回调

  • ADPSCallback(phase, label)(见 xnrg_15_teleinfo.ino):过载告警发生时发布 MQTT 消息{"TIC":{"ADPS":相位号}}并写日志;
  • DataCallback(me, flags)(见 xnrg_15_teleinfo.ino):把实时数据映射进 Tasmota 的Energy对象——电压(TENSION/URMS1/URMS2/URMS3)、电流(IINST/IINST1IRMS3)、视在/有功功率(PAPP/SINSTS/SINSTS1SINSTS3),并处理 Wh 累计值(Historique 的BASEHCHC+HCHP,Standard 的EASTEASF01/EASF02等)以及费率/合约(PTECLTARFOPTARIFNGTF);
  • NewFrameCallback(me)(见 xnrg_15_teleinfo.ino):重置能量看门狗Energy->data_valid[0],并根据Settings->teleinfo.raw_send决定是否把整帧原始遥信以 JSON 发布到 MQTT。

Tasmota 在FUNC_EVERY_250_MSECOND周期调用TInfoProcess()(见 xnrg_15_teleinfo.ino),将串口缓冲区的字节逐个送入tinfo.process(c),从而驱动整个解析状态机。

常用控制命令

Tasmota 控制台通过Teleinfo命令族配置遥信功能(命令枚举见 xnrg_15_teleinfo.ino):

命令说明
Teleinfo0设置为 Historique 模式(1200 波特)
Teleinfo1设置为 Standard 模式(9600 波特,Linky)
Teleinfo2关闭原始帧上报
Teleinfo3开启全量原始帧上报
Teleinfo4仅上报发生变化的原始帧
Teleinfo5 <n>原始模式下每n+1帧上报一次(帧跳数)
Teleinfo6 <n>限制原始帧只包含快速变化的值(如功率、电流)
Teleinfo7显示/清除/启用接收错误统计

同时EnergyConfig命令也可以携带这些子参数(如EnergyConfig Teleinfo Standard),并可在不带参数时打印当前遥信配置(模式、RX/EN 引脚、Raw 模式、Skip/Limit/Stats 值)。统计开关Teleinfo7 1会启用统计,此时 Web 界面 "Energy" 页面会额外显示四类错误计数:Bad Checksum(校验和错误)、Wrong Size(帧尺寸错误)、Bad Format(帧格式错误)、Interruption(帧中断),分别对应库中的getChecksumErrorCount()getFrameSizeErrorCount()getFrameFormatErrorCount()getFrameInterruptedCount()(见 xnrg_15_teleinfo.ino)。

典型标签速查

xnrg_15_teleinfo.ino 中通过kLabel表维护了驱动认识的全部标签,以下为常见标签的用途说明(Historique 与 Standard 的标签集略有差异,Standard 模式多用SINSTSURMSIRMSEASTEASFxxNGTFLTARF等):

标签含义
ADCO电表序列号(12 位,旧式)
ADSCLinky 电表序列号
BASE/HCHC/HCHP累计 Wh(Base 合约 / 谷时 / 峰时)
EAST总累计 Wh(Standard)
EASF01~EASF06各费率累计 Wh(Standard)
IINST/IINST1~IINST3瞬时电流(Historique,单相/三相)
IRMS1~IRMS3电流有效值(Standard,三相)
PAPP视在功率 VA(Historique)
SINSTS/SINSTS1~SINSTS3视在功率 VA(Standard,三相)
TENSION/URMS1~URMS3电压 V
OPTARIF/NGTF合约类型(Historique 编码值 / Standard 明文)
PTEC/LTARF/NTARF当前费率档位
ISOUSC订阅电流 A
IMAX/IMAX1~IMAX3最大电流
PMAX/SMAXSN最大功率
ADPS/ADIR1~ADIR3过载告警(触发回调后不长期保存)
DEMAIN明日颜色(Tempo 合约)
MSG1/MSG2/STGE电表状态/消息(部分标签被驱动列入黑名单不随遥测上报)

常见问题与调试建议

  • 接不上电表 / 无数据:先确认模板中 RX 引脚与GPIO_TELEINFO_RX对应,使能引脚(如有)已接并会被拉高;再核对模式:老电表用 Historique(1200),Linky 用 Standard(9600)。可通过Teleinfo0/Teleinfo1即时切换模式,切换时驱动会自动重初始化库(LibTeleinfoinit()时总会释放链表)。
  • 数据时断时续 / 校验和错误飙升:多为串口参数(7E1)或信号质量问题。开启统计(Teleinfo7 1)后观察四类错误计数:Bad Checksum多为线路干扰或光电头不稳;Interruption表示收到 EOT 帧中断;Wrong Size表示组长度异常。可配合Teleinfo5降低上报频率。
  • MQTT 原始帧过多:默认遥测只携带 Energy 摘要数据,原始帧需要显式开启Teleinfo3(全量)或Teleinfo4(仅变化),并用Teleinfo5 <n>做降频。若只想在 Web 上看统计而不要 MQTT 原始帧,保持Teleinfo2即可。
  • Raw 模式下偶发空报文:驱动只在确有数据(hasData)时才发布 MQTT,避免无用流量(见 xnrg_15_teleinfo.ino)。

许可与致谢

库头文件声明采用 Creative Commons Attribution Share-Alike License(CC-BY-SA 4.0,见 LibTeleinfo.h),原 README 中注明的许可为 Creative Commons Attribution - Pas d'Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International(非商业用途 + 相同方式共享),使用时请遵守对应条款;库作者欢迎硬件厂商在商业产品中使用时回赠样品。Tasmota 侧的能量驱动 xnrg_15_teleinfo.ino 则采用 GPL-3.0 许可,两者叠加使用时请分别遵守各自的许可证要求。Teleinfo 协议的官方规范可参考 Enedis 发布的技术文档(原 README 中引用了 ERDF/Enedis 的 NOI-CPT 02E 与 NOI-CPT 54E 数据手册)。

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 20:30:12

RAG检索增强生成完整落地:架构拆解、文本切片、向量检索、相似度匹配、知识库问答、工程避坑全方案

前言在前面几天的连载中&#xff0c;我们已经打通了 LLM推理、Prompt工程、上下文优化、反幻觉、批量吞吐、本地部署、模型量化、LoRA微调 的全链路能力。但目前的模型依然存在两个无法通过调参、微调彻底解决的工程短板&#xff1a;1. 知识滞后&#xff1a;模型训练数据固定&a…

作者头像 李华
网站建设 2026/9/12 20:29:56

传统流量失效:解析 AI 搜索生态中西安实体商业的 GEO 布局路径

在数字化浪潮的推动下&#xff0c;西安本地的实体商业正经历着一场深刻的变革。无论是美业门店从“单次服务售卖”向“定制化解决方案”的转型&#xff0c;还是文旅景区从“粗放式广撒网”向“精细化拓客”的升级&#xff0c;都标志着市场已进入专业化、精细化的运营新阶段。与…

作者头像 李华
网站建设 2026/9/12 20:29:15

储能EMS控制器(8) — 储能柜项目调试如何提升安全性?

当储能柜的项目需求变化比较大&#xff0c;或者对于新手调试运维工程师来说&#xff0c;在本地EMS能量管理系统的运行时直接调试有风险。那么&#xff0c;如何给储能柜调试提升安全性&#xff1f;简介当储能柜的项目需求变化比较大&#xff0c;或者对于新手调试运维工程师来说&…

作者头像 李华
网站建设 2026/9/12 20:27:29

手机远程操作手机怎么实现 手机远程操作的软件推荐

两部手机之间能不能实现远程操作&#xff1f;手机远程操作手机的需求出现在很多日常场景里&#xff0c;比如帮不熟悉智能手机的长辈调整设置&#xff0c;或者给朋友远程演示某个App的操作流程。手机远程操作手机并不是什么复杂的技术&#xff0c;无界趣连2.0在手机端提供了完整…

作者头像 李华