Seite 1 von 1

pymodbus 3.11.3 Logging der RTU Frames / Änderungen zu 3.02

Verfasst: Sonntag 23. November 2025, 20:31
von jr1
Hallo in die Runde,

ich bin neu hier, und eigentlich auch neu im Thema Python, aber ein paar Snipsel laufen doch.
Mein Problem:
Ich habe Code vom Notebook auf eine Ordid C4 / Ubuntu portiert und alles ist sehr seltsam.
Auf einem anderen C4 laufen die Progs schon, aber nicht auf dem "Neuen"
C4-Neu:
Python 3.10.12
pymodbus 3.11.3

Auf meinem Notebook:
Python 3.8.12
pymodbus 3.0.2


Auf dem Notebook , unter eclipse , läuft es wie erwartet.
Was ich beim Port auf den C4 machen muste: in den pymodbuscall: unit= durch device_id= ersetzen, ansonsten bekam ich immer eine Exception.

Aber das wird scheinbar nicht richtig verarbeitet.
Daher habe ich "versucht" das Logging der RTU Connection einzuschalten.
Obwohl der Code auf dem Nodebook incl. einen verständlichem Logging läuft, bekomme ich ich auf dem C4 für read_holding_registers gar kein Logging. Wieso ?

Und für client.write_register:

