Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Hardware
    4. Sonoff NSpanel und mqtt

    NEWS

    • ioBroker@Smart Living Forum Solingen, 14.06. - Agenda added

    • ioBroker goes Matter ... Matter Adapter in Stable

    • Monatsrückblick - April 2025

    Sonoff NSpanel und mqtt

    This topic has been deleted. Only users with topic management privileges can see it.
    • T
      Thorsten47 @Marc Berg last edited by Thorsten47

      @marc-berg
      wo finde ich das denn ich hab die autoexec.be und die nspanel.be und eine _persist.json an Dateien bin absuluter neuling mit dem sonoff nspanel hab auch in der hinsicht noch nix eingestellt hab das erst heute morgen mit Tasmota geflasht

      # Sonoff NSPanel Tasmota driver v0.47 | code by blakadder and s-hadinger
      var mode = "NSPanel"
      import persist
      var devicename = tasmota.cmd("DeviceName")["DeviceName"]
      persist.tempunit = tasmota.get_option(8) == 1 ? "F" : "C"
      if persist.has("dim")  else   persist.dim = "1"  end
      var loc = persist.has("loc") ? persist.loc : "North Pole"
      var weather_interval = persist.has("weather_interval") ? persist.weather_interval : "60"
      persist.save() # save persist file until serial bug fixed
      
        var widget = {
      # 1 = toggle switch horizontal
      # 2 = toggle switch double horizontal
      # 3 = toggle switch triple horizontal
      # 4 = toggle switch quad horizontal
      # 6 = toggle switch vertical
      # 7 = toggle switch double vertical
      # 8 = toggle switch triple vertical
      # 9 = toggle switch quad vertical
      # 33 = RGB light strip
      # 52 = CCT bulb
      # 69 = RGB+CCT bulb
      # leave empty brackets if you don't want a widget there
      # ctype scene doesn't have an uiid
      # index "name   ", "ctype", uiid | name max 8 characters, rest will be truncated)
        1: ["Index 1", "group", 1],
        2: ["Index 2", "group", 2],
        3: ["Index 3", "group", 3],
        4: ["Index 4", "group", 4],
        5: ["Index 5", "group", 33],
        6: ["Index 6", "device", 52],
        7: ["Index 7", "device", 69],
        8: ["Index 8", "scene"],
      }
      
      class NSPanel : Driver
        # set thermostat options
        static atc = { 
          "id":     "thermostat",
          "outlet": "0",  # outlet to use for trigger
          "etype":  "hot", # hot or cold
          "mirror":  false, # if true Tasmota will resend triggers as commands to keep the state on screen
        }
      
        static types = {
          '"switches":[{"outlet":':     0x87,
          "relation":   0x86,
          "ATC":      0x84,
          "index":    0x86,
          "params":     0x86,
          "wifiState":  0x85,
          "HMI_resources":0x86,
          "temp":     0x83,
          "year":     0x82,
          "weather":    0x81,
          "queryInfo":  0x80,
          "HMI_dimOpen":  0x87,
          "HMI_wallpaper":0x87,
        }
        static header = bytes('55AA') 
      
        var ser  # create serial port object
             
        # intialize the serial port, if unspecified Tx/Rx are GPIO 16/17
        def init(tx, rx)
          if !tx   tx = 16 end
          if !rx   rx = 17 end
          self.ser = serial(rx, tx, 115200, serial.SERIAL_8N1)
          tasmota.add_driver(self)
        end
      
        # determine type of message
        def findtype(value)
          import string
          for k:self.types.keys()
            if string.find(value, k) >= 0
              return self.types[k]
            end
          end
          return 0
        end
      
        def crc16(data, poly)
          if !poly  poly = 0xA001 end
          # CRC-16 MODBUS HASHING ALGORITHM
          var crc = 0xFFFF
          for i:0..size(data)-1
            crc = crc ^ data[i]
            for j:0..7
              if crc & 1
                crc = (crc >> 1) ^ poly
              else
                crc = crc >> 1
              end
            end
          end
          return crc
        end
      
        # encode using NSPanel protocol
        # input: payload:json string
        def encode(payload)
          var b = bytes()
          var nsp_type = self.findtype(payload)
          b += self.header
          b.add(nsp_type)       # add a single byte
          b.add(size(payload), 2)   # add size as 2 bytes, little endian
          b += bytes().fromstring(payload)
          var msg_crc = self.crc16(b)
          b.add(msg_crc, 2)       # crc 2 bytes, little endian
          return b
        end
      
        def split_55(b)
          var ret = []
          var s = size(b)   
          var i = s-2   # start from last-1
          while i > 0
            if b[i] == 0x55 && b[i+1] == 0xAA           
              ret.push(b[i..s-1]) # push last msg to list
              b = b[(0..i-1)]   # write the rest back to b
            end
            i -= 1
          end
          ret.push(b)
          return ret
        end
      
        # send a string payload (needs to be a valid json string)
        def send(payload)
          print("NSP: Sent =", payload)
          var payload_bin = self.encode(payload)
          self.ser.write(payload_bin)
          # print("NSP: Sent =", payload)
          log("NSP: NSPanel payload sent = " + str(payload_bin), 3)
        end
      
        # send a nextion payload
        def encodenx(payload)
          var b = bytes().fromstring(payload)
          b += bytes('FFFFFF')
          return b
        end
      
        def sendnx(payload)
          var payload_bin = self.encodenx(payload)
          self.ser.write(payload_bin)
          # print("NSP: Sent =", payload_bin)
          log("NSP: Nextion command sent = " + str(payload_bin), 3)
        end
      
        # sets time and date according to Tasmota local time
        def set_clock()
          var now = tasmota.rtc()
          var time_raw = now['local']
          var nsp_time = tasmota.time_dump(time_raw)
          var time_payload = '{"year":' + str(nsp_time['year']) + ',"mon":' + str(nsp_time['month']) + ',"day":' + str(nsp_time['day']) + ',"hour":' + str(nsp_time['hour']) + ',"min":' + str(nsp_time['min']) + ',"week":' + str(nsp_time['weekday']) + '}'
          log('NSP: Time and date synced with ' + time_payload, 3)
          self.send(time_payload)
        end
      
        # sync main screen power bars with tasmota POWER status
        def set_power()
          var ps = tasmota.get_power()
          for i:0..1
            if ps[i] == true
              ps[i] = "on"
            else 
              ps[i] = "off"
            end
          end
          var json_payload = '{\"switches\":[{\"outlet\":0,\"switch\":\"' + ps[0] + '\"},{\"outlet\":1,\"switch\":\"' + ps[1] +  '\"}]}'
          log('NSP: Switch state updated with ' + json_payload)
          self.send(json_payload)
        end  
      
        # draw widgets
        def draw()
          var i = 1
          while i < 9
            if size(widget[i]) > 1
              var wdgt = ""
              if widget[i][1] == "scene"
                wdgt = '{"HMI_resources":[{"index":' + str(i) + ',"ctype":"' + widget[i][1] + '","id":"' + str(i) + '"}]}'
              else
                wdgt = '{"HMI_resources":[{"index":' + str(i) + ',"ctype":"' + widget[i][1] + '","id":"' + str(i) + '","uiid":' + str(widget[i][2]) + '}]}'
              end
              var name = '{"relation":[{"ctype":"' + widget[i][1] + '","id":"' + str(i) + '","name":"' + widget[i][0][0..7] + '"}]}'
              self.send(wdgt)
              self.send(name)
            else
            self.send('{"index":' + str(i) + ',"type":"delete"}')
            end
            i += 1
          end
        end
      
      # update weather forecast, since the provider doesn't support range I winged it with FeelsLike temperature
        def set_weather()
          import json
            var weather_icon = {
              "": 30,      # Unknown             
              "113": 1,    # Sunny      
              "116": 2,    # PartlyCloudy   
              "119": 2,    # Cloudy             
              "122": 7,    # VeryCloudy           
              "143": 11,   # Fog                 
              "176": 40,   # LightShowers     
              "179": 24,   # LightSleetShowers 
              "182": 24,   # LightSleet        
              "185": 24,   # LightSleet        
              "200": 42,   # ThunderyShowers  
              "227": 20,   # LightSnow  
              "230": 22,   # HeavySnow        
              "248": 11,   # Fog                 
              "260": 11,   # Fog                 
              "263": 40,   # LightShowers     
              "266": 40,   # LightRain      
              "281": 24,   # LightSleet        
              "284": 24,   # LightSleet        
              "293": 40,   # LightRain      
              "296": 40,   # LightRain      
              "299": 18,   # HeavyShowers      
              "302": 18,   # HeavyRain        
              "305": 18,   # HeavyShowers      
              "308": 18,   # HeavyRain        
              "311": 24,   # LightSleet        
              "314": 24,   # LightSleet        
              "317": 24,   # LightSleet        
              "320": 20,   # LightSnow  
              "323": 22,   # LightSnowShowers 
              "326": 22,   # LightSnowShowers 
              "329": 22,   # HeavySnow        
              "332": 22,   # HeavySnow        
              "335": 29,   # HeavySnowShowers   
              "338": 22,   # HeavySnow        
              "350": 24,   # LightSleet        
              "353": 24,   # LightSleet        
              "356": 18,   # HeavyShowers      
              "359": 18,   # HeavyRain        
              "362": 24,   # LightSleetShowers 
              "365": 24,   # LightSleetShowers 
              "368": 22,   # LightSnowShowers 
              "371": 29,   # HeavySnowShowers   
              "374": 24,   # LightSleetShowers 
              "377": 24,   # LightSleet        
              "386": 42,   # ThunderyShowers  
              "389": 42,   # ThunderyHeavyRain  
              "392": 42,   # ThunderySnowShowers
              "395": 29,   # HeavySnowShowers   
            }   
          var temp
          var tmin
          var tmax
          var cl = webclient()
          var url = "http://wttr.in/" + loc + '?format=j2'
          cl.set_useragent("curl/7.72.0")
          cl.set_follow_redirects(true)
          cl.begin(url)
          if cl.GET() == "200" || cl.GET() == 200
            var b = json.load(cl.get_string())
      
            if persist.tempunit == "F"
              temp = b['current_condition'][0]['temp_F']
              tmin = b['weather'][0]['mintempF']
              tmax = b['weather'][0]['maxtempF']
            else
              temp = b['current_condition'][0]['temp_C']
              tmin = b['weather'][0]['mintempC']
              tmax = b['weather'][0]['maxtempC']
            end
      
            var wttr = '{"HMI_weather":' + str(weather_icon[b['current_condition'][0]['weatherCode']]) + ',"HMI_outdoorTemp":{"current":' + temp + ',"range":" ' + tmin + ', ' + tmax + '"}}'
            self.send(wttr)
            log('NSP: Weather update for location: ' + b['nearest_area'][0]['areaName'][0]['value'] + ", "+ b['nearest_area'][0]['country'][0]['value'])
          else
            log('NSP: Weather update failed!', 3)
          end
        end
      
        # commands to populate an empty screen, should be executed when screen initializes
        def screeninit()
          # self.send('{"queryInfo":"version"}')
          self.send('{"HMI_ATCDevice":{"ctype":"device","id":"' + self.atc['id'] + '","outlet":' + self.atc['outlet'] + ',"etype":"' + self.atc['etype'] + '"}')
          self.send('{"relation":[{"ctype":"device","id":"panel","name":"' + devicename + '","online":true}]}')
          self.send('{"HMI_dimOpen":' + persist.dim + '}')
          self.set_clock()
          self.set_power()
          self.set_weather()
          self.draw()
          tasmota.cmd("State")
          tasmota.cmd("TelePeriod")
        end
      
        # read serial port and decode messages according to protocol used
        def every_100ms()
          if self.ser.available() > 0
          var msg = self.ser.read()   # read bytes from serial as bytes
          import string
            if size(msg) > 0
              print("NSP: Received Raw =", msg)
              if msg[0..1] == self.header
                mode = "NSPanel"
                var lst = self.split_55(msg)
                for i:0..size(lst)-1
                  msg = lst[i]
                    if self.atc['mirror'] == true
                      if msg[2] == 0x84 self.ser.write(msg)   # resend messages with type 0x84 for thermostat page
                      end
                    end
                  var j = size(msg) - 1
                  while msg[j] != 0x7D
                    msg = msg[0..-1]
                    j -= 1
                  end        
                  msg = msg[5..j]
                    if size(msg) > 2
                      if msg == bytes('7B226572726F72223A307D') # don't publish {"error":0}
                      else 
                      var jm = string.format("{\"NSPanel\":%s}",msg.asstring())
                      tasmota.publish_result(jm, "RESULT")
                      end
                    end
                end
              elif msg == bytes('000000FFFFFF88FFFFFF')
                log("NSP: Screen Initialized")   # print the message as string
                self.screeninit()
              else
                var jm = string.format("{\"NSPanel\":{\"Nextion\":\"%s\"}}",str(msg[0..-4]))
                tasmota.publish_result(jm, "RESULT")        end       
            end
          end
        end
      end      
      
      nsp=NSPanel()
      
      tasmota.add_rule("power1#state", /-> nsp.set_power())
      tasmota.add_rule("power2#state", /-> nsp.set_power())
      
      # add NSPSend command to Tasmota
      def nspsend(cmd, idx, payload, payload_json)
        # NSPSend2 sends Nextion commands
        if idx == 2
        var command = nsp.sendnx(payload)
        tasmota.resp_cmnd_done()
        # NSPSend sends NSPanel commands, requires valid payload
        else
        import json
        var command = nsp.send(json.dump(payload_json))
        tasmota.resp_cmnd_done()
        end
      end
      
      tasmota.add_cmd('NSPSend', nspsend)
      
      # add NSPMode command to Tasmota
      def modeselect(NSPMode, idx, payload)
        if payload == "1"
          nsp.sendnx('DRAKJHSUYDGBNCJHGJKSHBDN')
          tasmota.resp_cmnd_done()
          mode = "Nextion"
        elif payload == "0"
          nsp.sendnx('recmod=1')
          nsp.sendnx('recmod=1')
          mode = "NSPanel"
          tasmota.resp_cmnd_done()
        else
        tasmota.resp_cmnd_str('{"Mode":"' + mode + '"}')
        end
      end
      
      tasmota.add_cmd('NSPMode', modeselect)
      
      # add NSPDim command to Tasmota
      def dimopen(NSPDim, idx, payload)
        if payload == "0" || payload == "1"
          persist.dim = payload
          nsp.send('{"HMI_dimOpen":' + payload + '}')
          tasmota.resp_cmnd_done()
        else
          payload = str(persist.dim)
        end
        import string
        var jm = string.format("{\"NSPanel\":{\"Energy-saving\":%s}}",payload)
        tasmota.publish_result(jm, "RESULT")
      end
      
      tasmota.add_cmd('NSPDim', dimopen)
      
      # add NSPLocation command to Tasmota
      def setloc(NSPLocation, idx, payload)
        if size(payload) > 1
          persist.loc = payload
          tasmota.resp_cmnd_done()
          persist.save()
          loc = persist.loc
          nsp.set_weather()
        else
          payload = loc
        end
        import string
        var jm = string.format("{\"NSPanel\":{\"Location\":\"%s\"}}",payload)
        tasmota.publish_result(jm, "RESULT")
      end
      
      tasmota.add_cmd('NSPLocation', setloc)
      
      # add NSPWInterval command to Tasmota
      def setWInterval(NSPLocation, idx, p)
        var payload = int(p)
        if payload > 0
          persist.weather_interval = payload
          tasmota.resp_cmnd_done()
          persist.save()
          weather_interval = persist.weather_interval
          nsp.set_weather()
        else
          payload = weather_interval
        end
        import string
        var jm = string.format("{\"NSPanel\":{\"Weather Interval\":\"%d\"}}",payload)
        tasmota.publish_result(jm, "RESULT")
      end
      
      tasmota.add_cmd('NSPWInterval', setWInterval)
      
      # set displayed indoor temperature to value:int
      def set_temp(value)
        var temp_payload = '{"temperature":' + str(value) + ',"tempUnit":"' + persist.tempunit + '"}'
        log('NSP: Indoor temperature set with ' + temp_payload, 3)
        nsp.send(temp_payload)
      end
      
      tasmota.add_rule("Tele#ANALOG#Temperature1", set_temp) # rule to run set_temp on teleperiod
      
      # set wifi icon status
      
      def set_wifi(value)
        var rssi = (value-1)/20
        rssi = '{"wifiState":"connected","rssiLevel":' + str(rssi) + '}'
        log('NSP: Wi-Fi icon set with ' + rssi, 3)
        nsp.send(rssi)
      end
      
      def set_disconnect()
        nsp.send('{"wifiState":"nonetwork","rssiLevel":0}')
      end
      
      def sync_weather() # set weather every 60 minutes
        var interval = persist.has("weather_interval") ? int(persist.weather_interval) : 60
        nsp.set_weather()
        print("Weather forecast synced")
        tasmota.set_timer(interval*60*1000, sync_weather)
      end
      
      tasmota.cmd("Rule3 1") # needed until Berry bug fixed
      tasmota.cmd("State")
      tasmota.add_rule("Time#Minute", /-> nsp.set_clock()) # set rule to update clock every minute
      tasmota.add_rule("Tele#Wifi#RSSI", set_wifi) # set rule to update wifi icon
      tasmota.add_rule("wifi#disconnected", set_disconnect) # set rule to change wifi icon on disconnect
      tasmota.add_rule("mqtt#disconnected", set_disconnect) # set rule to change wifi icon on disconnect
      tasmota.add_rule("system#boot", /-> nsp.screeninit()) 
      tasmota.add_rule("time#initialized", sync_weather)
      
      tasmota.cmd("TelePeriod")
      
      Das steht in der nspanel.be drinne
      
      Marc Berg 1 Reply Last reply Reply Quote 0
      • Marc Berg
        Marc Berg Most Active @Thorsten47 last edited by

        @thorsten47 sagte in Sonoff NSpanel und mqtt:

        bin absuluter neuling

        Okay, dann stehst Du aber wirklich noch ganz am Anfang und bist wahrscheinlich hier:

        https://forum.iobroker.net/topic/58170/sonoff-nspanel-mit-lovelace-ui

        besser aufgehoben.

        T 1 Reply Last reply Reply Quote 1
        • T
          Thorsten47 @Marc Berg last edited by

          @marc-berg
          mit esp 8266 hab ich schon vieles gemacht aber noch nie mit tasmota ich werde mir das mal durchlesen hab heute morgen gegoogelt und nix gefunden

          Armilar 1 Reply Last reply Reply Quote 1
          • Armilar
            Armilar Most Active Forum Testing @Thorsten47 last edited by Armilar

            @thorsten47

            Hi @Thorsten47,

            habe nicht ganz verstanden, welches System jetzt dein Primärsystem ist? HA oder ioBroker und unter welchem System soll das NSPanel laufen?

            Das "NSPanel Lovelace UI" Projekt ist eine Zusammenarbeit mit unterschiedlichsten SmartHome Systemen. Es funktioniert daher im ioBroker und im Home Assistant.

            Die Integration für den ioBroker findest du im Wiki:
            https://github.com/joBr99/nspanel-lovelace-ui/wiki

            Die Integration für den Home Assistant unter HACS:
            03edc907-cf92-499c-909f-d25741de9cca-image.png
            und die Doku:
            https://docs.nspanel.pky.eu/stable/

            P.S.: wir haben natürlich die Kalibrierung des Temperatursensors ebenfalls im Wiki beschrieben (Funktioniert natürlich für beide Systeme so, da Tasmota):
            https://github.com/joBr99/nspanel-lovelace-ui/wiki/NSPanel-Tasmota-FAQ#21--interner-raum-temperatursensor

            EDIT: Für den ioBroker findest du den Support-Thread unter:
            https://forum.iobroker.net/topic/58170/sonoff-nspanel-mit-lovelace-ui?_=1716146183145

            Im ioBroker ist die Funktionalität etwas größer als im Home Assistant. Auch lassen sich komplexe Anforderungen wie Integrationen mit Charts im ioBroker lösen (Aktuell im HA nicht machbar...)

            Hier auch ein paar Beispiele:
            https://forum.iobroker.net/topic/69942/sonoff-nspanel-mit-lovelace-ui-zeigt-her-eure-cards

            T 1 Reply Last reply Reply Quote 1
            • T
              Thorsten47 @Armilar last edited by

              @armilar mein System auf dem nspanel ist tasmota
              und ich habe 2 raspberry pi im einsatz einer ist der home assitant der andere mein io broker das funktioniert auch alles moechte nur auf dem nspanel statt der vergegebenen Temperaturen die von meiner MQTT Wetterstation einbinden

              T 1 Reply Last reply Reply Quote 0
              • Armilar
                Armilar Most Active Forum Testing last edited by Armilar

                @thorsten47

                schon klar, dass auf dem NSPanel Tasmota läuft.

                Unter welchem System (ioBroker oder Home Assistant) soll die Steuerung für das NSPanel laufen? Das ist die Frage 😊

                In einem vorherigen Beispiel hast du einen Auszug aus der Tasmota mit Stock-TFT gepostet
                78dddb9b-5ef2-4957-99f5-024fbd4ea85b-image.png

                Die ist natürlich maximal nutzlos, da sich damit so ziemlich gar nichts umsetzen lässt...

                Wir sprechen hier von einer alternativen TFT-Firmware mit Lovelace UI um alle Funktionalitäten des Smart Homes zu nutzen 😉

                T 1 Reply Last reply Reply Quote 1
                • T
                  TT-Tom @Thorsten47 last edited by

                  @thorsten47 wie @Armilar schon schrieb über welches System kommen die Daten. Kommen sie von homeAssistment oder vom Iobroker. Das müssen wir erstmal klären. Die Daten vom mqtt wo kommen sie denn an??

                  1 Reply Last reply Reply Quote 1
                  • T
                    Thorsten47 @Armilar last edited by

                    @TT-Tom welche ist die einfachste form des ganzen. Scheint ja sehr komplex zu sein aber steuern möchte ich eigentlich alles zentral mit dem home-assistant

                    Hab gestern Abend nochmal eine Anleitung befolgt nu macht das display20240520_090016.jpg sowas. Dazu meine frage komme ich da wieder zur original Firmware zurück wenn ja wie und wo bekomme ich die her.

                    Hab schon 2. NS Panel bestellt

                    Armilar 1 Reply Last reply Reply Quote 0
                    • Armilar
                      Armilar Most Active Forum Testing @Thorsten47 last edited by Armilar

                      @thorsten47 sagte in Sonoff NSpanel und mqtt:

                      Dazu meine frage komme ich da wieder zur original Firmware zurück wenn ja wie und wo bekomme ich die her.

                      Gar nicht... Sobald der Weg mit Tasmota beschritten ist, gibt es für das NSPanel kein zurück zur Original-Firmware von iTead mehr.

                      Scheint ja sehr komplex zu sein aber steuern möchte ich eigentlich alles zentral mit dem home-assistant

                      Das Panel benötigt jetzt ein Backend um die Entitäten des Home Assistant zu steuern und Seiten aufzubauen --> Augen zu und durch... sieht schlimmer aus, als es ist... Immer die Anleitung für HA befolgen...

                      Diese findest du in der Beschreibung für den Home Assistant:
                      https://docs.nspanel.pky.eu/stable/

                      EDIT: Hier wird es doch ganz ordentlich für HA erklärt...
                      https://www.youtube.com/watch?v=3kOQ4lhF8u0

                      T 1 Reply Last reply Reply Quote 0
                      • T
                        Thorsten47 @Armilar last edited by

                        @armilar Hab das nach der Anleitung versucht aber klappt nicht hab die die Verzeichnissstruktur
                        ( /addon_configs/a0d7b954_appdaemon/appdeamon.yaml) so auch nicht. sondersn so (/homeassistant/appdaemon/apps/apps.yaml ) die apps.yaml hatte ich auch nicht hab ich angelegt
                        aber irgendwie klappt nix davon

                        Armilar 1 Reply Last reply Reply Quote 0
                        • Armilar
                          Armilar Most Active Forum Testing @Thorsten47 last edited by Armilar

                          @thorsten47

                          Ich kann dir leider nur beim Betreiben des NSPanels auf der ioBroker Seite helfen.

                          Mit Home Assistant müsstest du auf ein Forum für Home Assistant um dir Hilfe zu suchen.

                          @joBr99 - gibt es für HA ein Forum in dem solche Fragen geklärt werden können?

                          T 1 Reply Last reply Reply Quote 0
                          • T
                            Thorsten47 @Armilar last edited by

                            @armilar moentan funktioniert es noch nicht werde mich damit in ruhe befassen erstmal muss ich die SD card von meinem Home Assistand reparieren die ist kaputt deswegen startet der auch nicht oder installiert nix

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

                            Support us

                            ioBroker
                            Community Adapters
                            Donate

                            792
                            Online

                            31.7k
                            Users

                            79.8k
                            Topics

                            1.3m
                            Posts

                            4
                            14
                            726
                            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