web-dev-qa-db-fra.com

pySerial 2.6: spécifie la fin de ligne dans readline ()

J'envoie des commandes à Eddie en utilisant pySerial. Je dois spécifier un retour chariot dans ma ligne de lecture, mais pySerial 2.6 s'en est débarrassé ... Existe-t-il une solution de contournement?

Voici le jeu de commandes Eddie est répertorié aux deuxième et troisième pages de ce PDF. Voici une image de sauvegarde dans le cas où le PDF est inaccessible.

Formulaire de commande général:

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

Comme vous pouvez le constater, toutes les réponses se terminent par un \r. Je dois dire à pySerial de s'arrêter.

Ce que j'ai maintenant:

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
10
Mr. Polywhirl

J'ai le même problème et j'ai implémenté ma propre fonction readline () que j'ai copiée et modifiée à partir du fichier serialutil.py présent dans le paquet pyserial.

La connexion série fait partie de la classe à laquelle cette fonction appartient et est enregistrée dans l'attribut '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)

C'est une option plus sûre, plus agréable et plus rapide que d'attendre le délai d'attente.

EDIT: J'ai rencontré this post en essayant de faire fonctionner la méthode io.TextIOWrapper (merci zmo ). Ainsi, au lieu d'utiliser le fonction readline personnalisée comme mentionné ci-dessus, vous pouvez utiliser:

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

Assurez-vous de passer l'argument 1 à la BufferedRWPair, sinon les données ne seront pas transmises à TextIOWrapper après chaque octet, ce qui entraînera une nouvelle expiration de la connexion série.

Lorsque vous définissez line_buffering sur True, vous ne devez plus appeler la fonction flush après chaque écriture (si l'écriture se termine par un caractère de nouvelle ligne).

EDIT: La méthode TextIOWrapper fonctionne en pratique pour les chaînes de commande small , mais son comportement est indéfini et peut entraîner erreurs lors de la transmission de plusieurs octets. Le plus sûr consiste à implémenter votre propre version de readline

20
lou

de pyserial's documentation :

(sic)

Remarque:

Le paramètre eol pour readline() n'est plus pris en charge lorsque pySerial est exécuté avec les versions plus récentes de Python (V2.6 +) où le module io est disponible. EOL

Pour spécifier le caractère EOL pour readline() ou pour utiliser le mode de nouvelle ligne universel, il est conseillé d'utiliser 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

lecture de 10 données du port 3 avec un débit de carte 38400, les données sont séparées par un caractère\n lorsqu’elles entrent dans les données entrantes

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

Depuis pyserial 3.2.1 (valeur par défaut depuis debian Stretch) read_until est disponible. si vous souhaitez remplacer la cartouche par défaut ('\ n') par '\ r', faites simplement:

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

"\ r" peut être remplacé par tout ce que vous utiliserez comme cartouche. 

0
Chenming Zhang