Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Hardware
    4. Kamstrup Multical 403 mit Raspberry Pi auslesen

    NEWS

    • ioBroker goes Matter ... Matter Adapter in Stable

    • Monatsrückblick - April 2025

    • Minor js-controller 7.0.7 Update in latest repo

    Kamstrup Multical 403 mit Raspberry Pi auslesen

    This topic has been deleted. Only users with topic management privileges can see it.
    • -cs-
      -cs- last edited by -cs-

      Hallo zusammen,

      seit langem versuche ich an die Daten eines Kamstrup Multical 403 zu kommen, leider finde ich nichts brauchbares was mir als Laien weiterhilft.
      Ich habe zwar schon einiges mit den Raspberrys und auch ioBroker gemacht, aber hier komme ich gar nicht weiter.
      (zur Info, es handelt sich um den Wärmemengenzähler eines örtlichen, befreundeten Lieferanten, der sich in dieser Beziehung aber überhaupt nicht auskennt, aber informiert ist)

      WMZ.jpg

      Der Wärmemengenzähler hat zwar ein M-BUS Modul verbaut, aber direkt verdrahtet möchte ich dann doch nicht eingreifen zudem funktioniert dieses ja schon mit der Steuerung der Übergabestation und des Pufferspeichers.

      M-Bus.jpg

      Angestoßen vom Lesekopf von @Jaschkopf kam das Thema wieder hoch, nur hat Kamstrup ja angeblich sein eigenes Übergabeprotokoll wozu ich als "kleiner Mann" keine Infos bekomme.

      Bis jetzt habe ich nur rausgefunden, das der Multical 403 die Daten "freiwillig" senden sollte wenn der Ringmagnet des Lesekopfes aufgelegt ist, also keinen "Anstoß" dafür brauchen soll und es es ziemlich gleich wie beim 402 sein soll, wobei der 402 einen "Anstoß" brauchte.

      Evtl. ist hier jemand, der dies schon mal gemacht hat oder weiter weis?
      Am liebsten wäre die Daten mit dem Lesekopf abzufangen und in ioBroker zu verarbeiten.

      Schöne Grüße
      Christian

      -cs- 1 Reply Last reply Reply Quote 0
      • -cs-
        -cs- @-cs- last edited by -cs-

        Leider schlief das Thema ein, aber durch andere Projekte würde mich es schon reizen, dies hinzubekommen.

        So, dann möchte ich mal Updaten, evtl. hat sich ja im letzten Jahr was getan, hier meine Erkenntnisse:

        Mit dem Optokopf von Weidmann konnte ich über Windows 10 und dem Programm Metertool von Kamstrup auf den Zähler zugreifen und die Zählerdaten auslesen, leider keine Werte.
        Soweit ich jetzt weis braucht der Multical 403 nicht extra aufwecken oder regelmäßig abgefragt zu werden um nicht abzuschalten (der Multical 402 tat dies ja anscheinend nach ca. 30 min.)

        Des weiteren habe ich im Domoticz – Forum hier ein paar Sachen gefunden.
        (Meine Beiträge in diesem Forum wurden vom Moderator gelöscht, da ich sie angeblich nicht richtig übersetzt hätte)
        In diesem Thread ist am 22.Nov.2020 auch ein Script auf Github



        <
        #! / usr / bin / env python3

        --------------------------------------------- ---------------------------

        "DIE BIERWARENLIZENZ" (Revision 42):

        phk@FreeBSD.ORG hat diese Datei geschrieben. Solange Sie diesen Hinweis behalten

        kann mit diesem Zeug machen, was immer du willst. Wenn wir uns eines Tages treffen und Sie denken

        dieses Zeug ist es wert, du kannst mir dafür ein Bier kaufen. Poul-Henning Kamp

        --------------------------------------------- ---------------------------

        Geändert für Domotics und Einzelanfragen.

        Modifiziert von Ronald van der Meer, Frank Reijn und Paul Bonnemaijers für die

        Kamstrup Multical 402

        Modifiziert von Tim van Werkhoven 20201112 für den generischen Gebrauch (zB mqtt / influxdb).

        Auch überflüssige Zählerablesung aus dem Skript beschnitten, um die Batterie des Zählers zu schonen

        life (vorherige Version hat alle 30 Variablen gelesen und nicht verwendete Daten verworfen)

        Verwendung: file <ComPort>

        aus future import print_function

        Sie benötigen pySerial

        Seriennummer importieren
        Mathe importieren
        sys importieren
        Datum / Uhrzeit importieren
        Import - Anfragen
        Paho importieren . mqtt . Kunde als Paho

        urllib importieren

        importiere urllib.request

        Codecs importieren

        Variablen

        reader = codecs . getreader ( "utf-8" )

        Debug = 1

        multical_var = { # Dezimalzahl im Befehl für Kamstrup Multical
        0x003C : " Wärmeenergie (E1)" , # 60
        0x0050 : "Power" , # 80
        0x0056 : "Temp1" , # 86
        0x0057 : "Temp2" , # 87
        0x0059 : "Tempdiff" , # 89
        0x004A : "Flow" , # 74
        0x0044 : "Volume" , # 68
        0x008D : "MinFlow_M" , # 141
        0x008B : "MaxFlow_M" , # 139
        0x008C : "MinFlowDate_M" , # 140
        0x008A : "MaxFlowDate_M" , # 138
        0x0091 : "MinPower_M" , # 145
        0x008F : "MaxPower_M" , # 143
        0x0095 : "AvgTemp1_M" , # 149
        0x0096 : "AvgTemp2_M" , # 150
        0x0090 : "MinPowerDate_M" , # 144
        0x008E : "MaxPowerDate_M" , # 142
        0x007E : "MinFlow_Y" , # 126
        0x007C : "MaxFlow_Y" , # 124
        0x007D : "MinFlowDate_Y" , # 125
        0x007B : "MaxFlowDate_Y" , # 123
        0x0082 : "MinPower_Y" , # 130
        0x0080 : "MaxPower_Y" , # 128
        0x0092 : "AvgTemp1_Y" , # 146
        0x0093 : "AvgTemp2_Y" , # 147
        0x0081 : "MinPowerDate_Y" , # 129
        0x007F : "MaxPowerDate_Y" , # 127
        0x0061 : "Temp1xm3" , # 97
        0x006E : "Temp2xm3" , # 110
        0x0071 : "Infoevent" , # 113
        0x03EC : "HourCounter" , # 1004
        }}

        multical_var_si = { # Dezimalzahl im Befehl für Kamstrup Multical
        0x003C : 1E + 0 , # Quelldaten bereits in Joule - " Wärmeenergie (E1)", # 60
        0x0050 : 1E-3 , # Quelldaten in MilliWatt - "Power", # 80
        0x0056 : 1E-9 , # Quelldaten in nanoCelcius - "Temp1", # 86
        0x0057 : 1E-9 , # Quelldaten in nanoCelcius - "Temp2", # 87
        0x0059 : 1E-9 , # Quelldaten in nanoCelcius - "Tempdiff", # 89
        0x004A : 1E-12 / 3600 , # Quelldaten Nanoliter / Stunde - "Flow", # 74
        0x0044 : 1E + 0 , # Quelldaten TBD - "Volume", # 68
        0x008D : 1E + 0 , # Quelldaten TBD - "MinFlow_M", # 141
        0x008B : 1E + 0 , # Quelldaten TBD - "MaxFlow_M", # 139
        0x008C : 1E + 0 , # Quelldaten TBD - "MinFlowDate_M", # 140
        0x008A : 1E + 0 , # Quelldaten TBD - "MaxFlowDate_M", # 138
        0x0091 : 1E + 0 , # Quelldaten TBD - "MinPower_M", # 145
        0x008F : 1E + 0 , # Quelldaten TBD - "MaxPower_M", # 143
        0x0095 : 1E + 0 , # Quelldaten TBD - "AvgTemp1_M", # 149
        0x0096 : 1E + 0 , # Quelldaten TBD - "AvgTemp2_M", # 150
        0x0090 : 1E + 0 , # Quelldaten TBD - "MinPowerDate_M", # 144
        0x008E : 1E + 0 , # Quelldaten TBD - "MaxPowerDate_M", # 142
        0x007E : 1E + 0 , # Quelldaten TBD - "MinFlow_Y", # 126
        0x007C : 1E + 0 , # Quelldaten TBD - "MaxFlow_Y", # 124
        0x007D : 1E + 0 , # Quelldaten TBD - "MinFlowDate_Y", # 125
        0x007B : 1E + 0 , # Quelldaten TBD - "MaxFlowDate_Y", # 123
        0x0082 : 1E + 0 , # Quelldaten TBD - "MinPower_Y", # 130
        0x0080 : 1E + 0 , # Quelldaten TBD - "MaxPower_Y", # 128
        0x0092 : 1E + 0 , # Quelldaten TBD - "AvgTemp1_Y", # 146
        0x0093 : 1E + 0 , # Quelldaten TBD - "AvgTemp2_Y", # 147
        0x0081 : 1E + 0 , # Quelldaten TBD - "MinPowerDate_Y", # 129
        0x007F : 1E + 0 , # Quelldaten TBD - "MaxPowerDate_Y", # 127
        0x0061 : 1E + 0 , # Quelldaten TBD - "Temp1xm3", # 97
        0x006E : 1E + 0 , # Quelldaten TBD - "Temp2xm3", # 110
        0x0071 : 1E + 0 , # Quelldaten TBD - "Infoevent", # 113
        0x03EC : 1E + 0 , # Quelldaten TBD - "HourCounter", # 1004
        }}

        #################################################### #######################

        Einheiten, bereitgestellt von Erik Jensen

        Einheiten = {
        0 : '' , 1 : 'Wh' , 2 : 'kWh' , 3 : 'MWh' , 4 : 'GWh' , 5 : 'j' , 6 : 'kj' , 7 : 'Mj' ,
        8 : 'Gj' , 9 : 'Cal' , 10 : 'kCal' , 11 : 'Mcal' , 12 : 'Gcal' , 13 : 'varh' ,
        14 : 'kvarh' , 15 : 'Mvarh' , 16 : 'Gvarh' , 17 : 'VAh' , 18 : 'kVAh' ,
        19 : 'MVAh' , 20 : 'GVAh' , 21 : 'kW' , 22 : 'kW' , 23 : 'MW' , 24 : 'GW' ,
        25 : 'kvar' , 26 : 'kvar' , 27 : 'Mvar' , 28 : 'Gvar' , 29 : 'VA' , 30 : 'kVA' ,
        31 : 'MVA' , 32 : 'GVA' , 33 : 'V' , 34 : 'A' , 35 : 'kV' , 36 : 'kA' , 37 : 'C' ,
        38 : 'K' , 39 : 'l' , 40 : 'm3' , 41 : 'l / h' , 42 : 'm3 / h' , 43 : 'm3xC' ,
        44 : 'ton' , 45 : 'ton / h' , 46 : 'h' , 47 : 'hh: mm: ss' , 48 : 'yy: mm: dd' ,
        49 : 'yyyy: mm: dd' , 50 : 'mm: dd' , 51 : '' , 52 : 'Bar' , 53 : 'RTC' ,
        54 : 'ASCII' , 55 : 'm3 x 10' , 56 : 'ton x 10' , 57 : 'GJ x 10' ,
        58 : 'Minuten' , 59 : 'Bitfeld' , 60 : 's' , 61 : 'ms' , 62 : 'Tage' ,
        63 : 'RTC-Q' , 64 : 'Datetime'
        }}

        #################################################### #######################

        Kamstrup verwendet das "echte" CCITT CRC-16

        def crc_1021 ( Nachricht 😞
        poly = 0x1021
        reg = 0x0000
        für Byte in Nachricht :
        Maske = 0x80
        while ( Maske > 0 😞
        reg << = 1
        wenn Byte & Maske :
        reg | = 1
        Maske >> = 1
        if reg & 0x10000 :
        reg & = 0xffff
        reg ^ = poly
        Rückgabe reg

        #################################################### #######################

        Bytewerte, die vor der Übertragung maskiert werden müssen

        entkommt = {
        0x06 : Wahr ,
        0x0d : Wahr ,
        0x1b : Wahr ,
        0x40 : Wahr ,
        0x80 : Richtig ,
        }}

        #################################################### #######################

        Und es geht los....

        Klasse Kamstrup ( Objekt 😞

        def  __init__ ( self , serial_port ):
            Selbst . debug_fd  =  open ( "/ tmp / _kamstrup" , "a" )
            Selbst . debug_fd . Schreiben ( " \ n \ n Start \ n " )
            Selbst . debug_id  =  Keine
        
            Selbst . ser  =  serial . Seriennummer (
                port  =  serial_port ,
                Baudrate  =  1200 ,
                Zeitüberschreitung  =  5,0 ,
                Bytesize  =  seriell . EIGHTBITS ,
                Parität  =  seriell . PARITY_NONE ,
                Stopbits  =  seriell . STOPBITS_TWO )
        

        xonxoff = 0,

        rtscts = 0)

        timeout = 20

        def  debug ( self , dir , b ):
            für  i  in  b :
                wenn  dir  ! =  Selbst . debug_id :
                    wenn  selbst . debug_id  ! =  Keine :
                        Selbst . debug_fd . schreiben ( " \ n " )
                    Selbst . debug_fd . schreibe ( dir  +  " \ t " )
                    Selbst . debug_id  =  dir
                Selbst . debug_fd . schreibe ( "% 02x"  %  i )
            Selbst . debug_fd . Flush ()
        
        def  debug_msg ( self , msg ):
            wenn  selbst . debug_id  ! =  Keine :
                Selbst . debug_fd . schreiben ( " \ n " )
            Selbst . debug_id  =  "Msg"
            Selbst . debug_fd . schreiben ( "Msg \ t "  +  msg )
            Selbst . debug_fd . Flush ()
        
        def  wr ( self , b ):
            b  =  Bytearray ( b )
            Selbst . Debug ( "Wr" , b );
            Selbst . ser . schreibe ( b )
        
        def  rd ( Selbst ):
            a  =  Selbst . ser . lesen ( 1 )
            wenn  len ( a ) ==  0 :
                Selbst . debug_msg ( "Rx Timeout" )
                Rückgabe  Keine
            b  =  Bytearray ( a ) [ 0 ]
            Selbst . Debug ( "Rd" , Bytearray (( b ,)));
            Rückkehr  b
        
        def  send ( self , pfx , msg ):
            b  =  Bytearray ( msg )
        
            b . anhängen ( 0 )
            b . anhängen ( 0 )
            c  =  crc_1021 ( b )
            b [ - 2 ] =  c  >>  8
            b [ - 1 ] =  c  &  0xff
        
            c  =  bytearray ()
            c . anhängen ( pfx )
            für  i  in  b :
                wenn  ich  in  entkommt :
                    c . anhängen ( 0x1b )
                    c . anhängen ( i  ^  0xff )
                sonst :
                    c . anhängen ( i )
            c . anhängen ( 0x0d )
            Selbst . wr ( c )
        
        def  recv ( Selbst ):
            b  =  bytearray ()
            während  wahr :
                d  =  Selbst . rd ()
                wenn  d  ==  Keine :
                    Rückgabe  Keine
                wenn  d  ==  0x40 :
                    b  =  bytearray ()
                b . anhängen ( d )
                wenn  d  ==  0x0d :
                    brechen
            c  =  bytearray ()
            i  =  1 ;
            während  i  <  len ( b ) -  1 :
                wenn  b [ i ] ==  0x1b :
                    v  =  b [ i  +  1 ] ^  0xff
                    wenn  v  nicht  in  entkommt :
                        Selbst . debug_msg (
                            "Fehlende Flucht% 02x"  %  v )
                    c . anhängen ( v )
                    i  + =  2
                sonst :
                    c . anhängen ( b [ i ])
                    i  + =  1
            wenn  crc_1021 ( c ):
                Selbst . debug_msg ( "CRC-Fehler" )
            return  c [: - 2 ]
        
        def  readvar ( self , nbr ):
            # Ich wäre nicht überrascht, wenn Sie mehr verlangen könnten als
            # eine Variable zu der Zeit, vorausgesetzt, die Länge ist
            # in der Antwort codiert. Habe es nicht versucht.
        
            Selbst . send ( 0x80 , ( 0x3f , 0x10 , 0x01 , nbr  >>  8 , nbr  &  0xff ))
        
            b  =  Selbst . recv ()
            if  b  ==  Keine :
                return ( Keine , Keine )
            wenn  b [ 0 ] ! =  0x3f  oder  b [ 1 ] ! =  0x10 :
                return ( Keine , Keine )
            
            wenn  b [ 2 ] ! =  nbr  >>  8  oder  b [ 3 ] ! =  nbr  &  0xff :
               return ( Keine , Keine )
        
            wenn  b [ 4 ] in  Einheiten :
                u  =  Einheiten [ b [ 4 ]]
            sonst :
                u  =  Keine
        
            # Dekodiere die Mantisse
            x  =  0
            für  i  im  Bereich ( 0 , b [ 5 ]):
                x << = 8
                x | = b [ i  +  7 ]
        
            # Dekodiere den Exponenten
            i  =  b [ 6 ] &  0x3f
            wenn  b [ 6 ] &  0x40 :
                i  =  - i
            i  =  math . pow ( 10 , i )
            wenn  b [ 6 ] &  0x80 :
                i  =  - i
            x  * =  i
        
            wenn  falsch :
                # Drucken debuggen
                s  =  ""
                für  i  in  b [: 4 ]:
                    s  + =  "% 02x"  %  i
                s  + =  "|"
                für  i  in  b [ 4 : 7 ]:
                    s  + =  "% 02x"  %  i
                s  + =  "|"
                für  i  in  b [ 7 :]:
                    s  + =  "% 02x"  %  i
        
                print ( s , "=" , x , Einheiten [ b [ 4 ]])
        
            return ( x , u )
        

        def influxdb_update ( Wert , prot = 'http' , ip = '127.0.0.1' , port = '8086' , db = "smarthome" , querybase = "Energie, Menge = Wärme, Quelle = multical, Typ = Verbrauchswert =" 😞
        "" "
        Drücken Sie das Update mit zweiter Genauigkeit auf influxdb
        "" "

        # Der Wert ist in GJ, wir konvertieren nach Joule, um SI in influxdb zu erhalten
        value_joule  =  value * 1000000000
        
        # So etwas wie req_url = "http: // localhost: 8086 / write? Db = smarthometest & präzise = s"
        req_url  =  "{}: // {}: {} / write? db = {} & präzise = s" . Format ( prot , ip , port , db )
        # So etwas wie post_data = "Energie, Typ = Wärme, Gerät = Landisgyr-Wert = 10"
        # Alternativ wie post_data = "energy landisgyr = 10"
        post_data  =  "{} {: d}" . Format ( Abfragebasis , int ( value_joule ))
        
        wenn  Debug  >  0 :
            print ( "Daten '{}' an influxdb senden" . format ( post_data ))
        
        
        versuchen Sie :
            httpresponse  =  Anfragen . post ( req_url , data = post_data , verify = False , timeout = 5 )
        außer  Ausnahme  als  inst :
            print ( "Zählerstand konnte nicht aktualisiert werden: {}" . format ( inst ))
            bestehen
        

        def mqtt_update ( Nutzlast , IP , Port , Benutzer , Passwort , Thema 😞
        "" "
        In mqtt veröffentlichen
        http://www.steves-internet-guide.com/publishing-messages-mqtt-client/
        https://pypi.org/project/paho-mqtt/#publishing
        "" "
        # Broker = "192.168.1.184"
        # port = 1883

        client1  =  paho . Client ( client_id = "multical" )
        client1 . username_pw_set ( user , passwd )
        
        versuchen Sie :
            client1 . verbinden ( ip , int ( port ))
        außer :
            print ( 'Verbindung zum mqtt-Broker konnte nicht hergestellt werden' )
        
        versuchen Sie :
            ret  =  client1 . veröffentlichen ( Thema , Nutzlast )
        außer :
            print ( 'mqtt-Wert konnte nicht veröffentlicht werden' )
        

        if name == "main" :

         Importzeit
        
        versuchen Sie :
            comport  =  sys . argv [ 1 ]
        außer  IndexError :
            print ( "Gerät erforderlich. Beispiel: / dev / ttyUSB0" )
            sys . exit ()
        
        # Das vorherige Skript hatte mehrere Argumente und wurde für unterschiedliche Zwecke auskommentiert
        #
        #command = int (sys.argv [2], 0)
        
        versuchen Sie :
            index  =  str ( sys . argv [ 2 ])
        außer  IndexError :
            print ( "Multical Befehle erforderlich." )
            sys . exit ()
        
        index  =  index . split ( ',' )
        
        wenn  Debug  >  0 :
            print ( "Parameter angegeben:" )
            für  i  im  Index :
                print ( "+"  +  i )
        
        foo  =  kamstrup ( comport )
        heat_timestamp  =  datetime . Datum / Uhrzeit . strftime ( datetime . datetime . today (), "% Y-% m-% d% H:% M:% S" )
        
        
        für  i  im  Index :
            ii  =  int ( i )
            multical_var [ ii ]
            x , u  =  foo . readvar ( ii )
        
            # In SI-Einheiten umrechnen
            xsi  =  x  *  multical_var_si [ ii ]
            
            print ( "{}, {}, {}" . Format ( multical_var [ ii ], xsi , u ))
        
        
        # influxdb_update (xsi)
        # mqtt_update (Nutzlast, IP, Port, Benutzer, Passwort, Thema)
        

        />


        Sorry, aber ich weis nicht warum es den Code im Spoiler so komisch anzeigt? 😧

        (darum hier der Link)


        verlinkt, leider sagt mir dieses Script ziemlich wenig, und ich bin zu doof es für mich anzupassen. (ob das überhaupt geht?).

        Schön währe es, das Script auf dem Raspi Slave (R3+) zum laufen zu bringen (evtl. alle 15 min mit cronjob?)und die Daten dann in ioBroker zu schreiben (MQTT?)

        Oder stehe ich mit dieser Absicht wieder mal komplett auf dem Schlauch?
        Hatte ja gehofft das es viell. irgend wann mal mit dem Smartmeter- Adapter funktionieren könnte, aber da liege ich wohl auch falsch.

        Oder gibt es zwischenzeitlich von jemanden eine andere Lösung?
        Eine Wired- Lösung habe ich komplett verworfen, da ich in das System selber nicht eingreifen möchte.

        Schöne Grüße
        Christian

        capitaenz H 2 Replies Last reply Reply Quote 0
        • capitaenz
          capitaenz @-cs- last edited by

          @csr Haben auch diesen Wärmezähler bekommen und ich habe folgendes gefunden:

          https://www.letscontrolit.com/forum/viewtopic.php?t=2828
          https://github.com/chipsi007/ESPEasyPluginPlayground/commit/7ae64fabbe05ebf79df5d3cffb9d8ba95a012072

          Das Plugin muss man dann noch in die EasyESP-Firmware bekommen, wozu ich allerdings keine besonders große Lust habe, da man wieder einen Rattenschwanz an Tools/Software installieren muss.

          Vielleicht hilft es dir ja weiter..?

          VG
          Leif

          0 jeroen85 committed to chipsi007/ESPEasyPluginPlayground
          Create _P130_Kamstrup.ino
          
          Plugin to read data from Kamstrup Multical 401 (district heating) into ESPEasy
          1 Reply Last reply Reply Quote 0
          • H
            HelmutLinner @-cs- last edited by

            @csr Hallo
            Ich habe eine Multical402 und verwende den Volkszähler TTL Lesekopf mit einem ESP8266 und dieser Software https://github.com/sebbebebbe/Multical402MQTT
            Um die Daten per MQTT direkt in Iobroker zu bekommen.
            Bei meinem 402 Schaltet es sich nach einer Zeit aus aber bei deiner sollte es ohne Probleme funktionieren.

            M 1 Reply Last reply Reply Quote 0
            • M
              maibua @HelmutLinner last edited by

              @helmutlinner said in Kamstrup Multical 403 mit Raspberry Pi auslesen:

              Volkszähler TTL Lesekopf

              Ich habe ebenfalls einen Multical 403 und möchte die Daten gerne auslesen. Habt ihr das mit dem Volkszähler TTL Lesekopf irgendwie hinbekommen?

              1 Reply Last reply Reply Quote 0
              • First post
                Last post

              Support us

              ioBroker
              Community Adapters
              Donate

              411
              Online

              31.6k
              Users

              79.5k
              Topics

              1.3m
              Posts

              auslesen kamstrup optisch optokopf raspberry volkszähler weidmann wärmemengenzähler
              4
              5
              2934
              Loading More Posts
              • Oldest to Newest
              • Newest to Oldest
              • Most Votes
              Reply
              • Reply as topic
              Log in to reply
              Community
              Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
              The ioBroker Community 2014-2023
              logo