Python PySerial readline function wrong use - python

I'm using a script importing PySerial
to read from COM4
messages I would like to intercept end with a couple of #
so I tried to use
bus.readline(eol='##')
where bus is my connection.
I expected to read like:
*#*3##
*#*3##
*#*3##
Unfortunalyy I found also
*#*1##*1*1*99##
that I expected to read spleetted into 2 lines
*#*1##
*1*1*99##
Clearly readline is not working but why?

The readline() method in pyserial reads one character at a time and compares it to the EOL character. You cannot specify multiple characters as the EOL. You'll have to read in and then split later using string.split() or re.split()

Related

Parse Data received from Pyserial read into string

I am reading data from a serial port using python (pyserial) I am able to read the data but when I try using it, it seems like this $*%\xff\x06$*%\xff\x02 referred to few resources on stack overflow and found that it needs to be decoded, I tried decoding it to ascii using processed = (binascii.b2a_qp(raw))using the binascii library but received the following output $*%=FF=00$*%=FF=08 I have also tried decoding the same to UTF-8 but still no success. Any suggestions about how to process the input received from the read() function. I also tried using the readline() but the program then goes blank or infinite execution seems there is no EOL marker in the serial output.
The Demo Code snip is as follows :
with serial.Serial('/dev/cu.usbserial-Device',9600) as ser:
ser.flushInput()
ser.flushOutput()
ser.write('S')
inputVal=[]
while(len(inputVal)<10000):
val = ser.read(10)
inputVal.append(binascii.b2a_qp(val))
Any suggestions ? Thanks in advance.
You can try to encode whilst writing to the serial port.
ser.write(str.encode('S\r')
While, to read, I would use something like
a = ser.readline()
b = v.rstrip()
c = b.decode('utf-8')

python3 for win and cygwin - line endings in buffer

Setup: python3.6 for windows in Cygwin (have to use Win version because of functionalities introduced in 3.5 and Cygwin is stuck at 3.4)
How to get \n new lines in buffer (stdout) output from a python script (instead of \r\n)? The output is a list of paths and I want to get one per line for further processing by other Cygwin/Windows tools.
All answers I've found so far are dealing with file writing and I just want to modify what is written to stdout. So far the only sure way to get rid of \r is piping results through sed 's/\\10//' which is awkward.
Weird thing is that even Windows applications fed with script output don't accept it with messages like:
Can't find file <asdf.txt
>
(note newline before >)
Supposedly sys.stdout.write is doing pure output but when doing:
sys.stdout.write(line)
I get a list of paths without any separation. If I introduce anything which resembles NL (\n, \012, etc.) it is automatically converted to CRLF (\r\n). How to stop this conversion?
You need to write to stdout in binary mode; the default is text mode, which translates everything you write.
According to Issue4571 you can do this by writing directly to the internal buffer used by stdout.
sys.stdout.buffer.write(line)
Note that if you're writing Unicode strings you'll need to encode them to byte strings first.
sys.stdout.buffer.write(line.encode('utf-8')) # or 'mbcs'

Python io module's TextIOWrapper or BuffereRWPair functions are not playing nicely with pySerial

I'm writing a serial adapter for some scientific hardware whose command set uses UTF-8 character encodings. All responses from the hardware are terminated with a carriage return (u'\r'). I would like to able to use pySerial's readline() function with an EOL character specified, so I have this setup, ala this thread:
import serial
import io
ser = serial.Serial(port='COM10', baudrate=128000)
sio = io.TextIOWrapper(io.BufferedRWPair(ser, ser, 1), encoding='utf-8', newline=u'\r')
ser.open()
# these commands move to coordintes (25000, 0, 25000)
cmd = 'M\x80\x1a\x06\x00\x00\x00\x00\x00\x80\x1a\x06\x00'
ucmd = u'M\x80\x1a\x06\x00\x00\x00\x00\x00\x80\x1a\x06\x00'
#this works
ser.write(cmd)
print sio.readline()
#this does not
sio.write(ucmd)
sio.flush()
print sio.readline()
Strangely, the first command string (non-unicode using pySerial directly) elicits the correct behavior from the hardware. The second (unicode via Python's io module) causes it to move erratically and then hang. Why would this be? Sending unicode command strings to the hardware does work IF the command string is only a couple of a characters. Once you start sending bytes with hex(ord(byte)) values > 0x7F (outside ASCII range), then you start running intro trouble. I can work around this problem without too much trouble, but would like to know what is going on. Thanks!
From io docs:
BufferedRWPair does not attempt to synchronize accesses to its
underlying raw streams. You should not pass it the same object as
reader and writer; use BufferedRandom instead.
I'm guessing that's your problem, as you are passing same object ser as reader and writer. BufferendRandom doesn't look like it quite fits the bill either.
So is your problem with serial that it hangs waiting for the EOL?

Reading both newline types from an already opened file in python

I'm using subprocess.popen to run a command and grab the stdout.
It so happens that the program (mplayer) sort of uses both eol types \n and \r. The \rs come from terminal control characters. So the output I end up with are regular lines interspersed with really long lines where the \rs were ignored.
I know if I had opened a file myself, I could set the newline type. However, I'm getting the stdout from popen so I have no control over that.
I had a look at the python 2.7 source and I image I can somehow use TextIOWrapper to respect both eol types. However I'm not too sure what I need to pass to it. I know I need to pass the constructor some sort of buffer, but I don't know how to get the buffer from an already opened file.
All in all, how to I readline() in python that breaks at both \n and \r given an already open file/stream?
Popen.subprocess (and Popen.check_output if the convenience function is enough for you), have a universal_newlines parameter which by default is False, but when set to True will give you the behaviour you need of converting all newline variants to \n.

pyserial.readline() with python 2.7

I am using python 2.7.2 with pyserial 2.6.
What is the best way to use pyserial.readline() when talking to a device that has a character other than "\n" for eol? The pyserial doc points out that pyserial.readline() no longer takes an 'eol=' argument in python 2.6+, but recommends using io.TextIOWrapper as follows:
ser = serial.serial_for_url('loop://', timeout=1)
sio = io.TextIOWrapper(io.BufferedRWPair(ser, ser))
However the python io.BufferedRWPair doc specifically warns against that approach, saying "BufferedRWPair does not attempt to synchronize accesses to its underlying raw streams. You should not pass it the same object as reader and writer; use BufferedRandom instead."
Could someone point to a working example of pyserial.readline() working with an eol other than 'eol'?
Thanks,
Tom
read() has a user-settable maximum size to the data it reads(in bits), if your data strings are a predictable length you could simply set that to capture a fixed-length string. it's sort of 'kentucky windage' in execution but so long as your data strings are consistent in size it won't bork.
beyond that, your real option is to capture and write the data stream to another file and split out your entries manually/programatically.
for example, you could write your datastream to a .csv file, and adjust the delimiter variable to be your EoL character.
Assume s is an open serial.serial object and the newline character is \r.
Then this will read to end of line and return everything up to '\r' as a string.
def read_value(encoded_command):
s.write(encoded_command)
temp = ''
response = ''
while '\r' not in response:
response = s.read().decode()
temp = temp + response
return temp
And, BTW, I implemented the io.TextIOWrapper recommendation you talked about above and it 1)is much slower and 2)somehow makes the port close.

Categories

Resources