12

我正在使用 pySerial 向 Eddie 发送命令。我需要在我的 readline 中指定一个回车符,但是 pySerial 2.6 摆脱了它......有解决方法吗?

以下是本 PDF 的第二页和第三页中列出的Eddie 命令集。这是 PDF 无法访问的情况下的备用图像

通用命令形式:

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

如您所见,所有响应都以\r. 我需要告诉 pySerial 停止。

我现在拥有的:

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
4

5 回答 5

20

我遇到了同样的问题并实现了我自己的 readline() 函数,我从 pyserial 包中的 serialutil.py 文件中复制和修改了该函数。

串行连接是该函数所属的类的一部分,并保存在属性“self.ser”中

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)

这是一个比等待超时更安全、更好、更快的选择。

编辑:我在尝试使 io.TextIOWrapper 方法工作时遇到了这篇文章(感谢zmo)。因此,您可以使用以下方法,而不是使用上面提到的自定义 readline 函数:

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()

确保将参数传递1BufferedRWPair,否则它不会在每个字节后将数据传递给 TextIOWrapper ,从而导致串行连接再次超时。

当设置line_bufferingTrue您不再需要flush在每次写入后调用该函数(如果写入以换行符终止)。

编辑: TextIOWrapper 方法实际上适用于命令字符串,但它的行为是未定义的,并且在传输超过几个字节时可能导致错误。最安全的做法是实现您自己的readline.

于 2013-06-06T12:17:16.510 回答
5

从 pyserial 3.2.1(默认来自 debian Stretch)read_until可用。如果您想将墨盒从默认 ('\n') 更改为 '\r',只需执行以下操作:

import serial
ser=serial.Serial('COM5',9600)
ser.write(b'command\r')  # sending command
ser.read_until(b'\r')   # read until '\r' appears

b'\r'可以更改为您将用作回车的任何内容。

于 2018-09-26T04:48:05.593 回答
4

来自 pyserial 的文档

(原文如此)

笔记:

当pySerial 与模块可用的较新 Python 版本 (V2.6+) 一起运行时,不再支持eol参数 for 。停产readline()io

要为通用换行模式指定EOL字符readline()或使用通用换行模式,建议使用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")
于 2013-06-06T12:28:09.850 回答
1

从端口 3 读取 10 条数据,板速 38400,传入数据时数据以 \n 字符分隔

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
于 2017-06-06T07:48:43.320 回答
-3

似乎发生超时是因为readline()等待'\n'来自串行设备的字符,它从不发送。

根据pyserial 文档,您可以指定行尾字符:

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

那样有用吗?

于 2013-05-10T00:11:28.330 回答