Ankündigung

Einklappen
Keine Ankündigung bisher.

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