如何在软件中将两个物理串行端口相互桥接(并记录数据)?

时间:2010-10-27 01:12:38

标签: serial-port

基本上,我想将计算机放在串行线路的中间,并记录通过它的对话。我正在尝试对这个对话进行反向工程,最终模仿对话的一端。

我正在尝试做的粗略图表:

通常,我有这个:

__________        __________  
|        |        |        |  
|Device 1|<======>|Device 2|  
|________|        |________|  

我想这样做:

__________     __________     __________  
|        |     |        |     |        |  
|Device 1|<===>|Computer|<===>|Device 2|  
|________|     |________|     |________|  

中间的计算机基本上可以连接两个设备之间的连接并记录经过的数据。

使用任何编程语言的答案可能都很有用。我最好能在Windows或Linux上执行此操作(如果有人对此问题有一般解决方案,则可以同时执行此操作)。

5 个答案:

答案 0 :(得分:4)

嗯,一种编程方式就是打开相关设备,开始在它们之间转发数据,同时保存到文件中。

大多数语言都可以做到。有很好的库,比如java和python。

Web上存在几个实现,我通过googling找到了一个叫做Telnet串行桥(TSB)的python,它允许你通过以太网桥接连接,并使用像putty这样的telnet工具进行记录。

虽然在过去,我已经使用rxtx.qbang.org的java rxtx串口通讯库来自己做,虽然我怀疑现在有更新版本,或者可能是JVM中内置的东西。

改编自该网站上的示例:

import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;

import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class TwoWaySerialComm
{
    void bridge( String portName1, String portName2 ) throws Exception
    {
        CommPortIdentifier portIdentifier1 = CommPortIdentifier.getPortIdentifier(portName1);
        CommPortIdentifier portIdentifier2 = CommPortIdentifier.getPortIdentifier(portName2);

        if ( portIdentifier1.isCurrentlyOwned() || portIdentifier2.isCurrentlyOwned())
        {
            System.out.println("Error: Port is currently in use");
        }
        else
        {
            CommPort commPort1 = portIdentifier1.open(this.getClass().getName(),2000);
            CommPort commPort2 = portIdentifier2.open(this.getClass().getName(),2000);

            if ( commPort instanceof SerialPort && commPort2 instanceof SerialPort )
            {
                SerialPort serialPort1 = (SerialPort) commPort1;
                serialPort1.setSerialPortParams(57600,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);

                InputStream in1 = serialPort1.getInputStream();
                OutputStream out1 = serialPort1.getOutputStream();

                SerialPort serialPort2 = (SerialPort) commPort2;
                serialPort2.setSerialPortParams(57600,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);

                InputStream in2 = serialPort2.getInputStream();
                OutputStream out2 = serialPort2.getOutputStream();

                (new Thread(new SerialReader(in1, out2))).start();
                (new Thread(new SerialReader(in2, out1))).start();
            }
            else
            {
                System.out.println("Error: Only serial ports are handled by this example.");
            }
        }     
    }

    /** */
    public static class SerialReaderWriter implements Runnable 
    {
        InputStream in;
        OutputStream out;

        public SerialReader ( InputStream in, OutputStream out )
        {
            this.in = in;
            this.out = out;
        }

        public void run ()
        {
            byte[] buffer = new byte[1024];
            int len = -1;
            try
            {
                while ( ( len = this.in.read(buffer)) > -1 )
                {
                    out.write(buffer,0, len);
                    System.out.print(new String(buffer,0,len));
                }
            }
            catch ( IOException e )
            {
                e.printStackTrace();
            }            
        }
    }

    public static void main ( String[] args )
    {
        try
        {
            (new TwoWaySerialComm()).bridge("COM1", "COM3");
        }
        catch ( Exception e )
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

答案 1 :(得分:1)

我可以使用2个软件实用程序为Windows提供解决方案:

TCP COM Bridge - 可以通过内部TCP连接连接2个COM端口。 高级串行端口监视器 - 可以监视和记录设备之间的对话。

这两个实用程序都在这里: http://www.aggsoft.com/

答案 2 :(得分:0)

好吧,我是一个新手,因为你没有对你所使用的平台说什么,我会告诉你我做了什么,但我会提前警告你,这取决于你可能的软件或者可能没有,这实际上可能根本就不是答案,所以请注意。

我的硬件是MacBook Pro 2.4 GHZ,运行速度为10.7.5,内存为4GB。 我试图做的是从Wine运行的应用程序中读取串行通信聊天(因为应用程序是基于Windows的,但我不想使用Windows(icky poo)。哎呀,我不想使用mac,但我没有在虚拟linux中取得进展,加上Ubuntu在他们使用的一些细节命令行“schtuff”的方向上有点奇怪。

启动所需的软件。 Parallels Desktop Build 7.0.15107(可能在Virtual Box中执行此操作,我还没试过) MultiCom(由Martin Louis for Mac提供的免费软件) http://members.iinet.net.au/~mgl/MartysPlace/MultiCom.html Ubuntu 8.0.4 Hardy Heron

可能还有其他方法,我一定要追赶十几种方法来做我想做的事情,而且我对输出感到不满意,所以这可能是浪费时间。

此解决方案不使用

  • strace
  • ttysnoop
  • gpspipe
  • socat
  • pyserial

说实话,ttysnoop似乎正是我想要的,socat似乎是一个遥远的第二,但对于一个新手来说有点太多了。

我与其他客户遇到的问题(可能是由于我无法弄清楚如何更改有关com连接的功能)与阻塞有关。当您监视串行端口时,您想要的是非阻塞连接。所以你只是听口喋喋不休,不要干涉。

如果您与客户建立连接,例如......

  • jpnevulator
  • 小型机
  • cutecom
  • 屏幕等

......似乎他们接管了com端口,突然无法让你监控串口。必须有一种方法来配置它们,所以情况并非如此,但我无法弄明白。再加上一个复杂的问题,如果你试图从mac端监视你的虚拟机中的端口正在做什么,它仍然有点粘性或试图用任何方式你可以通过这个“碰撞”如何发送相同数据到2个串口。所以,如果你比我更聪明,我邀请你,让我不那么愚蠢。

在Mac端......

  • 启动MultiCom

设置 - 端口A

  • a)配置为串行
  • b)串行设备/dev/cu.KeySerial(在我的情况下,您需要使用终端并尝试输入ls / dev / tty来发现您需要启发的端口。*
  • c)单击“确定”并选中启用复选框。

设置 - 端口B

  • a)套接字文件服务器
  • b)套接字文件:/Users/shadowwraith/Desktop/socket.txt

