python使用PyQt5开发桌面端串口通信

DATCOM 项目成果与核心 API 说明

学习的一个新的技术进行记录分享。

界面展示

  • 布局结构

    • 顶部双工具栏:操作栏与主工具栏,分别承载新增、删除、映射、清理虚拟串口、日志查看、退出、搜索等操作。
    • 中心区域:连接列表表格,展示各连接的串口/网络状态、目标地址、实时计数与设备信息。
    • 底部状态栏:版本信息与简要提示,便于发布与定位。
  • 交互与状态

    • 新增连接:弹出参数收集对话框(串口号、波特率、协议、IP/端口、设备信息与描述),确认后在表格新增一行。
    • 状态展示:串口与网络各自有状态字段(已就绪/已连接/未连接/失败),计数(接收/发送字节)实时累加。
    • 搜索过滤:在主工具栏输入关键字,表格实时过滤匹配行。
    • 日志查看:内置日志查看器,支持滚动与周期刷新。
    • 端口监控:定时轮询虚拟/物理端口占用情况,便于现场排查与清理。

项目概述

  • 桌面应用,面向串口数据采集与按 TCP/UDP 的实时转发
  • 支持虚拟串口配对与物理端口映射,内置日志查看与端口占用监控
  • 可一键打包为可执行文件,便于现场部署

成果亮点

  • 多连接管理:在一个界面下新增、删除与编辑多个串口到网络的桥接
  • 可靠转发:UDP 即发、TCP自动重连,统一队列保证发送顺序与统计准确
  • 可观测性:实时状态(串口/网络)与计数(接收/发送),滚动日志随时查看
  • 虚拟串口能力:创建/删除端口对、接线仿真与严格波特率、总线状态查询
  • 现场友好:端口占用监控、清理虚拟串口、搜索过滤、版本信息展示

典型使用场景

  • 将设备串口数据桥接到测试服务器,支持内网/外网联调
  • 在无真实双串口设备时,使用虚拟串口配对进行数据链路验证
  • 批量接入多个设备,统一转发到不同 IP 与端口

架构与模块

  • 桥接控制:将"串口采集线程"与"网络发送线程"进行桥接,并维护计数与状态分发
  • UI 装配:双层工具栏 + 连接表格 + 状态栏,提供新增/删除/映射/清理/搜索等操作
  • 驱动封装:对虚拟串口 SDK 的统一封装,兼容不同系统架构(x86/x64)
  • 日志与监控:滚动日志文件 + 内置查看器;定时器监控虚拟/物理端口占用

技术介绍

  • 技术选型

    • 桌面框架:采用 PyQt5 提供成熟窗口与控件体系,利于快速构建稳定桌面 UI。
    • 串口通信:使用 pyserial 进行跨平台串口访问,支持常见参数与非阻塞读取。
    • 网络传输:基于标准 socket 实现 TCP/UDP,便于控制连接、超时与重试策略。
    • 打包交付:使用 PyInstaller 将项目打包为单文件可执行,整合图标与资源。
  • 并发与线程模型

    • 采用 QThread + 信号/槽:串口读取与网络发送各在线程中运行,通过信号上报状态与数据,避免 GUI 阻塞与竞态。
    • 放弃 asyncio 的原因:在串口与 GUI 的结合场景下,QThread 更易与事件系统融合,且便于与第三方 DLL 协作。
    • 发送队列与背压:统一以队列承载待发送数据,TCP 建连失败时退避重试,UDP 即发确保低延迟。
  • 稳定性与错误处理

    • 自动重连:TCP 连接失败进入退避重试;串口异常短暂休眠后重试打开。
    • 统一日志:未处理异常通过 excepthook 写入滚动日志文件;按大小切分并保留备份。
    • 资源管理:停止时关闭串口与网络句柄,状态统一回传为"未连接",避免悬挂与句柄泄漏。
  • 虚拟串口(VSPD)集成

    • DLL 封装:对 vspdctl.dll 的导出函数进行封装,提供创建/删除端口对、严格波特率仿真、接线映射、总线查询与访问控制。
    • 架构适配:当运行环境与 DLL 架构不匹配时,自动启动 32 位代理进程,通过简单 JSON-RPC 实现进程间调用,确保在 x86/x64 上都可工作。
    • 安装与权限:提供安装程序调用支持(管理员权限),便于现场快速部署虚拟串口驱动。
  • 性能与可观测性

    • 非阻塞 IO 与固定缓冲:串口读取固定缓冲大小,减少频繁分配;网络发送按批量进行。
    • UI 最小更新:计数与状态的 UI 更新节制触发,确保在高频数据下界面流畅。
    • 内置日志查看器:每秒刷新并自动滚动,支持现场快速定位问题。

