Python time.time_ns unterschiedliche Zeiten im loop

Revolution

Commodore
Registriert
März 2008
Beiträge
4.965
Hallo zusammen,

Ich benutze innerhalb einer while schleife time.time_ns()

Python:
unixtime = str(time.time_ns())

und rufe den Parameter unixtime dann dreimal innerhalb der schleife auf. Ich ging davon aus das ich dadurch dreimal den exakt gleichen timestamp bekomme. Leider ist dem nicht so, gibt es eine Möglichkeit die Zeit zu fixieren für jeden loop?
 
Einmal am Beginn jeder Schleife definieren und dieses variable dann innerhalb des Loops verwenden?
 
  • Gefällt mir
Reaktionen: BeBur
Sorry das war etwas missverständlich. Mit Parameter war die variabel gemeint. Sprich später in der schleife verwenden ich dann nur noch unixtime. Womit ich eigentlich immer den gleichen Wert erwartet hätte.
 
Python:
i=0
        while True:
                i = i + 1
                line = ser.readline().decode('ascii', errors='replace')
                unixtime = str(time.time_ns())
                if "$GPRMC,,V,,,,,,,,,,N*53" in line:
                        pass
                elif    "$GPRMC" in line:
                            line = line.strip()
                            TOPIC = "car/123/rmc"
                            DATA = (line + sep + unixtime + sep)
                            client.publish(TOPIC, DATA, qos=QOS)
                            client.loop()

                if "$GPGGA,,,,,,0,,,,,,,,*66" in line:
                        pass
                elif    "$GPGGA" in line:
                            line = line.strip()
                            TOPIC = "car/123/gga"
                            DATA = (line + sep + unixtime + sep)
                            client.publish(TOPIC, DATA, qos=QOS)
                            client.loop()

                if "$GPVTG,,T,,M,,N,,K,N*2C" in line:
                        pass
                elif    "$GPVTG" in line:
                            line = line.strip()
                            TOPIC = "car/123/vtg"
                            DATA = (line + sep + unixtime + sep)
                            client.publish(TOPIC, DATA, qos=QOS)
                            client.loop()
 
Zuletzt bearbeitet:
unixtime = copy.deepcopy(str(..))

sollte das lösen können
 
Das Problem ist doch, dass hier 3 NMEA Nachrichten hintereinander empfangen werden und mit dem geposteten Code natürlich jede mit einer anderen Timestamp versehen wird. Falls die Nachrichten immer in der gleichen Reihenfolge und immer vollständig empfangen werden, dann wäre eine Lösung, die Timestamp bei der ersten Nachricht zu setzen und nicht direkt nach jedem Lesen von der seriellen Schnittstelle.
 
Nolag schrieb:
Das Problem ist doch, dass hier 3 NMEA Nachrichten hintereinander empfangen werden und mit dem geposteten Code natürlich jede mit einer anderen Timestamp versehen wird. Falls die Nachrichten immer in der gleichen Reihenfolge und immer vollständig empfangen werden, dann wäre eine Lösung, die Timestamp bei der ersten Nachricht zu setzen und nicht direkt nach jedem Lesen von der seriellen Schnittstelle.
Ich hab es gerade mal ins erste els und elsif geschoben. Daraufhin können die zweiten und dritten if nicht mehr darauf zugreifen.

M4ttX schrieb:
unixtime = copy.deepcopy(str(..))

sollte das lösen können
bekomme ich NameError: name 'copy' is not defined zurück hab mich mal schlau gemacht aber irgendwie blick ich die Funktionsweise nicht ganz
 
eigentlich sehe ich gar kein problem mit "unixtime", der string wird nicht verändert. kann eine line vom seriellen interface wirklich drei verschiedene nachrichtentypen enthalten, so dass man drei gleiche timestamps erwarten würde? normalerweise hat man doch eine message pro line und damit hast du auch unterschiedliche timestamps.

ist DATA wirklich ein tupel? ich glaube bei deinem letzten problem war es noch ein string? dazu hast du viel doppelten code drin, das lässt sich reduzieren.

Python:
def client_publish(client, topic, line, sep):
    unixtime = str(time.time_ns())
    client.publish(topic, line + sep + unixtime + sep, qos=QOS)
    client.loop()

with serial.Serial('/dev/ttyUSB1', baudrate=115200, timeout=1) as ser:
    i = 0
    while True:
        i += 1
        line = ser.readline().decode('ascii', errors='replace').strip()

        if "$GPRMC,,V,,,,,,,,,,N*53" in line:
            pass
   
        elif  "$GPRMC" in line:
            client_publish(client, "car/123/rmc", line, sep)

        if "$GPGGA,,,,,,0,,,,,,,,*66" in line:  # eigentlich auch elif?
            pass

        elif "$GPGGA" in line:
            client_publish(client, "car/123/gga", line, sep)

        if "$GPVTG,,T,,M,,N,,K,N*2C" in line:  # eigentlich auch elif?
            pass
   
        elif "$GPVTG" in line:
            client_publish(client, "car/123/vtg", line, sep)
 
Zuletzt bearbeitet:
Also ziel dahinter ist das ich VTG das von sich aus keine Zeit hat mit den anderen beiden verknüpft kann. Alle drei werden praktisch zur gleichen Zeit zu einem Server geschickt.

Na ja ich zerlege mir den String halt um ihn schöner in ne Datenbank zu bekommen.


