Serial Studio 项目编辑器完全指南:从 JSON 项目文件到仪表盘的完整建模
2026/9/19 13:44:31 网站建设 项目流程

Serial Studio 项目编辑器完全指南:从 JSON 项目文件到仪表盘的完整建模

【免费下载链接】Serial-StudioOpen-source telemetry dashboard. Supports UART, BLE, MQTT, Modbus, CAN Bus and more.项目地址: https://gitcode.com/GitHub_Trending/se/Serial-Studio

Serial Studio 的项目编辑器(Project Editor)是创建、编辑和调试 JSON 项目文件的图形化工具,它决定了应用如何解释串口、网络、BLE 等数据源送来的字节流,并在仪表盘(Dashboard)上呈现为分组、数据集与控件。本文以 Project-Editor.md 为主体骨架,结合仓库源码(如 core/Core/Checksum.cpp、core/Core/SerialStudio.h)逐层讲解项目层级、帧解析与校验和参数、分组与数据集建模、脚本解析器、多源架构与排错方法,读完即可独立搭建并调试一个完整的遥测项目。

项目编辑器是什么

项目编辑器让你创建和编辑 JSON 项目文件,这些文件定义了 Serial Studio 如何解释传入的数据并在仪表盘上显示。你可以通过工具栏的Project Editor按钮打开它,也可以从设备设置面板中的扳手按钮进入。编辑器的主窗口位于 app/qml/ProjectEditor/ProjectEditor.qml,其后端模型与命令处理位于 core/Ui/ProjectEditor/ProjectEditor.cpp。

一个项目文件描述三件事:

  1. 数据的结构——分组(Group)与数据集(Dataset)如何组织;
  2. 如何从线路上检测并解析帧——帧检测、解码与解析器;
  3. 用户可以向设备发送哪些操作(命令)——Action。

Serial Studio 在连接设备时读取该文件,并根据它构建仪表盘。即编辑项目是"建模"阶段,连接设备是"生效"阶段。

项目层级结构

项目树总览

一个 Serial Studio 项目文件对应一棵树,树的每一层都映射到仪表盘的某一部分:

有两个关键的组织规则:

  • 每个Action和每个Source都直接挂在项目根下——不存在中间的 "Actions" 或 "Sources" 节点;
  • 三个例外:项目级脚本(Control Loop、Lua Library、JavaScript Library)归入Project Scripts节点;实时数据导出(MQTT Publisher、InfluxDB Sink,Pro 版本)归入Data Export节点;分组归入Dashboard Widgets节点。

树视图在左侧面板展示项目层级,例如:

Project Root Project Scripts Control Loop Lua Library JavaScript Library Data Export MQTT Publisher InfluxDB Sink Action: "Reset Device" Source: "Main Device" Frame Parser Dashboard Widgets Group: "Sensors" Dataset: "Temperature" [IDX 1] Dataset: "Humidity" [IDX 2] Dataset: "Pressure" [IDX 3] Group: "Status" Dataset: "Battery" [IDX 4]

方括号中的数字是数据集的帧索引(frame index),即它在解析后数据数组中的位置。点击任一节点,右侧属性面板就会显示对应表单。

帧索引映射

传入数据帧中的每个值都被赋予一个从 1 开始的帧索引,配置数据集时引用它:

设备发送23.5,1013,45.2,解析器返回数组["23.5", "1013", "45.2"],则 Temperature=索引 1、Pressure=索引 2、Humidity=索引 3。索引是 1 基的:索引 1 对应数组元素 0。整个项目内每个索引应当唯一;新增数据集时编辑器会自动分配"当前最大索引 + 1",删除数据集留下的空缺不会被自动填补。

编辑器界面布局

编辑器窗口分为三个区域:顶部工具栏、左侧树视图、右侧属性面板。

工具栏

