Виртуальное последовательное устройство в Python?

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

6 ответов

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

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)

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

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

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

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

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

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

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

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

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

Другие вопросы по тегам