
Serial Studio YAML Data 解析器把扁平 key: value 文本帧转成固定通道顺序的锁存数据【免费下载链接】Serial-StudioOpen-source telemetry dashboard. Supports UART, BLE, MQTT, Modbus, CAN Bus and more.项目地址: https://gitcode.com/GitHub_Trending/se/Serial-Studio本篇围绕 Serial Studio 的 YAML Data 解析器模板yaml_data展开讲清它的线上帧格式、唯一的keys配置参数、逐行解析流程以及帧间锁存latch语义。读完后你可以直接把设备输出的扁平 YAML 文本接到数据源上完成通道映射并能从 C 原生实现、JS/Lua 脚本实现与单元测试三个层面验证其解析行为。模板定位一个只解析顶层 key: value 的轻量解析器Serial Studio 的解析器Frame Parser负责把数据源吐出的每个帧解码为一行多通道的数据。仓库中同一套解析能力存在三种形态原生 C 模板TextYamlData.cpp作为进程内模板注册是文档所描述的规范行为JavaScript 模板yaml_data.js供用户以脚本方式定制Lua 模板yaml_data.lua与 JS 版逻辑等价。三种形态在 parser/templates.json 中统一登记为条目yaml_data显示名 YAML data并带有 16 种语言的本地化名称。原生模板通过 NativeTemplate.h 定义的INativeTemplate描述符暴露稳定 id、参数 schema 和解析器工厂模板描述符注释中对其定位是Latching extractor for flat YAML key: value lines.对扁平 YAMLkey: value行做锁存提取官方说明文档见 yaml_data.md。线上帧格式Wire Format设备每帧发送的是一段扁平 YAML 文本只包含顶层key: value行。官方文档给出的典型帧如下temperature: 25.5 humidity: 60 # 行内注释会被剥掉 status: ok三个要点只认顶层键值对。缩进的嵌套映射、数组、多行值都不会被解析见 Limitations 一节注释按#截断。从第一个#到行尾的内容全部丢弃因此humidity: 60 # inline comments are stripped实际解析为humidity: 60字符串值可以带引号。ok与ok的成对外层引号会被去掉最终得到裸字符串ok。帧中的 YAML 文档标记---文档起始和...文档结束会被整行跳过不会参与解析。一个带标记的真实帧示例与单元测试输入一致--- temp: 25 # degrees flag: yes name: bob参数keys通道顺序即通道索引整个模板只有一个参数文档中的参数表如下参数类型默认值说明Keys (in channel order)texttemperature,humidity,pressure,voltage,current,altitude,speed逗号分隔的键名列表。每个键的位置决定其通道索引参数行为在源码中有明确对应YamlDataTemplate::params()用DataModel::nativeParam(keys, NativeParamType::String, ..., temperature,humidity,pressure,voltage,current,altitude,speed)声明该参数及其默认值TextYamlData.cpp 第 169–181 行makeParser()通过DataModel::nativeKeyList(params, keys, 默认CSV)把逗号分隔串解析为有序列表列表为空会报错At least one key is required.至少需要 1 个键并返回空解析器因此配置界面里至少必须写一个键名解析器构造时调用buildKeyIndex(keys)定义于 NativeTemplateSupport.h建立键名 → 下标的哈希索引m_keyIndex通道数即keys.size()键在列表中的位置就是输出行中的列位置。以默认配置为例输出行共有 7 列第 0 列 temperature、第 1 列 humidity、……第 6 列 speed。JS 模板中的写法直观体现了这一映射yaml_data.jsconst numItems 7; const keyToIndexMap { temperature: 0, humidity: 1, pressure: 2, voltage: 3, current: 4, altitude: 5, speed: 6 };Lua 版则是 1 起始的同一张表temperature 1…speed 7。逐行解析流程源码级C 实现的YamlDataParser::parseText()TextYamlData.cpp 第 58–83 行对每一行执行如下固定流水线截注释stripComment()找到行内第一个#并丢弃其后内容去空白与过滤trimmed()后为空、或整行等于---/...的行直接continue按第一个冒号切分line.indexOf(:)找不到冒号的行整行忽略冒号前是键、冒号后是值值侧会再 trim键名去引号stripQuotes()剥掉键两侧成对出现的或查键索引在m_keyIndex中查不到该键的行直接跳过——未知键不会报错也不会占列值归一化yamlValue()做类型归一下一节详述归一结果为空对应null/~/ 空值时不写回否则storeAt(it.value(), value)写入对应通道列。二进制路径parseBinary()的实现是parseText(QString::fromUtf8(frame))——即把字节帧按 UTF-8 文本走同一条文本路径因此即使数据源以二进制解码器接入只要内容是 UTF-8 文本也能解析。这套逐行逻辑与 JS 版parse(frame)、Lua 版parse(frame)完全同构removeComment()↔stripComment()↔line:find(#, 1, true)跳过---/...、首个冒号切分、键去引号、未知键跳过三处实现一一对应。值归一化与输出通道文档的 Output Channels 一节定义了输出规则每个配置的键对应一个通道标量按如下规则归一原始值归一结果true/yes/ontruefalse/no/offfalseok或ok成对外层引号去掉引号后的oknull/~/ 空值不更新保留该通道上一个帧的值其他如25.5、bob原样去引号后作为该通道值C 侧yamlValue()的归一逻辑TextYamlData.cpp 第 121–135 行空串/null/~返回空 QString表示保留旧值true/yes/on归一为字符串truefalse/no/off归一为false其余剥引号后原样保留。原生模板在管道中以字符串承载所有值而 JS/Lua 脚本模板的parseYAMLValue会进一步产出原生类型布尔true、浮点25.5、去引号字符串供脚本引擎直接做数值运算——从源码结构看这是原生模板统一走文本行与脚本模板保留类型的分工差异选型时以文档声明的字符串化规则为准。锁存语义缺键的帧不会清空通道Values latch between frames值在帧间锁存是该模板最关键的时序行为。实现落在基类 NativeLatchParser 上头文件注释写明其语义Base for parsers that latch one value row between frames: missing keys keep their previous values, matching the persistent parsedValues arrays of the JS/Lua templates.即解析器实例持有m_values通道数列的数组每次parseText()只覆盖本帧中出现的键未出现的键沿用上一帧值帧末尾统一返回整行锁存值latchedFrame()。JS/Lua 模板用等价的持久数组表达同一语义const parsedValues new Array(numItems).fill(0);声明在函数外跨帧存活。这一行为有单元测试钉死见 tst_cframe_parser.cpp 第 712–727 行用例yamlDataExtractsFlatKeysparams.insert(keys, temp,flag,name); // 第一帧完整覆盖三个键 row firstRow(parser.parseString(---\ntemp: 25 # degrees\nflag: yes\nname: \bob\\n)); // 期望得到 {25, true, bob} QCOMPARE(row, QStringList({25, true, bob})); // 第二帧只有 flag 键 QCOMPARE(firstRow(parser.parseString(flag: off)).at(1), false);测试同时验证了---标记被跳过、# degrees行内注释被剥掉、yes归一为true、bob去引号、off归一为false且第二帧只更新了 flag 通道temp与name通道仍锁存着上一帧的值。支持范围与限制Pipeline Notes文档 Pipeline Notes 一节明确了两条使用前提与源码实现逐条吻合配合 Plain Text 解码器使用。Serial Studio 的数据源解码器选项中包含Plain Text (UTF8)见 ProjectEditor.cpp 的解码器选项列表YAML 数据流应按文本帧接入不支持嵌套结构、多行值与锚点anchors/aliases。解析器逐行扫描、只看顶层key: value- list、key:后跟缩进子映射、anchor/*alias均无识别路径未知键静默忽略键不在keys列表中的行直接跳过不会导致解析失败——这点对设备偶尔输出额外诊断字段很友好但也意味着键名拼写错误只会表现为该通道一直是初始值配置时务必核对键名与通道顺序键列表非空makeParser对空列表返回错误At least one key is required.至少配置 1 个键。小结yaml_data模板是一个刻意收窄的解析器固定通道顺序、只认顶层键值行、注释/引号/文档标记安全剥离、yes/no/on/off等布尔别名统一归一、缺键与null值通过锁存保持通道连续。配置上只需维护一个keys逗号列表理解键的位置 通道索引与帧间锁存两条规则即可正确接入。需要行为层面的核对时可直接阅读 TextYamlData.cpp 的逐行解析与 tst_cframe_parser.cpp 中yamlDataExtractsFlatKeys用例两者共同构成该模板的规范依据。【免费下载链接】Serial-StudioOpen-source telemetry dashboard. Supports UART, BLE, MQTT, Modbus, CAN Bus and more.项目地址: https://gitcode.com/GitHub_Trending/se/Serial-Studio创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考