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

    • Neues Video über Aliase, virtuelle Geräte und Kategorien

    • Wir empfehlen: Node.js 22.x

    • Neuer Blog: Fotos und Eindrücke aus Solingen

    Homelink - Garagentorantrieb Marantec

    This topic has been deleted. Only users with topic management privileges can see it.
    • 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();
                  
                  
                  D 1 Reply Last reply Reply Quote 0
                  • D
                    drapo @Longbow last edited by drapo

                    @longbow vielen Dank fürs Teilen. Funktioniert Dein Script ohne hänger (von Zeit zu Zeit habe ich diese auch)? Resp. wie lange hast Du es bereits in Verwendung?

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

                      @drapo Guten Morgen, also ich habe es seit der ersten Juni Woche am laufen und es ist sehr gut und stabil...

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

                        Hallo, könntet Ihr es Testen und ausprobieren?

                        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

                        412
                        Online

                        32.1k
                        Users

                        80.6k
                        Topics

                        1.3m
                        Posts

                        17
                        69
                        8368
                        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