Skip to content
  • Home
  • Recent
  • Tags
  • 0 Unread 0
  • Categories
  • Unreplied
  • Popular
  • GitHub
  • Docu
  • Hilfe
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
ioBroker Logo

Community Forum

donate donate
  1. ioBroker Community Home
  2. Deutsch
  3. ioBroker Allgemein
  4. Homelink - Garagentorantrieb Marantec

NEWS

  • Monatsrückblick Januar/Februar 2026 ist online!
    BluefoxB
    Bluefox
    17
    1
    408

  • Jahresrückblick 2025 – unser neuer Blogbeitrag ist online! ✨
    BluefoxB
    Bluefox
    17
    1
    5.0k

  • Neuer Blogbeitrag: Monatsrückblick - Dezember 2025 🎄
    BluefoxB
    Bluefox
    13
    1
    1.4k

Homelink - Garagentorantrieb Marantec

Scheduled Pinned Locked Moved ioBroker Allgemein
69 Posts 17 Posters 10.7k Views 14 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D drapo

    @tombox wollte mal freundlich nachfragen ob Du dir das bereits ansehen konntest? Fand diese Lösung bis anhin ganz praktisch. Danke auf jeden Fall für Deine Unterstützung.

    T Offline
    T Offline
    tombox
    wrote on last edited by
    #51

    @drapo bräuchte nochmal funktionierende Zugangsdaten zum testen ruhig per mail an tombox2020@gmail.com

    D 1 Reply Last reply
    0
    • T tombox

      @drapo bräuchte nochmal funktionierende Zugangsdaten zum testen ruhig per mail an tombox2020@gmail.com

      D Offline
      D Offline
      drapo
      wrote on last edited by
      #52

      @tombox mit denen kannst du ja dann meine Garage steuern. Was genau wirst Du mit den Zugangsdaten machen und mit wievielen auf und zu meines Garagentores muss ich rechnen?

      T 1 Reply Last reply
      0
      • D drapo

        @tombox mit denen kannst du ja dann meine Garage steuern. Was genau wirst Du mit den Zugangsdaten machen und mit wievielen auf und zu meines Garagentores muss ich rechnen?

        T Offline
        T Offline
        tombox
        wrote on last edited by
        #53

        @drapo Also ich werde Tor nicht öffnen ich muss nur den Login Vorgang und Abruf der geräte Daten checken mehr nicht

        D 1 Reply Last reply
        0
        • T tombox

          @drapo Also ich werde Tor nicht öffnen ich muss nur den Login Vorgang und Abruf der geräte Daten checken mehr nicht

          D Offline
          D Offline
          drapo
          wrote on last edited by
          #54

          @tombox ok daten sind raus. Bitte gib mir rasch rückmeldumg wenn du fertig bist dann werde ich das PW wieder ändern

          1 Reply Last reply
          0
          • P Offline
            P Offline
            Patrick90
            wrote on last edited by
            #55

            Guten Tag,

            ich habe vom Maveosupport folgende Email erhalten

            es tut mir sehr leid, dass Sie so lange bereits auf diese Features warten. Leider ist die Integration dieser Systeme sehr aufwändig und mit einer Menge Zertifizierungen verbunden. Ich möchte Ihnen gerne ein Update zu diesem Thema geben:
            Wir arbeiten aktuell an der Integration des Smart Home Standards MATTER. Hiermit können wir mit einem Standard die Integration in HomeKit, Google Home und Alexa erreichen. Auch Android Auto ist bereits fertig entwickelt, aktuell warten wir hier mit dem Release noch auf die finale Integration von Apple CarPlay.

            Ist für euch lediglich zur Info.

            P 1 Reply Last reply
            0
            • P Patrick90

              Guten Tag,

              ich habe vom Maveosupport folgende Email erhalten

              es tut mir sehr leid, dass Sie so lange bereits auf diese Features warten. Leider ist die Integration dieser Systeme sehr aufwändig und mit einer Menge Zertifizierungen verbunden. Ich möchte Ihnen gerne ein Update zu diesem Thema geben:
              Wir arbeiten aktuell an der Integration des Smart Home Standards MATTER. Hiermit können wir mit einem Standard die Integration in HomeKit, Google Home und Alexa erreichen. Auch Android Auto ist bereits fertig entwickelt, aktuell warten wir hier mit dem Release noch auf die finale Integration von Apple CarPlay.

              Ist für euch lediglich zur Info.

              P Offline
              P Offline
              Patrick90
              wrote on last edited by
              #56

              @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
              0
              • P Patrick90

                @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 Offline
                R Offline
                Ritschy2000
                wrote on last edited by Ritschy2000
                #57

                @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
                0
                • T Offline
                  T Offline
                  TomTom24
                  wrote on last edited by
                  #58

                  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
                   }
                  });
                  
                  LongbowL D 2 Replies Last reply
                  0
                  • T TomTom24

                    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
                     }
                    });
                    
                    LongbowL Offline
                    LongbowL Offline
                    Longbow
                    wrote on last edited by
                    #59

                    @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
                    0
                    • LongbowL Longbow

                      @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 Offline
                      R Offline
                      Ritschy2000
                      wrote on last edited by Ritschy2000
                      #60

                      @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.

                      LongbowL 1 Reply Last reply
                      0
                      • R 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.

                        LongbowL Offline
                        LongbowL Offline
                        Longbow
                        wrote on last edited by
                        #61

                        @ritschy2000 sagte in Homelink - Garagentorantrieb Marantec:

                        Variante Stic

                        den WLAN Stick, gibt es die andere Variante noch?

                        R 1 Reply Last reply
                        0
                        • LongbowL Longbow

                          @ritschy2000 sagte in Homelink - Garagentorantrieb Marantec:

                          Variante Stic

                          den WLAN Stick, gibt es die andere Variante noch?

                          R Offline
                          R Offline
                          Ritschy2000
                          wrote on last edited by
                          #62

                          @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 € ;)

                          LongbowL 1 Reply Last reply
                          0
                          • R Ritschy2000

                            @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 € ;)

                            LongbowL Offline
                            LongbowL Offline
                            Longbow
                            wrote on last edited by
                            #63

                            @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
                            0
                            • T TomTom24

                              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
                               }
                              });
                              
                              D Offline
                              D Offline
                              drapo
                              wrote on last edited by
                              #64

                              @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
                              0
                              • D drapo

                                @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 Offline
                                D Offline
                                drapo
                                wrote on last edited by
                                #65

                                @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
                                0
                                • LongbowL Offline
                                  LongbowL Offline
                                  Longbow
                                  wrote on last edited by
                                  #66

                                  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
                                  0
                                  • LongbowL Longbow

                                    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 Offline
                                    D Offline
                                    drapo
                                    wrote on last edited by drapo
                                    #67

                                    @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?

                                    LongbowL 1 Reply Last reply
                                    0
                                    • D 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?

                                      LongbowL Offline
                                      LongbowL Offline
                                      Longbow
                                      wrote on last edited by
                                      #68

                                      @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
                                      0
                                      • LongbowL Offline
                                        LongbowL Offline
                                        Longbow
                                        wrote on last edited by
                                        #69

                                        Hallo, könntet Ihr es Testen und ausprobieren?

                                        1 Reply Last reply
                                        0
                                        Reply
                                        • Reply as topic
                                        Log in to reply
                                        • Oldest to Newest
                                        • Newest to Oldest
                                        • Most Votes


                                        Support us

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

                                        573

                                        Online

                                        32.7k

                                        Users

                                        82.5k

                                        Topics

                                        1.3m

                                        Posts
                                        Community
                                        Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen | Einwilligungseinstellungen
                                        ioBroker Community 2014-2025
                                        logo
                                        • Login

                                        • Don't have an account? Register

                                        • Login or register to search.
                                        • First post
                                          Last post
                                        0
                                        • Home
                                        • Recent
                                        • Tags
                                        • Unread 0
                                        • Categories
                                        • Unreplied
                                        • Popular
                                        • GitHub
                                        • Docu
                                        • Hilfe