python CAN Bus Nachricht empfangen mit timeout

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
muekno
User
Beiträge: 20
Registriert: Dienstag 28. Januar 2020, 18:20

Ich habe einen CAN Bus mit Python auf einen RASPI am laufen, für ein Smart Home Projekt. Kann senden und empfangen. Soweit alles gut.
Allerdings wenn ich nun mit <code>msg = bus.recv()</code> etwas empfangen will aber keine Nachricht kommt würde ich den Versuch gerne nach einen Timeout abbrechen. Schleife mit timeout ist auch klar, aber scheinbar wartet bus.recv() ewig.
Was ich bräuchte wäre ein Befehl mit dem ich testen kann ob eine Nachricht empfange wurde die ich dan abrufen kann. Trotz vielem Googeln hab eich nichts gefunden. Kann mir bitte jemand weiterhelfen.
Danke
Benutzeravatar
sparrow
User
Beiträge: 4538
Registriert: Freitag 17. April 2009, 10:28

Funktioniert es denn, wenn dann irgendwann eine Nachricht eintrifft? Warum ist es ein Problem darauf ewig zu warten?

Möglicherweise möchtest du asynchron oder in einem eigenen Thread die Daten empfangen und in eine queue schreiben.

Ansonsten wäre interessant, wie und mit welchem Modul du da Daten lesen willst. Aus der Zeile Code geht das nicht hervor.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

muekno
User
Beiträge: 20
Registriert: Dienstag 28. Januar 2020, 18:20

OK etwas ausführlicher, Ich habe verschieden CAN Knoten, die zum einen Informationen von Tastern, Sensoren auswerten und via CAN zu anderen Knoten senden und dort Anzeigen bzw. Aktionen auslösen sowie auch eine Antwort senden die auf dem ursprünglichen Knoten wiederum Aktionen auslösen, das funktioniert prima. Die knoten basieren auf Arduinos. Dann habe ich den Pi auf dem sind Konfigurationsdaten gespeichert, die via CAN zu den einzelnen Knoten gesendet werden um dort bestimmte Sachen einzustellen. Alle Arduino Knoten haben dieselbe Software, machen aber entsprechend er im EEPROM gespeicherten Konfiguration unterschiedliches. Ferner kann der Pi Statis und Konfiguration von den Knoten abfragen etc. Alles geht schön. Was ebenfalls geht ist ein CAN Monitor, der die Nachrichten auf dem Bus dekodiert anzeigt.
Nur wenn ich jetzt einen Knoten anspreche der aus ist oder defekt kommt keine Antwort und alles hängt. ganz simpel z.B. ein Ping, ist Knoten alive, der auf einen Antwort wartet, oder eine Schleife über alle Knotenadressen um festzustellen welche Knoten alive sind. jeder Knoten kennt in seiner Konfiguration seine Adresse die in der CAN ID kodiert ist, da in der CAN ID auch die Absender Adresse codiert ist kann der Knoten gezielt antworten .
So ist nun ein Knoten inaktiv, deffekt etc. "Ende Gelände", genau hier brauch ich den Timeout um weiter zu kommen.
Was ich inzwischen gefunden habe ist, ich kann recv() einen Timeout mitgeben, was auch funktioniert, aber dann habe ich eine leere Arbitartion ID und so dumm es klingt wie farge ich ab ob die leer ist, denn wen leer stirbt mein Programm bei der Dekodierung dieser ID mit einer Fehlermeldung.
Komplettes Projekt SmartHome demnächst auf meiner Website .

Danke

P.S. Programmiere schon seit fast 50 Jahren, bin aber relativ blutiger Anfänger in Python
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@muekno: Was heisst das denn konkret? Code? Ausnahme? Was heisst ”leer”? Gibt es das Attribut nicht? Oder hat das einen Wert mit dem Du nicht rechnest? Falls ja welcher Wert wäre das denn?
Zuletzt geändert von __blackjack__ am Mittwoch 11. März 2020, 08:55, insgesamt 1-mal geändert.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
sparrow
User
Beiträge: 4538
Registriert: Freitag 17. April 2009, 10:28

Hast du meinen Post gelesen?
Welches Modul verwendest du und wie sieht dein Code aus?
Wenn du seit über 50 Jahre programmierst, weißt du doch, dass Code viel mehr aussagt als eine Beschreibung der Umgebung.

Und dann dazu: Welches Verhalten erwartest du und welches Verhalten tritt bei deinem Code ein?
muekno
User
Beiträge: 20
Registriert: Dienstag 28. Januar 2020, 18:20

Danke inzwischen gelöst. Code wesentlicher Teil
<code>
# wait for an acknoledge of a send message
# return false if timeout of 1 seconds
# we check if is from the node we sent the data
# we ignore all other messages
def wait_PingReply(bus,target_id): # wait acknolage
msg = bus.recv(1) # get the receive message
if not (msg is None):
decode_id(msg.arbitration_id) # decode ID to global values
if M_type == PINGREPLY and S_ID == target_id: # check if ACK messag and from target
return True # return true on ACK
else:
return False # return false on tmeout
#=================
</code>

das "if not (msg is None):" also "if not (val is None):" war die Lösung.
Danke
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Bitte in Zukunft die richtigen code-tags benutzen, die haben hier im Forum [ statt <.

Und schoen, dass das Problem geloest ist. Es ist allerdings unidiomatisch, not (msg is None) zu schreiben. Zum einen ist die Klammerung ueberfluessig, vor allem aber zieht man das not *in* den Operator:

Code: Alles auswählen

if msg is not None:
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

Da ist so einiges falsch. Der Kommentar vor der Funktion gehört in die Funktion als doc-String. Variablen- und Funktionsnamen schreibt man komplett klein_mit_unterstrich.
Globale Variablen darf man nicht benutzen, decode_id sollte das, was es ermittelt als Rückgabewert haben. Keine Abkürzungen. Kommentare sollten beschreiben warum etwas passiert und nicht den Code nochmal wiedergeben. Kommentare sollten vor allem nicht falsch sein. Bei timeout gibt es gar keinen expliziten Rückgabewert - ein Fehler.
Diese komische Zeile mit den vielen Gleichheitszeichen gehört weg. Getrennt wird mit Leerzeilen.

Code: Alles auswählen

def wait_ping_reply(bus, target_id):
    """ wait for an acknoledge of a send message
    return false if timeout of 1 seconds
    we check if is from the node we sent the data
    we ignore all other messages
    """
    message = bus.recv(1) # get the receive message
    if message is None:
        return False # timeout
    message_type, swasauchimmer_id = decode_id(message.arbitration_id)
    # check if ACK message and from target
    return message_type == PINGREPLY and swasauchimmer_id == target_id
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Ergänzend zum ``is not``: Das ist genau wie ``not in`` jeweils *ein* Operator, also ``a is not b`` ist eine Operation während ``not a is b`` zwei Operationen sind (sofern der Compiler das nicht umschreibt/optimiert).
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten