PYSERIAL Convert LF to LF/CR - python

I am using the GhostPDL pcl6 application to print text files to PDFs. The text files contain captured text from a serial port connected to a PLC controller. Some of the print data is from an older system that used only line feed LF for end of line termination and did not provide the CR carriage return character. The results were the PDF prints had the "Stair Stepping" problem. A laser printer can be set to AUTO CR to allow the prints to print normally. However, I could find no solution to set up the -sDEVICE=pdfwrite settings in the pcl6 print command to add the auto CR.
My serial capture program is based on a modified version of pySerial tcp_serial_redirect.py.
https://github.com/jaredly/pydbgp/blob/master/symbian/serial_tcp_redirect.py
This is used on a Raspberry Pi to be used as a programmable Device Server. The serial print of forwarded to an Ethernet printer port 9100.
Along with other features, in order to capture the serial data to a text file, I added a write to file command to the program:
if data:
logfile = open("/var/www/active_log.txt","a")
logfile.write(data)
logfile.close()
The problem was the text file did not have the required CR characters. The Python program in Windows creates a text file and converts the LF to LF/CR but not on the Raspberry Pi.
My solution was found in the original pyserial program:
http://sourceforge.net/p/pyserial/code/HEAD/tree/trunk/pyserial/examples/tcp_serial_redirect.py
I simplified the join and split formula.
if data:
data = '\r\n'.join(data.split('\n'))
logfile = open("/var/www/active_log.txt","a")
logfile.write(data)
logfile.close()
After hours of searching for a solution, this one seems to be the simplest. I tried stty settings and other avenues. Perhaps this may help someone or maybe there is a better solution?

As I understand it you are trying to replace all the \n with \r\n. How about something like this?
data = data.replace('\n', '\r\n')
Hope this helps.

Related

Unable to read from the Serial Port using PySerial

This is my function. i am trying to send the word sensors to the COM Port and then get back the result.
def serialportcommunication():
ser = serial.Serial(
port='COM5',
baudrate=115200
)
print('Writing SENSORS command to COM7')
ser.write(b"sensors")
time.sleep(4)
print('Reading 10 bytes from serial buffer')
read_val = ser.read(size=10)
print(read_val)
print('Done printing output')
Output I get of the code above:
Writing SENSORS command to COM7
Reading 10 bytes from serial buffer
b'sensors\r\n '
Done printing output
If I execute the command "sensors" to the COM Port using a Terminal Program like Putty, I get a wall of text from my target device (the sample output is shown below, I had to white out most of the output though).
This text I am reading back, I want to read it in Python using teh command above of ser.read(size = ??), but I don't read anything back.
How to read it back?
MY SCREENSHOT FROM USING PUTTY
Resolved in comments:
Do you have to hit Enter when typing the command manually? Then you need to do the same here - ser.write(b"sensors\r") (or maybe \n, or \r\n). – jasonharper
Yes, when i enter the command in Putty, I to hit enter. Thank you thank you. I added the '\n in the end and it works now!!!! – Neil Dey

I am receiving \\r\\n on carriage return instead of \r\n

The project uses sockets to read from a connecting client until either there is no more characters to be read or it receives a \r\n. Here is a snippet of the code:
while True:
ch = connection.recv(1)
data += ch.decode('UTF-8')
if data.endswith('\r\n') or not ch:
data = data.replace('\r\n','')
break
The code works as intended when windows is used to run the server that reads from clients. However when I try to run it on a raspberry pi running rasbian, it always reads a carriage return as '\\r\\n'. For example when a client sends:
-list_networks wlan0 5180<return>
yields a string looking like:
-list_networks wlan0 5180\\r\\n
Why is this? Because of this it does not get read as a carriage return and is missed. I know different OS return different of strings for carriage return but I didn't find anything about this string when I researched a bit. Am I missing something? Suggestions and explanations are appreciated.
edit:
Forgot to add the command is sent through a telnet connection. I want to be able to connect to the socket via telnet. Type a command and when the enter key is pressed the command the loop will recognize and end the loop.

