Pymodbus RTU: Scripterror bzw. Scriptabbruch wenn Slave nicht erreichbar

L I V E Stammtisch ab 20:30 Uhr im Chat
  • Wie im folgenden Quellcode zu erkennen möchte ich mit meinem RPi3, als Modbusmaster, mehrere Slaves (Arduino Nano) abfragen bzw. deren Holding_Register auslesen. Dies klappt soweit auch ganz gut. Es gibt aber zwei Scenarien bei denen mir das jetzige Script mit einem Fehler abbricht. Aktuell ist das Script so eingestellt, dass statisch 10 Slaves abgefragt werden, zukünftig würde ich das Script so anpassen, dass die bei 4bit-Adresscodierung maximale Anzahl an Slaves abgefragt werden sollen, also max. 15 request´s.

    1. Die Anzahl der Slaves ist u.U. nicht immer gleich

    2. Das Klimadatenmesssystem soll schnellstmöglich an den Start gehen auch wenn noch nicht alle Slaves bauseitig installiert sind

    3. Es kann durchaus sein, dass ich noch einen Raum mehr messtechnisch erfassen möchte, dann soll aber das Script nicht dafür angefasst werden müssen

    Wie in einem vorherigen Thread schon erwähnt, die print()´s dienen derzeit nur zu Entwicklungszwecken bis die Daten in die SQL-Datenbank geschrieben werden. Sofern einer von X Slaves nicht erreichbar ist, schreibe ich dann 0-Werte in die DB oder lasse den Eintrag weg - das ist ein anderes Thema.

    :helpnew: Jetzt habe ich mich schon etwas mit Pymodbus und den mitgelieferten Modulen beschäftigt, kann aber für RTU irgendwie keine Möglichkeit finden Slaves, sozusagen, auf Existens oder Status=Online zu überprüfen. Hat dazu jemand von euch Erfahrenen einen Lösungsansatz? :helpnew:

    :danke_ATDE:

    Einmal editiert, zuletzt von Masterkennie (5. Oktober 2017 um 13:00)

  • Pymodbus RTU: Scripterror bzw. Scriptabbruch wenn Slave nicht erreichbar? Schau mal ob du hier fündig wirst!

  • Leider lässt sich dein Code schwer lesen weil ständig Leerzeilen eingefügt sind.. Bitte bearbeite deinen Beitrag und beachte: HowTo: CODE / PHP Code im Forum posten

    ...durch den Umzug des Forums auf eine neue Software sind einige Inhalte der Beiträge leider nicht mehr 100% zutreffend aber dennoch brauchbar...

    Bei deinem Code fällt mir direkt die fehlerhafte Nutzung der print auf... Dein Shebang zegt auf python, was python2 sein müsste, und somit sind deine print() Aufrufe falsch denn in python2 ist print keine Funktion - auch das aneinanderreihen durch str() ist Quatsch.

    Durch die falsche Handhabung machst du aus den Ausgaben tuples

    Es fallen mir noch mehr Fehler auf aber wie gesagt, ändere bitte erst die Darstellung des Codes ;)

  • Leider lässt sich dein Code schwer lesen weil ständig Leerzeilen eingefügt sind.. Bitte bearbeite deinen Beitrag und beachte: HowTo: CODE / PHP Code im Forum posten

    Moin,

    ich geh bald echt am Stock! Ich verbringe im Moment beinahe mehr Zeit damit Code Chick und schön zu machen, als der Lösung meiner Problemstellungen näher zu kommen. Habe jetzt manuell alle unnötigen Leerzeilen -- die übrigens das Forum da rein interpretiert hat -- entfernt. Der code-block ist eine Kopie aus einem bereits von mir "richtig" geposteten code-block eines vorherigen Themas.

    Ich nutze seit gestern Abend definitiv Python3, habe den Quellcode aber aktuell nicht hier und gestern Nacht nicht mehr daran gedacht ein Update zu posten.

    Wie in einem vorherigen Thread schon erwähnt, die print()´s dienen derzeit nur zu Entwicklungszwecken bis die Daten in die SQL-Datenbank geschrieben werden.

    Sorry ich habe es gestern Abend nicht mehr geschafft den aktuellen Quellcode mit print("", "") zu posten, aktuell habe ich ihn bis heute Abend auch nicht vorliegen. Allerdings hat meiner Meinung nach print "" und print("", "") nix mit der eigentlichen Problemstellung zu tun, oder irre ich mich da?

    Der Code wird von mir regelmäßig, dank des Tipps vom Bootsmann :bravo2: durch http://pep8online.com geschickt und entsprechend der Fehlermeldungen von mir bearbeitet.

  • Also erst mal solltest du deine print() Zeilen ändern ;)

    Zum Beispiel:

    print ("Start Measuring... please wait for ") + str( Delay*AnzMessungen)+ str(" seconds...")

    ändern in:

    print("Start Measuring... please wait for {} seconds...".format(Delay*AnzMessungen))

    Die Verbindung für jede Messung neu öffnen und wieder zu schließen halte ich nicht für effektiv, behalte die Verbindung lieber für die Dauer der Messungen aufrecht. So wie ich das sehe gibt die connect() Methode bei bereits bestehender Verbindung True zurück, was man hier ausnutzen könnte:

    https://github.com/riptideio/pymo…nt/sync.py#L330

    Dann weiß ich nicht genau wieso du am Anfang des Scripts Slave setzt und Verbindung_LeseRegister() diese auch noch mal setzt bzw zurück gibt - ich änder das meinem Empfinden auch mal ab, unter Vorbehalt :blush:

    Versuchs erstmal damit:

  • Der Code wird von mir regelmäßig, dank des Tipps vom Bootsmann durch http://pep8online.com geschickt und entsprechend der Fehlermeldungen von mir bearbeitet.

    Nicht dein Ernst? Wenn du Wert auf PEP8 legst (gut!), dir aber noch nicht alles merken kannst (kommt noch!), nimm doch ne gescheite IDE wie PyCHarm, die das bemängeln wird und Verbesserungsvorschläge bietet... bisschen effizienter ;)

    meigrafd Das mit dem Shebang ist so ne Sache, ich weiß, dass er sein python Binary auf Python 3 umgestellt hat, alle anderen natürlich nicht ;)

    Shebang wird aber soooo oft falsch gemacht, den braucht man eh nur, wenn man chmod +x macht und dann ./script.py, was ich allerdings vermeide, weil dann (mir) nicht sofort klar ist, was da jetzt für ne Python Version werkelt.

    Was mich jetzt wundert:

    1. Das tolle PEP8 tool müsste großgeschriebene Variablen (Temperature, MesungNr) bemängeln. Richtig wäre
    2. Ebenfalls die Aufrufe der print Funktion. Auch wenn es gültiges Python ist:
    Python
    Python 3.5.2 (default, Sep 14 2017, 22:51:06) 
    [GCC 5.4.0 20160609] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> print ('Test')
    Test
    >>> print            ('Test')
    Test
    >>>
    1. zwischen Funktionsname und Klammern gehören keine Leerzeichen!
  • meigrafd:

    1.Ich habe Slave oben im Script definiert da eine leere Liste, also

    Slave[] zu einem Abbruch beim Laufenlassen des Scripts geführt hat. Fand ich auch seltsam.

    2. Die Verbindung öffne und schließe ich für jede Abfrage der Messwerte weil ich derzeit nicht sicherstellen kann dass das Script sauber durch läuft. D.h. stoppt der Interpreter aufgrund eines nicht erreichbaren Slaves, wird Client.close()nicht mehr ausgeführt. Ich wollte damit also erreichen dass eine Verbindung möglichst immer sauber geschlossen wird.

    3. Noch mal: ich habe hier nicht den aktuellsten Code gepostet. Daher sind die print-Anweisungen da oben noch falsch. Mir ist das klar, dass python2 keine Print-Funktion enthält; und man in python3 mehrere Ausgaben nicht mit + str()verbindet sondern jede gewünschte Ausgabe als Parameter übergibt....

    Ich verstehe euch ja, auch dass der Code nach den gültigen Regeln erstellt werden soll und dies, gerade in der Lernphase am besten "gleich mit" zu lernen ist. aaaber: Wir beschäftigen uns doch grad nicht mit der eigentlichen Problemstellung :denker:

    Nur eins noch: Warum sollen/dürfen Variablennamen nicht großgeschrieben werden?

    Einmal editiert, zuletzt von Masterkennie (5. Oktober 2017 um 17:56)

  • Versuchs erstmal damit:

    Das haut nicht hin, ich hab zuvor auch schon festgestellt, dass leere Listen nicht akzeptiert werden:

    Code
    Start Measuring... please wait for 3.0 seconds...
    Traceback (most recent call last):
      File "ON_OFF_1.py", line 77, in <module>
        ReturnValue = Messung_Klimadaten(slave_number, client)
      File "ON_OFF_1.py", line 50, in Messung_Klimadaten
        Slave = LeseRegister(num, client)
      File "ON_OFF_1.py", line 37, in LeseRegister
        Slave[num] = client.read_holding_registers(0000, 4, unit=num)
    IndexError: list assignment index out of range

    So sieht übrigens der aktuelle Code aus, der unter Python3 auch funktioniert:

    Die Ausgabe sieht dann so aus:

    Nach dem "Badezimmer" wird dann versucht den dritten Slave zu erreichen, ich hab aber nur zwei Arduino´s am Bus (mehr hab ich derzeit auch noch gar nicht). Jetzt möchte ich einfach verhindern, dass das Script abgebrochen wird und er nach dem Timeout einfach von vorn mit den Messungen ab Slave1 beginnt.

    Einmal editiert, zuletzt von Masterkennie (5. Oktober 2017 um 19:26)

  • Ersetze den Teil:

    durch

    LG

    PS: Ich höre jetzt auf, auf PEP8 einzugehen, auch wenn mir print ("Messung Klimadaten abgebrochen") oder DHT_Error = DHT_Error+Slave... sehr missfällt ;)

  • Das haut nicht hin, ich hab zuvor auch schon festgestellt, dass leere Listen nicht akzeptiert werden:

    Code
    Start Measuring... please wait for 3.0 seconds...
                Traceback (most recent call last):
                  File "ON_OFF_1.py", line 77, in <module>
                    ReturnValue = Messung_Klimadaten(slave_number, client)
                  File "ON_OFF_1.py", line 50, in Messung_Klimadaten
                    Slave = LeseRegister(num, client)
                  File "ON_OFF_1.py", line 37, in LeseRegister
                    Slave[num] = client.read_holding_registers(0000, 4, unit=num)
                IndexError: list assignment index out of range

    ...Besser wär du bleibst bei dem von mir gezeigten Code - denn auch dein aktueller Code enthält viele Fehlhandhabungen, leider nicht nur der print()

    Wenn es mit Slave[num] Probleme gibt brauchst du in meinem Code ja nur die Zeile Slave = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] vor den Funktionen wieder einfügen... Allerdings ignoriert das erneut nur eine Fehlbehandlung und löst nicht das eigentliche Problem - insbesondere im Bezug auf dein Anliegen, denn mit dem hardcoded Füllen der Liste von 1 bis 10 wirst du das selbe Problem kriegen wenn du später mal einen weiteren Sensor hinzufügst.

    Die richtige Handhabung wäre:

    Python
    Room = ['Broadcast', 'Kind Ost', 'Badezimmer', 'Schlafzimmer', 'Kind West', 'Flur OG', 'Spitzboden', 'Aussen', 'Kueche', 'Flur EG', 'Flur UG']
    Slave = [l for l in Room]

    Oder anstatt einer List einfach ein Dictionary für Slave verwenden.

    Allerdings brauchst du das eigentlich überhaupt nicht, da Messung_Klimadaten() bereits alles weiß was benötigt wird und LeseRegister() keine List oder Dictionary zurück geben muss

    Vorschlag #2:

    ...damit müssten eigentlich mind. 2 Probleme behoben sein ;)

  • Hallo meigrafd,

    ich danke dir bis dahin erst mal für deine Unterstützung :bravo2::danke_ATDE: Allen Anderen natürlich auch, das macht das Erlernen doch angenehmer :)

    So langsam wird mir einiges etwas klarer, ich werde deinen Code gleich heute Abend mal testen. Dann muss ich mir nur mal Lektüre betreffend des if __name__ == '__main__': vor Augen führen um zu wissen was dort genau passiert.

    Die Geschichte mit dem Inkrement var += 1 war mir zwar schon klar, aber ich hatte einfach nicht die Zeit den Code anzupassen. Es ist unter der Woche keine Gute Idee von mir gewesen sich mal eben zwischendurch nach Feierabend an ein "bisschen" Python zu setzen, daher war das alles bisher offensichtlich mit der Heißen Nadel gestrickt, das muss ich mir abgewöhnen; ich gelobe Besserung.

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!