Последовательный ввод с линейной буферизацией

У меня есть последовательное устройство, с которого я пытаюсь считать входные данные. Я отправил ему строку «ID\r», и он возвращает «ID XX\r» (, где \r — это возврат каретки ASCII, шестнадцатеричный 0x0d).

Поскольку опция eol в serial.readline больше не поддерживается, я использую TextIOWrapper для чтения из последовательного порта и возврата строки за раз.

Моя проблема заключается в том, что вместо того, чтобы возвращать мою строку, как только она увидит возврат каретки, она ждет до тех пор, пока не удвоится время ожидания, которое я установил, когда открывал последовательный порт. Я бы хотел, чтобы он возвращал строку немедленно, как только он считывал всю строку, поскольку у меня могут быть сотни этих команд для отправки на устройство, и я не хочу каждый раз ждать тайм-аута. Если я установлю тайм-аут на 0, то я вообще не получу вывода (, предположительно потому, что мой скрипт перестанет ждать, прежде чем устройство сможет что-либо вывести ), а если я установлю тайм-аут на None, скрипт блокируется навсегда.

Вот простой тестовый сценарий.:

import serial
import io
import time

ser = serial.Serial("/dev/ttyUSB0", baudrate=9600,
                    bytesize=8, parity='N', stopbits=1,
                    xonxoff=0, rtscts=1, timeout=5)

sio = io.TextIOWrapper(io.BufferedRWPair(ser, ser),
                       newline=None)


sio.write(unicode("ID\r"))
sio.flush()

print "reading..."

x = sio.readline()

print len(x)
print x

Сценарий всегда занимает 10 секунд с момента, когда он говорит «чтение», до того, как он напечатает строку «ID XX», которую он прочитал из последовательного порта.

Я уверен, что устройство выводит возврат каретки, так как я использовал strace для наблюдения за чтением:

select(4, [3], [], [], {5, 0})          = 1 (in [3], left {4, 991704})
read(3, "I", 8192)                      = 1
select(4, [3], [], [], {5, 0})          = 1 (in [3], left {4, 999267})
read(3, "D", 8191)                      = 1
select(4, [3], [], [], {5, 0})          = 1 (in [3], left {4, 999420})
read(3, " ", 8190)                      = 1
select(4, [3], [], [], {5, 0})          = 1 (in [3], left {4, 999321})
read(3, "X", 8189)                      = 1
select(4, [3], [], [], {5, 0})          = 1 (in [3], left {4, 999355})
read(3, "X", 8188)                      = 1
select(4, [3], [], [], {5, 0})          = 1 (in [3], left {4, 999171})
read(3, "\r", 8187)                     = 1
select(4, [3], [], [], {5, 0})          = 0 (Timeout)
select(4, [3], [], [], {5, 0})          = 0 (Timeout)

Вы можете увидеть 2 таймаута select(), которые дают 10-секундную задержку, но вы также ясно видеть, как читается возврат каретки. Я попытался установить для параметра новой строки значение «Нет» и '' (, что должно автоматически разрешать \r, \n и \r\n), и значение '\ r', но с тем же результатом каждый время.

Я также пытался установить размер буфера_в вызове BufferedRWPair()равным 1, чтобы предотвратить буферизацию ввода, но это не имело значения.

Есть идеи, что я делаю не так?

Если я не смогу заставить это работать,моим следующим шагом будет использование serial.read()для чтения символов за раз и выполнения собственной буферизации строк, но я хотел сначала попытаться сделать это «правильным» способом с textiowrapper.

7
задан MPelletier 10 October 2013 в 19:54
поделиться