恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
Serial Studio 插件开发实战:从 info.json 到 gRPC/TCP 双通道外部程序扩展
首页
资讯中心
/
Serial Studio 插件开发实战:从 info.json 到 gRPC/TCP 双通道外部程序扩展
Serial Studio 插件开发实战:从 info.json 到 gRPC/TCP 双通道外部程序扩展
发布时间:2026/9/18 10:26:33
Serial Studio 插件开发实战从 info.json 到 gRPC/TCP 双通道外部程序扩展【免费下载链接】Serial-StudioOpen-source telemetry dashboard. Supports UART, BLE, MQTT, Modbus, CAN Bus and more.项目地址: https://gitcode.com/GitHub_Trending/se/Serial-StudioSerial Studio 的插件体系允许你用任意语言Python、C、Go、Rust、Node.js 等编写独立的外部进程通过 gRPC端口 8888或 TCP/JSON端口 7777连接其 API 服务器实时接收遥测数据、执行自定义可视化、推送数据到外部系统或反向控制硬件。本文以 Plugin-Development.md 为骨架结合仓库中的.proto服务定义、扩展管理器实现与示例代码完整讲解插件从元数据声明、双通道连接、状态持久化到打包分发的全流程让你能独立产出一个可安装、可运行、可跨平台的 Serial Studio 插件。插件能做什么插件是运行在 Serial Studio 之外的独立程序与主应用并行存在通过网络通信协作。典型的应用场景包括自定义可视化3D 渲染、地图叠加、专用图表等内置控件无法覆盖的展示形式数据处理实时过滤、FFT 频谱分析、异常检测数据推送把实时数据写入数据库、云服务或其他外部系统自动化测试自动执行连接 → 配置 → 校验 → 报告的测试序列硬件闭环控制根据接收到的数据反向向设备发送控制命令。插件通过 Extension Manager 分发与安装与主题、帧解析器、项目模板、QML 控件等扩展类型并列后者的开发方式参见 Widget Extension Development。工作原理进程模型与运行生命周期插件与 Serial Studio 之间的数据流如下图所示一次完整的插件运行周期为用户通过 Extension Manager 安装插件用户在插件卡片上点击RunSerial Studio 确保 API 服务器已启动必要时会提示用户启用随后启动插件进程插件连接 Serial Studio开始发送命令或持续接收数据流用户点击Stop或 Serial Studio 退出终止插件。从源码看插件的启动由扩展管理器统一调度core/Ui/Misc/ExtensionManager.cpp 中的launchPlugin()负责根据插件的entry、runtime与platforms解析出可执行命令并拉起进程当 Serial Studio 退出时所有仍在运行的插件会被自动停止。快速开始两个最小插件最小 Python 插件TCP/JSON创建一个文件夹内含两个文件即可。info.json{ id: my-first-plugin, type: plugin, title: My First Plugin, description: Prints connection status every second., author: Your Name, version: 1.0.0, entry: plugin.py, runtime: python3, terminal: true, files: [info.json, plugin.py] }plugin.pyimport socket import json import time def send_command(sock, command, paramsNone): msg {type: command, id: 1, command: command} if params: msg[params] params sock.sendall((json.dumps(msg) \n).encode()) return json.loads(sock.recv(4096).decode()) def main(): sock socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((127.0.0.1, 7777)) while True: result send_command(sock, io.getStatus) print(fConnected: {result.get(result, {}).get(isConnected)}) time.sleep(1) if __name__ __main__: main()注意当设备正在传输数据时服务器会在同一个 socket上额外推送帧批次{frames: [...]}、原始数据与生命周期事件。因此生产级插件应逐行读取 socket并且只把type: response的行当作命令响应按id字段与请求对应详见 API-Reference.md#server-push-messages。最小 Python 插件gRPC需要实时、高吞吐的帧流时改用 gRPCinfo.json{ id: my-grpc-plugin, type: plugin, title: My gRPC Plugin, description: Streams frames via gRPC., author: Your Name, version: 1.0.0, entry: plugin.py, runtime: python3, grpc: true, files: [ info.json, plugin.py, serialstudio_pb2.py, serialstudio_pb2_grpc.py ] }plugin.pyimport grpc import serialstudio_pb2 as pb import serialstudio_pb2_grpc as rpc def main(): channel grpc.insecure_channel(localhost:8888) stub rpc.SerialStudioAPIStub(channel) print(Streaming frames...) for batch in stub.StreamFrames(pb.StreamRequest()): for frame in batch.frames: print(frame.frame) if __name__ __main__: main()serialstudio_pb2.py与serialstudio_pb2_grpc.py需要根据.proto文件生成服务定义位于仓库 doc/grpc/serialstudio.proto生成步骤参见 gRPC Server 指南。设置grpc: true后Serial Studio 会在启动插件前确保 gRPC 服务器已就绪。插件结构一个插件在仓库内拥有独立文件夹plugin/my-plugin/ info.json # Required: metadata and entry point plugin.py # Entry point script requirements.txt # Optional: Python dependencies run.sh # Optional: launcher for macOS/Linux run.cmd # Optional: launcher for Windows serialstudio_pb2.py # Optional: gRPC stubs serialstudio_pb2_grpc.py # Optional: gRPC stubs启动脚本Launcher Scriptsrun.sh/run.cmd通常用于自动安装依赖例如在本地 venv 中通过 pip 安装grpcio设置环境变量在不指定 runtime 的情况下直接运行原生二进制。示例run.sh#!/bin/bash SCRIPT_DIR$(cd $(dirname $0) pwd) cd $SCRIPT_DIR # Create venv and install deps if needed if [ ! -d venv ]; then echo Setting up virtual environment... python3 -m venv venv echo Installing required packages (this may take a moment)... ./venv/bin/pip install -r requirements.txt echo Setup complete. fi ./venv/bin/python plugin.py示例run.cmdecho off setlocal set SCRIPT_DIR%~dp0 cd /d %SCRIPT_DIR% if not exist venv ( echo Setting up virtual environment... python -m venv venv echo Installing required packages (this may take a moment)... venv\Scripts\pip install -r requirements.txt echo Setup complete. ) venv\Scripts\python plugin.py使用启动脚本时info.json中的runtime应设为脚本本身就是可执行体。info.json 字段参考字段必填说明id是唯一标识小写、连字符在所有扩展中必须唯一type是必须为plugintitle是Extension Manager 中显示的名称description是卡片上显示的短描述author是作者名或组织名version是语义化版本号如1.0.0license否许可证标识如MIT、GPL-3.0category否Extension Manager 中用于过滤的分类screenshot否预览图的相对路径files是需要下载/安装的相对文件路径数组必须包含info.json本身entry是脚本或二进制入口如plugin.py、run.shruntime否缺省为python3解释器命令如python3原生二进制或启动脚本用空字符串terminal否true表示在系统终端窗口中启动默认falsegrpc否true表示插件使用 gRPC端口 8888Serial Studio 会在启动前确保 gRPC 服务器已运行默认falseplatforms否按平台覆盖的配置见平台特定构建dependencies否{name, executables, url, pip}数组。Serial Studio 会在启动前逐一检查executables是否存在于PATH中缺失时弹出带url链接的 Missing Dependency 对话框含pip键的条目跳过该检查改为在启动时触发 installing packages 的 venv 提示icon否图片相对路径显示在 Extension Manager 已安装插件列表中完整示例{ id: signal-analyzer, type: plugin, title: Signal Analyzer, description: Real-time FFT and spectral analysis of incoming data., author: Example Corp, version: 2.1.0, license: MIT, category: Analysis, screenshot: screenshot.png, entry: plugin.py, runtime: python3, terminal: false, grpc: true, files: [ info.json, plugin.py, analyzer.py, serialstudio_pb2.py, serialstudio_pb2_grpc.py, requirements.txt, screenshot.png ], platforms: { darwin/*: { entry: run.sh, runtime: , files: [run.sh] }, linux/*: { entry: run.sh, runtime: , files: [run.sh] }, windows/*: { entry: run.cmd, runtime: , files: [run.cmd] } } }连接 Serial StudiogRPC 与 TCP/JSON方案一gRPC实时数据推荐需要高频帧流时使用 gRPC并在info.json中设置grpc: trueimport grpc import serialstudio_pb2 as pb import serialstudio_pb2_grpc as rpc channel grpc.insecure_channel(localhost:8888) stub rpc.SerialStudioAPIStub(channel) # Execute any API command resp stub.ExecuteCommand(pb.CommandRequest( id1, commandio.getStatus)) # Stream frames (each item is a FrameBatch) for batch in stub.StreamFrames(pb.StreamRequest()): for frame in batch.frames: process(frame.frame)服务定义在 doc/grpc/serialstudio.proto其中SerialStudioAPI服务共提供六个 RPCExecuteCommand、ExecuteBatch批量执行、StreamFrames服务端流式返回FrameBatch每帧含timestamp_ms与google.protobuf.Struct形式的解析数据、StreamRawData流式返回设备原始字节、WriteRawData向设备写原始数据以及ListCommands枚举所有可用命令及其输入 schema。命令参数使用google.protobuf.Struct动态承载与 TCP/JSON 端口 7777 的命令语义保持一致。方案二TCP/JSON更简单的配置当没有 gRPC 工具链或只需简单的命令-响应模式时使用import socket import json sock socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((127.0.0.1, 7777)) msg json.dumps({ type: command, id: 1, command: io.getStatus }) \n sock.sendall(msg.encode()) response json.loads(sock.recv(4096).decode())完整的命令列表与协议规范参见 API Reference。平台特定构建插件可以为不同操作系统与 CPU 架构提供不同入口通过info.json的platforms字段实现platforms: { darwin/*: { entry: run.sh, runtime: , files: [run.sh] }, linux/x86_64: { entry: run.sh, runtime: , files: [run.sh, bin/analyzer-linux-x64] }, linux/arm64: { entry: run.sh, runtime: , files: [run.sh, bin/analyzer-linux-arm64] }, windows/*: { entry: run.cmd, runtime: , files: [run.cmd, bin/analyzer.exe] } }平台键采用os/arch或os/*格式*表示通用构建键匹配平台darwin/*macOS任意架构darwin/arm64仅 macOS Apple Siliconlinux/x86_64Linux x86_64linux/arm64Linux ARM64树莓派等windows/*Windows任意架构windows/x86_64仅 Windows x86_64*任意平台通用兜底解析顺序为先精确匹配os/arch键再匹配os/*最后匹配*。此外需注意三点行为约定平台特定的files在安装时会与基础files数组合并若插件没有匹配当前平台的条目Install按钮会被禁用并显示Unavailable徽章若不存在platforms字段则默认插件适用于所有平台。状态持久化插件状态窗口位置、设置、配置会随项目文件保存与控件布局数据存储在一起因此不同项目可以有不同的插件配置。何时保存状态Serial Studio从不主动调用extensions.saveState——必须由插件自行调用典型时机包括设备断开连接时插件退出前任何值得在日后恢复的变更之后。何时恢复状态插件通过extensions.loadState恢复状态典型时机包括插件启动时读取当前打开项目的状态新设备连接时项目可能已变化。通过 API 保存/恢复状态# Save state send_command(sock, extensions.saveState, { pluginId: my-plugin, state: {windowX: 100, windowY: 200, zoom: 1.5} }) # Load state result send_command(sock, extensions.loadState, { pluginId: my-plugin }) state result.get(result, {}).get(state, {})自动重启Serial Studio 关闭时仍在运行的插件会被记录并在下次设备连接仪表盘可用时自动重新启动。生命周期事件API 服务器会以独立 JSON 行的形式向所有已连接的 TCP/JSON 客户端广播事件。注意gRPC 客户端不会收到生命周期事件如需同步状态应轮询io.getStatus或观察流活动。事件时机典型插件动作{event: connected}设备连接开始处理、恢复状态{event: disconnected}设备断开保存状态、暂停处理# TCP/JSON: listen for events on the socket import json while True: data sock.recv(4096).decode() for line in data.strip().split(\n): msg json.loads(line) if msg.get(event) connected: on_device_connected() elif msg.get(event) disconnected: on_device_disconnected()Extension Manager API插件还可以编程方式与 Extension Manager 交互。下表命令在仓库的 core/Ui/ApiHandlers/ExtensionHandler.cpp 中完成注册其中仓库管理类命令仅在BUILD_COMMERCIAL编译分支下启用与文档中Pro only的标注一致命令说明extensions.list列出所有可用扩展返回count与addons数组extensions.getInfo按extensionId获取扩展详情附加installed、updateAvailable、installedVersion字段extensions.install按addonIndex安装扩展extensions.uninstall按addonIndex卸载扩展破坏性操作不可逆地删除扩展文件传dryRun:true可先预览将要删除的内容而不实际提交extensions.refresh从所有仓库刷新目录extensions.saveState将插件状态保存到项目pluginId、stateextensions.loadState从项目加载插件状态pluginIdextensions.listRepositories列出仓库 URLPro onlyextensions.addRepository添加仓库 URLPro onlyextensions.removeRepository按索引移除仓库Pro only从实现上看extensions.install会校验addonIndex参数小于 0 时返回INVALID_PARAMS错误然后设置所选索引并触发安装extensions.getInfo找不到扩展时返回NOT_FOUND错误。这些错误码与参数 schema 可由ListCommands/grpcurl直接查询便于在开发期核对调用签名。测试你的插件手动测试创建包含info.json与插件文件的文件夹让 Extension Manager 指向本地仓库Pro或手动把文件复制到~/Documents/Serial Studio/Extensions/plugin/your-plugin/完成安装在 Extension Manager 详情视图中点击Run在日志面板中查看输出与错误。独立测试 API 连接在编写完整插件之前可以先独立验证 API 连通性# Test TCP/JSON echo {type:command,id:1,command:io.getStatus} | nc localhost 7777 # Test gRPC grpcurl -plaintext localhost:8888 serialstudio.SerialStudioAPI/ListCommandsio.getStatus命令由 core/Api/API/Handlers/IOManagerHandler.cpp 提供是验证连接状态的最常用命令之一。常见问题问题原因解决办法Connection refusedAPI 服务器未启用在 Preferences → General → API Plugins → Enable API Server端口 7777中启用grpcio导入错误包未安装pip install grpcio grpcio-tools插件立即退出未捕获异常设置terminal: true以便查看错误无帧流设备未连接先连接设备打包与分发仓库结构my-extensions-repo/ manifest.json plugin/my-plugin/ info.json plugin.py run.sh run.cmd requirements.txt screenshot.pngmanifest.json{ version: 1, repository: My Extensions, extensions: [ plugin/my-plugin/info.json ] }托管方式除了随 Serial Studio 捆绑的默认社区仓库外添加任何自定义仓库都需要安装方持有 Serial Studio ProRepository Settings 与extensions.addRepository命令均为 Pro 功能GitHub推送到仓库并分享 manifest 的 raw URL本地文件夹开发期可在 Repository Settings 中用Browse指向包含manifest.json的本地文件夹任意 Web 服务器通过 HTTP(S) 托管文件files中的相对路径会基于info.json的 URL 解析。安装路径安装后的插件存放在~/Documents/Serial Studio/Extensions/plugin/your-plugin/关于扩展的浏览、安装、更新、卸载与仓库管理界面操作可进一步阅读 Extensions 文档若想深入了解 gRPC 服务的完整定义与 stub 生成方式可直接阅读仓库内的 doc/grpc/serialstudio.proto 与 gRPC Server 指南。对照以上步骤从最小 TCP/JSON 插件起步再按需切换到 gRPC 帧流、加入平台化启动脚本与状态持久化即可构建一个完整的、可分发到社区的 Serial Studio 插件。【免费下载链接】Serial-StudioOpen-source telemetry dashboard. Supports UART, BLE, MQTT, Modbus, CAN Bus and more.项目地址: https://gitcode.com/GitHub_Trending/se/Serial-Studio创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考