文件操作在左侧,其余工具栏是"添加"按钮,按创建对象分组:

  • New / Open / Save / Save As:文件操作。Save(Ctrl+S / Cmd+S)把项目写入磁盘;Open加载现有的.json.ssproj文件。
  • Protobuf:从 Protocol Buffers(.proto)模式生成项目。所有构建版本均可用;只有其生成的 Pro 控件需要许可证或免费试用,详见 Auto-Generating Projects。
  • Restore:恢复最近的自动快照,详见 Backups & Recovery。
  • Lock:设置密码并锁定编辑器,详见 Project Lock。
  • Add Device(Pro):为多设备项目添加另一个数据源。
  • Output / Action / Slider / Toggle / Knob / Text Field / Button:添加一个输出控件面板或一个动作。
  • Dataset / Plot / FFT Plot / Gauge / Level Indicator / Compass / LED Indicator:向选中分组添加数据集,并预配置对应控件。
  • Group / Image / Web View / Canvas / Table / Multi-Plot / 3D Plot / Accelerometer / Gyroscope / GPS Map:添加带对应分组控件的分组(Image、Canvas、3D Plot 为 Pro 功能)。

每个按钮及其图标都列在 Toolbar & Button Reference 中。

树视图与导航快捷操作

标题栏左侧是BackForward按钮,按文件管理器或浏览器的方式在访问过的节点间步进:Back 返回上一个选中的节点,Forward 回到后退前的节点;后退后选择新节点会丢弃此前的前进轨迹。已删除的节点会自动跳过。导航还有三种触发方式:

  • 鼠标上的前进/后退键(例如罗技 MX Master);
  • 在编辑器任意位置按Alt+Left(后退)与Alt+Right(前进);
  • 树获得键盘焦点时按Backspace后退——仅在文本框未聚焦时生效,不会干扰输入。

标题栏右侧是Move Up/Move Down,在当前选中节点的兄弟节点间重排,与右键菜单中的对应项效果一致。New FolderMove to Folder不在标题栏上,需从右键上下文菜单进入(选中分支根节点时,属性面板中也会出现Add Folder按钮)。

属性面板

右侧面板显示选中树节点的表单,每次更改立即作用于项目模型。表单字段取决于选中的是项目根、分组、数据集、动作还是数据源。

Project Overview:项目总览图

选中项目根节点后,右侧面板切换为Project Overview(又称 Summary)——整个项目配置的只读图,从左到右分为四列:

  1. Sources(设备):每个数据源一张卡片,含总线类型、帧检测与解码器;
  2. Frame parsers and actions:每个数据源附带的解析脚本,以及全局动作按钮;
  3. Groups:数据集容器与分组级控件(Multi-Plot、GPS、Accelerometer 等);
  4. Datasets:每个数据集一个胶囊块,其变换块(如有)绘制在分组与数据集胶囊之间。

共享表、输出控件和工作区作为独立卡片绘制在旁;箭头展示解析字节如何流入数据集、变换如何馈送给下游消费者。总览图由 core/Ui/ProjectEditor/EditorSummaries.cpp 生成,可交互使用:

  • 双击任意块跳转到对应配置表单:源卡片打开源设置、分组卡片打开分组表单、数据集胶囊打开数据集表单、帧解析卡片打开脚本编辑器、动作卡片打开动作表单、共享表卡片打开表编辑器、输出控件卡片打开输出编辑器;
  • 右键任意块弹出针对该节点的菜单:添加兄弟分组、向该分组添加数据集、重命名、上移/下移、复制、删除、编辑帧解析器或画布代码。右键空白背景则提供"添加源 / 添加表 / 添加动作"快捷项,项目整体形状定下来后无需回到左侧树即可继续生长;
  • Ctrl+滚轮缩放图,普通滚动平移(Shift+滚动水平平移),工具栏带重置缩放按钮。

总览图既是 sanity check("我的分组控件有没有它需要的三个数据集?"),也是项目过大、树视图装不下时的导航面。

用文件夹组织项目

当分组超过几个后,扁平树会变得很长。文件夹让你把条目归入带名字、可折叠的容器,保持树可读。文件夹在所有版本(免费与 Pro)中均可用,纯属组织用途,绝不改变数据解析方式

存在三棵相互独立的文件夹树,每个分支一棵:

  • Group folders组织分组;
  • Table folders组织共享表;
  • Workspace folders组织工作区。

一个分支的文件夹不能容纳另一分支的条目(分组文件夹只放分组,不放表)。未放入任何文件夹的条目留在其分支的顶层。

Groups Folder: "Powertrain" Folder: "Battery" Group: "Cell Voltages" Group: "Pack Temps" Group: "Motor" Group: "Cabin" (top level, no folder)

