PySerial 2.6: indicate end of line in readline ()

I am sending Eddie commands using pySerial. I need to specify a carriage return in my readline, but pySerial 2.6 got rid of it ... Is there a workaround?

Here is the Eddie Command Set on the second and third pages of this PDF file. Here is a backup image in case PDF is not available.

The general form of the command:

Input: <cmd>[<WS><param1>...<WS><paramN>]<CR> Response (Success): [<param1>...<WS><paramN>]<CR> Response (Failure): ERROR[<SP>-<SP><verbose_reason>]<CR> 

As you can see, all answers end in \r . I need to tell pySerial to stop it.

What I have now:

 def sendAndReceive(self, content): logger.info('Sending {0}'.format(content)) self.ser.write(content + '\r') self.ser.flush(); response = self.ser.readline() # Currently stops reading on timeout... if self.isErr(response): logger.error(response) return None else: return response 
+6
source share
4 answers

I have the same problem and implemented my own readline () function, which I copied and modified from the serialutil.py file found in the pyserial package.

A serial connection is part of the class to which this function belongs and is stored in the "self.ser" attribute

 def _readline(self): eol = b'\r' leneol = len(eol) line = bytearray() while True: c = self.ser.read(1) if c: line += c if line[-leneol:] == eol: break else: break return bytes(line) 

This is a safer, more convenient and faster option than waiting for a timeout.

EDIT: I came across this when trying to get io.TextIOWrapper to work (thanks to zmo ), so instead of using the custom readline function as above, you can use:

 self.ser = serial.Serial(port=self.port, baudrate=9600, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, timeout=1) self.ser_io = io.TextIOWrapper(io.BufferedRWPair(self.ser, self.ser, 1), newline = '\r', line_buffering = True) self.ser_io.write("ID\r") self_id = self.ser_io.readline() 

Be sure to pass argument 1 to BufferedRWPair , otherwise it will not pass data to TextIOWrapper after each byte, causing a reconnection to the timeout.

When setting line_buffering to True you no longer need to call the flush function after each record (if the record ends with a newline).

EDIT: The TextIOWrapper method works in practice for small command lines, but its behavior is undefined and can lead to errors when transmitting more than two bytes. The safest thing to do is implement your own version of readline .

+16
source

from pyserial documentation :

(so in the original)

Note:

The eol parameter for readline() no longer supported when pySerial starts with newer versions of Python (V2.6 +), where the io module is available. Eol

To specify an eol character for readline() or to use universal newline mode, we recommend using io.TextIOWrapper :

 import serial import io ser = serial.serial_for_url('loop://', timeout=1) sio = io.TextIOWrapper(io.BufferedRWPair(ser, ser)) sio.write(unicode("hello\n")) sio.flush() # it is buffering. required to get the data out *now* hello = sio.readline() print hello == unicode("hello\n") 
+3
source

reading 10 data from port 3 with the 38400 board, data is separated by the \ n character when it enters the incoming data

 import serial as self ser=self.Serial("COM3", 38400) buffer = [] count = 0.0 c = "\0" while count < 10: c = "\0" if ser.inWaiting(): while True: val = ser.read(1) if "\n" in val: break else: c += val buffer.append(c) # stores all data received into a list count += 1 print buffer 
+1
source

It seems that a timeout is occurring because readline() expects the character '\n' to come from a serial device that it never sends.

According to the pyserial documentation, you can specify the end of line character:

 response = self.ser.readline(eol='\r') 

It works?

-2
source

Source: https://habr.com/ru/post/944658/


All Articles