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.
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.
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
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
.
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")
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
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.