Виртуальное последовательное устройство в Python? - PullRequest
38 голосов
/ 18 февраля 2010

Я знаю, что могу использовать, например, pySerial, чтобы общаться с последовательными устройствами, но что, если у меня нет устройства прямо сейчас, но все еще нужно написать клиент для него? Как я могу написать «виртуальное последовательное устройство» на Python и поговорить с ним по pySerial, как, например, запустить локальный веб-сервер? Возможно, я просто плохо ищу, но не смог найти никакой информации по этой теме.

Ответы [ 6 ]

34 голосов
/ 26 февраля 2013

это то, что я делал и работал для меня до сих пор:

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)

Если вы создадите больше виртуальных портов, у вас не возникнет проблем, поскольку разные мастера получают разные файловые дескрипторы, даже если они имеют одинаковыеимя.

6 голосов
/ 18 февраля 2010

Может быть проще использовать что-то вроде com0com (если вы в Windows) для настройки виртуального последовательного порта и разработки на этом.

4 голосов
/ 26 мая 2016

Я смог эмулировать произвольный последовательный порт ./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 не очень хорошо работает с виртуальным портом

4 голосов
/ 19 февраля 2010

Это немного зависит от того, чего вы пытаетесь достичь сейчас ...

Вы можете обернуть доступ к последовательному порту в классе и написать реализацию, чтобы использовать сокет ввода-вывода или файловый ввод-вывод. Затем напишите свой класс последовательного ввода-вывода, чтобы использовать тот же интерфейс, и подключите его, когда устройство будет доступно. (На самом деле это хороший дизайн для тестирования функциональности без внешнего оборудования.)

Или, если вы собираетесь использовать последовательный порт для интерфейса командной строки, вы можете использовать stdin / stdout.

Или есть другой ответ о виртуальных последовательных устройствах для linux .

3 голосов
/ 24 апреля 2014

Если вы работаете в 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, и наоборот.

2 голосов
/ 18 февраля 2011

Возможно, петлевое устройство выполнит эту работу, если вам нужно протестировать ваше приложение без доступа к устройству. Включено в pySerial 2.5 https://pythonhosted.org/pyserial/url_handlers.html#loop

...