自用串口工具分享

粘土,一个面向嵌入式调试的串口工具,支持 多串口同时连接、自定义常用命令、
自动高亮匹配行、条件触发任务,以及 跨端口联动(在 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 桩,请使用 py launcher。

py -m pip install -r requirements.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: true
  source_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: true
  source_device: "调试口A"
  pattern: "temp=([0-9.]+)"
  condition: "m1 > target_temp"
  actions:
    - type: message
      content: "⚠ 温度 ${match.1} 超过阈值 ${target_temp}"  # 显示在消息面板
    - type: send
      target_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 自动排队跨线程)。
  • 性能:日志显示用 QTimer 50ms 批量 flush,QPlainTextEdit.setMaximumBlockCount(5000)
    防内存膨胀。
  • 安全:LLM 生成的配置 预览确认后才写入,配置保存前经 validate 校验。

🔧 打包成 exe(可选)

py -m pip install pyinstaller
py -m PyInstaller --noconsole --name Nento main.py
# 产物在 dist/Nento/

📝 备注

  • COM 口冲突:同一物理口不能被两个程序同时打开。
  • LLM 调用走外网,请确保网络可达;用 Ollama 则全程本地。
  • 日志文件在 serial_tool/logs/serial_tool.log(滚动 2MB×3)。

📥 下载

点此进入下载页面

Logo

一站式 AI 云服务平台

更多推荐