Ankündigung

Einklappen

Serverwartung 21.2.



Am 21.2. im Laufe des späten Abends wird eine Serverwartung durchgeführt. Das Forum ist dadurch für gut zwei Stunden nicht erreichbar.
Es wird eine Wartungsseite geschaltet.

Mehr anzeigen
Weniger anzeigen

modbus_tcp error importing Python package: cannot import name 'Endian' from 'pymodbus.constants'

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    modbus_tcp error importing Python package: cannot import name 'Endian' from 'pymodbus.constants'

    Hallo zusammen,
    ich bin gerade auf SHNG 1.11 umgestiegen. Leider gibt es die Plugins ksemmodbus+kostalmodbus nicht mehr. Wenn ich das richtig verstehe werden die durch das Plugin modbus_tcp ersetzt.
    Das führt bei mir leider zu Problemen.

    Setup:
    Ubuntu 24.04.3 LTS
    shng 1.11
    pymodbus 3.11.4
    python 3.12

    Ich habe auch schon pymodbus 3.8.6 + 3.3.2 ausprobiert. Hat aber leider nicht geholfen.

    Habt ihr eine Idee?

    Items:
    Code:
    KsemmodbusNew:
        plugin_name: modbus_tcp
        instance: ksem
        host: 192.168.178.30
        port: 502
        cycle: 5
        plugin_enabled: true
    
    KostalmodbusNew:
        plugin_name: modbus_tcp
        instance: kostal
        host: 192.168.178.28
        port: 1502
        cycle: 5
        plugin_enabled: true​
    Logs:
    Code:
    2025-12-08  10:13:45 ERROR    lib.plugin          Plugin 'KsemmodbusNew' error importing Python package: cannot import name 'Endian' from 'pymodbus.constants' (/usr/local/smarthome/venvs/py_3.12/lib/python3.12/site-packages/pymodbus/constants.py)
    2025-12-08  10:13:45 ERROR    lib.plugin          Plugin 'KsemmodbusNew' initialization failed, plugin not loaded
    2025-12-08  10:13:45 ERROR    lib.plugin          Plugin 'KostalmodbusNew' error importing Python package: cannot import name 'Endian' from 'pymodbus.constants' (/usr/local/smarthome/venvs/py_3.12/lib/python3.12/site-packages/pymodbus/constants.py)
    2025-12-08  10:13:45 ERROR    lib.plugin          Plugin 'KostalmodbusNew' initialization failed, plugin not loaded
    ​

    #2
    Hi,

    im plugin findest Du die Zeilen:

    HTML-Code:
    from .webif import WebInterface
    
    from pymodbus.constants import Endian
    from pymodbus.payload import BinaryPayloadDecoder
    from pymodbus.payload import BinaryPayloadBuilder​
    Ich musste bei meinen python Libraries bei pymodbus > 3.9.2 die fogenden Zeilen entfernen:

    HTML-Code:
    from pymodbus.constants import Endian
    from pymodbus.payload import BinaryPayloadDecoder​
    Kommentiere die einfach mal aus, dann sollte es eigentlich laufen.

    Siehe Hier:
    https://github.com/hasenradball/Heid...319cf7c099a08d

    Kommentar


      #3
      Hi Hasenradball,
      vielen Dank für die superschnelle Antwort!!!

      Hat geklappt. Ich musste allerdings alle 3 Zeilen auskommentieren, sonst bekam ich den "error importing Python package: No module named 'pymodbus.payload' "

      HTML-Code:
      from pymodbus.constants import Endian
      from pymodbus.payload import BinaryPayloadDecoder
      from pymodbus.payload import BinaryPayloadBuilder​​

      Kommentar


        #4
        Hallo,
        zu früh gefreut :-(
        Das plugin startet zwar so, aber wenn ich den error richtig interpretiere wird für das Auslesen von Registern Endian benötigt.

        Habt ihr noch eine andere Idee?

        plugin.yaml
        Code:
        KsemmodbusNew:
            plugin_name: modbus_tcp
            host: 192.168.178.30
            port: 502
            cycle: 5
            slaveUnit: 71
            plugin_enabled: true​
        Item:
        Code:
        ksem_4new:
            type: num
            name: ksem_4new
            modBusAddress: 4
            modBusDataType: uint32​
        error in logs:
        Code:
        2025-12-08  12:46:29 ERROR    lib.item.item       Item Haus.PVDach.Kostal.SmartMeter.ksem_4new: problem creating: name 'Endian' is not defined
                    > Traceback (most recent call last):
                    >   File "/usr/local/smarthome/plugins/modbus_tcp/__init__.py", line 190, in parse_item
                    >     byteOrder = Endian[(str(byteOrderStr).split('.')[-1]).upper()]
                    >                 ^^^^^^
                    > NameError: name 'Endian' is not defined​
        Es könnte gut sein, dass "from pymodbus.payload import BinaryPayloadDecoder" auch benötigt wird. Wird zumindest in "def __read_Registers(self, regPara: dict):" verwendet

        Kommentar


          #5
          Hi Jack,

          könntest Du mal folgenden Ansatz versuchen?

          HTML-Code:
          try:
              from pymodbus.constants import Endian
              from pymodbus.payload import BinaryPayloadDecoder
              from pymodbus.payload import BinaryPayloadBuilder
          except ImportError as e:
              print(f"pymodbus-Module nicht verfügbar: {e}")
              Endian = None
              BinaryPayloadDecoder = None
              BinaryPayloadBuilder = None
          Dann funktioniert es für ältere pymodbus Versionen und für neuere.
          So der Gedanke.

          Kommentar


            #6
            Zitat von Jack Sparrow Beitrag anzeigen
            Hallo,
            zu früh gefreut :-(
            Das plugin startet zwar so, aber wenn ich den error richtig interpretiere wird für das Auslesen von Registern Endian benötigt.

            Habt ihr noch eine andere Idee?

            plugin.yaml
            Code:
            KsemmodbusNew:
            plugin_name: modbus_tcp
            host: 192.168.178.30
            port: 502
            cycle: 5
            slaveUnit: 71
            plugin_enabled: true​
            Item:
            Code:
            ksem_4new:
            type: num
            name: ksem_4new
            modBusAddress: 4
            modBusDataType: uint32​
            error in logs:
            Code:
            2025-12-08 12:46:29 ERROR lib.item.item Item Haus.PVDach.Kostal.SmartMeter.ksem_4new: problem creating: name 'Endian' is not defined
            > Traceback (most recent call last):
            > File "/usr/local/smarthome/plugins/modbus_tcp/__init__.py", line 190, in parse_item
            > byteOrder = Endian[(str(byteOrderStr).split('.')[-1]).upper()]
            > ^^^^^^
            > NameError: name 'Endian' is not defined​
            Es könnte gut sein, dass "from pymodbus.payload import BinaryPayloadDecoder" auch benötigt wird. Wird zumindest in "def __read_Registers(self, regPara: dict):" verwendet
            Ja Endian ist so natürlich nicht mehr verfügbar.
            Man müsste mal in die pymodbus Doku schauen.

            Endian befindet sich nun unter => Constants

            https://pymodbus.readthedocs.io/en/v...nts.Endian.BIG
            Zuletzt geändert von Hasenradball; 08.12.2025, 13:18.

            Kommentar


              #7
              Ergänzung:
              Ich habe mit dem Befehl
              python3 -m pip install pymodbus --upgrade
              bei aktiviertem venv installiert.

              Ein
              python3 -m pip install pymodbus --user --upgrade
              wie in der Anleitung führt zu folgendem Fehler:
              ERROR: Can not perform a '--user' install. User site-packages are not visible in this virtualenv.​
              Bei deaktiviertem venv kommt dann die Meldung:
              error: externally-managed-environment
              × This environment is externally managed​

              Kommentar


                #8
                Früher war der Code beispielweise so:

                HTML-Code:
                    def decode_register_readings(self, readings, datatype, count):
                
                        """Decode the register readings dependend on datatype
                
                        """
                        decoder = BinaryPayloadDecoder.fromRegisters(readings.registers, \
                                                                     byteorder=Endian.BIG, wordorder=Endian.BIG)
                        #print(f'decoder : {decoder}')
                        data = []
                        if datatype == 'U16':
                            data = [decoder.decode_16bit_uint() for i in range(count)]
                        elif datatype == 'U32':
                            data = [decoder.decode_32bit_uint() for i in range(count)]
                        elif datatype == 'U64':
                            data = [decoder.decode_64bit_uint() for i in range(count)]
                        elif datatype == 'S16':
                            data = [decoder.decode_16bit_int() for i in range(count)]
                        elif datatype == 'S32':
                
                            data = [decoder.decode_32bit_int() for i in range(count)]
                
                        return data​
                Heute könnte man das so lösen:
                https://pymodbus.readthedocs.io/en/v3.6.9/source/client.html#pymodbus.client.mixin.ModbusClientMixi n.convert_from_registers

                HTML-Code:
                 def decode_register_readings(self, readings, datatype, count):
                        """Decode the register readings depend on datatype
                        """
                        data = []
                        if datatype == 'U16':
                            data = self._client.convert_from_registers(readings.registers, data_type=self._client.DATATYPE.UINT16)
                        elif datatype == 'U32':
                            data = self._client.convert_from_registers(readings.registers, data_type=self._client.DATATYPE.UINT32)
                        elif datatype == 'U64':
                            data = self._client.convert_from_registers(readings.registers, data_type=self._client.DATATYPE.UINT64)
                        elif datatype == 'S16':
                            data = self._client.convert_from_registers(readings.registers, data_type=self._client.DATATYPE.INT16)
                        elif datatype == 'S32':
                            data = self._client.convert_from_registers(readings.registers, data_type=self._client.DATATYPE.INT32)
                        return data​

                Kommentar


                  #9
                  gelöst!!!
                  man muss nichts in dem plugin auskommentieren. Einfach pymodbus 3.9.2 mit folgendem Befehl bei aktiviertem venv installieren:
                  Code:
                  pip3 install 'pymodbus<3.9.2'
                  Folgendes hat nicht geklappt: python3 -m pip install 'pymodbus<3.9.2'. Warum das Eine klappt, das Andere nicht bleibt mir ein Rätsel.

                  Kommentar


                    #10
                    So gehts natürlich auch, aber denn wirste nie das aktuelle pymodbus nutzen können.

                    Kommentar

                    Lädt...
                    X