自用串口工具分享
粘土,一个面向嵌入式调试的串口工具,支持多串口同时连接、自定义常用命令、
自动高亮匹配行、条件触发任务,以及跨端口联动(在 A 口检测到指定字符串时,
向 B 口发送预置命令)。命令模板和匹配规则支持正则表达式与参数化,并可接入
大模型,用自然语言生成配置。
主界面:每个串口一个页签,底部选择端口/波特率连接,中部为快捷命令按钮栏。
深色主题(工具栏 🌙 按钮切换)。
✨ 功能特性
- 多串口并行:每个串口一个标签页,独立连接/收发/显示,互不干扰。
- 高亮显示:按正则匹配整行着色(前景/背景/粗体/斜体),规则按顺序生效。
- 条件触发:收到匹配行后,可用表达式过滤(如
m1 > target_temp),再执行动作。 - 跨端口联动:A 口匹配 → 向 B 口发送渲染后的命令(核心特性)。
- 参数化命令:模板支持正则捕获组
${match.1}、内置变量${timestamp}/${date}/${time}/${port}、
用户变量${var_name},以及字符串处理管道:|upper |lower |hex |unhex |replace(a,b) |substr(0,4) |trim |pad(8,0),可链式。 - 大模型助手:OpenAI 兼容接口(智谱 GLM / OpenAI / DeepSeek / 本地 Ollama 等),
自然语言描述需求 → 生成 YAML 配置 → 预览确认后合并保存。 - 配置持久化:所有端口、规则、变量、命令、LLM 设置存于
config/config.yaml。 - 快捷命令栏:每个端口标签页底部显示指向该端口的常用命令按钮。
🚀 快速开始
1. 安装依赖
⚠️ 本机
python指向 Windows Store 桩,请使用pylauncher。
py-mpipinstall-rrequirements.txt依赖:PySide6、pyserial、PyYAML、openai
2. 启动
py main.py首次启动会加载config/default_config.yaml(含示例:两个端口、若干高亮/触发规则)。
界面修改后会自动写入config/config.yaml。
3. 配置大模型
首次使用 LLM 助手前,确认⚙ 配置 → 大模型配置的连接参数。
📖 使用说明
设备管理(页签)
每个设备对应主窗口中的一个页签,工具栏左侧的➕ 新增设备可添加。页签支持完整的增删改与排序,所有改动自动写入config/config.yaml。
新增设备
点工具栏➕ 新增设备,会生成一个不重名的设备(新设备、新设备2…),默认参数为:第一个可用 COM 口、115200 / 8 / N / 1。新建后该页签自动被选中,可直接:
- 在页签顶部的下拉框里改端口 / 波特率,点连接;
- 点波特率右侧的箭头展开数据位 / 校验 / 停止位(默认折叠),修改后 tooltip 会显示当前帧格式预览(如
8N1)。
下拉框中修改的连接参数会立即保存;若设备已连接,则保持当前连接,新参数在下次连接时生效。
复制设备
右键设备页签 →复制设备→ 输入新名字(默认「源名_副本」)。复制时会一并带走:
- 连接参数(COM 口、波特率、数据位、校验、停止位);
- 该设备在高亮 / 触发规则上的每设备启用状态;
- 快捷命令:原本指向源设备的命令,会同时指向新设备。
重命名
双击设备页签 → 输入新名字。校验:不能为空、不能与其它设备重名、不能含特殊字符
(:、#、[、]、{、}、&、*、!、|、>、'、"、%、@、`)。
重命名会全局更新所有引用:触发规则的source_device、动作的target_device、快捷命令的target_device、显示配置、规则启用状态,以及已连接的串口 worker —— 因此重命名不会丢消息或错乱按钮状态。
删除设备
点页签右侧的X→ 确认后会断开连接并从配置中移除。
拖动页签改变顺序
设备页签可拖动:按住页签左右拖动,松手即改变位置(VSCode 风格)——拖动时原页签变半透明,鼠标位置出现半透明的浮动页签副本,插入位置由蓝色竖线指示。顺序在松手时才同步到配置里的devices列表(拖动过程中不写盘),下次启动保持一致。
页签上的X 关闭按钮与圆点指示在拖动时也会跟随移动(已自绘,不会错位)。
页签选中色与连接指示
当前选中的设备页签以主题主色(蓝色)整块填色并显示白字,其余页签为中性灰底。
页签左侧的圆点表示连接状态:
- 当前选中页签:已连接 = 白色实心圆;未连接 = 白色空心圆(仅描边)。
- 非选中页签:已连接 = 绿色实心圆;未连接 = 灰色实心圆。
连接串口
每个设备标签页底部选择端口、波特率等参数,点连接。日志区会实时显示接收数据(带高亮),
底部输入框可发送命令(Enter 发送,Shift+Enter 换行)。
快捷命令
每个设备页签中部有一排快捷命令按钮,点击即发送预设命令。按钮只显示指向本设备的命令(或设为「所有设备」的命令)。命令模板支持变量和字符串管道(见后文「命令模板可用变量」)。
新增 / 管理
点页面左侧的➕打开「快捷命令管理」对话框:
- 上半部分列出系统中所有快捷命令,勾选即加入本设备,取消勾选即从本设备移除。
「目标设备」列显示该命令当前归属哪些设备(「所有设备」表示对全部设备可见)。 - 取消勾选一个「所有设备」命令时,会自动转为「显式列出其它所有设备」(不影响别的设备)。
- 下半部分可直接新增:填写名称、发送字符串、可选的周期间隔 / 持续时长、按钮颜色,点「添加到列表」。
「快捷命令管理」对话框:勾选控制命令在本设备的可见性,下方可直接新增。
编辑 / 删除
右键任一按钮 →编辑…或删除。编辑对话框可修改名称、发送字符串、周期参数、颜色。
拖动改顺序
按住按钮拖动到目标位置释放即可调整顺序(VSCode 风格):拖动时原按钮半透明,鼠标跟随一个半透明的放大预览图(带阴影),插入位置由蓝色竖线指示。顺序在松手时写回配置,所有设备共享同一份命令列表。
周期发送
在周期间隔里填数字(秒),该命令按钮会带 ⏰ 前缀,表示是周期命令:
- 点击启动周期发送(立即发一次,之后按间隔循环),按钮变蓝高亮;
- 再次点击停止。
- 「持续时长」留空或 0 = 无限循环;填数字 = 持续若干秒后自动停止。
按钮颜色
新增 / 编辑时可给按钮选一种背景色。提供 10 种柔和预设色,文字颜色会根据背景亮度自动取蓝色或同色相深色(保证可读):
| 0 浅红 | 1 浅橙 | 2 浅黄 | 3 浅黄绿 | 4 浅绿 |
|---|---|---|---|---|
| 5 浅青绿 | 6 浅青 | 7 浅蓝 | 8 浅紫 | 9 浅粉 |
配置写法
快捷命令存在config.yaml的quick_commands列表里,可手编;也可在⚙ 配置 → 快捷命令里表格化管理(名称、目标设备、命令、周期、颜色):
quick_commands:-name:"复位"command:"RESET\n"target_device:"调试口A"# 单个设备;留空=所有设备;也可写成列表-name:"读温度"command:"GET TEMP"target_device:["调试口A","设备口B"]color:4# 0~9,见上表;省略=默认无背景色interval:2.0# 周期间隔(秒);省略=单次发送duration:30# 持续时长(秒);省略或 0=无限高亮规则
在⚙ 配置 → 高亮规则增删改。每条规则:
-name:"错误"pattern:"(?i)error|fail|exception"# Python 正则foreground:"#FFFFFF"background:"#C62828"bold:true⚙ 配置 → 高亮规则:逐条编辑正则、前景/背景色、粗体。
工具栏☰ 规则概览(Ctrl+R)可按当前设备勾选启用/停用每条规则,无需打开配置对话框:
触发规则(跨端口联动)
在⚙ 配置 → 触发规则配置。这是工具的核心:
-name:"温度超限 -> B口降速"enabled:truesource_port:"调试口A"# 在此端口接收的行做匹配pattern:"temp=([0-9.]+)"# 正则,可带捕获组condition:"m1 > target_temp"# 可选;m0=整行,m1..=捕获组,可直接用变量名actions:-type:send# 跨端口发送target_port:"设备口B"# 可与 source_port 不同command:"SET_FAN ${match.1} ON"# ${match.N} 引用捕获组-type:log# 记录提示message:"⚠ 温度 ${match.1} 超过阈值 ${target_temp}"⚙ 配置 → 触发规则:源设备 + 正则 + 条件 + 动作列表,双击动作单元格可编辑。
命令模板可用变量
| 写法 | 含义 |
|---|---|
${match.0} | 整个匹配行 |
${match.1}…${match.9} | 正则捕获组 |
${timestamp} | 完整时间戳2026-08-08 14:30:05 |
${date}/${time} | 日期 / 时间 |
${port} | 来源端口名 |
${变量名} | 用户自定义变量(配置 → 变量) |
变量在⚙ 配置 → 变量里维护(键值对),命令模板与条件表达式均可引用:
字符串处理管道(可链式)
${match.1|upper} 转大写 ${match.1|lower} 转小写 ${match.1|trim} 去首尾空白 ${match.1|hex} 十进制转十六进制 ${match.1|unhex} 十六进制转十进制 ${match.1|replace(-,_)} 替换 ${match.1|substr(0,4)} 取子串 ${match.1|pad(8,0)} 左填充到 8 位用 '0'组合示例:${match.1|trim|upper}
条件表达式
condition为可选布尔表达式,使用安全求值(白名单 AST,禁危险函数)。
匹配组可用m0/m1/..,变量直接用名字:
condition:"m1 > target_temp"# 捕获组1 大于 变量condition:"int(m1) >= 50"# 显式取整比较condition:"m1 in ('OK', 'READY')"# 成员判断condition:"m1 > 50 and port == 'A'"# 组合表达式中数值会自动尝试转换,便于直接比较。
动作类型
actions支持四种动作,可写多条依次执行:
| type | 作用 | 关键字段 |
|---|---|---|
send | 向设备发送命令(可跨设备) | target_device、command |
log | 在来源设备日志区显示一条提示(warn 风格) | message |
set_port_param | 运行时修改端口参数(已连接即时生效,并写入配置) | baudrate/bytesize/parity/stopbits/port |
message | 生成一条消息,显示到「消息」面板并持久化 | content(或message) |
message动作示例(配合下文「消息面板」使用):
-name:"温度告警记录"enabled:truesource_device:"调试口A"pattern:"temp=([0-9.]+)"condition:"m1 > target_temp"actions:-type:messagecontent:"⚠ 温度 ${match.1} 超过阈值 ${target_temp}"# 显示在消息面板-type:sendtarget_device:"设备口B"command:"SET_FAN ${match.1} ON"消息面板
点工具栏💬 消息(或Ctrl+M)打开右侧的消息面板。它以表格形式收集并展示由触发规则生成的消息(即type: message动作的输出),适合用来集中查看各设备的告警、状态摘要等。
界面构成
- 工具条第一行:设备过滤下拉框(默认「全部设备」)、自动滚动开关、当前消息计数。
- 工具条第二行:删除该设备 / 删除选中 / 清空全部。
- 表格:三列 —— 时间、设备、消息。整行选中,不可直接编辑单元格。
设备分色
不同设备的消息行使用不同的浅色背景(淡蓝、淡靛蓝、淡青、淡绿、淡橙、淡紫、淡粉、淡深紫 …),按设备创建顺序循环,便于在一堆消息里快速识别来源。
设备过滤
下拉框选某个具体设备,则只显示该设备的消息。此时「删除该设备」按钮可用;选「全部设备」时该按钮禁用。
删除
- 删除该设备:删除当前过滤设备的全部消息(需先在过滤里选定设备)。
- 删除选中:删掉表格中选中(可多选)的行。
- 清空全部:删掉所有消息。
以上操作均有二次确认。
自动滚动
「自动滚动」勾选时,新消息到来会自动滚动到底部;取消勾选则保持当前位置,方便查阅历史。最多保留2000条,超出后自动丢弃最早的。
持久化
消息会自动保存到config/messages.json(防抖写入:1 秒内多次改动只写一次)。程序重启后自动加载历史消息,所以关掉再打开面板,之前的消息仍在;退出程序时也会立即保存。
消息面板默认隐藏,需要时用工具栏按钮或
Ctrl+M打开;面板显示时会自动收窄到默认宽度,避免把主窗口撑宽。
大模型助手
点击✨ LLM 助手(或Ctrl+L),用自然语言描述需求,例如:
当调试口A 收到 temp= 开头且数值大于 50 时,向设备口B 发送 SET_FAN 加上该数值和 ON
粘土助手:左侧描述需求 → 流式生成 YAML → 确认后「应用(合并到配置)」。
模型会生成对应 YAML ,可手动编辑后点应用合并到配置并保存。
生成过程流式显示,出错会提示。
🗂️ 项目结构
serial_tool/ ├── main.py # 入口 ├── requirements.txt ├── config/ │ ├── default_config.yaml # 默认模板(只读) │ └── config.yaml # 用户配置(运行时生成) ├── core/ │ ├── serial_worker.py # 单串口读写线程 │ ├── port_manager.py # 多端口生命周期 │ ├── highlight_engine.py # 高亮规则匹配 │ ├── command_engine.py # 命令渲染与触发 │ ├── config_store.py # YAML 读写校验 │ └── llm_service.py # OpenAI 兼容客户端 ├── ui/ │ ├── main_window.py # 主窗口 │ ├── port_tab.py # 端口标签页 │ ├── log_view.py # 高亮日志显示 │ ├── config_dialog.py # 配置编辑 │ └── llm_panel.py # LLM 助手 ├── utils/ │ ├── expression.py # 表达式/参数引擎 │ └── logger.py # 日志 └── README.md🏗️ 架构要点
- 线程模型:每个串口一个
SerialWorker(QObject.moveToThread),读循环在子线程,
通过Signal(str)把整行回传主线程。绝不跨线程操作 GUI/串口对象。 - 主线程集中处理:高亮匹配、命令渲染、触发调度都在主线程完成,避免锁。
- 跨端口联动:主窗口收到某端口的行 → 喂给
CommandEngine→ 渲染动作 → 调目标端口的
worker 发送(worker 的send是 slot,Qt 自动排队跨线程)。 - 性能:日志显示用
QTimer50ms 批量 flush,QPlainTextEdit.setMaximumBlockCount(5000)
防内存膨胀。 - 安全:LLM 生成的配置预览确认后才写入,配置保存前经
validate校验。
🔧 打包成 exe(可选)
py-mpipinstallpyinstaller py-mPyInstaller--noconsole--nameNento main.py# 产物在 dist/Nento/📝 备注
- COM 口冲突:同一物理口不能被两个程序同时打开。
- LLM 调用走外网,请确保网络可达;用 Ollama 则全程本地。
- 日志文件在
serial_tool/logs/serial_tool.log(滚动 2MB×3)。
📥 下载
点此进入下载页面