Используя PySerial, можно ли ждать данных?
У меня есть программа Python, которая читает данные из последовательного порта через PySerial
модуль. Два условия, которые мне нужно иметь в виду: я не знаю, сколько данных будет поступать, и я не знаю, когда ожидать данные.
Исходя из этого, я придумал следующие фрагменты кода:
#Code from main loop, spawning thread and waiting for data
s = serial.Serial(5, timeout=5) # Open COM5, 5 second timeout
s.baudrate = 19200
#Code from thread reading serial data
while 1:
tdata = s.read(500) # Read 500 characters or 5 seconds
if(tdata.__len__() > 0): #If we got data
if(self.flag_got_data is 0): #If it's the first data we recieved, store it
self.data = tdata
else: #if it's not the first, append the data
self.data += tdata
self.flag_got_data = 1
Таким образом, этот код будет зацикливаться на получение данных от последовательного порта. Мы получим до 500 символов для хранения данных, а затем оповестим основной цикл, установив флаг. Если данных нет, мы просто вернемся спать и будем ждать.
Код работает, но мне не нравится время ожидания 5 с. Мне это нужно, потому что я не знаю, сколько данных ожидать, но мне не нравится, что он просыпается каждые 5 секунд, даже если данных нет.
Есть ли способ проверить, когда данные становятся доступными, прежде чем делать read
? Я думаю что-то вроде select
Команда в Linux.
РЕДАКТИРОВАТЬ:
Просто подумал, что заметил, что нашел inWaiting()
метод, но на самом деле это, кажется, просто меняет мой "сон" на опрос, так что это не то, что я хочу здесь. Я просто хочу поспать, пока данные не придут, а потом иди за ними.
3 ответа
Хорошо, я действительно собрал что-то, что мне нравится для этого. Используя комбинацию read()
без таймаута и тому inWaiting()
метод:
#Modified code from main loop:
s = serial.Serial(5)
#Modified code from thread reading the serial port
while 1:
tdata = s.read() # Wait forever for anything
time.sleep(1) # Sleep (or inWaiting() doesn't give the correct value)
data_left = s.inWaiting() # Get the number of characters ready to be read
tdata += s.read(data_left) # Do the read and combine it with the first character
... #Rest of the code
Кажется, это дает желаемые результаты, я думаю, что этот тип функциональности не существует как отдельный метод в Python
Вы можете установить timeout = None
тогда read
Вызов будет заблокирован, пока не будет запрошенное количество байтов. Если вы хотите дождаться прибытия данных, просто выполните read(1)
с таймаутом None
, Если вы хотите проверить данные без блокировки, сделайте read(1)
с нулевым временем ожидания, и проверьте, возвращает ли он какие-либо данные.
(см. документацию http://pyserial.sourceforge.net/pyserial_api.html)
def cmd(cmd,serial):
out='';prev='101001011'
serial.flushInput();serial.flushOutput()
serial.write(cmd+'\r');
while True:
out+= str(serial.read(1))
if prev == out: return out
prev=out
return out
Назовите это так:
cmd('ATZ',serial.Serial('/dev/ttyUSB0', timeout=1, baudrate=115000))