2

I'm no Linux expert so please go easy ;).

Ok, the situation is that I have a single board computer running Debian Wheezy. I know its old/risky etc etc but its not actually "my" equipment and therefore I have no control over this.

There is some software running on it, written in c# and ran through mono. Again, this is not my software and I have zero control over it or the ability to alter the code.

The software sends AT commands down a physical serial port (/dev/ttyS1) to a modem which returns the appropriate responses to the commands.

The modems are no longer available and therefore I need to develop some alternative. Therefore I thought I could run a simple python script on the SBC that would "intercept" the AT commands, send back the appropriate responses to the c# software and then I can use the python script to talk to another device however I need to.

Having had a good "google", socat seemed to be the best option for doing this. However, I have tried I dont know how many combinations and cannot get it to work the way I need it to.

The physical setup is that I currently have the serial port plugged into my laptop so I can see the AT commands coming up the pipe (on ttyS1) I then ssh into the SBC and fire up minicom to view the new "virtual ports" created by socat.

Existing Setup

C# <-> ttyS1 <-> Old Modem

Desired Setup

C# <-> socat <-> python -> New Modem

Below is just two of the variations I've tried:

socat -x /dev/ttyS1,raw,echo=0,crnl PTY,link=/dev/ttyV1,raw,echo=0,crnl

... also tried the other way around in case I misunderstood ...

socat -x PTY,link=/dev/ttyV1,raw,echo=0,crnl /dev/ttyS1,raw,echo=0,crnl

I've also tried many different variations, pushing to files, "teeing" off to files, different command switches, configuring the ports using stty etc etc

Every time I have the same issue that I cannot actually see the AT commands being sent from the c# software?!

I can type into minicom on the SBC and see the output turning up on the serial port reader on my laptop, likewise I can type into the serial port reader on my laptop and see the input in minicom on the SBC, however what I cannot seem to intercept is the actual AT commands being sent from the c# software even though the software is configured to use ttyS1.

The one bit of control I do have over the software is which port it uses to talk to the modem on. Therefore I have also tried changing this to a virtual port e.g. /dev/ttyV1 and running socat to create the virtual port during startup and before the c# program starts so that the virtual port is actually available. Again I have exactly the same issue where I still cannot see the AT commands being sent by c# software.

Hope someone can help as I've been at this two full days now and cannot get it to work. I'm pretty sure socat is the tool to use and hopefully I've just fundamentally misunderstood how it works.

0

2 Answers 2

0

There's probably one mandatory part that is missing: the serial port rate.

Attempting a similar experiment works once I set the serial port rate in socat options:

socat -x PTY,link=/dev/ttyV1,raw,echo=0,crnl /dev/ttyS1,b115200,raw,echo=0,crnl

Here for 115200 bauds I used b115200. socat's man tell to use this command to see what are all the possible b... options:

socat -hh |grep 'b[1-9]'

(and also:

Note: On some operating systems, these options may not be available. Use ispeed or ospeed instead.

)

Using as test application (yes, screen can handle a serial port):

screen /dev/ttyV1 115200

instead of

screen /dev/ttyS1 115200

I was able to login as usual with an other system configured to have console through serial port (screen's 115200 parameter becomes useless but that's to show this shouldn't disrupt an application).

Everything sent or received was displayed in hex by -x.


I think I answered your question as stated. Your goal appears to be aiming at altering traffic which is a bigger task, but you asked how to read traffic that pass through a serial port.

You'd need a dedicated tool to alter traffic, especially when characters are not buffered (making using sed & alike in the middle of the pipeline probably more difficult).

Typically there would be a 1st socat command for the first half (the PTY) that would call with EXEC: an executable for traffic alteration (which can be a shell script or python or whatever and will have to manage both sides possibly using up to 4 different FDs) which would call a 2nd socat for the second half (ttyS1).

1
  • Hi AB, thanks for taking a look and your detailed response. I had already tried the baud rate setting but still not managed to get it working. I did however give it another go and still hitting the same problem whereby I cannot see the AT commands being sent by the physical hardware. If I open a terminal on the device in either ttyS1 or ttyV1 and then also have my serial program open at the other end of the physical serial port then these two terminals will basically echo whatever I type in either terminal. However the issue still persists where I cannot see/read the AT commands being sent.
    – RobF
    Commented Aug 1, 2022 at 12:16
0

HardwareW - /dev/ttyUSB0 <---> socat/logging <---> ~/myserial <---> Python Serial script

  1. Plug your ttyUSB0 device, and get your user access to ttyUSB0 using:

    sudo chown youruser.youruser -R /dev/ttyUSB0
    
  2. Start Socat

    socat -d -d -x /dev/ttyUSB0,b9600,rawer  PTY,link=$HOME/myserial,rawer,echo=0 2>log3
    
  3. Send data/requests to RS232 device.

    python myserial-client.py '*IDN?'
    

    Please note, that often devices require certain sequence of chars,eg. *IDN?, and will not respond to Minicom terminal, which send data char by char *,I,D,N,?.

    Example myserial-client.py:

    import sys
    import serial
    DEFAULT_ADDR = '/home/krzys/myserial'
    DEFAULT_CMD = 'R5'
    args = len(sys.argv) - 1
    if args == 0:
        addr, cmd = DEFAULT_ADDR, DEFAULT_CMD
    elif args == 1:
        addr, cmd = DEFAULT_ADDR, sys.argv[1]
    else:
        addr, cmd = sys.argv[1:3]
    
    cmd += '\r\n'
    s = serial.Serial("/home/krzys/myserial",9600,timeout=0.5)
    s.write(cmd.encode())
    print(s.readline())
    
  4. It is good to check your script, ahead by writing virtual myserver.py script, where you could test+validate sending and receiving frames.

Please check this Gist, on how to setup in linux virtual Python simulator, and client to test serial communication.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .