Python Linux下的伪串行通信
我有一个应用程序,我想模拟设备和“调制解调器”之间的连接。该设备将连接到串行端口,并通过该端口与软件调制解调器通信 出于测试目的,我希望能够使用模拟软件设备来测试发送和接收数据 Python代码示例Python Linux下的伪串行通信,python,linux,serial-port,Python,Linux,Serial Port,我有一个应用程序,我想模拟设备和“调制解调器”之间的连接。该设备将连接到串行端口,并通过该端口与软件调制解调器通信 出于测试目的,我希望能够使用模拟软件设备来测试发送和接收数据 Python代码示例 device = Device() modem = Modem() device.connect(modem) device.write("Hello") modem_reply = device.read() 现在,在我的最后一个应用程序中,我将只通过/dev/ttyS1或COM1或应用程序
device = Device()
modem = Modem()
device.connect(modem)
device.write("Hello")
modem_reply = device.read()
现在,在我的最后一个应用程序中,我将只通过/dev/ttyS1或COM1或应用程序要使用的任何东西。
但我如何在软件中做到这一点?我正在运行Linux,应用程序是用Python编写的
我已经试过做一个FIFO(mkfifo~/my_FIFO
),这确实有效,但是我需要一个FIFO用于写入,一个用于读取。我想要的是打开~/my\u-fake\u-serial\u-port
并对其进行读写
我还使用了pty
模块,但也无法使其正常工作。我可以从pty.openpty()
获取主文件描述符和从文件描述符,但尝试读取或写入它们只会导致IOError错误文件描述符
错误消息
更新
评论将我引向SO问题,该问题使用socat
设置虚拟串行连接。
我是这样用的:
#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;
}
socat PTY,link=$HOME/COM1 PTY,link=$HOME/COM2
其他人,谢谢你们给我提供了宝贵的信息。
我选择接受Vinay Sajips的回答,因为这是我在socat建议出现之前所寻求的解决方案。它似乎工作得很好。可能最好使用它与串行端口通信,您只需创建一个模拟版本的
串行.serial
类,它实现了读取
、读取线
、写入
以及您需要的任何其他方法。您使用伪终端的方法是正确的。要做到这一点,您的模拟软件设备需要首先打开一个伪终端主机-这是它将读取和写入的文件描述符,当它与您正在测试的串行软件通信时。然后,它需要授予对伪终端从设备的访问权限并解锁,并获取从设备的名称。然后,它应该在某个地方打印出从设备的名称,以便您可以告诉其他软件将其作为串行端口打开(即,该软件将打开一个类似/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;
}
定义源代码
#包括
#包括
#包括
int main(int argc,char*argv[])
{
int-pt;
pt=打开(“/dev/ptmx”,O_RDWR | O_NOCTTY);
if(pt<0)
{
perror(“open/dev/ptmx”);
返回1;
}
格兰特普特(pt);
解锁(pt);
fprintf(stderr,“从设备:%s\n”,ptsname(pt));
/*现在开始假装是调制解调器,读写“pt”*/
/* ... */
返回0;
}
希望这很容易转换成Python。以下是pts模拟(caf)串行通信的Python版本:
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()
与模拟串行相比,它有一些优点,即使用串行代码和一些串行端口人工制品
如果您想测试串行端口的打开,可以交换主端口和从端口,并使用os.ttyname(salve\u fd)
作为串行端口名。但我不能保证交换主从的副作用。最值得注意的是,您可以关闭和重新打开奴隶,但您关闭主奴隶也会死亡
如果您的测试代码在同一个进程中运行,这就像一个魅力。我还没有通过多个/单独的流程解决这些问题。您是否尝试过类似PTY模块的方法?mtrw:谢谢!成功了!检查一下这个谢谢,这就是我最后要做的。