Skip to content
  • Home
  • Aktuell
  • Tags
  • 0 Ungelesen 0
  • Kategorien
  • Unreplied
  • Beliebt
  • 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

  • Standard: (Kein Skin)
  • Kein Skin
Einklappen
ioBroker Logo

Community Forum

donate donate
  1. ioBroker Community Home
  2. Deutsch
  3. Praktische Anwendungen (Showcase)
  4. Hardware für 8 und mehr Velux/Somfi Geräte

NEWS

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

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

  • Weihnachtsangebot 2025! 🎄
    BluefoxB
    Bluefox
    25
    1
    2.2k

Hardware für 8 und mehr Velux/Somfi Geräte

Geplant Angeheftet Gesperrt Verschoben Praktische Anwendungen (Showcase)
3 Beiträge 3 Kommentatoren 898 Aufrufe 3 Watching
  • Älteste zuerst
  • Neuste zuerst
  • Meiste Stimmen
Antworten
  • In einem neuen Thema antworten
Anmelden zum Antworten
Dieses Thema wurde gelöscht. Nur Nutzer mit entsprechenden Rechten können es sehen.
  • T Offline
    T Offline
    tristan
    schrieb am zuletzt editiert von tristan
    #1

    Hallo Zusammen,

    ich hatte mal Bock was mit einem NodeMCU zusammen zu bauen und habe es zum Anlass genommen endlich mal meine Velux-Rolläden in meinen ioBroker zu integrieren. Und zwar ohne mich von Velux weiter veräppeln zu lassen mit KLF-200-Firmware-Updates oder irgendwelchen teueren nicht-smarten INTEGRA-Produkten.

    Dazu habe ich 3x Relais-Boards mit drei I/O-Extension-Boards an einen NodeMCU angeschlossen (~40EUR).
    Die 8 INTEGRA Fernbedienungen habe ich gestapelt und an die Relais angeschlossen. Versorgt werden sie über den 3V Ausgang vom NodeMCU. Versorgt wird das Ganze über ein USB Ladegerät.

    Ich nennen das Projekt F**K-YOU-VELUX-Stack.

    Die Einbindung habe ich über Tasmota gemacht, eine großartige Firmware. Erkennt automatisch die I/O-Extensions und stellt jeden Kontakt als MQTT zur Verfügung.

    Macht richtig Spaß dem Klackern der Relais zu lauschen. :-D

    f--k_you_Velux_Stack-2.jpg

    Loetpunkte-Velux-INTEGRA-KLI-2_.png

    screenshot-device.png

    VG Tristan

    const og_bad            = "javascript.0.Velux.og_bad.";
    const og_empore         = "javascript.0.Velux.og_empore.";
    // viele weitere Velux Geräte...
    
    const dr_o = "/vis.0/main/dg_rolladen_open.svg";
    const dr_m = "/vis.0/main/dg_rolladen_middle.svg";
    const dr_c = "/vis.0/main/dg_rolladen_close.svg";
    
    const wr_o = "/vis.0/main/fenster_rolladen_open.svg";
    const wr_m = "/vis.0/main/fenster_rolladen_middle.svg";
    const wr_c = "/vis.0/main/fenster_rolladen_close.svg";
    
    const w_o = "/vis.0/main/dg_window_close.svg"; // ACHTUNG! Invertierung wegen 100% Velux UI-FUCK
    const w_m = "/vis.0/main/dg_window_middle.svg";
    const w_c = "/vis.0/main/dg_window_open.svg"; // ACHTUNG! Invertierung wegen 100% Velux UI-FUCK
    
    
    function createRolladen(name){
        createState("javascript.0.Velux."+name+".position", "", {
            "name": "position",
            "role": "",
            "type": "number",
            "desc": "Position des Rolladen in % (0% ist offen).",
            "unit": "%",
            "min": 0,
            "max": 100,
            "def": 0,
            "read": true,
            "write": true
        });
        console.log("Objekt close für Rolladen "+name+" erstellt.");
    
        createState("javascript.0.Velux."+name+".target_position", "", {
            "name": "target_position",
            "role": "",
            "type": "number",
            "desc": "Wunsch-Position des Rolladen in % (0% ist offen).",
            "unit": "%",
            "min": -1,
            "max": 100,
            "def": 0,
            "read": true,
            "write": true
        });
        console.log("Objekt target_position für Rolladen "+name+" erstellt.");
    
        createState("javascript.0.Velux."+name+".runtime", 0, {
            "name": "runtime",
            "role": "",
            "type": "number",
            "desc": "Gibt in Sekunden an wie lange der Rolladen für einen kompletten Lauf benötigt ",
            "unit": "s",
            "min": 0,
            "max": 1000,
            "def": 15,
            "read": true,
            "write": true
        });
        console.log("Objekt runtime für Rolladen "+name+" erstellt.");
    
        createState("javascript.0.Velux."+name+".icon", "",  {
            "name": "icon",
            "role": "",
            "type": "string",
            "desc": "Speichert den Icon-Namen zur Position.",
            "def": "open",
            "read": true,
            "write": true
        });
        console.log("Objekt icon für Rolladen "+name+" erstellt.");
    
        // Hier muss noch geprüft werden, was sein Problem mit dem Type in Common ist...
        createState("javascript.0.Velux."+name+".deviceType", 0,  {
            "name": "deviceType",
            "role": "",
            "type": "state",
            "desc": "Speichert den Icon-Namen zur Position.",
            "def": 0,
            "read": true,
            "write": true,
            "states": {
                0: "DachRolladen",
                1: "FensterRolladen",
                2: "Fenster"
            }
        });
        console.log("Objekt deviceType für Device "+name+" erstellt.");
    
        createState("javascript.0.Velux."+name+".open", "", {
            "name": "open",
            "role": "",
            "type": "string",
            "desc": "Speichert den Pfad zum Objekt für die Aktion: open.",
            "def": "",
            "read": true,
            "write": true
        });
        console.log("Objekt open für Rolladen "+name+" erstellt.");
    
        createState("javascript.0.Velux."+name+".stop", "", {
            "name": "stop",
            "role": "",
            "type": "string",
            "desc": "Speichert den Pfad zum Objekt für die Aktion: stop.",
            "def": "",
            "read": true,
            "write": true
        });
        console.log("Objekt stop für Rolladen "+name+" erstellt.");
    
        createState("javascript.0.Velux."+name+".close", "", {
            "name": "close",
            "role": "",
            "type": "string",
            "desc": "Speichert den Pfad zum Objekt für die Aktion: close.",
            "def": "",
            "read": true,
            "write": true
        });
        console.log("Objekt close für Rolladen "+name+" erstellt.");
    
        createState("javascript.0.Velux."+name+".reed", "", {
            "name": "reed",
            "role": "",
            "type": "string",
            "desc": "Speichert den Pfad zum Objekt für den reed-Kontakt.",
            "def": "",
            "read": true,
            "write": true
        });
        console.log("Objekt reed für Rolladen "+name+" erstellt.");
    
        createState("javascript.0.Velux."+name+".action", "", {
            "name": "action",
            "role": "",
            "type": "string",
            "desc": "Befehl an den Rolladen.",
            "def": false,
            "read": true,
            "write": true
        });
        console.log("Objekt action für Rolladen "+name+" erstellt.");
    
        createState("javascript.0.Velux."+name+".lastaction", "", {
            "name": "lastaction",
            "role": "",
            "type": "string",
            "desc": "Letzter Befehl an den Rolladen.",
            "def": "",
            "read": true,
            "write": true
        });
        console.log("Objekt lastaction für Rolladen "+name+" erstellt.");
    
        createState("javascript.0.Velux."+name+".lastaction_time", "", {
            "name": "lastaction_time",
            "role": "",
            "type": "string",
            "desc": "Zeitpunkt der letzten Änderung.",
            "def": "",
            "read": true,
            "write": true
        });
        console.log("Objekt lastaction_time für Rolladen "+name+" erstellt.");
    }
    
    //createRolladen("og_bad");
    //createRolladen("og_empore");
    // viele weitere Velux Geräte...
    
    
    
    function moveVelux(idTarget, action, target_position){
        var deviceType = getState(idTarget+"deviceType").val;
    
        // Fensterkontakt
        var idReed = getState(idTarget+"reed").val;
        if(idReed != ""){
            if(getState(idReed).val == true){
                console.log("Reed Kontakt sagt offen. => Abbruch");
                return(false);
            }
        }
    
        if(deviceType == 0){ // DachRolladen
            var device_open = dr_o;
            var device_middle = dr_m;
            var device_close = dr_c;
        }
        if(deviceType == 1){ // FensterRolladen
            var device_open = wr_o;
            var device_middle = wr_m;
            var device_close = wr_c;
        }
        if(deviceType == 2){ // Fenster 
            var device_open = w_o;
            var device_middle = w_m;
            var device_close = w_c;
        }
        
    
        var oldPosition = getState(idTarget+"position").val;
        // Percent per Second berechnen
        var pps = 100 / getState(idTarget+"runtime").val;
        var seconds;
    
        var time = formatDate(new Date(), "YYYY-MM-DD hh:mm:ss");
    
        if(target_position == ""){ // Es wurde keine Ziel-Position geliefert wir gehen einfach in den modus open/stop/close
            setState(idTarget+"lastaction", action);
            // console.log(action + " für das Target "+idTarget+action);
            //console.log("Aktuelle Pos.: "+getState(idTarget+"position").val);
    
            if(action == "open"){
                // Berechne die Laufzeit bis zum Ziel von 0%
                seconds = oldPosition / pps;
                //console.log("Das Ding braucht "+seconds+" Sekunden von der aktuellen Pos. bis 0%.");
            }
            if(action == "close"){
                // Berechne die Laufzeit bis zum Ziel von 100%
                seconds = (100 - oldPosition) / pps;
                //console.log("Das Ding braucht "+seconds+" Sekunden von der aktuellen Pos. bis 100%.");
            }
            if(action == "stop"){
                seconds = 0;
            }
        }else{
            // Es wurde eine Ziel-Position übergeben wir ignorieren alles andere.
            //console.log("Ziel-Position erkannt: "+target_position);
            // Datenpunkt auf -1 setzen damit er neue Werte Bemerkt.
            setState(idTarget+"target_position", -1);
            if(oldPosition >= target_position){
                // Rolladen muss Richtung 0% fahren
                seconds = (oldPosition - target_position) / pps;
                var action = "open";        
            }else{
                // Rolladen muss Richtung 100% fahren
                seconds = (target_position - oldPosition) / pps;
                var action = "close";
            }
        }
    
        if(action == "open"){
            setState(idTarget+"lastaction_time", time);
            console.log("Rolladen "+idTarget+" Klick auf OPEN");
            setState(getState(idTarget+"open").val, true);
        }
        if(action == "close"){
            setState(idTarget+"lastaction_time", time);
            console.log("Rolladen "+idTarget+" Klick auf CLOSE");
            setState(getState(idTarget+"close").val, true);
        }
        if(action == "stop"){
            setState(idTarget+"lastaction_time", time);
            console.log("Rolladen "+idTarget+" Klick auf STOP");
            setState(getState(idTarget+"stop").val, true);
        }
    
        seconds = Math.round(seconds);
        var i = 0;
        var newPosition = oldPosition;
    
        if(action == "open" || action == "close"){
            //console.log("Wir starten von Pos. " + newPosition + " und gehen in den Interval.");
            let interval = setInterval(function(){
                //console.log("Noch "+i+"/"+seconds+" Sekunden. newPosition: "+newPosition);
                i++;
                if(action == "open"){
                    newPosition = newPosition - pps;
                }
                if(action == "close"){
                    newPosition = newPosition + pps;
                }
                if(i >= seconds || getState(idTarget+"lastaction").val == "stop"){
                    //console.log("####### ENDE #######");
                    //console.log("newPosition für "+idTarget+"position = "+Math.round(newPosition));
                    if(target_position != ""){
                        console.log("Rolladen "+idTarget+" Klick auf STOP");
                        setState(getState(idTarget+"stop").val, true);
                        //console.log("Bewegung wegen erreichter target_position gestoppt.");
                    }
                    clearInterval(interval);
                }
                if(newPosition >100 || newPosition < 0){ // Irgendwas ist schief gegangen, daher Intervall stoppen.
                    clearInterval(interval);
                }
                setState(idTarget+"position", Math.round(newPosition));
                if(newPosition <= 10){
                    setState(idTarget+"icon",device_open);
                }
                if(newPosition > 10 && newPosition < 90 ){
                    setState(idTarget+"icon",device_middle);
                }
                if(newPosition >= 90){
                    setState(idTarget+"icon",device_close);
                }
            }, 1000);
        }
    }
    
    
    // Beobachte alle Velux Geräte auf Wunsch-Ziel-Position-Änderungen
    on(og_bad+"target_position", function(obj) {  
        if(obj.state.val > obj.oldState.val){
            var target_position = getState(og_bad+"target_position").val;
            wait(500);
            //console.log("Wir gehen in den TargetModus mit: "+target_position);
            moveVelux(og_bad, "", target_position);
        }
    });
    on(og_empore+"target_position", function(obj) {  
        if(obj.state.val > obj.oldState.val){
            var target_position = getState(og_empore+"target_position").val;
            wait(500);
            //console.log("Wir gehen in den TargetModus mit: "+target_position);
            moveVelux(og_empore, "", target_position);
        }
    });
    // viele weitere Velux Geräte...
    
    
    
    // ##################################################### //
    // Beobachte alle Velux Geräte auf Wunsch-Action-Änderungen
    on(og_bad+"action", function(obj) {  
        var action = getState(og_bad+"action").val;
        setState(og_bad+"action", "");
        wait(500);
        if( action == "open" || action == "close" || action == "stop" ){ 
            //console.log("moveVelux mit der action: "+action);
            moveVelux(og_bad, action, "");
        } 
    });
    on(og_empore+"action", function(obj) {  
        var action = getState(og_empore+"action").val;
        setState(og_empore+"action", "");
        wait(500);
        if( action == "open" || action == "close" || action == "stop" ){ 
            //console.log("moveVelux mit der action: "+action);
            moveVelux(og_empore, action, "");
        } 
    });
    // viele weitere Velux Geräte...
    
    
    UncleSamU M 2 Antworten Letzte Antwort
    2
    • T tristan

      Hallo Zusammen,

      ich hatte mal Bock was mit einem NodeMCU zusammen zu bauen und habe es zum Anlass genommen endlich mal meine Velux-Rolläden in meinen ioBroker zu integrieren. Und zwar ohne mich von Velux weiter veräppeln zu lassen mit KLF-200-Firmware-Updates oder irgendwelchen teueren nicht-smarten INTEGRA-Produkten.

      Dazu habe ich 3x Relais-Boards mit drei I/O-Extension-Boards an einen NodeMCU angeschlossen (~40EUR).
      Die 8 INTEGRA Fernbedienungen habe ich gestapelt und an die Relais angeschlossen. Versorgt werden sie über den 3V Ausgang vom NodeMCU. Versorgt wird das Ganze über ein USB Ladegerät.

      Ich nennen das Projekt F**K-YOU-VELUX-Stack.

      Die Einbindung habe ich über Tasmota gemacht, eine großartige Firmware. Erkennt automatisch die I/O-Extensions und stellt jeden Kontakt als MQTT zur Verfügung.

      Macht richtig Spaß dem Klackern der Relais zu lauschen. :-D

      f--k_you_Velux_Stack-2.jpg

      Loetpunkte-Velux-INTEGRA-KLI-2_.png

      screenshot-device.png

      VG Tristan

      const og_bad            = "javascript.0.Velux.og_bad.";
      const og_empore         = "javascript.0.Velux.og_empore.";
      // viele weitere Velux Geräte...
      
      const dr_o = "/vis.0/main/dg_rolladen_open.svg";
      const dr_m = "/vis.0/main/dg_rolladen_middle.svg";
      const dr_c = "/vis.0/main/dg_rolladen_close.svg";
      
      const wr_o = "/vis.0/main/fenster_rolladen_open.svg";
      const wr_m = "/vis.0/main/fenster_rolladen_middle.svg";
      const wr_c = "/vis.0/main/fenster_rolladen_close.svg";
      
      const w_o = "/vis.0/main/dg_window_close.svg"; // ACHTUNG! Invertierung wegen 100% Velux UI-FUCK
      const w_m = "/vis.0/main/dg_window_middle.svg";
      const w_c = "/vis.0/main/dg_window_open.svg"; // ACHTUNG! Invertierung wegen 100% Velux UI-FUCK
      
      
      function createRolladen(name){
          createState("javascript.0.Velux."+name+".position", "", {
              "name": "position",
              "role": "",
              "type": "number",
              "desc": "Position des Rolladen in % (0% ist offen).",
              "unit": "%",
              "min": 0,
              "max": 100,
              "def": 0,
              "read": true,
              "write": true
          });
          console.log("Objekt close für Rolladen "+name+" erstellt.");
      
          createState("javascript.0.Velux."+name+".target_position", "", {
              "name": "target_position",
              "role": "",
              "type": "number",
              "desc": "Wunsch-Position des Rolladen in % (0% ist offen).",
              "unit": "%",
              "min": -1,
              "max": 100,
              "def": 0,
              "read": true,
              "write": true
          });
          console.log("Objekt target_position für Rolladen "+name+" erstellt.");
      
          createState("javascript.0.Velux."+name+".runtime", 0, {
              "name": "runtime",
              "role": "",
              "type": "number",
              "desc": "Gibt in Sekunden an wie lange der Rolladen für einen kompletten Lauf benötigt ",
              "unit": "s",
              "min": 0,
              "max": 1000,
              "def": 15,
              "read": true,
              "write": true
          });
          console.log("Objekt runtime für Rolladen "+name+" erstellt.");
      
          createState("javascript.0.Velux."+name+".icon", "",  {
              "name": "icon",
              "role": "",
              "type": "string",
              "desc": "Speichert den Icon-Namen zur Position.",
              "def": "open",
              "read": true,
              "write": true
          });
          console.log("Objekt icon für Rolladen "+name+" erstellt.");
      
          // Hier muss noch geprüft werden, was sein Problem mit dem Type in Common ist...
          createState("javascript.0.Velux."+name+".deviceType", 0,  {
              "name": "deviceType",
              "role": "",
              "type": "state",
              "desc": "Speichert den Icon-Namen zur Position.",
              "def": 0,
              "read": true,
              "write": true,
              "states": {
                  0: "DachRolladen",
                  1: "FensterRolladen",
                  2: "Fenster"
              }
          });
          console.log("Objekt deviceType für Device "+name+" erstellt.");
      
          createState("javascript.0.Velux."+name+".open", "", {
              "name": "open",
              "role": "",
              "type": "string",
              "desc": "Speichert den Pfad zum Objekt für die Aktion: open.",
              "def": "",
              "read": true,
              "write": true
          });
          console.log("Objekt open für Rolladen "+name+" erstellt.");
      
          createState("javascript.0.Velux."+name+".stop", "", {
              "name": "stop",
              "role": "",
              "type": "string",
              "desc": "Speichert den Pfad zum Objekt für die Aktion: stop.",
              "def": "",
              "read": true,
              "write": true
          });
          console.log("Objekt stop für Rolladen "+name+" erstellt.");
      
          createState("javascript.0.Velux."+name+".close", "", {
              "name": "close",
              "role": "",
              "type": "string",
              "desc": "Speichert den Pfad zum Objekt für die Aktion: close.",
              "def": "",
              "read": true,
              "write": true
          });
          console.log("Objekt close für Rolladen "+name+" erstellt.");
      
          createState("javascript.0.Velux."+name+".reed", "", {
              "name": "reed",
              "role": "",
              "type": "string",
              "desc": "Speichert den Pfad zum Objekt für den reed-Kontakt.",
              "def": "",
              "read": true,
              "write": true
          });
          console.log("Objekt reed für Rolladen "+name+" erstellt.");
      
          createState("javascript.0.Velux."+name+".action", "", {
              "name": "action",
              "role": "",
              "type": "string",
              "desc": "Befehl an den Rolladen.",
              "def": false,
              "read": true,
              "write": true
          });
          console.log("Objekt action für Rolladen "+name+" erstellt.");
      
          createState("javascript.0.Velux."+name+".lastaction", "", {
              "name": "lastaction",
              "role": "",
              "type": "string",
              "desc": "Letzter Befehl an den Rolladen.",
              "def": "",
              "read": true,
              "write": true
          });
          console.log("Objekt lastaction für Rolladen "+name+" erstellt.");
      
          createState("javascript.0.Velux."+name+".lastaction_time", "", {
              "name": "lastaction_time",
              "role": "",
              "type": "string",
              "desc": "Zeitpunkt der letzten Änderung.",
              "def": "",
              "read": true,
              "write": true
          });
          console.log("Objekt lastaction_time für Rolladen "+name+" erstellt.");
      }
      
      //createRolladen("og_bad");
      //createRolladen("og_empore");
      // viele weitere Velux Geräte...
      
      
      
      function moveVelux(idTarget, action, target_position){
          var deviceType = getState(idTarget+"deviceType").val;
      
          // Fensterkontakt
          var idReed = getState(idTarget+"reed").val;
          if(idReed != ""){
              if(getState(idReed).val == true){
                  console.log("Reed Kontakt sagt offen. => Abbruch");
                  return(false);
              }
          }
      
          if(deviceType == 0){ // DachRolladen
              var device_open = dr_o;
              var device_middle = dr_m;
              var device_close = dr_c;
          }
          if(deviceType == 1){ // FensterRolladen
              var device_open = wr_o;
              var device_middle = wr_m;
              var device_close = wr_c;
          }
          if(deviceType == 2){ // Fenster 
              var device_open = w_o;
              var device_middle = w_m;
              var device_close = w_c;
          }
          
      
          var oldPosition = getState(idTarget+"position").val;
          // Percent per Second berechnen
          var pps = 100 / getState(idTarget+"runtime").val;
          var seconds;
      
          var time = formatDate(new Date(), "YYYY-MM-DD hh:mm:ss");
      
          if(target_position == ""){ // Es wurde keine Ziel-Position geliefert wir gehen einfach in den modus open/stop/close
              setState(idTarget+"lastaction", action);
              // console.log(action + " für das Target "+idTarget+action);
              //console.log("Aktuelle Pos.: "+getState(idTarget+"position").val);
      
              if(action == "open"){
                  // Berechne die Laufzeit bis zum Ziel von 0%
                  seconds = oldPosition / pps;
                  //console.log("Das Ding braucht "+seconds+" Sekunden von der aktuellen Pos. bis 0%.");
              }
              if(action == "close"){
                  // Berechne die Laufzeit bis zum Ziel von 100%
                  seconds = (100 - oldPosition) / pps;
                  //console.log("Das Ding braucht "+seconds+" Sekunden von der aktuellen Pos. bis 100%.");
              }
              if(action == "stop"){
                  seconds = 0;
              }
          }else{
              // Es wurde eine Ziel-Position übergeben wir ignorieren alles andere.
              //console.log("Ziel-Position erkannt: "+target_position);
              // Datenpunkt auf -1 setzen damit er neue Werte Bemerkt.
              setState(idTarget+"target_position", -1);
              if(oldPosition >= target_position){
                  // Rolladen muss Richtung 0% fahren
                  seconds = (oldPosition - target_position) / pps;
                  var action = "open";        
              }else{
                  // Rolladen muss Richtung 100% fahren
                  seconds = (target_position - oldPosition) / pps;
                  var action = "close";
              }
          }
      
          if(action == "open"){
              setState(idTarget+"lastaction_time", time);
              console.log("Rolladen "+idTarget+" Klick auf OPEN");
              setState(getState(idTarget+"open").val, true);
          }
          if(action == "close"){
              setState(idTarget+"lastaction_time", time);
              console.log("Rolladen "+idTarget+" Klick auf CLOSE");
              setState(getState(idTarget+"close").val, true);
          }
          if(action == "stop"){
              setState(idTarget+"lastaction_time", time);
              console.log("Rolladen "+idTarget+" Klick auf STOP");
              setState(getState(idTarget+"stop").val, true);
          }
      
          seconds = Math.round(seconds);
          var i = 0;
          var newPosition = oldPosition;
      
          if(action == "open" || action == "close"){
              //console.log("Wir starten von Pos. " + newPosition + " und gehen in den Interval.");
              let interval = setInterval(function(){
                  //console.log("Noch "+i+"/"+seconds+" Sekunden. newPosition: "+newPosition);
                  i++;
                  if(action == "open"){
                      newPosition = newPosition - pps;
                  }
                  if(action == "close"){
                      newPosition = newPosition + pps;
                  }
                  if(i >= seconds || getState(idTarget+"lastaction").val == "stop"){
                      //console.log("####### ENDE #######");
                      //console.log("newPosition für "+idTarget+"position = "+Math.round(newPosition));
                      if(target_position != ""){
                          console.log("Rolladen "+idTarget+" Klick auf STOP");
                          setState(getState(idTarget+"stop").val, true);
                          //console.log("Bewegung wegen erreichter target_position gestoppt.");
                      }
                      clearInterval(interval);
                  }
                  if(newPosition >100 || newPosition < 0){ // Irgendwas ist schief gegangen, daher Intervall stoppen.
                      clearInterval(interval);
                  }
                  setState(idTarget+"position", Math.round(newPosition));
                  if(newPosition <= 10){
                      setState(idTarget+"icon",device_open);
                  }
                  if(newPosition > 10 && newPosition < 90 ){
                      setState(idTarget+"icon",device_middle);
                  }
                  if(newPosition >= 90){
                      setState(idTarget+"icon",device_close);
                  }
              }, 1000);
          }
      }
      
      
      // Beobachte alle Velux Geräte auf Wunsch-Ziel-Position-Änderungen
      on(og_bad+"target_position", function(obj) {  
          if(obj.state.val > obj.oldState.val){
              var target_position = getState(og_bad+"target_position").val;
              wait(500);
              //console.log("Wir gehen in den TargetModus mit: "+target_position);
              moveVelux(og_bad, "", target_position);
          }
      });
      on(og_empore+"target_position", function(obj) {  
          if(obj.state.val > obj.oldState.val){
              var target_position = getState(og_empore+"target_position").val;
              wait(500);
              //console.log("Wir gehen in den TargetModus mit: "+target_position);
              moveVelux(og_empore, "", target_position);
          }
      });
      // viele weitere Velux Geräte...
      
      
      
      // ##################################################### //
      // Beobachte alle Velux Geräte auf Wunsch-Action-Änderungen
      on(og_bad+"action", function(obj) {  
          var action = getState(og_bad+"action").val;
          setState(og_bad+"action", "");
          wait(500);
          if( action == "open" || action == "close" || action == "stop" ){ 
              //console.log("moveVelux mit der action: "+action);
              moveVelux(og_bad, action, "");
          } 
      });
      on(og_empore+"action", function(obj) {  
          var action = getState(og_empore+"action").val;
          setState(og_empore+"action", "");
          wait(500);
          if( action == "open" || action == "close" || action == "stop" ){ 
              //console.log("moveVelux mit der action: "+action);
              moveVelux(og_empore, action, "");
          } 
      });
      // viele weitere Velux Geräte...
      
      
      UncleSamU Offline
      UncleSamU Offline
      UncleSam
      Developer
      schrieb am zuletzt editiert von
      #2

      Schöne Lösung! Ich habe dasselbe direkt an einem Raspberry Pi gemacht (I2C Adapter, PCF8574 und 16x Relais Karte).

      Bitte bei Problemen mit meinen Adaptern, Issue auf GitHub erfassen: Loxone | I2C | Luxtronik2
      ♡-lichen Dank an meine Sponsoren

      1 Antwort Letzte Antwort
      0
      • T tristan

        Hallo Zusammen,

        ich hatte mal Bock was mit einem NodeMCU zusammen zu bauen und habe es zum Anlass genommen endlich mal meine Velux-Rolläden in meinen ioBroker zu integrieren. Und zwar ohne mich von Velux weiter veräppeln zu lassen mit KLF-200-Firmware-Updates oder irgendwelchen teueren nicht-smarten INTEGRA-Produkten.

        Dazu habe ich 3x Relais-Boards mit drei I/O-Extension-Boards an einen NodeMCU angeschlossen (~40EUR).
        Die 8 INTEGRA Fernbedienungen habe ich gestapelt und an die Relais angeschlossen. Versorgt werden sie über den 3V Ausgang vom NodeMCU. Versorgt wird das Ganze über ein USB Ladegerät.

        Ich nennen das Projekt F**K-YOU-VELUX-Stack.

        Die Einbindung habe ich über Tasmota gemacht, eine großartige Firmware. Erkennt automatisch die I/O-Extensions und stellt jeden Kontakt als MQTT zur Verfügung.

        Macht richtig Spaß dem Klackern der Relais zu lauschen. :-D

        f--k_you_Velux_Stack-2.jpg

        Loetpunkte-Velux-INTEGRA-KLI-2_.png

        screenshot-device.png

        VG Tristan

        const og_bad            = "javascript.0.Velux.og_bad.";
        const og_empore         = "javascript.0.Velux.og_empore.";
        // viele weitere Velux Geräte...
        
        const dr_o = "/vis.0/main/dg_rolladen_open.svg";
        const dr_m = "/vis.0/main/dg_rolladen_middle.svg";
        const dr_c = "/vis.0/main/dg_rolladen_close.svg";
        
        const wr_o = "/vis.0/main/fenster_rolladen_open.svg";
        const wr_m = "/vis.0/main/fenster_rolladen_middle.svg";
        const wr_c = "/vis.0/main/fenster_rolladen_close.svg";
        
        const w_o = "/vis.0/main/dg_window_close.svg"; // ACHTUNG! Invertierung wegen 100% Velux UI-FUCK
        const w_m = "/vis.0/main/dg_window_middle.svg";
        const w_c = "/vis.0/main/dg_window_open.svg"; // ACHTUNG! Invertierung wegen 100% Velux UI-FUCK
        
        
        function createRolladen(name){
            createState("javascript.0.Velux."+name+".position", "", {
                "name": "position",
                "role": "",
                "type": "number",
                "desc": "Position des Rolladen in % (0% ist offen).",
                "unit": "%",
                "min": 0,
                "max": 100,
                "def": 0,
                "read": true,
                "write": true
            });
            console.log("Objekt close für Rolladen "+name+" erstellt.");
        
            createState("javascript.0.Velux."+name+".target_position", "", {
                "name": "target_position",
                "role": "",
                "type": "number",
                "desc": "Wunsch-Position des Rolladen in % (0% ist offen).",
                "unit": "%",
                "min": -1,
                "max": 100,
                "def": 0,
                "read": true,
                "write": true
            });
            console.log("Objekt target_position für Rolladen "+name+" erstellt.");
        
            createState("javascript.0.Velux."+name+".runtime", 0, {
                "name": "runtime",
                "role": "",
                "type": "number",
                "desc": "Gibt in Sekunden an wie lange der Rolladen für einen kompletten Lauf benötigt ",
                "unit": "s",
                "min": 0,
                "max": 1000,
                "def": 15,
                "read": true,
                "write": true
            });
            console.log("Objekt runtime für Rolladen "+name+" erstellt.");
        
            createState("javascript.0.Velux."+name+".icon", "",  {
                "name": "icon",
                "role": "",
                "type": "string",
                "desc": "Speichert den Icon-Namen zur Position.",
                "def": "open",
                "read": true,
                "write": true
            });
            console.log("Objekt icon für Rolladen "+name+" erstellt.");
        
            // Hier muss noch geprüft werden, was sein Problem mit dem Type in Common ist...
            createState("javascript.0.Velux."+name+".deviceType", 0,  {
                "name": "deviceType",
                "role": "",
                "type": "state",
                "desc": "Speichert den Icon-Namen zur Position.",
                "def": 0,
                "read": true,
                "write": true,
                "states": {
                    0: "DachRolladen",
                    1: "FensterRolladen",
                    2: "Fenster"
                }
            });
            console.log("Objekt deviceType für Device "+name+" erstellt.");
        
            createState("javascript.0.Velux."+name+".open", "", {
                "name": "open",
                "role": "",
                "type": "string",
                "desc": "Speichert den Pfad zum Objekt für die Aktion: open.",
                "def": "",
                "read": true,
                "write": true
            });
            console.log("Objekt open für Rolladen "+name+" erstellt.");
        
            createState("javascript.0.Velux."+name+".stop", "", {
                "name": "stop",
                "role": "",
                "type": "string",
                "desc": "Speichert den Pfad zum Objekt für die Aktion: stop.",
                "def": "",
                "read": true,
                "write": true
            });
            console.log("Objekt stop für Rolladen "+name+" erstellt.");
        
            createState("javascript.0.Velux."+name+".close", "", {
                "name": "close",
                "role": "",
                "type": "string",
                "desc": "Speichert den Pfad zum Objekt für die Aktion: close.",
                "def": "",
                "read": true,
                "write": true
            });
            console.log("Objekt close für Rolladen "+name+" erstellt.");
        
            createState("javascript.0.Velux."+name+".reed", "", {
                "name": "reed",
                "role": "",
                "type": "string",
                "desc": "Speichert den Pfad zum Objekt für den reed-Kontakt.",
                "def": "",
                "read": true,
                "write": true
            });
            console.log("Objekt reed für Rolladen "+name+" erstellt.");
        
            createState("javascript.0.Velux."+name+".action", "", {
                "name": "action",
                "role": "",
                "type": "string",
                "desc": "Befehl an den Rolladen.",
                "def": false,
                "read": true,
                "write": true
            });
            console.log("Objekt action für Rolladen "+name+" erstellt.");
        
            createState("javascript.0.Velux."+name+".lastaction", "", {
                "name": "lastaction",
                "role": "",
                "type": "string",
                "desc": "Letzter Befehl an den Rolladen.",
                "def": "",
                "read": true,
                "write": true
            });
            console.log("Objekt lastaction für Rolladen "+name+" erstellt.");
        
            createState("javascript.0.Velux."+name+".lastaction_time", "", {
                "name": "lastaction_time",
                "role": "",
                "type": "string",
                "desc": "Zeitpunkt der letzten Änderung.",
                "def": "",
                "read": true,
                "write": true
            });
            console.log("Objekt lastaction_time für Rolladen "+name+" erstellt.");
        }
        
        //createRolladen("og_bad");
        //createRolladen("og_empore");
        // viele weitere Velux Geräte...
        
        
        
        function moveVelux(idTarget, action, target_position){
            var deviceType = getState(idTarget+"deviceType").val;
        
            // Fensterkontakt
            var idReed = getState(idTarget+"reed").val;
            if(idReed != ""){
                if(getState(idReed).val == true){
                    console.log("Reed Kontakt sagt offen. => Abbruch");
                    return(false);
                }
            }
        
            if(deviceType == 0){ // DachRolladen
                var device_open = dr_o;
                var device_middle = dr_m;
                var device_close = dr_c;
            }
            if(deviceType == 1){ // FensterRolladen
                var device_open = wr_o;
                var device_middle = wr_m;
                var device_close = wr_c;
            }
            if(deviceType == 2){ // Fenster 
                var device_open = w_o;
                var device_middle = w_m;
                var device_close = w_c;
            }
            
        
            var oldPosition = getState(idTarget+"position").val;
            // Percent per Second berechnen
            var pps = 100 / getState(idTarget+"runtime").val;
            var seconds;
        
            var time = formatDate(new Date(), "YYYY-MM-DD hh:mm:ss");
        
            if(target_position == ""){ // Es wurde keine Ziel-Position geliefert wir gehen einfach in den modus open/stop/close
                setState(idTarget+"lastaction", action);
                // console.log(action + " für das Target "+idTarget+action);
                //console.log("Aktuelle Pos.: "+getState(idTarget+"position").val);
        
                if(action == "open"){
                    // Berechne die Laufzeit bis zum Ziel von 0%
                    seconds = oldPosition / pps;
                    //console.log("Das Ding braucht "+seconds+" Sekunden von der aktuellen Pos. bis 0%.");
                }
                if(action == "close"){
                    // Berechne die Laufzeit bis zum Ziel von 100%
                    seconds = (100 - oldPosition) / pps;
                    //console.log("Das Ding braucht "+seconds+" Sekunden von der aktuellen Pos. bis 100%.");
                }
                if(action == "stop"){
                    seconds = 0;
                }
            }else{
                // Es wurde eine Ziel-Position übergeben wir ignorieren alles andere.
                //console.log("Ziel-Position erkannt: "+target_position);
                // Datenpunkt auf -1 setzen damit er neue Werte Bemerkt.
                setState(idTarget+"target_position", -1);
                if(oldPosition >= target_position){
                    // Rolladen muss Richtung 0% fahren
                    seconds = (oldPosition - target_position) / pps;
                    var action = "open";        
                }else{
                    // Rolladen muss Richtung 100% fahren
                    seconds = (target_position - oldPosition) / pps;
                    var action = "close";
                }
            }
        
            if(action == "open"){
                setState(idTarget+"lastaction_time", time);
                console.log("Rolladen "+idTarget+" Klick auf OPEN");
                setState(getState(idTarget+"open").val, true);
            }
            if(action == "close"){
                setState(idTarget+"lastaction_time", time);
                console.log("Rolladen "+idTarget+" Klick auf CLOSE");
                setState(getState(idTarget+"close").val, true);
            }
            if(action == "stop"){
                setState(idTarget+"lastaction_time", time);
                console.log("Rolladen "+idTarget+" Klick auf STOP");
                setState(getState(idTarget+"stop").val, true);
            }
        
            seconds = Math.round(seconds);
            var i = 0;
            var newPosition = oldPosition;
        
            if(action == "open" || action == "close"){
                //console.log("Wir starten von Pos. " + newPosition + " und gehen in den Interval.");
                let interval = setInterval(function(){
                    //console.log("Noch "+i+"/"+seconds+" Sekunden. newPosition: "+newPosition);
                    i++;
                    if(action == "open"){
                        newPosition = newPosition - pps;
                    }
                    if(action == "close"){
                        newPosition = newPosition + pps;
                    }
                    if(i >= seconds || getState(idTarget+"lastaction").val == "stop"){
                        //console.log("####### ENDE #######");
                        //console.log("newPosition für "+idTarget+"position = "+Math.round(newPosition));
                        if(target_position != ""){
                            console.log("Rolladen "+idTarget+" Klick auf STOP");
                            setState(getState(idTarget+"stop").val, true);
                            //console.log("Bewegung wegen erreichter target_position gestoppt.");
                        }
                        clearInterval(interval);
                    }
                    if(newPosition >100 || newPosition < 0){ // Irgendwas ist schief gegangen, daher Intervall stoppen.
                        clearInterval(interval);
                    }
                    setState(idTarget+"position", Math.round(newPosition));
                    if(newPosition <= 10){
                        setState(idTarget+"icon",device_open);
                    }
                    if(newPosition > 10 && newPosition < 90 ){
                        setState(idTarget+"icon",device_middle);
                    }
                    if(newPosition >= 90){
                        setState(idTarget+"icon",device_close);
                    }
                }, 1000);
            }
        }
        
        
        // Beobachte alle Velux Geräte auf Wunsch-Ziel-Position-Änderungen
        on(og_bad+"target_position", function(obj) {  
            if(obj.state.val > obj.oldState.val){
                var target_position = getState(og_bad+"target_position").val;
                wait(500);
                //console.log("Wir gehen in den TargetModus mit: "+target_position);
                moveVelux(og_bad, "", target_position);
            }
        });
        on(og_empore+"target_position", function(obj) {  
            if(obj.state.val > obj.oldState.val){
                var target_position = getState(og_empore+"target_position").val;
                wait(500);
                //console.log("Wir gehen in den TargetModus mit: "+target_position);
                moveVelux(og_empore, "", target_position);
            }
        });
        // viele weitere Velux Geräte...
        
        
        
        // ##################################################### //
        // Beobachte alle Velux Geräte auf Wunsch-Action-Änderungen
        on(og_bad+"action", function(obj) {  
            var action = getState(og_bad+"action").val;
            setState(og_bad+"action", "");
            wait(500);
            if( action == "open" || action == "close" || action == "stop" ){ 
                //console.log("moveVelux mit der action: "+action);
                moveVelux(og_bad, action, "");
            } 
        });
        on(og_empore+"action", function(obj) {  
            var action = getState(og_empore+"action").val;
            setState(og_empore+"action", "");
            wait(500);
            if( action == "open" || action == "close" || action == "stop" ){ 
                //console.log("moveVelux mit der action: "+action);
                moveVelux(og_empore, action, "");
            } 
        });
        // viele weitere Velux Geräte...
        
        
        M Offline
        M Offline
        Master-Rudi
        schrieb am zuletzt editiert von
        #3

        @tristan

        Netter Tower :-)

        Ich habe estwas ähnliches in sehr viel kleiner für zwei RTS Rollos gemacht:

        https://forum.iobroker.net/topic/32200/diverse-rolläden-in-iobroker-einbinden/24

        1 Antwort Letzte Antwort
        0
        Antworten
        • In einem neuen Thema antworten
        Anmelden zum Antworten
        • Älteste zuerst
        • Neuste zuerst
        • Meiste Stimmen


        Support us

        ioBroker
        Community Adapters
        Donate

        676

        Online

        32.6k

        Benutzer

        82.2k

        Themen

        1.3m

        Beiträge
        Community
        Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen | Einwilligungseinstellungen
        ioBroker Community 2014-2025
        logo
        • Anmelden

        • Du hast noch kein Konto? Registrieren

        • Anmelden oder registrieren, um zu suchen
        • Erster Beitrag
          Letzter Beitrag
        0
        • Home
        • Aktuell
        • Tags
        • Ungelesen 0
        • Kategorien
        • Unreplied
        • Beliebt
        • GitHub
        • Docu
        • Hilfe