webentwicklung-frage-antwort-db.com.de

Mit PySerial kann auf Daten gewartet werden?

Ich habe ein Python-Programm, das Daten von einem seriellen Port über das PySerial-Modul liest. Die zwei Bedingungen, die ich berücksichtigen muss, sind: Ich weiß nicht, wie viele Daten entstehen werden, und ich weiß nicht, wann ich mit Daten rechnen muss.

Darauf basierend habe ich die folgenden Code-Snipets gefunden:

#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

Daher wird dieser Code für immer in einer Schleife ausgeführt, um Daten von der seriellen Schnittstelle zu erhalten. Wir erhalten bis zu 500 Zeichen, um die Daten zu speichern, und alarmieren Sie die Hauptschleife, indem Sie ein Flag setzen. Wenn keine Daten vorhanden sind, schlafen wir einfach weiter und warten.

Der Code funktioniert, aber ich mag das 5s-Timeout nicht. Ich brauche es, weil ich nicht weiß, wie viele Daten zu erwarten sind, aber es gefällt mir nicht, dass es alle 5 Sekunden aufwacht, selbst wenn keine Daten vorhanden sind. 

Gibt es eine Möglichkeit zu überprüfen, wann Daten verfügbar sind, bevor Sie das read-Objekt ausführen? Ich denke so etwas wie den select-Befehl in Linux.

BEARBEITEN:
Ich dachte nur, ich würde feststellen, dass ich die inWaiting()-Methode gefunden habe, aber wirklich scheint es, als würde ich meinen "Schlaf" in eine Umfrage umwandeln. Ich möchte einfach nur schlafen, bis Daten eingehen, und dann gehen Sie los.

16
Mike

Ok, ich habe tatsächlich etwas zusammengestellt, das mir gefällt. Verwenden einer Kombination aus read() ohne Timeout und der inWaiting()-Methode:

#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

Dies scheint die Ergebnisse zu liefern, die ich wollte. Ich glaube, diese Art von Funktionalität existiert in Python nicht als einzelne Methode

17
Mike

Sie können timeout = None setzen, dann wird der Aufruf read blockiert, bis die angeforderte Anzahl von Bytes vorhanden ist. Wenn Sie warten möchten, bis Daten eingehen, führen Sie einfach eine read(1) mit Timeout None aus. Wenn Sie Daten ohne Blockierung prüfen möchten, führen Sie eine read(1) mit Timeout Null durch und prüfen Sie, ob Daten zurückgegeben werden.

(siehe Dokumentation http://pyserial.sourceforge.net/pyserial_api.html )

11
TJD
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

nenne es so:

cmd('ATZ',serial.Serial('/dev/ttyUSB0', timeout=1, baudrate=115000))
0
user5509884