如何使用UART通讯构建GUI应用程序,以保持对用户的响应

时间:2019-02-27 05:59:35

标签: python pyqt5

我正在用PyQt5编写一个应用程序,该应用程序将用于产品的校准和测试。重要细节:

  • 被测产品使用9600波特的老式UART /串行通信链接。
  • ...并且测试/校准操作涉及与另一个具有UART /串行通信链接的设备进行通信,波特率为300波特(!)
  • 在两种情况下,通信协议都是ASCII文本,消息以换行符\r\n终止。

在测试/校准周期中,GUI需要与设备通信,获取读数并将这些读数记录到屏幕上的各个框中。问题在于,UART通信速度慢(如果出现通信中断,超时时间长),如何保持GUI的响应速度?

最低可接受解决方案(已在工作)是创建一个可通过串行端口进行通信的GUI,但是当该GUI等待调用{ {1}}完成或超时。

所需解决方案是一个GUI,即使在发送和接收串行数据时,它也具有良好的平滑响应感。

Stretch Goal (扩展目标)解决方案是一个GUI,它将串行通信的每个单个字符记录到用于调试的文本显示中,同时仍为实际逻辑提供了一些不错的“消息级”抽象的应用程序。

我目前的“最低可接受”实现使用状态机,在该状态机上运行一系列短函数,通常包括serial.read()serial.write()命令,并带有暂停以允许GUI更新。但是状态机使GUI逻辑难以遵循。如果以简单的线性方式编写用于与设备通信的程序流,则代码将更容易理解。

我真的很犹豫在整个代码中散布一堆serial.read()调用。甚至那些在等待processEvents()时也无济于事。因此正确的解决方案可能涉及线程,信号和插槽,但是我猜想“线程”与“优化”具有两个相同的黄金法则:规则1:不要这样做。规则2(仅限专家):暂时不要做。

是否有任何现有的体系结构或设计模式可以用作此类应用程序的起点?

2 个答案:

答案 0 :(得分:1)

Qt不仅是制作GUI的库,而且是具有其他模块(例如Qt Networt,Qt WebEngine,Qt Mqtt等)的库,这些模块可以在不阻塞Qt事件循环的情况下工作,在这种情况下,最好使用Qt SerialPort避免了总是带来线程的问题。例如,在this answer中,我展示了使用Qt SerialPort和线程+ pyserial实现相同解决方案的方法。

答案 1 :(得分:0)

好吧,在过去的几天里,我一直在挖掘,并弄清楚如何做到这一点。既然没有任何回应,而且我确实认为此问题可能适用于其他人,所以我将继续发布解决方案。简要地:

  • 是的,解决此问题的最佳方法是使用PyQt线程,并使用Signals和Slots在线程之间进行通信。
  • 对于基本功能(上面的“所需”解决方案),请遵循PyQt多线程GUI应用程序的现有基本设计模式:
    • GUI线程,其唯一的工作就是显示数据并中继用户输入/命令,并且
    • 执行其他所有工作的工作者线程(在这种情况下,包括串行comms)。
  • 一个绊脚石:我很喜欢将工作线程编写为一个线性代码流,但是不幸的是,这是不可能的,因为工作线程有时需要从GUI获取信息。
    • 在两个线程之间来回获取数据的唯一方法是通过信号和插槽,并且插槽(即接收端)必须是可调用的,因此我无法实现某种类型的{{ 1}}在函数中间进行操作。取而代之的是,工作线程必须构造为一堆单独的函数,在从GUI接收到适当的信号后,每个函数都会启动。
  • 获得串行数据监视功能(上面的“ Stretch目标”)实际上非常容易-只需在我的代码中已经有低级串行发送和接收例程就可以为该数据发出信号,GUI线程可以接收和接收记录这些信号。

总而言之,它最终只是对现有原理的非常简单的应用,但是我正在写下来,因此希望下一个家伙不必像我一路走下去那样走那么多盲巷。