Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. ioBroker Allgemein
    4. Homelink - Garagentorantrieb Marantec

    NEWS

    • Wir empfehlen: Node.js 22.x

    • Neuer Blog: Fotos und Eindrücke aus Solingen

    • ioBroker goes Matter ... Matter Adapter in Stable

    Homelink - Garagentorantrieb Marantec

    This topic has been deleted. Only users with topic management privileges can see it.
    • P
      Patrick90 @Patrick90 last edited by

      @patrick90

      kommt mir definitiv länger vor als gerade mal ein Jahr. Ich habe dennoch mal nachgefragt, worauf man jetzt noch wartet.

      2024-07-30 19_23_29-Window.png

      R 1 Reply Last reply Reply Quote 0
      • R
        Ritschy2000 @Patrick90 last edited by Ritschy2000

        @patrick90 darf man fragen, ob du schon neue Infos erhalten hast ? Die Integration in Android Auto würde mich auch interessieren...

        1 Reply Last reply Reply Quote 0
        • T
          TomTom24 last edited by

          Hi,
          ich habe mir ein Script gebastelt mit JS-Adapter. Das funktioniert sehr gut und man kann darüber einfach Schalter in Homekit anlegen und z.b. die Garage öffnen. Läuft hier seit über einem Jahr einwandfrei. Ab und zu muss der Adapater/Host neu gestartet werden, weil der Host aus irgendwelchen Gründen dann den Client nicht mehr kennt.

          1. Datenpunkte anlegen
          2. Dann braucht ihr nur noch ein kleines Script, dass die Werte open, close, stop, lighton, lightoff in den dp_cmd schreibt.
          3. DeviceName muss so sein, wie Eure Garage in Eurer App heißt!!

          Wie gesagt, läuft hier sehr zuverlässig.

          // wenns nicht geht - IP-Adresse Garage prüfen
          // Benötigt mqtt -wenns nicht geht - IP-Adresse Garage prüfen
          //
          //
          var net = require('net'); 
          
          var dp_door = "0_userdata.0.Garage.Garage_Status_Tor"; //door state
          var dp_light = "0_userdata.0.Garage.Garage_Status_Licht"; //light state
          var dp_cmd = "0_userdata.0.Garage.Garage_Command2"; //Befehlsdatenpunkt: Mögliche Werte: open, close, stop, lighton, lightoff. Nach Beschreiben wird der Datenpunkt wieder auf leer gesetzt
          
          var deviceName = "GARAGENNAME"; 
          var host = "IP_ADRESSE";
          var port = 2785;
          
          // random client, weil nach Stromausfall das Script nicht mehr lief, erst als anderer Client angegeben wurde.
          let x = Math.floor((Math.random() * 30) + 1);
          
          var client=x.toString; // Client mit übergeben
          
          function startClient() {
              client = new net.Socket();                 // Erzeugen eines neuen Verbindungsobjekts
              client.connect(port, host, function() {     // Gerät über host:port anwählen und Verbindung erzeugen
                  console.log('cliend started');
              });
              client.on('data', function(data) {          // Wenn daten ankommen, dann verarbeiten
                  console.log('client received: ' + data + " for device: " + deviceName);
                  var dataS = data.toString().trim();              // Datenbuffer in lesbaren Text umwandeln
                  switch(dataS) {                           // je nach rückgabewert unterschiedliche Bearbeitung
                      case "S;"+deviceName+";open":         // wenn open
                          setState(dp_door,"open",false);             // dann Datenpunkt setzen
                          setState(dp_door,"open",true);             // dann Datenpunkt setzen
                          // Garagentür ebenfalls öffnen
                          setState('alias.0.Garage.Garagentuer'/*Garagentuer auf zu*/, true)
                          console.log("Script Garage: "+dataS,"info");
                          break;
                      case "S;"+deviceName+";closed":
                          setState(dp_door,"closed",false);
                          setState(dp_door,"closed",true);
                          // Garagentür ebenfalls schließen
                          setState('alias.0.Garage.Garagentuer'/*Garagentuer auf zu*/, false) 
                          console.log("Script Garage: "+dataS,"info");
                          break;
                      case "S;"+deviceName+";opening":
                          setState(dp_door,"opening",false);
                          setState(dp_door,"opening",true);
                          console.log("Script Garage: "+dataS,"info");
                          break;
                      case "S;"+deviceName+";closing":
                          setState(dp_door,"closing",false);
                          setState(dp_door,"closing",true);
                          console.log("Script Garage: "+dataS,"info");
                          break;
                      case "S;"+deviceName+";lightOn":
                          setState(dp_light,"lightOn",false);
                          setState(dp_light,"lightOn",true);
                          console.log("Script Garage: "+dataS,"info");
                          break;
                      case "S;"+deviceName+";lightOff":
                          setState(dp_light,"lightOff",false);
                          setState(dp_light,"lightOff",true);
                          console.log("Script Garage: "+dataS,"info");
                          break;
                  }
              });
              client.on("error",(err)=>{                  // wenn ein Fehler entsteht
                  console.log("client error " + err.toString());
              });
              client.on("timeout",()=>{                   // wenn timeout entsteht
                  console.log("client timeout");
              });
          }
          
          function sendMessage(host, port, message) {
              return new Promise((resolve, reject) => {     // Funktion ist asynchron, daher Rückgabe promise
                  if (!client) {
                      console.log("No Client available :"+x);
                      resolve("Error");
                      return;
                  }
                  client.write(message);
                  resolve("OK");
              });
          }
          
          onStop (function(){
               /* do something when script is stopped */
               if (client) {
                  console.log('client ended ');
                  client.end();
               }
          }, 1000);
          
          startClient();
          
          on(dp_cmd, function (obj) {                     // trigger wenn datenpunkt beschrieben wird
           var cmd;
           if (obj.state.ack || !obj.state.ack) {                       // aber nur wenn es sich um einen unbestätigten wert handelt
               cmd = String(obj.state.val).toLowerCase();  // Datenpunktinhalt in Kleinbuchstaben umwandeln
               console.log('execute command: ' + cmd);
               switch(cmd) {                           // je nach Datenpunktinhalt verschiedene Befehle
                   case "open":                        // wenn open
                       sendMessage(host, port, "C;"+deviceName+";open"); // dann richtigen Befehl an Gerät senden
                       
                       break;
                   case "close":
                       sendMessage(host, port, "C;"+deviceName+";close");
                       break;
                   case "stop":
                       sendMessage(host, port, "C;"+deviceName+";stop");
                       break;
                   case "lighton":
                       sendMessage(host, port, "C;"+deviceName+";lightOn");
                       break;
                   case "lightoff":
                       sendMessage(host, port, "C;"+deviceName+";lightOff");
                       break;
               }
               
               setState(obj.id, {val: "", ack: false}); // datenpunkt auf leer als bestätigt setzen
           }
          });
          
          Longbow D 2 Replies Last reply Reply Quote 0
          • Longbow
            Longbow @TomTom24 last edited by

            @tomtom24

            Hallo, ich habe das Script gerade probiert.

            Das ist die Fehlermeldung: script.js.common.Scripte.Auffahrt.Marantec_Steuerung: client error Error: connect ECONNREFUSED 192.168.7.34:2785

            Also IP stimmt, Name von dem Stick stimmt. An was kann es noch liegen?

            R 1 Reply Last reply Reply Quote 0
            • R
              Ritschy2000 @Longbow last edited by Ritschy2000

              @longbow hast du den "neuen" WLAN-Stick oder noch die Variante Stick mit zusätzlichem Gateway?

              Mit den neuen WLAN-Sticks funktioniert es nicht (soweit mir bekannt ist), da bei diesen die Api nicht aktiviert werden kann.

              Longbow 1 Reply Last reply Reply Quote 0
              • Longbow
                Longbow @Ritschy2000 last edited by

                @ritschy2000 sagte in Homelink - Garagentorantrieb Marantec:

                Variante Stic

                den WLAN Stick, gibt es die andere Variante noch?

                R 1 Reply Last reply Reply Quote 0
                • R
                  Ritschy2000 @Longbow last edited by

                  @longbow direkt bei Maveo nicht. Bei Ebay oder anderen Online- Händlern schon.

                  Suche mal nach "maveo Starter Bundle" oder "Maveo box Starterpaket".
                  Ist dann Gateway + "alter" Stick .... kostet auch "nur" günstige 190 € 😉

                  Longbow 1 Reply Last reply Reply Quote 0
                  • Longbow
                    Longbow @Ritschy2000 last edited by

                    @ritschy2000

                    Danke, habe ich gemacht. Nur leider verbindet sich der Stick nicht mit dem Torantrieb. Habe den X.82, der soll aber gehen, da dieses Bundel mit allen Torantrieben ab 2014 gehen soll... Geht aber nicht leider nicht....

                    Wer kennst sich mit den Torantrieben Marantec aus und kann mir helfen?

                    1 Reply Last reply Reply Quote 0
                    • D
                      drapo @TomTom24 last edited by

                      @tomtom24 ich hatte das auch über längere Zeit einwandfrei und ohne Probleme am Laufen. Seit ein paar Monaten gehts es bei mir nicht mehr. Geht es bei Dir noch?

                      D 1 Reply Last reply Reply Quote 0
                      • D
                        drapo @drapo last edited by

                        @drapo hab die box geresettet neu verbunden extra auch ein 2,4ghz wlan netz erstellt und nun funktioniert wieder alles wie eh und je

                        1 Reply Last reply Reply Quote 0
                        • Longbow
                          Longbow last edited by

                          Hallo in die Runde,

                          da ich auch so einen Antrieb habe und die Box, hatte ich das Script auch so übernommen.
                          Leider hing es hin und wieder bei mir, daher habe ich mich dran gesetzt und das nun gebaut.

                          Hoffe es ist selbst erklärend und gefällt euch, wenn ihr Fragen habt, melde Euch einfach bei mir.

                          // ===== TCP-Client Garagentor (ioBroker JavaScript) =====
                          // Robust: Reconnect + Backoff, KeepAlive, sauberes Line-Parsing (S;..., R;...),
                          // AutoClose nach X Minuten mit Rest-SECONDS-Datenpunkt, DP-Autoanlage,
                          // Licht-Status als boolean, shutdown-sicher (keine DB-closed-Fehler)
                          const net = require('net');
                          
                          // ==== KONFIG ====
                          const deviceName = "Auffahrt";
                          const host = "xxx.xxx.x.xxx";
                          const port = 2785;
                          const SEND_NEWLINE = true;
                          
                          // ==== BASIS-PFAD ====
                          const base = "0_userdata.0.Eigene_Datenpunkte.Garage.";
                          
                          // ==== DATENPUNKTE ====
                          const dp_door         = base + "Garage_Status_Tor";          // "open|closed|opening|closing"
                          const dp_light        = base + "Garage_Status_Licht";        // boolean
                          const dp_cmd          = base + "Garage_Command";             // "open|close|stop|lighton|lightoff"
                          const dp_connected    = base + "Garage_TcpConnected";        // boolean
                          const dp_lastReply    = base + "Garage_LastReply";           // string
                          const dp_lastError    = base + "Garage_LastError";           // string
                          const dp_ac_enabled   = base + "AutoClose_Enabled";          // boolean
                          const dp_ac_delay     = base + "AutoClose_DelayMin";         // number (1..120)
                          const dp_ac_left_s    = base + "AutoClose_RemainingSec";     // number (Sek., read-only)
                          const dp_lastOpened   = base + "Garage_LastOpened";          // ISO-Zeit
                          const dp_lastClosed   = base + "Garage_LastClosed";          // ISO-Zeit
                          
                          // ---- Dein vorhandener Notify-DP (nicht anlegen, nur schreiben) ----
                          const dp_notify = "hm-rega.0.31016"; // bestehender Homematic-ReGa Datenpunkt/Variable
                          
                          // ---- Notify-Logik: Frühwarnung & Hysterese ----
                          const EARLY_TRIGGER_SEC = 60;        // ab so vielen Sekunden vor Auto-Close -> notify = true
                          const NOTIFY_FALSE_DELAY_MS = 5000;  // Hysterese: erst nach 5s "closed" -> notify = false
                          let notifyFalseTimer = null;
                          
                          // ==== DP-AUTOANLAGE (nur eigene 0_userdata.*) ====
                          function ensureState(id, defVal, common) {
                            if (!existsState(id)) {
                              createState(id, defVal, common, () => log(`State angelegt: ${id}`, 'info'));
                            }
                          }
                          ensureState(dp_door,        '',    { name:'Torstatus',        type:'string',  role:'text',                 read:true, write:false });
                          ensureState(dp_light,       false, { name:'Lichtstatus',      type:'boolean', role:'indicator.light',      read:true, write:false });
                          ensureState(dp_cmd,         '',    { name:'Befehl',           type:'string',  role:'text',                 read:true, write:true  });
                          ensureState(dp_connected,   false, { name:'TCP verbunden',    type:'boolean', role:'indicator.reachable',  read:true, write:false });
                          ensureState(dp_lastReply,   '',    { name:'Letzte Antwort',   type:'string',  role:'text',                 read:true, write:false });
                          ensureState(dp_lastError,   '',    { name:'Letzter Fehler',   type:'string',  role:'text',                 read:true, write:false });
                          ensureState(dp_ac_enabled,  true,  { name:'AutoClose aktiv',  type:'boolean', role:'switch',               read:true, write:true  });
                          ensureState(dp_ac_delay,    5,     { name:'AutoClose Minuten',type:'number',  role:'level', unit:'min',    read:true, write:true  });
                          ensureState(dp_ac_left_s,   0,     { name:'Rest-Sekunden',    type:'number',  role:'value', unit:'s',      read:true, write:false });
                          ensureState(dp_lastOpened,  '',    { name:'Letzte Öffnung',   type:'string',  role:'date',                 read:true, write:false });
                          ensureState(dp_lastClosed,  '',    { name:'Letzter Verschluss',type:'string', role:'date',                 read:true, write:false });
                          
                          // ==== SHUTDOWN-SAFE ====
                          let shuttingDown = false;
                          function safeSetState(id, val, ack = true) {
                            if (shuttingDown) return;
                            try { setState(id, val, ack); } catch (_) {}
                          }
                          
                          // ==== TCP ====
                          let client = null;
                          let reconnectTimer = null;
                          let reconnectDelayMs = 2000;
                          const reconnectDelayMaxMs = 30000;
                          let recvBuffer = '';
                          
                          function startClient() {
                            clearTimeout(reconnectTimer);
                            client = new net.Socket();
                            client.setKeepAlive(true, 10000);
                            client.setEncoding('utf8');
                          
                            client.connect(port, host, () => {
                              log(`[${deviceName}] Verbunden mit ${host}:${port}`, 'info');
                              safeSetState(dp_connected, true);
                              reconnectDelayMs = 2000;
                            });
                          
                            client.on('data', (chunk) => {
                              recvBuffer += chunk;
                              const parts = recvBuffer.split(/\r?\n|\r/);
                              recvBuffer = parts.pop();
                              for (const raw of parts) {
                                const line = (raw || '').trim();
                                if (line) handleIncoming(line);
                              }
                            });
                          
                            client.on('error', (err) => {
                              log(`[${deviceName}] TCP Fehler: ${err.message}`, 'warn');
                              safeSetState(dp_connected, false);
                              safeSetState(dp_lastError, err.message);
                              scheduleReconnect();
                            });
                          
                            client.on('close', (hadError) => {
                              log(`[${deviceName}] TCP geschlossen${hadError ? ' (Fehler)' : ''}`, 'warn');
                              safeSetState(dp_connected, false);
                              scheduleReconnect();
                            });
                          }
                          
                          function scheduleReconnect() {
                            try { if (client) client.destroy(); } catch (_) {}
                            client = null;
                            reconnectTimer = setTimeout(startClient, reconnectDelayMs);
                            reconnectDelayMs = Math.min(Math.round(reconnectDelayMs * 1.5), reconnectDelayMaxMs);
                          }
                          
                          // ==== AUTO-CLOSE ====
                          let autoCloseTimer = null;
                          let autoCloseDeadline = 0;
                          let autoCloseTicker = null;
                          let acInternalTrigger = false;
                          
                          function getAcEnabled() {
                            const v = getState(dp_ac_enabled)?.val;
                            return v === true || v === 1 || v === 'true';
                          }
                          function getAcDelayMin() {
                            let m = Number(getState(dp_ac_delay)?.val);
                            if (!isFinite(m) || m <= 0) m = 5;
                            return Math.max(1, Math.min(120, Math.floor(m)));
                          }
                          
                          function scheduleAutoClose() {
                            if (!getAcEnabled()) { safeSetState(dp_ac_left_s, 0); return; }
                            const min = getAcDelayMin();
                            autoCloseDeadline = Date.now() + min * 60000;
                          
                            clearTimeout(autoCloseTimer);
                            autoCloseTimer = setTimeout(performAutoClose, min * 60000);
                          
                            startAutoCloseTicker();
                            updateRemainingSeconds();
                            log(`[${deviceName}] AutoClose geplant in ${min} Min`, 'info');
                          }
                          
                          function performAutoClose() {
                            if (shuttingDown) return;
                            autoCloseTimer = null;
                            const st = getState(dp_door)?.val;
                            if (st === 'open') {
                              log(`[${deviceName}] AutoClose ausgelöst -> schließe`, 'info');
                              acInternalTrigger = true;
                              try { setState(dp_cmd, { val: 'close', ack: false }); } catch (_) {}
                            } else {
                              log(`[${deviceName}] AutoClose übersprungen (Status: ${st})`, 'info');
                            }
                            stopAutoCloseTicker();
                            safeSetState(dp_ac_left_s, 0);
                            autoCloseDeadline = 0;
                            // dp_notify bleibt bis "closed" true (Hysterese regelt das Zurücksetzen)
                          }
                          
                          function cancelAutoClose(reason = '', suppressWrite = false) {
                            if (autoCloseTimer) clearTimeout(autoCloseTimer);
                            if (autoCloseTicker) clearInterval(autoCloseTicker);
                            autoCloseTimer = null;
                            autoCloseTicker = null;
                            autoCloseDeadline = 0;
                            if (!suppressWrite) safeSetState(dp_ac_left_s, 0);
                            if (reason) log(`[${deviceName}] AutoClose abgebrochen: ${reason}`, 'info');
                          }
                          
                          function updateRemainingSeconds() {
                            if (!autoCloseDeadline || shuttingDown) return;
                            const secLeft = Math.max(0, Math.ceil((autoCloseDeadline - Date.now()) / 1000));
                            safeSetState(dp_ac_left_s, secLeft);
                          
                            // Frühwarnung: ≤ EARLY_TRIGGER_SEC -> notify true
                            if (secLeft > 0 && secLeft <= EARLY_TRIGGER_SEC) {
                              clearTimeout(notifyFalseTimer);
                              safeSetState(dp_notify, true, /*ack*/ false); // bewusst ack=false, falls Triggers benötigt
                            }
                          }
                          
                          function startAutoCloseTicker() {
                            if (autoCloseTicker) return;
                            autoCloseTicker = setInterval(updateRemainingSeconds, 1000);
                          }
                          function stopAutoCloseTicker() {
                            if (!autoCloseTicker) return;
                            clearInterval(autoCloseTicker);
                            autoCloseTicker = null;
                          }
                          
                          // ==== EINGEHEND ====
                          function handleIncoming(line) {
                            const parts = line.split(';');
                            if (parts.length < 2) {
                              log(`[${deviceName}] Unbekanntes Paket: "${line}"`, 'warn');
                              return;
                            }
                            const prefix = parts[0];
                          
                            if (prefix === 'S') {
                              const dev = parts[1];
                              const value = parts.slice(2).join(';');
                              if (dev !== deviceName) return;
                          
                              switch (value) {
                                case 'open':
                                  safeSetState(dp_door, 'open');
                                  safeSetState(dp_lastOpened, new Date().toISOString());
                                  clearTimeout(notifyFalseTimer);
                                  safeSetState(dp_notify, true, /*ack*/ false); // sofort true
                                  scheduleAutoClose();
                                  break;
                          
                                case 'opening':
                                  safeSetState(dp_door, 'opening');
                                  clearTimeout(notifyFalseTimer);
                                  safeSetState(dp_notify, true, /*ack*/ false); // sofort true
                                  // kein Cancel hier
                                  break;
                          
                                case 'closing':
                                  safeSetState(dp_door, 'closing');
                                  clearTimeout(notifyFalseTimer);
                                  safeSetState(dp_notify, true, /*ack*/ false); // sofort true
                                  cancelAutoClose('Status=closing');
                                  break;
                          
                                case 'closed':
                                  safeSetState(dp_door, 'closed');
                                  safeSetState(dp_lastClosed, new Date().toISOString());
                                  cancelAutoClose('Status=closed');
                                  // Hysterese: erst nach 5s false
                                  clearTimeout(notifyFalseTimer);
                                  notifyFalseTimer = setTimeout(() => {
                                    safeSetState(dp_notify, false, /*ack*/ false);
                                  }, NOTIFY_FALSE_DELAY_MS);
                                  break;
                          
                                case 'lightOn':
                                  safeSetState(dp_light, true);
                                  break;
                          
                                case 'lightOff':
                                  safeSetState(dp_light, false);
                                  break;
                          
                                default:
                                  log(`[${deviceName}] Status: ${value}`, 'info');
                                  break;
                              }
                              return;
                            }
                          
                            if (prefix === 'R') {
                              const code = parts[1] || '';
                              safeSetState(dp_lastReply, code);
                              if (/ERR|UNKNOWN/i.test(code)) safeSetState(dp_lastError, code);
                              else log(`[${deviceName}] Antwort: ${code}`, 'info');
                              return;
                            }
                          
                            log(`[${deviceName}] Unbekanntes Paket: "${line}"`, 'warn');
                          }
                          
                          // ==== SENDEN ====
                          function sendMessage(msg) {
                            return new Promise(resolve => {
                              if (!client) { log(`[${deviceName}] Kein Client aktiv`, 'warn'); return resolve('Error'); }
                              try { client.write(SEND_NEWLINE ? (msg + '\n') : msg); resolve('OK'); }
                              catch (e) { log(`[${deviceName}] Sendefehler: ${e.message}`, 'error'); safeSetState(dp_lastError, e.message); resolve('Error'); }
                            });
                          }
                          
                          // ==== BEFEHL-TRIGGER ====
                          on({ id: dp_cmd, change: 'ne' }, async obj => {
                            if (obj.state.ack) return;
                            const cmd = String(obj.state.val || '').toLowerCase().trim();
                          
                            // Manuelle Befehle canceln AutoClose (interner Trigger nicht)
                            if (acInternalTrigger) {
                              log(`[${deviceName}] DP-Command (intern): ${cmd}`, 'info');
                            } else {
                              if (cmd === 'open' || cmd === 'close' || cmd === 'stop') {
                                cancelAutoClose(`Befehl: ${cmd}`);
                              }
                            }
                          
                            let payload = null;
                            switch (cmd) {
                              case 'open':     payload = `C;${deviceName};open`; break;
                              case 'close':    payload = `C;${deviceName};close`; break;
                              case 'stop':     payload = `C;${deviceName};stop`; break;
                              case 'lighton':  payload = `C;${deviceName};lightOn`; break;
                              case 'lightoff': payload = `C;${deviceName};lightOff`; break;
                              default:
                                log(`[${deviceName}] Unbekannter Befehl: ${cmd}`, 'warn');
                                safeSetState(dp_lastError, `UNKNOWN_CMD:${cmd}`);
                                break;
                            }
                          
                            if (payload) await sendMessage(payload);
                            safeSetState(dp_cmd, '', true);
                          
                            if (acInternalTrigger) acInternalTrigger = false;
                          });
                          
                          // ==== SETTINGS-ÄNDERUNGEN ====
                          on({ id: dp_ac_enabled, change: 'ne' }, () => {
                            const st = getState(dp_door)?.val;
                            if (getAcEnabled() && st === 'open') scheduleAutoClose();
                            else cancelAutoClose('AutoClose disabled');
                          });
                          on({ id: dp_ac_delay, change: 'ne' }, () => {
                            const st = getState(dp_door)?.val;
                            if (getAcEnabled() && st === 'open') scheduleAutoClose();
                          });
                          
                          // ==== START/STOP ====
                          onStop(() => {
                            shuttingDown = true;
                            clearTimeout(reconnectTimer);
                            clearTimeout(notifyFalseTimer);
                            if (client) { try { client.destroy(); } catch (_) {} }
                            cancelAutoClose('Script stop', true);
                          }, 1000);
                          
                          startClient();
                          
                          
                          1 Reply Last reply Reply Quote 0
                          • First post
                            Last post

                          Support us

                          ioBroker
                          Community Adapters
                          Donate
                          FAQ Cloud / IOT
                          HowTo: Node.js-Update
                          HowTo: Backup/Restore
                          Downloads
                          BLOG

                          457
                          Online

                          32.0k
                          Users

                          80.5k
                          Topics

                          1.3m
                          Posts

                          17
                          66
                          8156
                          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