创建与填充文件夹

  • 添加文件夹:选中分支根(Groups、Variables 或 Workspaces),属性面板工具栏出现Add Folder按钮;或右键分支选择New Folder
  • 嵌套文件夹:选中已有文件夹,点击Add Sub-folder,或右键选New Sub-Folder,可任意深度嵌套;
  • 移入条目:右键分组、表、工作区或文件夹,使用Move to Folder子菜单,它镜像文件夹树,可放入任意深度或回到顶层;
  • 直接添加进文件夹:选中文件夹后,对应的添加按钮(Add GroupAdd Shared TableAdd Workspace)会直接把新条目创建在该文件夹内。

工作区配置文件(Workspace profiles)

工作区配置文件是工作区文件夹的命名子集:某个操作员、测试台或机型变体应看到的工作区。一个服务多种引擎变体的项目,可以把所有分组和工作区保存在一个文件里,为每个变体声明一个 profile。

  • 定义:在工作区视图(仅自定义工作区)中Add Profile,勾选要显示的文件夹。勾选的文件夹显示其整个子树;什么都没勾选的 profile 显示所有内容。Profile 随项目保存;
  • 加载时选择:含两个及以上 profile 的项目打开时会询问显示哪一个,并记住该文件的答案。以--profile <name>启动应用可跳过询问,运行时也可用project.workspace.profile.select选择;
  • 影响范围:只影响任务栏的工作区列表和切换器。Project Editor 始终显示整个项目,自动的按分组工作区仍然可见,项目数据不受任何影响。

重命名与删除

选中文件夹用Rename改名。Delete删除文件夹但绝不删除其内容:文件夹内的条目与子文件夹会提升到被删文件夹的父级(若原本就在顶层则提升到顶层)。确认对话框会明确说明这一点,例如 "The folder is removed; its groups and sub-folders move up to the parent.";对表文件夹,还会提示被移动表的访问路径随之改变。

分组文件夹如何塑造仪表盘

在自动仪表盘布局中,任务栏 Start 菜单里的工作区树会镜像你的分组文件夹树为级联菜单(文件夹变成子菜单,工作区变成可点击项)。两条规则决定分组如何变成工作区:

  • 叶子分组文件夹(无子文件夹)折叠成单个工作区,聚合其内所有分组的全部控件,工作区取文件夹名;
  • 位于容器文件夹(有子文件夹)中的分组或顶层分组,获得自己的工作区,以分组命名。

这样你可以把若干小分组放进一个叶子文件夹、合并到一个仪表盘屏幕,而较大的分组保留在自己的屏幕上。表和文件夹的工作区文件夹仅是组织用途,对仪表盘无副作用。

持久化与兼容性

文件夹以增量方式保存在.ssproj文件中,即groupFolderstableFoldersworkspaceFolders三个数组(见 core/Pipeline/DataModel/Project/ProjectPersistence.cpp 中的序列化逻辑),每个分组、表和工作区携带一个parentFolderId(位于顶层时省略)。先于文件夹功能的老项目加载时行为不变:没有文件夹数组就全部视为顶层。使用文件夹的项目在旧版构建中也能打开——旧版忽略未知键并显示扁平树。

一步一步创建项目

第 1 步:新建项目

  1. 打开 Project Editor;
  2. 点击工具栏New
  3. 在树中点击项目根进行配置;
  4. 设置Project Title(显示在仪表盘页眉)。

第 2 步:配置帧解析

在树中选中数据源(每个项目至少有一个,默认名为 "Device A",单设备项目也一样),配置字节流如何切成帧、每帧如何解码、哪个解析器把它变成值。这些设置位于源表单上;选中项目根只会显示 Project Title 字段。

检测、解码与完整性校验

以下设置运行在解析器之前,适用于所有解析器类型(Built-In、Lua、JavaScript 一视同仁):

设置说明选项
Frame detection methodSerial Studio 如何在字节流中找到帧边界。End Delimiter Only(帧以已知序列如\n结尾,最常见);Start + End Delimiter(以起始和结束标记界定,如/**/);Start Delimiter Only(每个帧以头开始,下一个头结束上一个);No Delimiters(整个捕获块即一帧,用于定长或带长度前缀的协议)。
Start delimiter / end delimiter实际的定界符字符串,哪些生效取决于检测方式。任意字符串,如\n/**/
Hex delimiters勾选表示定界符以十六进制书写。如换行为0A
Data conversion (decoder)定界符内的字节在交给解析器前如何解码。Plain Text (UTF8)(默认文本模式);Hexadecimal(每两个字节读作一个十六进制值);Base64(先做 Base64 解码);Binary (Direct)(原始字节直接作为字节数组/表传给解析器)。
Checksum algorithm附加到每帧的可选完整性校验,校验失败的帧被丢弃。XOR-8, MOD-256, CRC-8, CRC-16, CRC-16-MODBUS, CRC-16-CCITT, Fletcher-16, CRC-32, Adler-32。