在虚拟机端(Parallels Ubuntu 8.0.4)

  • a)使用VM shutdown configure,通过指定完整路径,添加2个引用与CLIENTS(而非服务器)相同的套接字文件的串行端口。
  • b)通过选中复选框启用两者(注意:请记住,就VM而言,串行设备没有USB连接。您通过MultiCom软件进行连接(或者如果您知道其他方式)一,MultiCom正在做的是充当USB串行连接器的单端口连接的管道,然后将所有I / O复制到所有客户端可以连接的套接字文件服务器,其中可以是多个VM或多个串行端口同一个VM。)
  • c)引导VM并为您的程序设置一个串口,为您的嗅探设置另一个串口。和POOF ..你去。

请参阅下文,了解更多关于该做什么的技术细节...... Linux的 如何显示串口? dmesg | grep tty

这是你输入嗅探器读取输入的内容,假设您选择主动使用串行连接的串口在另一个插座端口上,例如ttyS0在com 1(ttyS1在com 3 in这可以通过使用dmesg | grep tty来解决这个问题。

查看信息...... jpnevulator --ascii --timing-print --tty“/ dev / ttyS1”-read


你不应该使用的无关信息,但是导致我理解为什么这是错误的做法...

如何映射linux中的com端口(当你不担心嗅探端口或使用configure添加串口时)? ln -s / dev / ttyUSB0 com3

撤消此类型 unlink com3

其中ttyUSB0是从dmesg |找到的端口grp tty和com3是Wine的理想端口。这在〜/ .wine / dosdevices目录中完成。

答案 3 :(得分:0)

这是一个在两个物理端口之间桥接的小型Python脚本#!/ usr / bin / python

import time, sys, serial
import collections
import re
from serial import SerialException
from termcolor import colored

SERIALPORT1 = "/dev/rfcomm0"  # the default com/serial port the receiver is connected to
BAUDRATE1 = 115200      # default baud rate we talk to Moteino

SERIALPORT2 = "/dev/ttyUSB0"  # the default com/serial port the receiver is connected to
BAUDRATE2 = 9600      # default baud rate we talk to Moteino


# MAIN()
if __name__ == "__main__":
    try:
        # open up the FTDI serial port to get data transmitted to Moteino
        ser1 = serial.Serial(SERIALPORT1, BAUDRATE1, timeout=1) #timeout=0 means nonblocking
        ser1.flushInput();
        print "\nCOM Port [", SERIALPORT1, "] found \n"
    except (IOError, SerialException) as e:
        print "\nCOM Port [", SERIALPORT1, "] not found, exiting...\n"
        exit(1)

    try:
        # open up the FTDI serial port to get data transmitted to Moteino
        ser2 = serial.Serial(SERIALPORT2, BAUDRATE2, timeout=1) #timeout=0 means nonblocking
        ser2.flushInput();
        print "\nCOM Port [", SERIALPORT2, "] found \n"
    except (IOError, SerialException) as e:
        print "\nCOM Port [", SERIALPORT2, "] not found, exiting...\n"
        exit(1)

    try:    

        while 1:
            ser1_waiting = ser1.inWaiting()
            if ser1_waiting > 0:
                #rx1 = ser1.read(ser1_waiting)
                rx1 = ser1.readline()
                ser2.write(rx1)
                print colored(rx1, 'red')
            ser2_waiting = ser2.inWaiting()
            if ser2_waiting > 0:
                #rx2 = ser2.read(ser2_waiting)
                rx2 = ser2.readline()
                ser1.write(rx2)
                print rx2       


    except IOError:
        print "Some IO Error found, exiting..." `

答案 4 :(得分:0)

例如,使用从设备的rx / tx到计算机com端口rx引脚的电缆,并运行终端或串行端口记录器。就是这样。