J'ai un programme python qui lit les données d'un port série via le module PySerial
. Les deux conditions que je dois garder à l'esprit sont les suivantes: je ne sais pas quelle quantité de données va être générée et je ne sais pas quand attendre des données.
Sur cette base, je suis arrivé avec les extraits de code suivants:
#Code from main loop, spawning thread and waiting for data
s = serial.Serial(5, timeout=5) # Open COM5, 5 second timeout
s.baudrate = 19200
#Code from thread reading serial data
while 1:
tdata = s.read(500) # Read 500 characters or 5 seconds
if(tdata.__len__() > 0): #If we got data
if(self.flag_got_data is 0): #If it's the first data we recieved, store it
self.data = tdata
else: #if it's not the first, append the data
self.data += tdata
self.flag_got_data = 1
Donc, ce code restera en boucle pour obtenir des données du port série. Nous aurons jusqu'à 500 caractères pour stocker les données, puis alerterons la boucle principale en définissant un drapeau. Si aucune donnée n'est présente, nous allons simplement nous rendormir et attendre.
Le code fonctionne, mais je n'aime pas le délai d'attente de 5 secondes. J'en ai besoin parce que je ne sais pas combien de données attendre, mais je n'aime pas que cela se réveille toutes les 5 secondes, même en l'absence de données.
Existe-t-il un moyen de vérifier quand les données deviennent disponibles avant de faire la variable read
? Je pense à quelque chose comme la commande select
sous Linux.
MODIFIER:
Je pensais juste que j’ai remarqué que j’avais trouvé la méthode inWaiting()
, mais cela semble vraiment changer mon "sommeil" en un sondage, donc ce n’est pas ce que je veux ici. Je veux juste dormir jusqu'à l'arrivée des données, puis aller les chercher.
Ok, j'ai en fait quelque chose que j'aime bien pour ça. Utilisation d'une combinaison de read()
sans délai d'expiration et de la méthode inWaiting()
:
#Modified code from main loop:
s = serial.Serial(5)
#Modified code from thread reading the serial port
while 1:
tdata = s.read() # Wait forever for anything
time.sleep(1) # Sleep (or inWaiting() doesn't give the correct value)
data_left = s.inWaiting() # Get the number of characters ready to be read
tdata += s.read(data_left) # Do the read and combine it with the first character
... #Rest of the code
Cela semble donner les résultats que je voulais, je suppose que ce type de fonctionnalité n'existe pas en tant que méthode unique en Python
Vous pouvez définir timeout = None
, puis l'appel read
sera bloqué jusqu'à ce que le nombre d'octets demandé soit atteint. Si vous voulez attendre que les données arrivent, faites simplement une read(1)
avec timeout None
. Si vous souhaitez vérifier des données sans bloquer, effectuez une opération read(1)
avec timeout zéro et vérifiez si elle renvoie des données.
(voir documentation http://pyserial.sourceforge.net/pyserial_api.html )
def cmd(cmd,serial):
out='';prev='101001011'
serial.flushInput();serial.flushOutput()
serial.write(cmd+'\r');
while True:
out+= str(serial.read(1))
if prev == out: return out
prev=out
return out
appelez ça comme ça:
cmd('ATZ',serial.Serial('/dev/ttyUSB0', timeout=1, baudrate=115000))