how to let serial work well background and also foreground?

只谈情不闲聊 提交于 2021-02-19 08:13:05

问题


i have a serial app, The Robot class need to always receive serial message and then to do some thing, the Demo gui need to interactive Robot and get Robot.handle_readData, if no data get, need to get again and again until had data. Now i had no idea how to solve this problem, need someone give me good idea.

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtSerialPort import *

class Robot(QObject):
    def __init__(self):
        super().__init__()
        self.serial = QSerialPort()
        self.serial.setPortName('COM2')
        self.serial.setBaudRate(QSerialPort.Baud115200)
        self.serial.readyRead.connect(self.handle_readData)
        self.serial.open(QIODevice.ReadWrite)

    #background message auto process
    def handle_readData(self):
        data = self.serial.readAll()
        self.do_something(data)

        return data

    def do_something(self, data):pass

class Demo(QDialog):
    def __init__(self):
        super().__init__()
        layout = QHBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        self.search_bn = QPushButton('query', clicked=self.get_query_info)
        layout.addStretch(1)
        layout.addWidget(self.search_bn)

        main_layout = QVBoxLayout()
        main_layout.addLayout(layout)
        main_layout.addWidget(QTextEdit('msg'))
        self.setLayout(main_layout)

        #robot object
        self.robot = Robot()

    #forground message process, pseudo code
    def get_query_info(self, checked):
        self.robot.serial.write('show version')
        #how to get Robot.handle_readData  data,
        data = Robot.handle_readData() # need to get this data
        #if data is None, need to get again and again until data have some meaningful msg.
        do_someting(data)


        self.robot.serial.write('show system info')
        # how to get Robot.handle_readData  data,
        data = Robot.handle_readData()  # need to get this data
        # if data is None, need to get again and again until data have some meaningful msg.
        do_someting1(data)


app = QApplication([])
demo = Demo()
demo.show()
app.exec()

回答1:


Qt is designed to work asynchronously, and instead your possible implementation is made for synchronous logic. The solution for these cases is to transform the implementation and in this case for example with the help of flags.

On the other hand do not process the information where you receive the information, instead it emits a signal so that it can be used elsewhere.

from enum import Enum, auto


from PyQt5.QtCore import pyqtSignal, pyqtSlot, QIODevice, QObject
from PyQt5.QtWidgets import (
    QApplication,
    QDialog,
    QHBoxLayout,
    QPushButton,
    QVBoxLayout,
    QTextEdit,
)
from PyQt5.QtSerialPort import QSerialPort


class Robot(QObject):
    dataChanged = pyqtSignal(bytes)

    def __init__(self):
        super().__init__()
        self.serial = QSerialPort()
        self.serial.setPortName("COM2")
        self.serial.setBaudRate(QSerialPort.Baud115200)
        self.serial.readyRead.connect(self.handle_readData)
        self.serial.open(QIODevice.ReadWrite)

        self.dataChanged.connect(self.do_something)

    @pyqtSlot()
    def handle_readData(self):
        data = self.serial.readAll()
        self.dataChanged.emit(data)

    @pyqtSlot(bytes)
    def do_something(self, data):
        pass


class State(Enum):
    NoneState = auto()
    VersionState = auto()
    InfoState = auto()


class Demo(QDialog):
    def __init__(self):
        super().__init__()
        layout = QHBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        self.search_bn = QPushButton("query", clicked=self.get_query_info)
        layout.addStretch(1)
        layout.addWidget(self.search_bn)

        main_layout = QVBoxLayout(self)
        main_layout.addLayout(layout)
        main_layout.addWidget(QTextEdit("msg"))

        self.current_state = State.NoneState

        self.robot = Robot()
        self.robot.dataChanged.connect(self.process_data)

    @pyqtSlot()
    def get_query_info(self):
        self.robot.serial.write(b"show version")
        self.current_state = State.VersionState

    @pyqtSlot(bytes)
    def process_data(self, data):
        if self.current_state == State.VersionState:
            do_someting(data)
            self.robot.serial.write(b"show system info")
            self.current_state = State.InfoState
        elif self.current_state == State.InfoState:
            do_someting1(data)
            self.current_state = State.NoneState


if __name__ == "__main__":
    import sys

    app = QApplication(sys.argv)
    demo = Demo()
    demo.show()
    sys.exit(app.exec_())


来源:https://stackoverflow.com/questions/58554809/how-to-let-serial-work-well-background-and-also-foreground

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!