Я знаю, что могу использовать, например, pySerial, чтобы общаться с последовательными устройствами, но что, если у меня сейчас нет устройства, но мне все еще нужно написать для него клиент? Как я могу написать «виртуальное последовательное устройство» на Python и заставить pySerial разговаривать с ним, как я бы, скажем, запустил локальный веб-сервер? Возможно, я просто плохо ищу, но мне не удалось найти никакой информации по этой теме.
Виртуальное последовательное устройство в Python?
Ответы (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)
Если вы создадите больше виртуальных портов, у вас не будет проблем, так как разные мастера получают разные файловые дескрипторы, даже если у них одинаковое имя.
s_name
), но всякий раз, когда я выдаю ser.write("...")
, этот текст просто возвращается эхом в следующий раз, когда я os.read(master,1000)
, независимо от того, есть ли что-нибудь подключен к порту, а другой конец порта, похоже, не получает данные.
- person Ponkadoodle; 23.07.2015
File "<stdin>", line 1, in <module> File "/usr/local/lib/python2.7/dist-packages/serial/serialutil.py", line 180, in __init__ self.open() File "/usr/local/lib/python2.7/dist-packages/serial/serialposix.py", line 311, in open self._update_dtr_state() File "/usr/local/lib/python2.7/dist-packages/serial/serialposix.py", line 605, in _update_dtr_state fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_DTR_str) IOError: [Errno 22] Invalid argument
- person Samuel Góngora; 10.03.2016
/dev/tty
, запустив python с помощью sudo или сменив владельца файла на вас.
- person Patrick Steadman; 26.05.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 плохо работает с виртуальным портом < / а>
Может быть проще использовать что-то вроде com0com (если вы работаете в Windows) для настройки виртуального последовательного порта. , и развивайтесь на этом.
com0com
альтернатива (с API), которую я могу использовать в своем коммерческом программном обеспечении as it is
? Мне просто нужно, чтобы у пользователя были виртуальные последовательные порты
- person mrid; 12.05.2020
Если вы используете 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
, и наоборот.
Возможно, петлевое устройство выполнит эту работу, если вам нужно протестировать приложение без доступа к устройству. Он включен в pySerial 2.5 https://pythonhosted.org/pyserial/url_handlers.html#loop
Это немного зависит от того, чего вы сейчас пытаетесь достичь ...
Вы можете обернуть доступ к последовательному порту в класс и написать реализацию для использования ввода-вывода сокетов или файлового ввода-вывода. Затем напишите свой класс последовательного ввода-вывода для использования того же интерфейса и подключите его, когда устройство будет доступно. (На самом деле это хороший дизайн для тестирования функциональности без использования внешнего оборудования.)
Или, если вы собираетесь использовать последовательный порт для интерфейса командной строки, вы можете использовать stdin / stdout.
Или есть другой ответ о виртуальных последовательных устройствах для Linux.