从串口日志到可视化:第一版设备调试台
旧记录整理:本文根据当时的代码提交、截图和测试笔记重新编排。日期按原始实验时间归档,不把补档当作新成果。
最初的需求很朴素:设备偶发重启时,串口会在几百毫秒内刷出几十行信息,而人工复制经常只留下最后一屏。更麻烦的是,研发、测试和现场同事使用不同的串口工具,同一个问题被描述成三种样子。于是我做了一版很小的桌面调试台,目标不是“替代所有终端”,而是固定一条可复现的证据链。
先定义一行日志是什么
我没有先画界面,而是把输入统一成四个字段:主机接收时间、设备时间、通道和原文。设备没有时钟时,device_time 可以为空,但接收时间必须由同一个单调时钟生成。
@dataclass
class Frame:
received_at: float
channel: str
raw: bytes
text: str
串口线程只负责读取和入队,解码、着色、保存都放到消费端。这个边界解决了一个隐蔽问题:界面卡顿不再阻塞串口读取,日志丢失可以通过队列长度和丢帧计数被看见,而不是悄悄发生。
可视化不是堆颜色
第一版界面只保留四块:连接状态、实时文本、过滤条件、标记时间轴。关键字颜色最多四种,红色只给错误,黄色给状态变化。每次人工操作可以插入一条 MARK,例如“按下复位键”或“拔掉传感器”。导出时,标记和设备日志按时间合并,复盘者能知道故障前发生了什么。
过滤器支持包含、排除和正则表达式,但默认只启用包含模式。正则输入错误时保留上一次有效规则,并在状态栏提示,避免调试过程中突然出现“空白窗口”。
一次有价值的失败
早期版本每收到一行就立即写磁盘。机械硬盘环境下,写入抖动会让 UI 一秒钟冻结两三次。后来改成内存批次,每 500 毫秒或累计 100 条写一次,同时在异常退出钩子里冲刷剩余队列。测试时主动杀进程,确认最多只损失最后半秒,而连接和过滤不受影响。
我也曾尝试自动识别所有日志级别,结果设备端格式稍变,规则就把普通数值误判成错误。最后只识别明确的 [E]、ERROR 和崩溃栈开头,其余交给用户过滤。工具可靠,往往来自主动缩小承诺。
当时的验收清单
- [x] 断开设备后自动停止读取,不产生空循环
- [x] 115200 波特率连续运行两小时无已知丢帧
- [x] 导出文件包含配置、标记和原始字节摘要
- [x] 错误编码使用替换字符展示,同时保留原始字节
- [x] 重新连接不清空当前会话,另起一个段落记录
- [x] 日志超过设定大小后滚动保存,而不是无限增长
留到今天的结论
调试工具最重要的不是漂亮,而是“发生过什么”可以被另一台电脑复现。把输入、时间、动作和导出格式固定下来之后,许多争论会自动消失。后来的蓝牙上位机、固件升级器和服务监控页都沿用了同一原则:采集路径尽量短,解释逻辑可以迭代,原始证据永远保留。
评论区