选错解码/检测组合会静默产生乱码二进制或永远切不出帧。尤其注意:Plain Text 走QString::fromUtf8,任何非合法 UTF-8 的字节(大多数二进制负载含0x00或大于0x7F的值)都会被替换为U+FFFD,原始字节丢失。非文本数据务必选Binary (Direct)。底层检测/解码枚举定义在 core/Core/SerialStudio.h(FrameDetection的四个取值)与 core/Core/IO/FrameConfig.h(FrameConfig结构体,默认起始序列为/*、结束序列为*/)。

校验和参数。算法名称在多项式、初始值和字节序上各不相同;为期望特定配置的设备选错算法,会让每一帧都静默地校验失败。下表给出各算法的完整参数与检查值,其实现均可在 core/Core/Checksum.cpp 中逐行核对:

算法宽度多项式初值反射 in/out字节序Check("123456789"
XOR-88-bit-0x00-单字节0x31
MOD-2568-bit-(模和)0x00-单字节0xDD
CRC-88-bit0x310xFFno / no单字节0xF7
CRC-1616-bit0x10210xFFFFno / no大端0x29B1
CRC-16-MODBUS16-bit0x8005(反射 0xA001)0xFFFFyes / yes小端0x4B37
CRC-16-CCITT16-bit0x10210x0000no / no大端0x31C3
Fletcher-1616-bit-(模和)0-大端0x1EDE
CRC-3232-bit0x04C11DB7(反射 0xEDB88320)0xFFFFFFFFyes / yes大端0xCBF43926
Adler-3232-bit-(模和)1-大端0x091E01DE

Check 列是算法对 ASCII 字符串123456789算出的校验值,可用于确认设备端实现是否使用同一配置。CRC-16 与 CRC-16-CCITT 共用0x1021多项式但初值不同(0xFFFF0x0000,名字相近却对同一输入产生不同字节,不可互换。CRC-16-MODBUS 是多字节校验中唯一的例外:Serial Studio 按最低有效字节在前写出;表中其余多字节校验均按最高有效字节在前。源码中这一差异体现在打包函数上——packU16BE/packU32BEpackU16LE(见 core/Core/Checksum.cpp 的checksumFunctionMap)。

两个默认值对手写或很老的项目文件很重要:当项目的sources数组整体缺失(旧版单源格式)时,帧检测方式默认Start + End Delimiter;当sources数组中的单个条目省略该键时,默认End Delimiter Only。编辑器保存的新项目总是显式写出该键,因此这两个默认值只会在手工编写或预多源时代生成的文件上出现。

每个保存的源都会同时写出短 JSON 别名(checksumdecoder)和长名(checksumAlgorithmdecoderMethod);加载时若两者都在,长名优先。短别名是遗留的、仅用于加载的兼容字段——手改项目文件时不要针对它们。

解析器语言

解析器把解码后的帧变成值数组,每个值对应一个数据集帧索引。在解析器编辑器工具栏的 Platform 下拉框选择语言:

语言配置什么最适合
Built-In不写代码。选一个模板并填写其参数表单。新项目的默认解析器。常见线格式零配置上手:定界/CSV、定宽、键值、NMEA 0183/2000、JSON、XML、YAML、MessagePack、Modbus、UBX、MAVLink、COBS/SLIP,以及批量/时间序列多帧数据。
Lua一个parse(frame)函数(推荐脚本语言)。模板覆盖不到的自定义逻辑,脚本开销最低。
JavaScript一个parse(frame)函数。偏好 JavaScript 或需要JSON.parse式手感的自定义逻辑。

Built-In 的参数表单因模板而异:例如Delimited text暴露分隔符、可选引号字符和 trim/skip-empty 开关,而Modbus frames暴露通道数、寄存器偏移和 signed-registers 开关。完整模板目录与参数见 Frame Parser Scripting。源码层面,Native(内置模板)语言用 JSON 描述符{"template": ..., "params": ...}表示解析器,参数校验在 core/Ui/ProjectEditor/Editors/FrameParserModel.cpp 的validateParams中执行。

Lua 或 JavaScript 的parse()编写见下文第 7 步;Built-In 模板不需要脚本——参数表单本身就是配置,可直接跳到第 3 步。

第 3 步:添加分组

分组组织相关数据集,并决定仪表盘上使用哪个分组级控件。

  1. 点击工具栏中的一个分组按钮(Group为普通容器;TableMulti-PlotAccelerometerGyroscopeGPS Map等为预配置控件);
  2. 在树中选中新分组进行配置;
  3. 设置Group Title(例如 "Environmental Sensors");
  4. 设置Composite Widget(分组控件类型选择器):
控件说明数据集要求
Data Grid所有值的表格视图任意数量
Bar Panel每个数据集一根告警带配色条任意数量
Multiple Plot叠加的时间序列曲线一个及以上
Accelerometer3D 加速度可视化恰好 3 个(X, Y, Z)
Gyroscope3D 姿态可视化恰好 3 个(X, Y, Z)
GPS Map地图上的地理跟踪2 或 3 个(lat, lon, 可选 alt)
3D Plot (Pro)3D 散点/轨迹恰好 3 个(X, Y, Z)
Image View (Pro)二进制图像流无(图像数据在帧内)
Canvas Widget (Pro)自定义 JavaScript 渲染画布任意数量
Web View内嵌网页任意数量
None无分组控件,数据集单独显示任意数量

第 4 步:添加数据集

数据集映射到设备输出的各个数据字段。

  1. 在树中选中一个分组;
  2. 点击工具栏Dataset(或旁边的数据集控件按钮:PlotFFT PlotGaugeLevel IndicatorCompassLED Indicator);
  3. 配置数据集属性:

General(通用)

  • Dataset Title:显示标签(例如 "Temperature");
  • Measurement Unit:测量单位后缀(例如 "deg C"、"hPa"、"%");
  • Frame Index:解析后数据数组中的 1 基位置。设备发23.5,1013,45.2时,Temperature=1、Pressure=2、Humidity=3;
  • Widget:数据集级可视化:Bar、Gauge、Compass、Meter 或 None。四种控件在仪表盘上以两页滑动视图呈现——第 0 页是模拟可视化,第 1 页是大号等宽数字读数,当前激活页按控件保存在项目文件中;
  • Minimum Value / Maximum Value:数据集的基础值域,默认均为 0。控件与 FFT 在自身 min/max 未设置时回退到该值域。

Plot Settings(绘图设置)

  • Enable Plot Widget:Yes/No 选择器(非复选框);选Yes将该数据集作为时间序列绘图。

FFT(频率分析)

  • Enable FFT Analysis:启用频域分析;
  • FFT Window Size:窗口大小(64、128、256、512、1024 等);
  • FFT Window Function:变换前施加的窗函数,用于降低频谱泄漏,同时影响 FFT 图与水瀑布图。默认Blackman-Harris。可选:Rectangular (None)、Bartlett (Triangular)、Hann、Hamming、Blackman、Blackman-Harris、Nuttall、Blackman-Nuttall、Flat Top、Welch、Bartlett-Hann、Bohman、Cosine (Sine)、Lanczos、Parzen;
  • FFT Sampling Rate (Hz, required):必须与真实数据速率一致,频率轴标注才正确;
  • Minimum Value (optional) / Maximum Value (optional):FFT 图的 Y 轴范围;留空时回退到 General 节的 Minimum Value / Maximum Value。

Waterfall(水瀑布图,Pro)

  • Enable Waterfall Plot:为该数据集显示滚动的时频图(频谱图)。复用上述 FFT 设置(窗口、采样率、范围);
  • Waterfall Y Axis:垂直轴来源。默认Time(较老的频谱向下滚动);改选其他数据集则用该数据集的值驱动 Y 轴——典型用于阶次跟踪(例如 RPM 对频率)。

LED

  • Show in LED Panel:在 LED 面板中显示该数据集;
  • LED On Threshold (required):超过该阈值 LED 点亮。仅当数据集没有告警带时显示;一旦定义了告警带,就由告警带驱动 LED 的颜色、标签和闪烁状态。

Alarm bands(告警带)

  • Alarm Bands(数据集工具栏,位于Transform旁):打开对话框,为 Bar、Gauge、Meter 和 LED 数据集定义带严重级别的彩色值域。每个带含 min/max 范围、严重级别(Info / OK / Warning / Critical)、可选的颜色覆盖与标签,以及 LED 面板的闪烁开关。为没有告警带的 LED 数据集打开对话框时,会从LED On Threshold预填一个带,使既有配置原地迁移。

Widget Settings(控件设置)

  • Minimum Value (optional) / Maximum Value (optional):Bar、Gauge、Meter 显示的值域;留空时回退到 General 节的 Minimum Value / Maximum Value。

第 5 步:添加动作(可选)

动作在仪表盘上放置按钮,向连接的设备发送命令。

  1. 点击工具栏Action
  2. 配置动作:
  • Action Title:按钮标签(例如 "Reset Device");
  • Action Icon:从内置图标集选择;
  • Send as Binary:勾选后负载以十六进制字节而非文本输入;
  • Transmit Data:要发送的字符串或十六进制字节(例如RST);
  • End-of-Line Sequence:追加行结束符:New Line(\n)、Carriage Return(\r)、CRLF(\r\n)或 None。仅在Send as Binary关闭时可编辑;若在切到二进制模式前已配置了序列,它仍会作为原始字节追加在十六进制负载之后;
  • Auto-Execute on Connect:设备连接时自动发送该命令;
  • Timer Mode
模式行为
Off仅手动点击(默认)。
Auto Start连接时定时器自动启动,按配置间隔重复发送命令。
Start on Trigger第一次点击时启动定时器,命令重复直到停止。
Toggle on Trigger每次点击切换重复定时器的开/关。
Repeat N Times每次点击按固定次数(Repeat Count)发送命令,间隔为配置的 Interval。
  • Interval (ms):重复间隔毫秒数(默认 100 ms),模式为 Off 时禁用;
  • Repeat Count:Repeat N Times 模式下的发送次数(默认 3)。

完整动作参考(含多源目标与示例)见 Actions 页面。

第 6 步:添加数据源(多设备项目)

数据源定义数据从哪里来。单设备项目有一个隐式源;多设备项目使用显式源。

  1. 点击工具栏Add Device(Pro);
  2. 配置:
    • Title:描述性标签(例如 "Arduino Uno");
    • Bus Type:Serial Port、Network Socket、Bluetooth LE,或(Pro)Audio Input、Modbus、CAN Bus、Raw USB、HID Device、Process、MQTT Subscriber;
    • Frame Detection / Delimiters:与第 2 步相同字段,每源独立配置;
    • Data Conversion / Checksum:与第 2 步相同字段,每源独立配置;
    • Connection Settings:总线特定参数(COM 口、波特率、IP 地址等)随项目保存。

每个源都有独立的 Frame Parser 标签页,用于配置每源解析脚本。

第 7 步:编写帧解析脚本(可选)

本步适用于LuaJavaScript解析器。如果你在第 2 步选了Built-In模板,参数表单就是你的解析器(无需写脚本),可直接跳过。

对不是纯 CSV、也没有 Built-In 模板覆盖的数据,写一个parse()函数把每帧变换成值数组。Serial Studio 支持 Lua(默认,推荐)与 JavaScript,语言在解析器编辑器工具栏的 Platform 下拉框选择。

  1. 在树中选中一个源(单源项目也可选 "Frame Parser" 节点);
  2. 打开 Frame Parser 视图;
  3. 在 Platform 下拉框选择脚本语言;
  4. 编写函数:

Lua(默认):

function parse(frame) -- 'frame' 是字符串(PlainText/Hex/Base64)或字节表(Binary (Direct))。 -- 返回与数据集帧索引对应的值表。 local result = {} for field in frame:gmatch("([^,]+)") do result[#result + 1] = field end return result end

JavaScript:

function parse(frame) { // 'frame' 是字符串(PlainText/Hex/Base64)或字节数组(Binary (Direct))。 // 返回与数据集帧索引对应的值数组。 return frame.split(","); }
  1. 解析器代码随输入自动存入项目。用Validate按钮检查脚本(语法检查 + 对第一个源的运行时探测,见第 7b 步),用Test With Sample Data以样例帧运行。

规则:

  • 函数必须命名为parse,且必须接受至少一个参数(帧负载)。JavaScript 会特别拒绝已废弃的双参数parse(frame, separator)形式,但声明额外的未使用参数是允许的;Lua 完全不检查参数个数;
  • 必须返回表(Lua)或数组(JavaScript),每个元素映射到一个数据集帧索引;
  • parse()外部声明的全局变量在多次调用之间持久存在,适合有状态协议;
  • console.log()(两种语言)或print()(Lua 简写)把调试消息打印到 Serial Studio 终端。完整的console表(logdebuginfowarnerror)在 JavaScript 和 Lua 中均可使用;error还会弹出应用通知,warn在设置中启用Route Warnings to Notifications时同样如此(默认关闭)。

示例:二进制协议(Lua)。

function parse(frame) -- frame 是 Binary (Direct) 模式下的字节表(1 基索引) local temp = (frame[1] << 8) | frame[2] local humidity = (frame[3] << 8) | frame[4] return {temp / 10.0, humidity / 10.0} end

第 7b 步:用 Test 对话框测试整条管线

解析器工具栏上的Test With Sample Data按钮打开Test Frame Parser对话框。它运行与实时仪表盘相同的"字节到通道"管线,因此你在这里看到的就是仪表盘对同一输入会看到的结果。(代码编辑器工具栏上的独立Validate按钮不止检查语法:它先编译脚本,再用运行时探测帧调用parse()——依次尝试"0"、单字节数组和""——以捕获只有运行时才暴露的错误。探测仅对多源项目中的第一个源执行,其余源只做语法检查。)

对话框有三个区段:

  1. Pipeline configuration(管线配置):检测模式、起始/结束定界符、hex 定界符开关、解码方法与校验和算法。它们与活动源联动:在对话框里修改会立即改写项目源,实时帧读取器也会拾取该变化,无需单独的 "Apply" 步骤;
  2. Frame data input(帧数据输入):一个输入框,输入要测试的原始流字节。勾选Hex可以空格分隔的十六进制对输入字节(01 A2 FF 3C)——这是喂二进制协议的安全方式。纯文本模式按 UTF-8 读取输入。在输入框中按Return或点击对话框底部的Evaluate运行管线并填充下方结果;
  3. Pipeline results(管线结果):统计行显示frames extracted | bytes consumed | bytes buffered | dropped。其下是一棵树,把每个提取帧展开为原始字节(hex)、解码器输出(解析器实际收到的内容),以及每个通道一个节点的解析行。

自上而下读树能精确定位失败阶段:

  • 零帧提取:定界符/检测模式与输入不匹配,复查起始/结束字段;
  • 有帧但行为空:解析器运行了但没返回数组——通常是parse()返回了nilundefined或非数组值;
  • 有行但数量不对parse()中的索引映射有误,对比行索引与各数据集的Frame Index字段;
  • 对话框中有且正确的行在仪表盘上缺失:数据集上的变换在拒绝该值(返回nil/NaN),或控件 min/max 在裁剪它。

该对话框底层对应 core/Pipeline/DataModel/Scripting/FrameParserPipeline.h 中的PipelineSpec/PipelineResult结构——PipelineResult记录了提取数、消耗字节、剩余字节与丢弃帧数,与界面统计行一一对应;runFrameParserPipeline系列函数实现"提取 + 解码 + 解析"的整条链路。

解码+检测设置如何到达解析器

第 2 步配置的检测模式、定界符和解码器在解析器之前运行。它们决定每个帧在哪里开始和结束,以及parse(frame)收到什么:Plain Text 收到QString::fromUtf8字符串,十六进制或 Base64 收到对应字符串,Binary (Direct) 收到原始字节缓冲区(Lua 中为 1 基表,JavaScript 中为带长度键的对象)。完整选项列表与 UTF-8 陷阱见第 2 步的表。

数据集值变换

每个数据集都可以选配一个transform(value)函数,把原始解析值转换为工程值,再交给仪表盘。变换适用于标定、单位换算、滤波和信号调理。

添加变换:选中数据集,点击工具栏Transform按钮,打开带语法高亮、内置模板和实时测试区的专用编辑器。

完整文档见 Dataset Value Transforms。

多源架构

当项目有多个源时,每个源代表一台独立物理设备,拥有自己的连接、总线类型、帧检测和解析器(Built-In、Lua 或 JavaScript)。

  1. 在树中每台设备添加一个源;
  2. 通过分组或数据集属性中的Input Device下拉框把分组分配给源;
  3. 在主窗口点击 "Connect" 时所有设备同时连接;
  4. 每台设备的数据独立路由到其分配的分组与数据集。

保存与加载

  • 点击Save(Ctrl+S / Cmd+S)把项目以.ssproj文件写入磁盘;
  • 之后可用Open重新打开,或设为默认项目后自动加载;
  • 关闭编辑器或打开其他文件时,Serial Studio 会提示保存未保存的更改;
  • Examples浏览器(主工具栏)打开工作项目文件作为参考。

项目文件在磁盘上被更改时

Serial Studio 监视打开的项目文件。检查比较的是文件内容而非时间戳,因此应用自身的保存不会触发它,只有外部更改才会。

  • 被其他程序修改(文本编辑器、git checkout、同步工具):弹出 "Project file changed on disk" 提示询问是否重新加载。有未保存更改时,提示会警告重新加载将丢弃这些更改。回答No保留内存中的项目并标记为已修改,下一次保存会覆盖外部编辑;
  • 被删除或重命名:发布警告通知并将项目标记为已修改。保存项目即可在原路径重建文件。

重新加载会替换内存中的项目。Restore对话框仍列出重新加载前拍摄的快照,因此误触发的重新加载可从 Backups & Recovery 撤销。

常见错误与修复

数据集索引不匹配

症状。控件显示 "0"、错误数据或无数据。

修复。检查每个数据集的帧索引是否与解析器返回数组的正确位置对应。索引 1=第一个元素、索引 2=第二个元素,依此类推。

帧解析器错误

症状。控制台显示 "undefined" 或解析错误。

修复:

  1. 检查控制台中的错误消息;
  2. 添加console.log()调用检查原始帧与解析输出;
  3. 确保函数始终返回数组,绝不返回字符串、对象或 undefined;
  4. 编辑解析器代码后使用Validate确认脚本语法与运行时均干净。

定界符不匹配

症状。检测不到帧,或数据乱码。

修复:

  1. 打开 Console 视图检查原始字节;
  2. 开启十六进制视图以发现隐藏字符,如\r\0
  3. 常用选择:\n(大多数串口设备)、\r\n(Windows 风格),或自定义标记如/**/

控件与数据类型不匹配

症状。控件出现但显示不正确。

修复:

  • Gauge、Bar、Meter 需要有界的数值。在 Widget Settings 中设置 Minimum Value / Maximum Value;
  • Accelerometer 和 Gyroscope 分组需要恰好 3 个数据集;
  • GPS Map 需要 2 或 3 个数据集(纬度、经度、可选海拔);
  • Compass 期望 0 到 360 之间的值。

分组控件缺数据集

症状。分组控件不出现在仪表盘上。

修复。确保分组的数据集数量满足其控件类型要求,参见第 3 步的表。

实用技巧

  • Duplicate(右键)快速创建相似的分组或数据集;
  • 树中数据集名称旁显示帧索引,便于快速参考;
  • 切换到 Dashboard 前先用 Console 视图测试配置;
  • 把会话记录为 CSV,再用 CSV Player 在无硬件连接的情况下迭代仪表盘布局;
  • 使用清晰的数据集标题和单位——它们直接显示在仪表盘控件上;
  • 为仪表、条形图和表头设置合适的 Minimum Value / Maximum Value,而不是依赖自动缩放。

延伸阅读

  • Widget Reference:全部控件类型的完整指南;
  • Frame Parser Scripting:Lua 与 JavaScript 解析器完整参考;
  • Dataset Value Transforms:数据集级标定、滤波与单位换算;
  • Data Flow:数据在 Serial Studio 中的流动路径;
  • Operation Modes:Console Only、Quick Plot 与 Project File 三种模式;
  • Troubleshooting:常见问题的修复。

【免费下载链接】Serial-StudioOpen-source telemetry dashboard. Supports UART, BLE, MQTT, Modbus, CAN Bus and more.项目地址: https://gitcode.com/GitHub_Trending/se/Serial-Studio

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

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

立即咨询