Ответ 1
Вероятно, лучше использовать pyserial для связи с последовательным портом, и вы можете просто создать макетную версию serial.Serial
класс, который реализует read
, readline
, write
и любые другие методы, которые вам нужны.
У меня есть приложение, в котором я хочу имитировать соединение между устройством и "модемом". Устройство будет подключено к последовательному порту и будет разговаривать с программным модемом.
В целях тестирования я хочу иметь возможность использовать макет программного обеспечения для проверки отправки и получения данных.
Пример кода Python
device = Device()
modem = Modem()
device.connect(modem)
device.write("Hello")
modem_reply = device.read()
Теперь, в моем последнем приложении, я просто передам /dev/ttyS 1 или COM1 или что-то другое для использования приложения. Но как я могу сделать это в программном обеспечении? Я использую Linux, а приложение написано в Python.
Я попытался сделать FIFO (mkfifo ~/my_fifo
), и это действительно работает, но тогда мне понадобится один FIFO для записи и один для чтения. Я хочу открыть ~/my_fake_serial_port
и читать и писать на него.
Я также lpayed с модулем pty
, но не могу заставить это работать. Я могу получить дескриптор ведущего и подчиненного файлов из pty.openpty()
, но попытка их чтения или записи вызывает сообщение об ошибке IOError Bad File Descriptor
.
Комментарии указали мне на вопрос SO Есть ли какая-то программа, например COM0COM в linux?, которая использует socat
для установки виртуального последовательного соединения.
Я использовал его так:
socat PTY,link=$HOME/COM1 PTY,link=$HOME/COM2
Для всех вас, спасибо за предоставленную мне ценную информацию. Я решил согласиться с ответом Винай Саипса, потому что это решение, к которому я пошел, пока не появилось предложение соната. Кажется, он работает достаточно хорошо.
Вероятно, лучше использовать pyserial для связи с последовательным портом, и вы можете просто создать макетную версию serial.Serial
класс, который реализует read
, readline
, write
и любые другие методы, которые вам нужны.
Вы находитесь на правильном пути с псевдотерминалами. Для этого вашему макетному программному устройству необходимо сначала открыть псевдотерминальный мастер - это файловый дескриптор, с которого он будет считывать и записывать, когда он разговаривает с серийным программным обеспечением, которое вы тестируете. Затем ему необходимо предоставить доступ и разблокировать псевдотерминальный ведомый и получить имя подчиненного устройства. Затем он должен распечатать имя ведомого устройства где-нибудь, чтобы вы могли сообщить другому программному обеспечению, чтобы он открыл это как его последовательный порт (то есть, это программное обеспечение будет открывать имя, например /dev/pts/0
вместо /dev/ttyS1
).
Затем программное обеспечение симулятора просто считывает и записывает с главной стороны псевдотерминала. В C это будет выглядеть так:
#define _XOPEN_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
int pt;
pt = open("/dev/ptmx", O_RDWR | O_NOCTTY);
if (pt < 0)
{
perror("open /dev/ptmx");
return 1;
}
grantpt(pt);
unlockpt(pt);
fprintf(stderr, "Slave device: %s\n", ptsname(pt));
/* Now start pretending to be a modem, reading and writing "pt" */
/* ... */
return 0;
}
Надеюсь, это достаточно просто, чтобы преобразовать в Python.
Здесь pythonic версия pts-emulated (caf's) последовательной связи:
from serial import Serial
driver = MyDriver() # what I want to test
peer = serial.Serial()
driver.port.fd, peer.fd = posix.openpty()
driver.port._reconfigurePort()
peer.setTimeout(timeout=0.1)
peer._reconfigurePort()
driver.start()
# peer.write("something")
# driver.get_data_from_serial()
Он имеет некоторые преимущества перед издевательским Serial, а именно, что используется Serial-код и используются некоторые артефакты последовательного порта.
Если вы хотите проверить открытие последовательных портов, вы можете поменять местами ведущие и подчиненные и использовать os.ttyname(salve_fd)
как имя последовательного порта. Однако я не могу ручаться за побочные эффекты обмена мастером и подчиненными. Наиболее примечательным является то, что вы можете закрыть и снова открыть ведомый, но fi вы также закроете главные подчиненные матрицы.
Это работает как шарм, если ваш тестовый код работает в одном и том же процессе. Я еще не сгладил перегибы с несколькими/отдельными процессами.