socatでシリアルデバイスの分離をシミュレートする方法

socatでシリアルデバイスの分離をシミュレートする方法

このテストプログラムがあります。

import sys

for line in sys.stdin:
    print(line.strip())

print("DONE")

実際のデバイス(FTDI)でラインを印刷する場合

python3 demo.py < /dev/ttyUSB0

その後、送信したすべての行を印刷してUSBケーブルを抜くと、DONEメッセージが表示されます。

一方、socatを使って偽のttyを生成すると、

socat -d -d pty,raw,echo=0,link=ttyFake pty,raw,echo=0,link=ttyFake.interface

その後、Pythonプログラムを使用して偽のデバイスを監視します。

python3 demo.py < ttyFake

このようにメッセージを送信できます。

echo test >> ttyFake.interface

印刷されています。

ただし、SIGINT または SIGTERM を使用して socat プロセスを停止すると、次のメッセージが表示されます。

$ python3 demo.py < ttyFake
test
Traceback (most recent call last):
  File "~/serial-experiment/demo.py", line 3, in <module>
    for line in sys.stdin:
OSError: [Errno 5] Input/output error

私もこれを試しましたが、運がありませんでした。

$ echo -ne '\004' >> ttyFake.interface # send ^D

socatに切断操作をシミュレートする方法はありますか?それを送るより良い方法が必要ですか^D

^Dサブ質問:プロセスが標準入力で検出した内容が入力が完了したかどうかを判断するのか、それとも入力を終了するために端末エミュレータに送信するのかは実際にはわかりません。

答え1

テストを正常に実行できる回避策があります。これは簡単に問題の一部である可能性があります。したがって、「Cunninghamの法則」を利用しようとすることもできます(Cunningham自身はこれとは何の関係もないようです)。

$ mkdir solution
$ cd solution
$ cat > demo.py
import sys

for line in sys.stdin:
    print(line.strip())

print("DONE")
$ # make sure you ctrl+D at then end
$ mkfifo ttyConnector # DIFFERENT FROM QUESTION
$ socat -d -d pty,raw,echo=0,link=ttyFake pty,raw,echo=0,link=ttyFake.interface

新しいターミナル:

$ cd solution
$ cat > ttyConnector < ttyFake # DIFFERENT FROM QUESTION

新しいターミナル:(こんな感じアプリケーション端末)

$ cd solution
$ python3 demo.py < ttyConnector # DIFFERENT FROM QUESTION

新しいターミナル:

$ cd solution
$ cat > ttyFake.interface
test
test
test
$ # make sure you ctrl+D at then end

(最後にctrlpython3デモ。py <ttyConnector + Dがあることを確認してください)

今見てアプリケーション端末

$ python3 demo.py < ttyConnector
test
test
test

ptyへの転送を終了しても、fifoはまだ開いています。

しかし、socat端末に戻ってCtrl + Cを押して確認してください。アプリケーション端末

$ python3 demo.py < ttyConnector
test
test
test
DONE

したがって、USBからFTDIを分離する動作をシミュレートするために、fifoを介してすべてを渡してsocatを終了できるようです。 ptyペア(FTDIデバイスをエミュレートするプログラムと受信するプログラム)を介して2つのプログラムが一緒に接続されています。現在、この回避策を使用できる理由は、レシーバが読み取りのためにptyペアの端だけを開くのに対し、偽デバイスは読み取りと書き込みを実行し、テスト自体では書き込みを実行するためです。

            /--> P --> FIFO --> demo.py
FAKE DEVICE      T
            \<-- Y <-- TEST

両端で単方向通信のみが必要な場合は、socatをスキップしてfifoのみを使用してください。

FAKE DEVICE --> FIFO --> demo.py

完全な双方向コミュニケーションが必要な場合は、実用的な解決策が必要ですが、まだわかりません。

            /--> P -->\ 
FAKE DEVICE      T      demo.py
            \<-- Y <--/

Demo.pyが同じパスを読み書きすることを期待している場合、2つのfifoを挿入するのはそれほど簡単ではないからです。

だから私はこの回避策なしでPTYを正しく終了するために何をすべきかを知りたいと思います。

関連情報