Creating a remote a file over serial using python

I have a host connected to a Linux target over serial. The target is using the serial port for shell I/O. I need to save a text file on the target with contents from the host.
I thought I could get away with doing:
ser.write("cat > file.txt\n")
ser.write([contents I need to add to the file])
ser.write(chr(4))
ser.write(chr(4))
But the 's I'm sending aren't closing the file. I've tried a few variations of chr(4)... \x04, print, str =, and a few others, but they all fail the same way.
If I simulate this with minicom, and follow up sending the [contents...] with uploading a 2 byte file that holds 0x04 0x04, the file closes as expected.
I haven't tried opening the "EOF" file in python and sending it yet. I'll do it, I'm about out of options. But I'm new to python, so I must be doing something wrong.
Any obvious newb-fixing answer to this one?
Thanks.
As a workaround, could you use a heredoc ?
ser.write("cat > file.txt << END_OF_FILE\n")
ser.write([contents I need to add to the file])
ser.write("\nEND_OF_FILE\n");
For a more robust solution, you should probably have to look at some file transfer protocol over serial line, like Kermit.

Writing raw IP data to an interface (linux)

I have a file which contains raw IP packets in binary form. The data in the file contains a full IP header, TCP\UDP header, and data. I would like to use any language (preferably python) to read this file and dump the data onto the line.
In Linux I know you can write to some devices directly (echo "DATA" > /dev/device_handle). Would using python to do an open on /dev/eth1 achieve the same effect (i.e. could I do echo "DATA" > /dev/eth1)
Something like:
#!/usr/bin/env python
import socket
s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW)
s.bind(("ethX", 0))
blocksize = 100;
with open('filename.txt') as fh:
while True:
block = fh.read(blocksize)
if block == "": break #EOF
s.send(block)
Should work, haven't tested it however.
ethX needs to be changed to your interface (e.g. eth1, eth2, wlan1, etc.)
You may want to play around with blocksize. 100 bytes at a time should be fine, you may consider going up but I'd stay below the 1500 byte Ethernet PDU.
It's possible you'll need root/sudoer permissions for this. I've needed them before when reading from a raw socket, never tried simply writing to one.
This is provided that you literally have the packet (and only the packet) dumped to file. Not in any sort of encoding (e.g. hex) either. If a byte is 0x30 it should be '0' in your text file, not "0x30", "30" or anything like that. If this is not the case you'll need to replace the while loop with some processing, but the send is still the same.
Since I just read that you're trying to send IP packets -- In this case, it's also likely that you need to build the entire packet at once, and then push that to the socket. The simple while loop won't be sufficient.
No; there is no /dev/eth1 device node -- network devices are in a different namespace from character/block devices like terminals and hard drives. You must create an AF_PACKET socket to send raw IP packets.

Pyserial testing

I am new to Pyserial and Hardware area. I am trying to run the sample applications given in http://pyserial.sourceforge.net/shortintro.html#opening-serial-ports
import serial
ser = serial.Serial(0) # open first serial port
print ser.portstr # check which port was really used
ser.write("hello") # write a string
ser.close()
I have written this program in a python file and running it. Now if I want to test this application to check if I am sending correct string (eg: Hyperterminal or something) how can I do this. Can anyone guide me?
Use virtual serial port for your test.
For Windows I use com0com and socat for Linux.
Then, use Putty for visualization of your send.
Another quick way to test a physical serial port is to take a wire/screwdriver, crocodile clamp or anything that you have in hand and bridge the RX and TX (receive and transmit) together. At that point, everything that you send out will be looped back at you. YOu can receive it afterward by using this code snippet here:
import serial
ser = serial.Serial(0, timeout = 1) # open first serial port
print ser.portstr # check which port was really used
ser.write("hello") # write a string
msg = ser.read("100") #read the content of the input buffer until you get 100 byte or a timeout event
print(msg) #print the content you might need to decode it print(decode(msg))
ser.close()
The key aspect again for this code to work properly is to bridge RX and TX together. A lot of tutorial will show you how to do this.

Categories

Resources