web-dev-qa-db-ja.com

pySerial 2.6:readline()で行末を指定する

PySerialを使用してコマンドをEddieに送信しています。 readlineで改行を指定する必要がありますが、pySerial 2.6はそれを取り除きました...回避策はありますか?

こちらが Eddieコマンドセット で、このPDFの2ページ目と3ページ目に記載されています。 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
12
Mr. Polywhirl

私は同じ問題を抱えており、pyserialパッケージにあるserialutil.pyファイルからコピーして変更した独自のreadline()関数を実装しています。

シリアル接続は、この関数が属するクラスの一部であり、属性 '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メソッドを機能させようとしたときに this 投稿に遭遇しました(ありがとう 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_bufferingからTrueへの書き込みごとにflush関数を呼び出す必要がなくなりました(書き込みが改行文字で終了している場合)。

編集:TextIOWrapperメソッドはsmallコマンド文字列に対して実際に機能しますが、その動作は定義されておらず、送信時に errors につながる可能性があります数バイト以上。実際に最も安全なことは、独自のバージョンのreadlineを実装することです。

20
lou

pyserialの ドキュメント から:

(シック)

注意:

readline()eolパラメーターは、pySerialがモジュールioが使用可能な新しいPythonバージョン(V2.6 +)で実行されている場合、サポートされなくなりました。EOL

readline()EOL文字を指定するか、ユニバーサル改行モードを使用するには、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")
4
zmo

ボードレート38400でポート3から10個のデータを読み取ります。着信データに入ると、データは\ 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
1
sajin

Pyserial 3.2.1以降(デフォルトはdebian Stretchから)read_untilが利用可能です。カートリッジをデフォルト( '\ n')から '\ r'に変更するには、次のようにします。

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

'\ r'は、カートリッジとして使用するものに変更できます。

0
Chenming Zhang