Könntest du mir noch kurz nen gefallen tun und mein Kennzeichen aus dem Code entfernen habe es zu spät gesehen das es drin war :D. Danke
 
können denn "rmc", "gga" und "vtg" wirklich gleichzeitig in einer "line" vom seriellen interface stehen? falls ja, muss unixtime in der while(True) schleife gesetzt werden - aber auch dort ändert sich der wert nicht, wenn man es zu einem anderen string zusammensetzt.

sind die drei werte immer in einzelnen zeilen, dann garantiert auch dein ansatz nicht, dass alle drei werte mit dem selben timestamp in der datenbank landen, denn bei jedem durchlauf von while(True) kann sich "unixtime" ändern
Ergänzung ()

Revolution schrieb:
bekomme ich NameError: name 'copy' is not defined zurück hab mich mal schlau gemacht aber irgendwie blick ich die Funktionsweise nicht ganz
"import copy" wenn das ausprobieren möchtest.
 
  • Gefällt mir
Reaktionen: mercury
ok das mit copy war ne selten dämliche Frage :D bringt leider nur auch nichts.

nein die drei können Systembedingt nicht in einer Line stehe aber sie kommen innerhalb von einer Sekunde oder weniger hintereinander. Ich möchte den timestamp für alle drei Parameter praktisch als link verwenden um einen durchlauf zu identifizieren. Klar könnte ich auch von 1 bis X zählen aber bei jedem Neustart wäre ich dann wieder bei 0 außer ich Speicher das jedes mal wo ab was ich auch nicht unbedingt will.
 
Revolution schrieb:
nein die drei können Systembedingt nicht in einer Line stehe aber sie kommen innerhalb von einer Sekunde oder weniger hintereinander.
ok, also 3 werte in 3 schleifendurchgängen - wenn du time.time_ns() verwendest, ist es doch kein wunder, wenn du jedesmal einen anderen wert in "unixtime" hast. du holst dir einen timestamp in nanosekunden-genauigkeit. so schnell kann deine schleife und die abfrage der seriellen schnittstelle gar nicht sein, als dass sich der wert über mehrere schleifendurchgänge hinweg nicht ändern würde.

du kannst auf sekunden-genauigkeit runtergehen str(int(time.time())) - aber auch dann ist nicht garantiert, dass nicht "rmc", "gga" in sekunde x und "vtg" in sekunde x+1 kommt.

wenn es immer drei datensätze "rmc", "gga" und "vtg" sind, dann sammel die ersten beiden und schicke alle mit einem timestamp ab wenn "vtg" gelesen wurde:
Python:
with serial.Serial('/dev/ttyUSB1', baudrate=115200, timeout=1) as ser:
    i = 0
    rmc = ""
    gga = ""

    while True:
        i = i + 1
        line = ser.readline().decode('ascii', errors='replace').strip()

        if "$GPRMC,,V,,,,,,,,,,N*53" in line:
            pass
       
        elif  "$GPRMC" in line:
            rmc = line

        elif "$GPGGA,,,,,,0,,,,,,,,*66" in line:
            pass

        elif "$GPGGA" in line:
            gga = line

        elif "$GPVTG,,T,,M,,N,,K,N*2C" in line:
            pass
       
        elif "$GPVTG" in line:
            # nur vollständige datensätze verschicken
            if rmc and gga:  
                unixtime = str(time.time_ns())
                client.publish("car/123/rmc", rmc + sep + unixtime + sep, qos=QOS)
                client.loop()  # k.a. ob .loop() immer gleich notwendig ist
                client.publish("car/123/gga", gga + sep + unixtime + sep, qos=QOS)
                client.loop()
                client.publish("car/123/vtg", line + sep + unixtime + sep, qos=QOS)
                client.loop()
                rmc, gga = "", ""
 
Zuletzt bearbeitet:
Ok ich glaub ich hab ein Verständnis Problem.

Ich ging bisher immer davon aus das mit unixtime = str(time.time_ns()) innerhalb einer schleife einmalig eine Zeit generiert und ich diesen wert immer wieder holen kann ohne das er sich verändert da er nur einmalig in der schleife erzeugt wird und nicht durch jeden Aufruf.

Im Prinzip müsste ich den wert auslesen einfrieren und nach vtg wieder löschen. Jetzt muss ich nur noch wissen wie das geht :D
 
Revolution schrieb:
Ich ging bisher immer davon aus das mit unixtime = str(time.time_ns()) innerhalb einer schleife einmalig eine Zeit generiert und ich diesen wert immer wieder holen kann ohne das er sich verändert da er nur einmalig in der schleife erzeugt wird und nicht durch jeden Aufruf.
das ist auch so. aber wenn jede serielle line nur einen wert "rmc", "gga" oder "vtg" enthält, dann musst du für alle 3 werte auch mindestens 3mal deine while(True) schleife durchlaufen. und weil du time.time_ns() verwendest bekommst du jedesmal einen anderen timestamp.

ich hatte meinen vorherigen post nochmal ergänzt. vielleicht hilft das weiter.
 
  • Gefällt mir
Reaktionen: Revolution
Ein echtes Minimalbeispiel zu bauen hilft btw. in 99,9% der Fälle, das Problem sofort zu identifizieren.
 
Ich denke, dass das Problem inzwischen verstanden ist. Die Annahme des TE, dass die drei Nachrichten mit einem Schleifendurchlauf behandelt werden, ist einfach nicht richtig. Es sind drei Durchläufe und daher ist die Zeit immer unterschiedlich.
 
Zurück
Oben