01 — 需求规格说明
版本:v1.0 | 日期:2026-05-30 | 作者:[你的名字]
本文档定义 PulseQt 上位机系统的功能需求、非功能需求、约束条件和验收标准。
1. 引言
1.1 编写目的
明确 PulseQt 系统的功能边界和技术指标,作为开发和验收的统一基准。同时作为面试时展示”需求分析能力”的证明材料。
1.2 项目背景
在工业数据采集场景中,需要一款轻量级上位机软件,通过串口或 TCP 从下位机/传感器接收实时数据流,完成可视化展示、持久化存储和历史回溯。市面现有方案(如 LabVIEW、MATLAB)过于庞大,不适合嵌入式设备调试和轻量部署。
1.3 术语定义
| 术语 | 说明 |
|---|
| 帧(Frame) | 一次完整的数据传输单元,包含帧头、长度、类型、数据负载、CRC 校验 |
| 通道(Channel) | 数据来源的抽象,可以是串口(COM/ttyUSB)或 TCP Socket |
| 数据点(DataPoint) | 单次采集的多个通道值,如 {timestamp, ch0, ch1, ch2} |
| 粘包/拆包 | TCP 字节流无边界导致的接收端数据帧错位问题 |
2. 功能需求
2.1 通信模块
| 编号 | 功能 | 描述 | 优先级 |
|---|
| F1.1 | 串口通信 | 支持配置端口号、波特率、数据位、停止位、校验位;打开/关闭串口 | P0 |
| F1.2 | TCP 客户端 | 支持连接/断开远程 TCP 服务器,配置 IP 和端口 | P0 |
| F1.3 | 通道抽象 | 串口和 TCP 使用统一 IChannel 接口,上层业务代码不感知通道类型 | P0 |
| F1.4 | 断线重连 | 通道异常断开时自动重连,采用指数退避策略(1s → 2s → 4s → … → 30s 上限) | P1 |
| F1.5 | 心跳检测 | 空闲时每 5 秒发送心跳帧,30 秒无响应判定断线 | P1 |
| F1.6 | 通信速率统计 | 状态栏实时显示接收字节数、帧数、帧率(FPS) | P2 |
2.2 协议模块
| 编号 | 功能 | 描述 | 优先级 |
|---|
| F2.1 | 帧解码 | 从字节流中提取完整帧,支持粘包拆包处理 | P0 |
| F2.2 | CRC16 校验 | 每帧带 CRC16-CCITT 校验,校验失败丢弃并记录日志 | P0 |
| F2.3 | 多数据类型 | 支持 uint8/uint16/int16/float32 四种通道数据类型 | P0 |
| F2.4 | 帧类型区分 | 数据帧 / 心跳帧 / 应答帧 / 错误帧 四种帧类型 | P1 |
2.3 数据管理
| 编号 | 功能 | 描述 | 优先级 |
|---|
| F3.1 | 环形缓冲 | 内存中维护最近 N 条数据的环形缓冲区(默认 10000 条),线程安全 | P0 |
| F3.2 | SQLite 持久化 | 所有数据实时写入 SQLite 数据库,支持 WAL 模式 | P0 |
| F3.3 | 批量事务写入 | 每 100 条数据一个事务批量写入,避免逐条提交的性能问题 | P1 |
| F3.4 | 历史查询 | 按时间范围查询历史数据,支持翻页 | P1 |
| F3.5 | 数据清理 | 自动清理超过 N 天的历史数据(可配置),防止数据库无限膨胀 | P2 |
2.4 界面展示
| 编号 | 功能 | 描述 | 优先级 |
|---|
| F4.1 | 实时曲线 | 自绘 QWidget 实现,支持 8 条通道同时绘制,100Hz 刷新 | P0 |
| F4.2 | 数据表格 | QTableView + 自定义 Model 展示最新数据,自动滚动 | P0 |
| F4.3 | 曲线交互 | 滚轮缩放 X 轴、鼠标拖拽平移、右键重置视图 | P1 |
| F4.4 | 历史回放 | QSlider 控制时间轴,拖动到历史时刻查看当时曲线 | P1 |
| F4.5 | CSV 导出 | 将指定时间范围的数据导出为 CSV 文件 | P1 |
| F4.6 | 暗色主题 | QSS 暗色主题,类似 IDE 风格 | P2 |
| F4.7 | 通道配置 | 可配置每条曲线颜色、线宽、是否显示 | P2 |
3. 非功能需求
| 类别 | 指标 | 目标值 |
|---|
| 性能 | 数据采集刷新率 | ≥ 100Hz(10ms 间隔) |
| 性能 | 曲线渲染帧率 | ≥ 30 FPS |
| 性能 | 内存占用 | 运行态 < 150MB |
| 性能 | SQLite 写入速率 | ≥ 500 条/秒 |
| 可靠性 | 连续运行稳定性 | 72 小时无崩溃、无内存泄漏 |
| 可靠性 | 断线恢复 | 网络恢复后 30s 内自动重连成功 |
| 可用性 | 启动时间 | < 3 秒 |
| 可维护性 | 日志 | 分级日志(DEBUG/INFO/WARN/ERROR),可配置输出文件 |
4. 约束条件
| 约束 | 说明 |
|---|
| 开发语言 | C++17 |
| UI 框架 | Qt 6.5+ (Widgets) |
| 构建系统 | CMake 3.20+ |
| 数据库 | SQLite 3(通过 Qt SQL 模块) |
| 平台 | Linux (Ubuntu 22.04 主力开发),预留 Windows 兼容 |
| 开发周期 | 4 天(2026-05-30 ~ 2026-06-02) |
| 测试设备 | 可用的 USB 转串口模块 ×1,或使用虚拟串口 socat 模拟 |
5. 验收标准
| 编号 | 验收项 | 通过条件 |
|---|
| AC1 | 串口采集 | 连接串口 → 发送模拟数据 → 界面显示曲线(截图作为证据) |
| AC2 | TCP 采集 | 用 ncat 模拟 TCP 服务端,上位机连接并显示数据(截图) |
| AC3 | 粘包处理 | 模拟端连续发送多帧不加间隔,上位机正确拆分(日志截图) |
| AC4 | 断线重连 | 拔掉串口 → 界面提示断开 → 插回 → 30s 内自动恢复(截图) |
| AC5 | 历史回放 | 采集 1 小时后,拖动滑块回到 30 分钟前,曲线正确展示 |
| AC6 | CSV 导出 | 导出文件用 Excel 打开,数据完整无乱码 |
| AC7 | 72h 压测 | 程序连续运行 72 小时(可夜间跑),无崩溃,内存稳定 |
| AC8 | 代码质量 | 无裸 new/delete,全部智能指针;clang-tidy 无严重警告 |
6. 模拟测试数据源
由于不一定有真实硬件,开发期间使用 Python 脚本模拟数据源:
# simulator.py — 放在项目 tools/ 目录下
import serial
import struct
import time
import random
# 模拟串口设备,每秒发 100 帧
ser = serial.Serial('/dev/pts/2', 115200)
def make_frame(ch0, ch1, ch2):
# 帧格式见 docs/03_通信协议设计.md
payload = struct.pack('<HHH', ch0, ch1, ch2) # 3 个 uint16 通道
frame = b'\xA5\x5A' # 帧头
frame += struct.pack('<B', len(payload)) # 长度
frame += b'\x01' # 类型:数据帧
frame += payload
crc = crc16_ccitt(frame)
frame += struct.pack('<H', crc)
return frame
while True:
frame = make_frame(
random.randint(0, 1023),
random.randint(0, 1023),
random.randint(0, 1023)
)
ser.write(frame)
time.sleep(0.01) # 100Hz