核心 API 能力

  • 串口采集
    • 功能:打开串口,非阻塞读取,持续产出数据流;状态变更事件(就绪/未连接/失败)
    • 关键参数:串口号、波特率、校验位、数据位、停止位、读取缓冲大小
    • 行为特性:自动重连、异常退避、资源关闭与状态回传
  • 网络转发
    • 功能:支持 UDP 即发与 TCP 建连重试,内部队列化发送;连接与发送状态事件
    • 关键参数:协议类型(TCP/UDP)、目标 IP、目标端口、连接超时与重试策略
    • 行为特性:TCP 失败自动重试、UDP 无连接即发、发送成功计数上报
  • 数据桥接
    • 功能:串口数据进入桥接层后转发到网络(与可选物理串口写出),并维护接收/发送累计计数
    • 关键能力:是否可发送判断(网络就绪)、多目标输出(网络 + 物理)、按行索引更新 UI 统计
    • 行为特性:线程安全的事件分发、统一异常处理、轻量耦合 UI 更新
  • 虚拟串口驱动
    • 功能:创建/删除虚拟端口对、查询总线状态、设置波特率仿真与接线映射、访问白名单
    • 关键参数:端口名、严格仿真开关、接线映射(DTR/RTS 等)、查询缓冲大小
    • 行为特性:封装 DLL 接口并自动选择代理进程(在架构不匹配时),统一错误处理与返回值
  • 日志与端口监控
    • 功能:滚动日志文件(自动切分与保留)、内置日志查看器(定时刷新与跟随滚动)
    • 关键参数:日志目录、文件大小与备份数、刷新周期
    • 行为特性:未处理异常统一写入日志,查看器只读与轻量刷新;端口占用周期性轮询
  • UI 交互
    • 功能:新增/删除连接、映射物理端口、清理虚拟串口、查看日志、退出与搜索过滤
    • 行为特性:所有操作产生统一事件,桥接层按行索引更新表格状态与计数

用户操作流程

  • 打开应用后,通过工具栏点击"新增",填写串口与网络参数(协议、IP、端口等)
  • 确认后,列表新增一行,显示串口与网络的状态、接收/发送字节数
  • 如需模拟设备或桥接到本机测试工具,可通过"映射物理端口/清理虚拟串口"进行管理
  • 遇到异常时,打开"运行日志",定位连接失败、重试与发送统计等信息

性能与稳定性策略

  • 串口非阻塞读取 + 队列化发送,避免界面阻塞
  • TCP 建连失败退避重试,UDP 即发确保低延迟
  • 统一异常捕获与日志落地,便于回溯与现场排查
  • 资源生命周期清晰:停止时关闭串口与网络对象,状态统一回传

部署与交付

  • 依赖简单:Python 环境与基础库
  • 支持一键打包为单文件应用,便于在测试产线或客户现场快速落地
  • 可选捆绑虚拟串口驱动安装包(含多平台与架构变体)

可扩展性

  • 配置持久化(JSON/INI)、批量操作与多选、图标与版本资源、错误提示与重试策略可调
  • 未来可增加带宽与丢包统计、断点续传策略、TLS 加密与访问控制

总结

  • 核心定位是"多连接串口采集 + 可靠网络转发 + 虚拟串口能力"的桌面工具
  • 通过清晰的桥接与事件模型,实现可观测、可维护、易扩展的工程落地
  • 面向分享与展示,我们仅呈现成果与 API 能力,保留源码细节以便后续商业或内部使用

核心 API

以下仅展示少量关键接口片段,帮助理解能力边界与调用方式。

  • 串口采集线程
python 复制代码
class SerialWorker(QThread):
    bytes_received = pyqtSignal(bytes)
    status_changed = pyqtSignal(str)
    def run(self):
        while self._running:
            if self._ser is None or not self._ser.is_open:
                self._ser = serial.Serial(self.port, self.baudrate, timeout=0.1)
                self.status_changed.emit("已就绪")
            data = self._ser.read(4096)
            if data:
                self.bytes_received.emit(data)
  • 网络发送线程
python 复制代码
class SocketClient(QThread):
    status_changed = pyqtSignal(str)
    bytes_sent = pyqtSignal(int)
    def run(self):
        while self._running:
            if self._sock is None:
                if self.protocol == "UDP":
                    self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
                    self.status_changed.emit("已就绪")
                else:
                    self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                    self._sock.settimeout(3)
                    self.status_changed.emit("连接中...")
                    self._sock.connect((self.host, self.port_remote))
                    self.status_changed.emit("已连接")
            data = self._q.get(timeout=0.2)
            if self.protocol == "UDP":
                self._sock.sendto(data, (self.host, self.port_remote))
                self.bytes_sent.emit(len(data))
            else:
                self._sock.sendall(data)
                self.bytes_sent.emit(len(data))
  • 数据桥接与计数
python 复制代码
def on_serial_data(self, data: bytes):
    self.serial_rx += len(data)
    self.signals.counters_changed.emit(self._row_index(), self.serial_rx, self.net_tx)
    if self.net.can_send():
        self.net.send(data)
    if self.phys_out and self.phys_out.can_send():
        self.phys_out.send(data)
  • 虚拟串口驱动接口
python 复制代码
driver = VSPDDriver()
driver.create_pair("COM5", "COM6")
driver.set_strict_baudrate("COM5", True)
driver.delete_pair("COM5")
相关推荐
手揽回忆怎么睡2 小时前
Java集成whisper.cpp
java·开发语言·whisper
wjs20242 小时前
R 基础语法
开发语言
JS_GGbond2 小时前
用美食来理解JavaScript面向对象编程
开发语言·javascript·美食
Dxy12393102162 小时前
Python的正则表达式入门:从小白到能手
服务器·python·正则表达式
艾上编程2 小时前
第三章——爬虫工具场景之Python爬虫实战:行业资讯爬取与存储,抢占信息先机
开发语言·爬虫·python
Pyeako2 小时前
网络爬虫相关操作--selenium库(超详细版)
爬虫·python·selenium
dagouaofei2 小时前
全面整理6款文档生成PPT工具,PDF转PPT不再难
python·pdf·powerpoint
β添砖java2 小时前
python第一阶段第10章
开发语言·python
伊玛目的门徒3 小时前
HTTP SSE 流式响应处理:调用腾讯 智能应用开发平台ADP智能体的 API
python·网络协议·http·腾讯智能体·adp·智能应用开发平台