news 2026/9/18 22:30:53

Serial Studio 输出控件(Output Controls)完整指南:用 JavaScript 让仪表盘向设备发送命令

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Serial Studio 输出控件(Output Controls)完整指南:用 JavaScript 让仪表盘向设备发送命令

Serial Studio 输出控件(Output Controls)完整指南:用 JavaScript 让仪表盘向设备发送命令

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

本指南围绕 Serial Studio 的 Output Controls 输出控件展开:从控件类型、transmit 函数编写、协议辅助函数,到状态反馈与布局规则,完整讲解如何让遥测仪表盘不仅能“读”设备数据,还能向设备发送命令、设定值与参数。读完本文,你将掌握 Button/Slider/Toggle/Text Field/Knob 五类交互控件的配置方法,能够编写跨协议复用的transmit(value)脚本,并借助内置 Modbus、CAN Bus 辅助函数构造二进制报文。

概览:什么是输出控件

Serial Studio 的标准控件负责将传入的遥测数据可视化,而**输出控件(Output Controls)**是与之互补的交互式仪表盘组件,负责把数据发回给已连接的设备。它们传输命令、设定值和参数,使仪表盘既能从设备读取数据,也能向设备写入数据。

每个输出控件的核心是一个用户自定义的 JavaScripttransmit(value)函数,它把控件交互(点击按钮、拖动滑块、输入文本)转换为设备期望的精确字节。由于传输逻辑完全由 JavaScript 决定,输出控件是协议无关的:同一个滑块控件,只要更换transmit函数,就能驱动纯文本串口命令、JSON 载荷或二进制数据包。

注意:输出控件需要Pro 许可证。源码 core/Ui/UI/Widgets/Output/Base.cpp 中deliverValue()在评估脚本之前先检查Licensing::CommercialToken与许可证守卫,未激活时直接返回,不发送任何数据。

输出控件的工作原理

输出控件的交互流程可以概括为四步:

  1. 用户在仪表盘上操作控件(点击按钮、拖动滑块、输入文本等);
  2. 控件将交互值传给其 JavaScripttransmit(value)函数;
  3. 函数返回一个字符串(二进制载荷是使用String.fromCharCode构造的字节串);
  4. Serial Studio 将结果发送给已连接的设备。

传输过程有速率限制:连续两次发送之间至少间隔 50 ms,防止滑块拖动等连续交互时设备缓冲区溢出。这一机制在 Base.h 中以m_rateLimiter(QElapsedTimer)与m_flushTimer(QTimer)实现,见Base::sendValue():落在限速窗口内的调用不会丢弃,而是暂存为m_pendingValue,等窗口结束后以最新值发送——因此拖动滑块时快速变化的中间值会被折叠,最终停留在松开鼠标时的位置。

传输安全边界

evaluateTransmitFunction()(见 Base.cpp)在源码层面落实了文档中的三条硬性约束:

  • 返回值必须是字符串:非字符串结果按toByteArray()处理,返回普通数字数组不会发送任何数据;
  • 载荷上限 65536 字节:超过kMaxPayloadBytes的载荷会被中止(kMaxPayloadBytes = 65536);
  • 500 ms 执行超时transmit()调用超过kTransmitWatchdogMs = 500毫秒会被JsWatchdog看门狗中止(kTransmitWatchdogMs = 500)。

以上两种情况都会中止发送并在控件上闪烁红色边框,鼠标悬停可查看具体错误信息。

输出控件类型

输出控件共有五种类型,各自把不同类型的值传入transmit()

Button(按钮)

单击发送单条命令;启用Toggle Button(闩锁按钮)后可在按下/释放两种状态间切换。

属性传入transmit()的值
普通按钮1(整数)
闩锁按钮按下1/ 释放0

适用场景:复位、启动/停止、触发测量、继电器和使能线。

属性默认值说明
Button Icon(无)标题旁显示的图标
Colorize Icon用按钮颜色为图标着色
Button Color自动自定义填充色;自动时使用分组强调色
Button SizeNormalSmall、Normal、Large 或 Extra Large
Toggle Button在点击之间保持按下状态,发送1(开)/0(关)
On Label(空)闩锁时显示的标题;为空时回退到控件标签
Off Label(空)释放时显示的标题;为空时回退到控件标签

闩锁按钮在开启时以按钮颜色填充、关闭时显示为普通按钮,因此无需打开设备即可读出状态。它发送的值与 Toggle 完全相同,为一个控件编写的transmit函数可以直接用于另一个。Button Size会同时缩放按钮、图标和标题,面板打包器会为它预留成比例更大的单元格,大按钮不会被相邻控件裁剪。设置自定义Button Color时,标题会在黑色和白色之间自动切换以保证可读性。

Slider(滑块)

从可拖动滑块发送数值。

属性默认值说明
Min Value0滑块范围下限
Max Value100滑块范围上限
Step Size1离散位置之间的增量
Initial Value0起始位置

传入transmit()的值是钳制在 [Min, Max] 范围内的数字。拖动过程中持续发送,受 50 ms 速率限制。

Toggle(开关)

二值开/关开关。

属性默认值说明
Initial Value0起始状态(0 = 关,1 = 开)

打开时向transmit()传入1,关闭时传入0

Text Field(文本输入框)

接受任意文本输入并作为字符串发送。

属性传入transmit()的值
交互方式按 Enter 或点击 Send
传入值输入的字符串

适用场景:AT 命令、调试控制台、自定义查询。

Knob(旋钮)

用于连续设定值调节的旋转拨盘。数值属性与 Slider 相同(Min、Max、Step、Initial Value),但以圆形拨盘形式显示,在面板布局中属于“高控件”,会占满整个列高。

创建输出控件

在 Project Editor(工具栏扳手图标)中按以下步骤创建:

  1. 打开 Project Editor;
  2. 点击工具栏中的Add Output按钮之一(Button、Slider、Toggle、Text Field 或 Knob);
  3. 如果不存在Output Panel分组,会自动创建一个;
  4. 在树视图中选中新控件配置属性,然后点击工具栏中的Edit Code编写其 transmit 函数。

输出控件位于Output Panel分组内。你也可以先通过工具栏添加 Output Panel 分组,再向其中添加控件。每个 Output Panel 可容纳多个混合类型控件,根据可用宽度自动打包成尽可能多的列。

从源码结构看,五种控件分别对应 core/Ui/UI/Widgets/Output 目录下的Button.cppSlider.cppToggle.cppTextField.cpp,旋钮控件与滑块共用Slider的数值通道,面板布局由Panel.cpp/PanelLayout.cpp负责。

transmit 函数详解

每个输出控件都有一个 JavaScripttransmit(value)函数,决定交互如何变成设备命令。该函数在仪表盘打开时编译一次,在每次交互时执行。

编写 transmit 函数

在 Project Editor 中选中控件并点击工具栏Edit Code,transmit 函数会在独立窗口中打开:窗口头部提供模板列表、导入、校验和测试功能,代码旁有控件的实时预览,状态栏会随着输入实时报告脚本是否编译成功、是否定义了transmit(value)

无法编译或从未定义transmit(value)的脚本不会被保存:项目会保留上一个可用的版本,关闭窗口时若脚本损坏,会先询问是否放弃。

预览功能驱动真实的控件(使用其自身的范围、步长和标签),并显示脚本产生的精确字节。预览永远不会真正发送——不会有任何数据到达已连接的设备,因此即使挂着硬件,也可以安全地演练继电器或 PWM 脚本。这一安全性由 TransmitScriptEnvironment.cpp 保证:非 Live 表面会以惰性记录器(kInertBridges)替换所有有副作用的桥接(deviceWriteactionFireapiCalltableSetmqttPublish等),并安装探针(kInertProbe)验证替换确实生效后才允许编译。

函数接收单个value参数,必须返回字符串:

function transmit(value) { // value 的取值: // 1 Button 点击 // 0 或 1 Toggle 状态变化及闩锁 Button // number Slider 和 Knob // "string" TextField 输入 return "CMD " + value + "\r\n"; }

返回值必须是字符串。对于二进制协议,用String.fromCharCode(...)构造字节串(见 Binary Packet 模板);返回普通数字数组不会发送任何数据。载荷上限 65536 字节,单次transmit()调用超过 500 ms 会被看门狗终止——两种情况都会中止发送并让控件闪烁红色边框,悬停可查看错误信息。

内置模板

代码编辑器内置一组开箱即用的模板:Simple command、JSON command、Binary packet、PWM control、PID setpoint、Relay toggle、AT command、Modbus write、CAN Bus frame、G-Code command、GRBL command、NMEA sentence、SCPI command、SLCAN command 和 Default template。从模板下拉框选择一个并针对自己的设备定制即可。

这些模板的真实实现位于 app/rcc/scripts/output 目录(如simple_command.jsjson_command.jsbinary_packet.jspwm_control.jspid_setpoint.jsrelay_toggle.jsat_command.jsmodbus_write.jscanbus_frame.jsgcode_command.jsgrbl_command.jsnmea_sentence.jsscpi_command.jsslcan_command.jsdefault_template.js)。

Simple Command(简单命令)

发送带行终止符的纯文本,自动适配控件类型。

function transmit(value) { if (typeof value === "string") return value + "\r\n"; if (value === 1) return "ON\r\n"; if (value === 0) return "OFF\r\n"; return "SET " + value + "\r\n"; }
JSON Command(JSON 命令)

发送结构化 JSON 对象,适合固件解析 JSON 输入的场景。

function transmit(value) { var obj = { cmd: "set", value: value, ts: Date.now() }; return JSON.stringify(obj) + "\n"; }
Binary Packet(二进制数据包)

发送带 STX/ETX 分隔符的成帧二进制数据。

function transmit(value) { var STX = String.fromCharCode(0x02); var ETX = String.fromCharCode(0x03); var cmd = String.fromCharCode(0x01); var val = String.fromCharCode(Math.round(value) & 0xFF); // XOR checksum over cmd + value var chk = String.fromCharCode(0x01 ^ (Math.round(value) & 0xFF)); return STX + cmd + val + chk + ETX; }
PWM Control(PWM 控制)

发送占空比值(0-255),用于电机调速、LED 亮度或加热器控制。

var CHANNEL = 0; function transmit(value) { var duty = Math.round(Math.max(0, Math.min(255, value))); return "PWM " + CHANNEL + " " + duty + "\r\n"; }

注意CHANNEL声明在transmit()之外——脚本顶层变量在多次调用之间保持存在(见下文“Tips”)。

PID Setpoint(PID 设定值)

为 PID 控制器发送带 2 位小数的浮点设定值。

var SP_MIN = 0.0; var SP_MAX = 100.0; function transmit(value) { var sp = Math.max(SP_MIN, Math.min(SP_MAX, Number(value))); return "SP " + sp.toFixed(2) + "\r\n"; }
Relay Toggle(继电器切换)

为继电器或数字输出发送不同的 ON/OFF 命令。

var CHANNEL = 0; function transmit(value) { var state = value ? "ON" : "OFF"; return "RELAY " + CHANNEL + " " + state + "\r\n"; }
AT Command(AT 命令)

为调制解调器、蓝牙模块和 WiFi 模块发送 AT 风格命令。

function transmit(value) { if (typeof value === "string" && value.length > 0) return "AT+" + value + "\r\n"; return "AT\r\n"; }
Modbus Register Write(Modbus 寄存器写入)

使用内置辅助函数将滑块值直接写入 Modbus 保持寄存器。

function transmit(value) { return modbusWriteRegister(0x0001, value); }
CAN Bus Frame(CAN 总线帧)

使用内置辅助函数将数值作为 CAN 帧发送。

function transmit(value) { return canSendValue(0x100, value, 2); }

从文件导入

点击 transmit 函数窗口头部的Import可从磁盘加载.js文件,便于跨项目共享 transmit 函数或单独进行版本控制。

状态反馈(State Feedback)

默认情况下,输出控件显示的是你最后一次设置的状态。但设备可能自行变化:联锁跳闸、有人使用本地面板、命令被拒绝。此时控件仍显示你最后一次点击的结果,向操作员传达的是与机器实际状态不符的信息。

将控件绑定到**状态源(state source)**后,控件显示的是设备报告的状态。在 Project Editor 中选中控件,将State Source设置为某个数据集或表格变量,然后选择具体的数据源。

负载组(load bank)是一个典型场景:停止负载组也会停止其冷却风扇,因为二者在设备侧(而非 Serial Studio 中)互锁。将风扇控件绑定到携带风扇状态的数据集,负载组一旦停机,风扇控件立即不再声称风扇在运行。

On Value(判定为“开”的值)

对于 Toggle 或闩锁按钮,On Value决定哪些读数表示“开”。

留空时,任何非零数字都表示“开”。这适用于数据集报告10的情况;但报告文本(如RUNSTOP)的设备不携带数字,此时即使设备正在运行也会被读作“关”——填入RUN后控件会精确匹配它,并自动以文本或数字方式进行比较。

更复杂的情况(状态字中的某个位、阈值、滞回)应交给数据集自身的变换(transform)处理,这正是它的用途。在那里产生干净的01,然后让On Value保持为空。

等待与无数据(Waiting and No Data)

绑定后的控件显示三种状态而非两种:

  • live(实时):数据源正在报告,控件显示其报告的内容;
  • waiting…(等待中):你操作了但设备尚未确认。Confirm Within (ms)决定这个窗口持续多久——接触器可能在不到一秒内闭合,而风扇需要数秒。在此窗口内控件持续显示你请求的内容,反馈不会覆盖它;
  • no data(无数据):数据源未报告或已静默。控件变暗并明确提示,因为把“我们没听到”显示成“关”正是该功能要消除的失败。

反馈永远不会发送:反映设备状态不是操作员动作,因此绑定控件不可能在循环中命令自身。拖动已绑定的滑块也永远不会被打断:反馈被暂时挂起,直到你松开为止。

从源码看,状态判定逻辑位于 StateBinding.cpp,Base::refreshState()每个显示周期都会重新计算判定(Verdict),因为“等待确认”窗口是按时钟而非按采样到达与否推进的——设备在命令后静默,也必须停止显示“waiting”。observeState()是外部值进入控件的唯一通道,且刻意不接触发送目标,从机制上杜绝了命令自身的环路(见 Base.cpp 的注释,对应 spec 0080 R3)。

如果你删除了控件绑定的数据集或变量,项目仍能加载、控件仍能工作——只是不再自我校正,并且 Problems 列表会报告该问题。

协议辅助函数

每个输出控件的 JavaScript 引擎都内置了 Modbus 和 CAN Bus 协议辅助函数(app/rcc/api/prelude.js)。它们处理二进制字节打包,无需手动构造原始字节。

Modbus 辅助函数

所有 Modbus 辅助函数都接受一个可选的尾随unit参数(1 到 247)。给出该参数时,载荷会以前缀0xFF 0x83 <unit>开头,Modbus 驱动将写入该设备而非连接自身的 unit——这正是控件指挥共享 RS-485 总线上第二个设备的方式(见__ssModbusUnit的实现:prelude.js,越界 unit 会被忽略并回退到连接自身 unit)。由于辅助函数返回字节串,请将控件的传输编码设置为Latin-1,避免 127 以上的字节被重新编码。

modbusWriteRegister(address, value, unit)

将 16 位整数写入单个保持寄存器。

参数类型说明
addressNumber寄存器地址(0x0000–0xFFFF)
valueNumber要写入的值(取整为整数,0–65535)
function transmit(value) { return modbusWriteRegister(0x0001, value); }

实现上,该函数将地址和值各截断为 16 位并大端打包为 4 字节[addr_hi, addr_lo, value_hi, value_lo]

modbusWriteCoil(address, on, unit)

按 ON/OFF 约定(ON = 0xFF00,OFF = 0x0000)写入保持寄存器。此辅助函数目前是modbusWriteRegister()的别名:它打包相同的 4 字节保持寄存器写入,并不发出原生 Modbus 线圈写入(功能码 5/15)——驱动始终以保持寄存器为目标(功能码 6/16)。当下游 PLC 程序将该保持寄存器映射到物理继电器或线圈时使用它;它无法用于期望真正线圈写入的设备。

参数类型说明
addressNumber保持寄存器地址(0x0000–0xFFFF)
onBoolean/Number真值 = ON,假值 = OFF
// Toggle 控件向 PLC 映射到继电器的保持寄存器写入 ON/OFF function transmit(value) { return modbusWriteCoil(0x0000, value); }

其源码实现即modbusWriteRegister(address, on ? 0xFF00 : 0x0000, unit)(见 prelude.js)。

modbusWriteFloat(address, value, unit)

跨两个连续的保持寄存器(大端)写入 IEEE-754 32 位浮点数。

参数类型说明
addressNumber起始寄存器地址
valueNumber浮点数值
// 滑块以 32 位浮点数写入温度设定值 function transmit(value) { return modbusWriteFloat(0x0010, value); }

实现使用DataView.setFloat32(0, value, false)得到大端字节序,再拼接寄存器地址后输出 6 字节载荷。

此外,prelude.js 还提供了modbusWriteRegisters(address, values, unit),用于将一组 16 位值写入连续多个寄存器。

CAN Bus 辅助函数

canSendFrame(id, payload)

发送具有指定标识符和载荷的任意 CAN 帧。

参数类型说明
idNumberCAN 标识符
payloadArray 或 String载荷字节(0–255 的数字数组)或原始字符串
// Button 发送固定命令帧 function transmit(value) { return canSendFrame(0x200, [0x01, 0x00, 0xFF]); }
// Slider 将值打包进 3 字节载荷 function transmit(value) { var v = Math.round(value); return canSendFrame(0x100, [0x01, (v >> 8) & 0xFF, v & 0xFF]); }

从实现看,id > 0x7FF时按扩展帧(29 位,加 EFF 标志位)打包,否则按标准帧(11 位)打包,并自动附带 DLC 长度字节(见 prelude.js)。

canSendValue(id, value, bytes)

将数值按大端序打包进 CAN 帧。

参数类型默认值说明
idNumber必填CAN 标识符
valueNumber必填数值(取整为整数)
bytesNumber2载荷字节数(1–8)
// Slider 在 CAN ID 0x100 上发送 16 位值 function transmit(value) { return canSendValue(0x100, value, 2); }
// Knob 在 CAN ID 0x300 上发送 32 位值 function transmit(value) { return canSendValue(0x300, value, 4); }

组合辅助函数与自定义逻辑

辅助函数返回字符串,因此可以拼接或按条件选择:

// 根据开关状态写入不同寄存器 function transmit(value) { if (value) return modbusWriteRegister(0x0010, 1); // Enable else return modbusWriteRegister(0x0010, 0); // Disable }
// 发送带头部字节和控件值的 CAN 帧 function transmit(value) { return canSendFrame(0x150, [0xAA, Math.round(value) & 0xFF]); }

Output Panel 布局

输出控件显示在仪表盘的 Output Panel 控件中,面板使用自适应布局引擎:

  • 控件根据可用宽度自动打包成尽可能多的列,列数由每个控件的最小宽度推导;
  • 小控件(Button、Slider、Toggle、TextField)在列内垂直堆叠;
  • 高控件(Knob)占满整个列高;
  • 控件超出可见区域时,面板垂直滚动。

相关实现见 Panel.cpp 与 PanelLayout.cpp。

多数据源项目

在具有多个数据源(设备)的项目中,目标设备由控件所属Output Panel 分组的数据源决定,而非某个控件属性。组内每个控件都发送到该组的数据源。要发送到不同设备,请将控件放入分配给该数据源的 Output Panel 分组。

从源码看,每个控件通过sourceId与目标绑定(Base.h 中的Q_PROPERTY(int sourceId)),该值来自DataModel::OutputWidget::sourceId,即所属分组对应的设备源。

输出控件与 Actions 的对比

输出控件和 Actions 都能向已连接设备发送数据,但用途不同:

特性输出控件Actions
控件类型5 种(按钮、滑块、开关、文本框、旋钮)仅按钮
数据格式化JavaScripttransmit()函数固定 TX Data + EOL
连续值支持(滑块、旋钮)不支持
定时器/自动重复不支持支持(5 种定时模式)
连接时自动执行不支持支持
许可证Pro免费

使用 Actions的场景:简单的 fire-and-forget 命令、周期性轮询、连接时自动执行序列。使用输出控件的场景:需要带连续值的交互式控件、自定义数据格式化,或混合控件类型。

实战示例

电机速度控制器

用滑块控制电机速度,加一个急停按钮。

控件类型属性
SpeedSliderMin: 0, Max: 100, Units: "%"
Emergency StopButton

速度 transmit 函数:

function transmit(value) { return "SPD " + Math.round(value) + "\r\n"; }

急停 transmit 函数:

function transmit(value) { return "ESTOP\r\n"; }

继电器控制面板

独立切换 3 个继电器。

控件类型属性
Relay 1ToggleON: "Closed", OFF: "Open"
Relay 2ToggleON: "Closed", OFF: "Open"
Relay 3ToggleON: "Closed", OFF: "Open"

每个继电器使用带各自继电器编号的定制 transmit 函数:

// Relay 1 function transmit(value) { return value ? "R1 ON\r\n" : "R1 OFF\r\n"; }

传感器校准界面

组合文本字段(命令)与旋钮(微调)。

控件类型属性
CommandTextField
OffsetKnobMin: -10, Max: 10, Step: 0.1, Units: "mV"

命令 transmit 函数:

function transmit(value) { return "CAL " + value + "\r\n"; }

偏移 transmit 函数:

function transmit(value) { return "OFFSET " + Number(value).toFixed(1) + "\r\n"; }

Modbus PID 控制器

通过 Modbus 控制 PID 回路:向保持寄存器写入设定值、Kp 和使能/禁用。

控件类型属性
SetpointSliderMin: 0, Max: 500, Step: 0.5, Units: "°C"
Kp GainKnobMin: 0, Max: 10, Step: 0.01
EnableToggleON: "Running", OFF: "Stopped"

设定值 transmit 函数(32 位浮点写入寄存器 0x0010–0x0011):

function transmit(value) { return modbusWriteFloat(0x0010, value); }

Kp Gain transmit 函数(32 位浮点写入寄存器 0x0012–0x0013):

function transmit(value) { return modbusWriteFloat(0x0012, value); }

Enable transmit 函数(通过modbusWriteCoil别名写入保持寄存器 0x0000,下游映射到继电器):

function transmit(value) { return modbusWriteCoil(0x0000, value); }

CAN 总线电机控制器

通过 CAN Bus 控制电机:速度设定值与急停。

控件类型属性
SpeedSliderMin: 0, Max: 10000, Units: "RPM"
DirectionToggleON: "Forward", OFF: "Reverse"
E-StopButton

速度 transmit 函数(CAN ID 0x100 上的 16 位值):

function transmit(value) { return canSendValue(0x100, value, 2); }

方向 transmit 函数(CAN ID 0x101 上的单字节):

function transmit(value) { return canSendFrame(0x101, [value ? 0x01 : 0x00]); }

急停 transmit 函数(CAN ID 0x1FF 上的固定命令帧):

function transmit(value) { return canSendFrame(0x1FF, [0xFF, 0x00]); }

常见错误排查

控件未出现在仪表盘上

症状:输出控件已在 Project Editor 中配置,但仪表盘上不显示。

修复:确保设备已连接——Output Panel 仅在连接激活时显示在仪表盘上。同时确认控件位于 Output Panel 分组内(分组类型必须为 "Output")。

设备收不到命令

症状:控件可见且可交互,但设备无响应。

修复

  1. 检查Console视图确认数据确实在发送;
  2. 验证 transmit 函数返回了正确终止的字符串(多数设备期望\r\n);
  3. 在多数据源项目中,确认控件位于分配给正确设备的 Output Panel 分组内;
  4. 检查 Pro 许可证是否激活——未激活时传输被禁用。

滑块发送太多命令

症状:拖动滑块时设备过载或串口缓冲区溢出。

修复:内置的 50 ms 速率限制能阻止大多数刷屏,但如果设备需要更长的命令间隔,可以增大步长以减少离散值数量,或在 transmit 函数中加入去抖逻辑。

transmit 函数错误

症状:控件显示红色文本 "No transmit function defined" 而非控件本身。

修复:打开 Project Editor 检查 transmit 函数语法错误。函数必须是名为transmit的有效 JavaScript 函数,接受一个参数并返回字符串。字段为空时也会显示此标签。transmit 期间的运行时错误(看门狗超时、脚本异常或载荷过大)会让控件闪烁红色边框数秒,悬停可读取错误信息。

实用技巧

  • 从内置模板开始修改,避免常见语法错误;
  • 打开 Console 视图测试,观察实际发送的字节;
  • 在同一仪表盘上组合输出控件与输入控件,实现完整的闭环监控(例如用滑块设定目标温度,同时用仪表显示实际温度);
  • 优先使用内置协议辅助函数(modbusWriteRegistercanSendFrame等)而非手工打包二进制字节;
  • 对于超出内置辅助函数的协议,在脚本中transmit()旁边定义自己的辅助函数。在transmit()外部声明的变量在多次调用之间持续存在(如 PWM 模板中的CHANNEL)。

相关文档

  • SDK Reference:transmit()返回的协议编码器(modbusWriteRegistercanSendFrame等)及更广泛的脚本接口;
  • Actions:带定时器支持的简单命令按钮;
  • Project Editor:创建和配置项目的完整指南;
  • Toolbar & Button Reference:Project Editor 的添加控件按钮及应用其余界面元素;
  • Widget Reference:所有输入与可视化控件类型;
  • Frame Parser Scripting:Lua 和 JavaScript 解析器参考;
  • Data Sources:配置设备连接。

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

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

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

HMC5883L在STM32F4上的可靠驱动与高精度磁力计校准

1. 为什么HMC5883L在STM32F4上跑不稳&#xff1f;——从“能通信”到“测得准”的真实断层你手里的STM32F4开发板接上了HMC5883L磁力计&#xff0c;I2C扫描能识别0x1E地址&#xff0c;读寄存器也返回了非零值&#xff0c;串口打印出的原始X/Y/Z数据跳变剧烈、方向感混乱&#x…

作者头像 李华
网站建设 2026/9/18 22:26:35

PS2022扩展面板未经正确签署:CEP签名与PlayerDebugMode修复

PS2022装上扩展面板&#xff0c;满怀期待点开&#xff0c;结果面板区域甩出一句"未经正确签署"&#xff0c;旁边那个扩展图标灰着点不动&#xff0c;连配置按钮都是死的——这个场景我在同行群里见过太多次&#xff0c;也帮人远程排查过好几轮。很多人第一反应是&quo…

作者头像 李华
网站建设 2026/9/18 22:25:51

电视盒子刷机装Armbian系统:免费完整指南

电视盒子刷机装Armbian系统&#xff1a;免费完整指南 【免费下载链接】amlogic-s9xxx-armbian Supports running Armbian on Amlogic, Allwinner, and Rockchip devices. Support a311d, s922x, s905x3, s905x2, s912, s905d, s905x, s905w, s905, s905l, rk3588, rk3568, rk33…

作者头像 李华
网站建设 2026/9/18 22:24:58

AD智能路由不切换?健康检查与会话保持排错指南

简介&#xff1a;一份面向网络运维工程师的深信服AD智能路由排错指导PPT&#xff0c;以故障现象为线索&#xff0c;覆盖智能路由不生效、出站链路负载不均、DNS解析异常及DNS代理失效等场景&#xff0c;系统梳理从配置检查、链路状态确认到路由测试的完整排查路径。资源包共1个…

作者头像 李华
网站建设 2026/9/18 22:23:26

res-downloader:视频号、抖音、小红书资源下载器

res-downloader&#xff1a;视频号、抖音、小红书资源下载器 【免费下载链接】res-downloader 视频号、小程序、抖音、快手、小红书、直播流、m3u8、酷狗、QQ音乐等常见网络资源下载! 项目地址: https://gitcode.com/GitHub_Trending/re/res-downloader res-downloader …

作者头像 李华
网站建设 2026/9/18 22:22:01

Matlab实现FLASH序列二维布洛赫模拟:从RF激发到径向k空间采集

做MRI序列仿真的人&#xff0c;搜索“FLASH Matlab”时大概率会翻车。搜出来前几页全是nand flash、spi flash、flash download failed之类的嵌入式内容&#xff0c;很难找到真正想找的MRI里的FLASH序列。这个项目标题里的FLASH&#xff0c;是Fast Low Angle Shot的缩写&#x…

作者头像 李华