入力を読み取ろうとしているシリアルデバイスがあります。「ID\r」という文字列を送信すると、「ID XX\r」が返されます (\r は ASCII キャリッジ リターンで、16 進数の 0x0d です)。
serial.readline の eol オプションはサポートされなくなったため、TextIOWrapper を使用してシリアル ポートから読み取り、一度に 1 行ずつ返します。
私の問題は、改行が表示されるとすぐに文字列を返すのではなく、シリアルポートを開いたときに設定したタイムアウトの 2 倍になるまで待機していることです。デバイスに送信するこれらのコマンドが何百もある可能性があり、毎回タイムアウトを待ちたくないので、行全体を読み取るとすぐに文字列を返すようにしたいと思います。タイムアウトを 0 に設定すると、まったく出力が得られません (おそらく、デバイスが何かを出力する前にスクリプトが待機を停止するため)。タイムアウトを [なし] に設定すると、スクリプトは永久にブロックされます。
簡単なテスト スクリプトを次に示します。
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
スクリプトは、「読み取り中」と表示されてから、シリアル ポートから読み取った「ID XX」文字列を出力するまで、常に 10 秒かかります。
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)
10 秒の遅延を与える 2 つの select() タイムアウトを確認できますが、キャリッジ リターンが読み取られていることもはっきりと確認できます。改行パラメータを 'None' と '' (\r、\n、および \r\n を自動的に許可する必要があります)、および '\r' に設定しようとしましたが、毎回同じ結果になります。
また、BufferedRWPair() 呼び出しで buffer_size を '1' に設定して、入力をバッファリングしないようにしようとしましたが、違いはありませんでした。
私が間違っていることは何か分かりますか?
これが機能しない場合、次のステップは、serial.read() を使用して一度に 1 文字ずつ読み取り、独自の行バッファリングを行うことですが、textiowrapper を使用して「正しい」方法でそれを実行したかったのです。最初。