2025-11-23 20:16:22,301 MainThread DEBUG base :72 Processing: 0xc9 0x6 0x0 0xc 0x0 0x0 0x59 0x81
2025-11-23 20:16:22,302 MainThread DEBUG decoders :79 decoded PDU function_code(6 sub -1) -> WriteSingleRegisterResponse(dev_id=0, transaction_id=0, address=12, count=0, bits
Wobei in der ersten Zeile die Adresse noch richtig geloggt wird. In der zweiten Zeile ist die Adresse "0" -- Verstehe ich nicht!

Hier der Code: des write:
def qxdo24_setDuty ( client, io, wert ):
lunit = int(config_tempctl.ADDR_QXDO24)
val = int(wert * 10)
reg = 0x0
reg += io -1
print( "Set Unit= " + str(lunit) + " Reg: " + str(reg) + " Val: " + str(val) )
client.write_register(reg, val, device_id=lunit)
return()



Das Main sieht aus wie folgt:

#!/usr/bin/env python3
# coding=utf-8
from pymodbus.client import ModbusSerialClient as ModbusClient
from qxdo24 import qxdo24_readConfig1, qxdo24_setAddr, qxdo24_setDuty, qxdo24_setFreq, qxdo24_setCtrl

import logging
FORMAT = ('%(asctime)-15s %(threadName)-15s '
'%(levelname)-8s %(module)-15s:%(lineno)-8s %(message)s')
logging.basicConfig(format=FORMAT)
log = logging.getLogger()
log.setLevel(logging.DEBUG)





print ( "Vorr RTU Connection" )
baudrate = 9600

client = ModbusClient(
# method = 'rtu'
#,
port=config_tempctl.port
,baudrate=baudrate
,parity = 'N'
,bytesize = 8
,stopbits = 1
,timeout=2
# war 2 Sek
)
connection = client.connect()
if connection is None:
print ( "Fehler RTU Connection" )
log_msg( "E","0", "0", "Fehler RTU Connect" )
exit ()
if connection == False:
print ( "Fehler RTU Connection" )
log_msg( "E","0", "0", "Fehler RTU Connect" )
exit ()






print ( "Nach RTU Connection" )

config_tempctl.client = client


#QX-DO24 PWM Outout
qxdo24_readConfig1 ( config_tempctl.client )
# qxdo24_setAddr ( config_tempctl.client )
qxdo24_setDuty ( config_tempctl.client , 1, 0 )




Soweit die Fragmente
Meine Fragen:
Wieso verhält sich das Logging so anders?
Und wie übergebe ich unter 3.11.3 die Adresse den nun richtig ?
Ich weiss, das der Write keine Fehlerbearbeitung hat........
Für mich sieht es aus, als wenn hier Versionen massiv NICHT zusammen passen.
Aber wie erkennen ...und dann beheben.



Vielen Dank für jeden Hinweis
JR

Re: pymodbus 3.11.3 Logging der RTU Frames / Änderungen zu 3.02

Verfasst: Montag 24. November 2025, 19:51
von __blackjack__
Das Modul hat eine Dokumentation die unter anderem einen „API changes“-Abschnitt enthält. Wo man auch sieht wie verdammt weit die beiden Versionen bei Dir auseinander sind.

Anmerkungen zum Quelltext: Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (PascalCase).

Man schreibt nicht den Modulnamen als Prefix für alle Funktionen. Das Modul ist doch schon der Namensraum. Es macht keinen Sinn diese Information noch mal zu wiederholen.

Namen sollten keine kryptischen Pre- oder Postfixe enthalten. Und auch keine angehängten nichtssagenden Nummern.

Es wird in dem bisschen Code `logging`, `print()`, *und* dann auch noch eine `log_msg()`-Funktion verwendet.

Auf Modulebene sollte nur Code stehen, der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

`ModbusClient`-Objekte sind Kontextmanager, die sollte man mit der ``with``-Anweisung verwenden.

`connection` wäre ein Name für eine Verbindung, nicht für einen Wahrheitswert. Der auch nicht `None` werden kann. Selbst wenn er es könnte machen die *zwei* Prüfungen die dann jeweils den gleichen Code im ``if``-Zweig stehen haben keinen Sinn. Das ist einfach ``if not client.connect():``.

Wurde `exit()` explizit aus dem `sys`-Modul importiert? Denn sonst verlässt man sich auf eine andere Funktion die so heisst und die es nicht zwingend ”einfach so” geben muss. Zudem sollte man da auch einen Rückgabecode angeben, denn *das* ist der Zweck dieser Funktion. Sonst hätte man nämlich die Hauptfunktion an der Stelle auch einfach per ``return`` verlassen können.

Der Client sollte nicht als globale Variable im Konfigurationsmodul gesetzt werden!

Bei der `set_duty()`-Funktion herrscht ziemliches Namenschaos. Im Konfigurationsmodul heisst das was an `lunit` gebunden wird `ADDR_*`, ist aber gar keine Adresse, das ist `reg`, und wird als `device_id` übergeben. Und `value` auszuschreiben bringt einen auch nicht um. Was auch immer das `l` in `lunit` bedeuten soll. `reg` wird auch komisch gebildet. Klar kann man was auf 0 addieren. Man kann aber auch einfach gleich den Wert zuweisen den man da addiert.

Eine Funktion die Grundsätzlich ein leeres Tupel zurück gibt, mit dem der Aufrufer dann auch überhaupt gar nichts anfängt, macht keinen Sinn.

Die `set_duty()`-Funktion würde eher so aussehen:

Code: Alles auswählen

def set_duty(client, io, value):
    address = io - 1
    value = int(value * 10)
    device_id = config.ADDR_QXDO24
    log.debug("Set Unit=%r  Reg: %r  Val: %r", device_id, address, value)
    client.write_register(address, value, device_id=device_id)
Und das Hauptprogramm so:

Code: Alles auswählen

#!/usr/bin/env python3
import logging
import sys

import config
import qxdo24
from pymodbus.client import ModbusSerialClient as ModbusClient

BAUDRATE = 9600
logging.basicConfig(
    format=(
        "%(asctime)-15s %(threadName)-15s "
        "%(levelname)-8s %(module)-15s:%(lineno)-8s %(message)s"
    )
)
log = logging.getLogger()
log.setLevel(logging.DEBUG)


def main():
    log.debug("Vor RTU Connection")
    with ModbusClient(
        port=config.PORT,
        baudrate=BAUDRATE,
        parity="N",
        bytesize=8,
        stopbits=1,
        timeout=2,
    ) as client:
        if not client.connect():
            log.fatal("Fehler RTU Connection")
            sys.exit(1)

        log.debug("Nach RTU Connection")
        qxdo24.read_config(client)
        # qxdo24.set_addr(client)
        qxdo24.set_duty(client, 1, 0)


if __name__ == "__main__":
    main()

Re: pymodbus 3.11.3 Logging der RTU Frames / Änderungen zu 3.02

Verfasst: Dienstag 25. November 2025, 20:44
von jr1
Hallo _blackjock_

Danke für die Hinweise.
Werde das Prog. überarbeiten, bzw Deine Korrekturen übernehmen.
Das Prog. ist nunmehr schon ziemlich verbastelt, weil ich auch versuchte, den Fehler einzugrenzen.


Zum Thema Modbus:
Ok, die Vers. liegen auseinder.
Die API Docu habe ich gelesen .
Da habe ich ja auch die "devide_id " Änderung her

Was mich so ersaunt: Das der Code mit dem 3.1 nicht mehr läuft und das ohne , für mich, erkennbaren Grund.

Ich habe doch ...nur .. das OS geupdated.
Da hätte ich mehr erwartet, auch in den Change.logs

der Lesebefehl wird gar nicht mehr geloggt

Der Schreibbefehl erzeugt nur noch 2 Zeilen, statt den gewohnten 10-15 Zeilen.

Und dann in den Zeilen ist die Ausgabe mehr als verwirrend:

2025-11-23 20:16:22,301 MainThread DEBUG base :72 Processing: 0xc9 0x6 0x0 0xc 0x0 0x0 0x59 0x81
2025-11-23 20:16:22,302 MainThread DEBUG decoders :79 decoded PDU function_code(6 sub -1) -> WriteSingleRegisterResponse(dev_id=0, transaction_id=0, address=12, count=0, bits

In der ersten Zeile ist die Client Adresse mit 0xc9 erkennbar
in der zweiten Zeile ist dann "(dev_id=0, " Das widerspricht sich enorm. Aber so strubbelig kann doch die pymodbus nicht sein! Das kann ich mir nicht vorstellen !!!!

Ich bin ziemlich "verwirrt" ganz vorsichtig ausgedrückt



Hat schon jemand Erfahrung mit der pymodbus 3.11.3
Für mich sieht es aus, als wenn die Debug Lines etwas anderes als RTU verarbeiten wollen ...?


Danke für jeden Hinweis

JR

Re: pymodbus 3.11.3 Logging der RTU Frames / Änderungen zu 3.02

Verfasst: Mittwoch 26. November 2025, 00:51
von __blackjack__
@jr1: Bei der langen Liste an Änderungen zwischen den Bibliotheksversionen wundert mich nicht dass man da was umschreiben muss. Die haben da einiges geändert in den grob 11 Versionen mit API-Änderungen, die dazwischen liegen. Die haben da ja streckenweise in den letzten 3 Jahren monatlich eine Version mit API-Änderungen raus gehauen.

Hast Du das Logging für `pymodbus` denn konfiguriert? Vielleicht waren denen oder den Nutzern das früher auch einfach zu viele Logausgaben.