web-dev-qa-db-ja.com

Pythonの仮想シリアルデバイス?

私は私が使用できることを知っていますpySerialを使用してシリアルデバイスと通信しますが、現在デバイスがなくてもクライアントを作成する必要がある場合はどうなりますか? Python=に「仮想シリアルデバイス」を記述して、私がローカルWebサーバーを実行するように、pySerialに通信させるにはどうすればよいですか?たぶん私はうまく検索していないだけかもしれませんが、このトピックに関する情報は見つかりませんでした。

41
tdavis

これは私がやったことでこれまでに私のために働いたものです:

import os, pty, serial

master, slave = pty.openpty()
s_name = os.ttyname(slave)

ser = serial.Serial(s_name)

# To Write to the device
ser.write('Your text')

# To read from the device
os.read(master,1000)

さらに多くの仮想ポートを作成すると、マスターが同じ名前であってもマスターごとに異なるファイル記述子が取得されるため、問題は発生しません。

39
Aquiles

com0com (Windowsを使用している場合)のようなものを使用して仮想シリアルポートを設定し、その上で開発する方が簡単な場合があります。

6
mtrw

次のコードを使用して、任意のシリアルポート./fooをエミュレートできました。

SerialEmulator.py

import os, subprocess, serial, time

# this script lets you emulate a serial device
# the client program should use the serial port file specifed by client_port

# if the port is a location that the user can't access (ex: /dev/ttyUSB0 often),
# Sudo is required

class SerialEmulator(object):
    def __init__(self, device_port='./ttydevice', client_port='./ttyclient'):
        self.device_port = device_port
        self.client_port = client_port
        cmd=['/usr/bin/socat','-d','-d','PTY,link=%s,raw,echo=0' %
                self.device_port, 'PTY,link=%s,raw,echo=0' % self.client_port]
        self.proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        time.sleep(1)
        self.serial = serial.Serial(self.device_port, 9600, rtscts=True, dsrdtr=True)
        self.err = ''
        self.out = ''

    def write(self, out):
        self.serial.write(out)

    def read(self):
        line = ''
        while self.serial.inWaiting() > 0:
            line += self.serial.read(1)
        print line

    def __del__(self):
        self.stop()

    def stop(self):
        self.proc.kill()
        self.out, self.err = self.proc.communicate()

socatをインストールする必要があります(Sudo apt-get install socat)およびpyserial pythonパッケージ(pip install pyserial)。

pythonインタープリターを開き、SerialEmulatorをインポートします。

>>> from SerialEmulator import SerialEmulator
>>> emulator = SerialEmulator('./ttydevice','./ttyclient') 
>>> emulator.write('foo')
>>> emulator.read()

その後、クライアントプログラムは./ttyclientをpyserialでラップして、仮想シリアルポートを作成できます。クライアントのコードを変更できない場合は、client_portを/dev/ttyUSB0または同様に設定することもできますが、Sudoが必要になる場合があります。

この問題にも注意してください: Pyserialは仮想ポートではうまく機能しません

5

それはあなたが今達成しようとしていることに少し依存します...

クラスのシリアルポートへのアクセスをラップし、ソケットI/OまたはファイルI/Oを使用する実装を作成できます。次に、同じインターフェイスを使用するようにシリアルI/Oクラスを記述し、デバイスが利用可能になったときにプラグインします。 (これは実際には、外部ハードウェアを必要とせずに機能をテストするのに適した設計です。)

または、コマンドラインインターフェイスにシリアルポートを使用する場合は、stdin/stdoutを使用できます。

または、- linuxの仮想シリアルデバイス に関する他の回答があります。

4
Dave Bacher

デバイスにアクセスせずにアプリケーションをテストする必要がある場合は、ループデバイスが適切に機能するでしょう。 pySerial 2.5に含まれています https://pythonhosted.org/pyserial/url_handlers.html#loop

3
steko

Linuxを実行している場合は、次のように socat コマンドを使用できます。

socat -d -d pty,raw,echo=0 pty,raw,echo=0

コマンドを実行すると、作成したシリアルポートが通知されます。私のマシンではこれは次のようになります:

2014/04/23 15:47:49 socat[31711] N PTY is /dev/pts/12
2014/04/23 15:47:49 socat[31711] N PTY is /dev/pts/13
2014/04/23 15:47:49 socat[31711] N starting data transfer loop with FDs [3,3] and [5,5]

これで/dev/pts/13に書き込み、/dev/pts/12で受信できます。逆も同様です。

3
Richard