我想在运行 GUI 时每当有数据要从串行端口读取时触发一个事件。这pySerial
模块显然具有实验性功能,但没有特别详细的记录(我找不到任何有用的示例在 API 中 https://pyserial.readthedocs.io/en/latest/pyserial_api.html#module-serial.threaded).
这个问题 https://stackoverflow.com/questions/4169219/constantly-reading-from-a-serial-port-with-a-background-thread似乎处理相同或至少非常相似的任务,但不提供复制它的说明或工作代码示例。
我想出了这个代码:
import tkinter as tk
import serial
import threading
# Create GUI window
window = tk.Tk()
# Initialize the port
myPort = serial.Serial('/dev/ttyUSB0')
# Function to call whenever there is data to be read
def readFunc(port):
port.readline()
print('Line read')
# Configure threading
t1 = threading.Thread(target = readFunc, args=[myPort])
t1.start()
# Main loop of the window
window.mainloop()
运行它确实会触发该事件,但只会触发一次。这是为什么?是否有“推荐”的方法来执行此操作,例如使用以下功能pySerial
itself?
或者,我也会运行该函数来读取和处理事件数据,就像使用 GUI 元素一样。如果这是更好的解决方案,该怎么做?
相关问题 https://stackoverflow.com/questions/26600753/event-handler-in-python-serial-port-data-received(未回答),可能会使这个问题重复
编辑:这是从下面的答案中得出的一个最小示例,每当将数据读取到传入数据时,就会更改标签的文本:
import tkinter as tk
from serial import Serial
from serial.threaded import ReaderThread, Protocol
app = tk.Tk()
label = tk.Label(text="A Label")
label.pack()
class SerialReaderProtocolRaw(Protocol):
port = None
def connection_made(self, transport):
"""Called when reader thread is started"""
print("Connected, ready to receive data...")
def data_received(self, data):
"""Called with snippets received from the serial port"""
updateLabelData(data)
def updateLabelData(data):
data = data.decode("utf-8")
label['text']=data
app.update_idletasks()
# Initiate serial port
serial_port = Serial("/dev/ttyACM0")
# Initiate ReaderThread
reader = ReaderThread(serial_port, SerialReaderProtocolRaw)
# Start reader
reader.start()
app.mainloop()