Ich versuche jetzt schon seit einige Zeit eine ordentliche Rolladen Lux Automatik mit dem Shelly Door2 hinzubekommen, leider ist das Teil so träge das es recht schwer ist damit etwas anzufangen.
Das ist mein derzeitiges Iobroker_NodeRed [Funktions Block] Js Skript, das läuft zwar aber wirklich zufrieden bin ich nicht.
Funktion:
Man gibt einen Lux Ziel Wert ein, sowie ein paar extreme Grenzen, das Skript versucht dann den Ziel Lux Wert zu halten, da der Sensor so träge ist werden auch ein paar Blind Anpassungen vorgenommen bei der geschätzt wird wo der Rolladen sich ca. befinden sollte anhand des vorherigen Lux Wertes.
const zielLux = 2000; //Ziel, Lux Wert.
const abweichung = 300; //Erlaubte Abweichung vom Ziel Lux Wert.
const leichteAnpassung = 5; //Rolladen leichte Anpassungs Schritte in %.
const abweichungLeichteAnpassung = 600; //Abweichung ab der nur noch eine leichte Anpassung durchgeführt wird.
const normaleAnpassung = 10; //Rolladen normale Anpassungs Schritte in %.
const starkeAnpassung = 20; //Rolladen starke Anpassungs Schritte in %.
const obereGrenzeStarkeAnpssung = 3000; //Lux Wert, obere Grenze ab der eine starke Anpassung durchgeführt wird.
const untereGrenzeStarkeAnpssung = 500; //Lux Wert, untere Grenze ab der eine starke Anpassungen durchgeführt wird.
const wiederholungsZeitraum = 15; //Pause in Minuten zwischen blinden Anpassungs-Versuchen.
let aktuelleLux = context.get("aktuelleLux");
let rolladenProzent = context.get("rolladenProzent");
let letzterOutput = context.get("letzterOutput");
let output = {};
let luxDifferenz;
let anpassungLimit;
let timerAnpassung = global.get("RolladenNewTimer1") || null;
//Übergabe der Werte und Speicherung.
if (msg.topic == "Lux") {
aktuelleLux = parseInt(msg.payload, 10);
context.set("aktuelleLux", aktuelleLux);
luxDifferenz = aktuelleLux - zielLux;
}
if (msg.topic == "Rolladen") {
rolladenProzent = parseInt(msg.payload, 10);
context.set("rolladenProzent", rolladenProzent);
return;
}
//Debug, hilfe
//node.warn("Input Lux: " + aktuelleLux + " Input Rolladen: " + rolladenProzent);
//Anpassungs-/Annäherungs-prozess an Lux Ziel
function AdjustRolladen(anpassungen) {
if (anpassungen >= anpassungLimit || Math.abs(luxDifferenz) <= abweichung) {
clearTimeout(timerAnpassung);
global.set("RolladenNewTimer1", timerAnpassung);
return;
}
if (luxDifferenz > 0) {
if (aktuelleLux > obereGrenzeStarkeAnpssung) {
rolladenProzent += starkeAnpassung;
} else {
if (Math.abs(luxDifferenz) <= abweichungLeichteAnpassung){
rolladenProzent += leichteAnpassung;
}else{
rolladenProzent += normaleAnpassung;
}
}
} else if (luxDifferenz < 0) {
if (aktuelleLux < untereGrenzeStarkeAnpssung) {
rolladenProzent -= starkeAnpassung;
} else {
if (Math.abs(luxDifferenz) <= abweichungLeichteAnpassung) {
rolladenProzent -= leichteAnpassung;
} else {
rolladenProzent -= normaleAnpassung;
}
}
}
//Definiere Grenzen für Ausgabe
rolladenProzent = Math.min(Math.max(rolladenProzent, 0), 88);
context.set("rolladenProzent", rolladenProzent);
//Ausgabe Objekt/Msg erstellen
output.topic = "Ausgabe";
output.payload = rolladenProzent;
if(output.payload !== letzterOutput){
node.send(output);
context.set("letzterOutput", output.payload);
}
node.done();
//Intervall/Wiederholung, Annäherung an Lux Ziel
timerAnpassung = setTimeout(() => {
AdjustRolladen(anpassungen + 1);
}, wiederholungsZeitraum * 60 * 1000);
global.set("RolladenNewTimer1", timerAnpassung);
}
//Kontrolle ob die werte aktuell und vorhanden sind
if (aktuelleLux === undefined || rolladenProzent === undefined) {
clearTimeout(timerAnpassung);
global.set("RolladenNewTimer1", timerAnpassung);
return;
} else {
if (aktuelleLux > obereGrenzeStarkeAnpssung || aktuelleLux < untereGrenzeStarkeAnpssung){
anpassungLimit = 2;
} else {
if (Math.abs(luxDifferenz) <= abweichungLeichteAnpassung){
anpassungLimit = 2;
}
anpassungLimit = 3;
}
// Starte den Anpassungs-/Annäherungs-prozess
if (msg.topic == "Lux") {
AdjustRolladen(0);
}
}
return;
Alles anzeigen
Hier ist das Ganze nochmal in einen leeren Flow als Json exportiert, falls es jemand kopieren will, der chg Block ändert das Topic zu Lux und Rolladen und EntPrell sorgt dafür, dass nur ein Wert übertragen wird, der min. 5sek. fix ist.
Spoiler anzeigen
[
{
"id": "0f6df9154830780b",
"type": "tab",
"label": "Flow 1",
"disabled": false,
"info": "",
"env": []
},
{
"id": "9e4c4a8c37c936d6",
"type": "function",
"z": "0f6df9154830780b",
"name": "Rolladen-Automatik",
"func": "const zielLux = 2000; //Ziel, Lux Wert.\nconst abweichung = 300; //Erlaubte Abweichung vom Ziel Lux Wert.\nconst leichteAnpassung = 5; //Rolladen leichte Anpassungs Schritte in %.\nconst abweichungLeichteAnpassung = 500; //Abweichung ab der nur noch leichte Anpassungen durchgeführt werden.\nconst normaleAnpassung = 10; //Rolladen normale Anpassungs Schritte in %.\nconst starkeAnpassung = 20; //Rolladen starke Anpassungs Schritte in %.\nconst obereGrenzeStarkeAnpssung = 3000; //Lux Wert, obere Grenze ab der starke Anpassungen durchgeführt werden.\nconst untereGrenzeStarkeAnpssung = 500; //Lux Wert, unere Grenze ab der starke Anpassungen durchgeführt werden.\nconst wiederholungsZeitraum = 2; //Angeben in Minunten zwischen blinden Anpassungs-Versuchen.\n\nlet aktuelleLux = context.get(\"aktuelleLux\");\nlet rolladenProzent = context.get(\"rolladenProzent\");\nlet letzterOutput = context.get(\"letzterOutput\");\nlet output = {};\nlet luxDifferenz;\nlet anpassungLimit;\nlet timerAnpassung = global.get(\"RolladenNewTimer1\") || null;\n\n//Übergabe der Werte und Speicherung.\nif (msg.topic == \"Lux\") {\n aktuelleLux = parseInt(msg.payload, 10);\n context.set(\"aktuelleLux\", aktuelleLux);\n luxDifferenz = aktuelleLux - zielLux;\n}\nif (msg.topic == \"Rolladen\") {\n rolladenProzent = parseInt(msg.payload, 10);\n context.set(\"rolladenProzent\", rolladenProzent);\n return;\n}\n//Debug, hilfe\n//node.warn(\"Input Lux: \" + aktuelleLux + \" Input Rolladen: \" + rolladenProzent);\n\n//Anpassungs-/Annäherungs-prozess an Lux Ziel\nfunction AdjustRolladen(anpassungen) {\n if (anpassungen >= anpassungLimit || Math.abs(luxDifferenz) <= abweichung) {\n clearTimeout(timerAnpassung);\n global.set(\"RolladenNewTimer1\", timerAnpassung);\n return;\n }\n if (luxDifferenz > 0) {\n if (aktuelleLux > obereGrenzeStarkeAnpssung) {\n rolladenProzent += starkeAnpassung;\n } else {\n if (Math.abs(luxDifferenz) <= abweichungLeichteAnpassung){\n rolladenProzent += leichteAnpassung;\n }else{\n rolladenProzent += normaleAnpassung;\n }\n }\n } else if (luxDifferenz < 0) {\n if (aktuelleLux < untereGrenzeStarkeAnpssung) {\n rolladenProzent -= starkeAnpassung;\n } else {\n if (Math.abs(luxDifferenz) <= abweichungLeichteAnpassung) {\n rolladenProzent -= leichteAnpassung;\n } else {\n rolladenProzent -= normaleAnpassung;\n }\n }\n }\n //Definiere Grenzen für Ausgabe\n rolladenProzent = Math.min(Math.max(rolladenProzent, 0), 88);\n context.set(\"rolladenProzent\", rolladenProzent);\n //Ausgabe Objekt/Msg erstellen\n output.topic = \"Ausgabe\";\n output.payload = rolladenProzent;\n if(output.payload !== letzterOutput){\n node.send(output);\n context.set(\"letzterOutput\", output.payload);\n }\n node.done();\n //Intervall/Wiederholung, Annäherung an Lux Ziel\n timerAnpassung = setTimeout(() => {\n AdjustRolladen(anpassungen + 1);\n }, wiederholungsZeitraum * 60 * 1000);\n global.set(\"RolladenNewTimer1\", timerAnpassung);\n}\n\n//Kontrolle ob die werte akteulle sind und vorhanden\nif (aktuelleLux === undefined || rolladenProzent === undefined) {\n clearTimeout(timerAnpassung);\n global.set(\"RolladenNewTimer1\", timerAnpassung);\n return;\n} else {\n if (aktuelleLux > obereGrenzeStarkeAnpssung || aktuelleLux < untereGrenzeStarkeAnpssung){\n anpassungLimit = 2;\n } else {\n anpassungLimit = 4;\n }\n // Starte den Anpassungs-/Annäherungs-prozess\n if (msg.topic == \"Lux\") {\n AdjustRolladen(0);\n }\n}\nreturn;\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 870,
"y": 380,
"wires": [
[
"b44025f5b06f3991"
]
]
},
{
"id": "7de4bac33850fa9c",
"type": "ioBroker in",
"z": "0f6df9154830780b",
"name": "get Rolladen NZ",
"topic": "klf200.0.products.1.currentPosition",
"payloadType": "value",
"onlyack": "",
"func": "rbe",
"gap": "",
"fireOnStart": "true",
"outFormat": "MQTT",
"x": 340,
"y": 340,
"wires": [
[
"0e7a830b2c3fdd78"
]
]
},
{
"id": "bb59c1082cbce8e3",
"type": "ioBroker in",
"z": "0f6df9154830780b",
"name": "get Lux RN (Door2)",
"topic": "shelly.1.SHDW-2#10531C69527D#1.sensor.lux",
"payloadType": "value",
"onlyack": "",
"func": "rbe",
"gap": "",
"fireOnStart": "true",
"outFormat": "MQTT",
"x": 330,
"y": 420,
"wires": [
[
"18293f21c9d7f474"
]
]
},
{
"id": "0e7a830b2c3fdd78",
"type": "change",
"z": "0f6df9154830780b",
"name": "chg",
"rules": [
{
"t": "delete",
"p": "topic",
"pt": "msg"
},
{
"t": "set",
"p": "topic",
"pt": "msg",
"to": "Rolladen",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 530,
"y": 340,
"wires": [
[
"f33338a8878f239e"
]
]
},
{
"id": "18293f21c9d7f474",
"type": "change",
"z": "0f6df9154830780b",
"name": "chg",
"rules": [
{
"t": "delete",
"p": "topic",
"pt": "msg"
},
{
"t": "set",
"p": "topic",
"pt": "msg",
"to": "Lux",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 530,
"y": 420,
"wires": [
[
"9e2ee34b30055510"
]
]
},
{
"id": "b44025f5b06f3991",
"type": "ioBroker out",
"z": "0f6df9154830780b",
"name": "set Rolladen NZ",
"topic": "klf200.0.products.1.targetPosition",
"ack": "false",
"autoCreate": "false",
"stateName": "",
"role": "",
"payloadType": "",
"readonly": "",
"stateUnit": "",
"stateMin": "",
"stateMax": "",
"x": 1080,
"y": 380,
"wires": []
},
{
"id": "f33338a8878f239e",
"type": "trigger",
"z": "0f6df9154830780b",
"name": "EntPrell",
"op1": "",
"op2": "",
"op1type": "nul",
"op2type": "payl",
"duration": "5",
"extend": true,
"overrideDelay": false,
"units": "s",
"reset": "",
"bytopic": "all",
"topic": "topic",
"outputs": 1,
"x": 680,
"y": 340,
"wires": [
[
"9e4c4a8c37c936d6"
]
]
},
{
"id": "9e2ee34b30055510",
"type": "trigger",
"z": "0f6df9154830780b",
"name": "EntPrell",
"op1": "",
"op2": "",
"op1type": "nul",
"op2type": "payl",
"duration": "5",
"extend": true,
"overrideDelay": false,
"units": "s",
"reset": "",
"bytopic": "all",
"topic": "topic",
"outputs": 1,
"x": 680,
"y": 420,
"wires": [
[
"9e4c4a8c37c936d6"
]
]
}
]
Alles anzeigen
Hat jemand ein besseres Skript für eine Rollladenautomatik mit Shelly Lux Werten? Es muss nicht unbedingt NodeRed sein, solange es Js_Skript ist, kann ich es bei Bedarf anpassen.
Für Verbesserungsvorschläge bin ich auch offen.
Eigentlich könnte man das auch nur mit einem Shelly Skript in nem Plus2PM via Endpoints, Keys, und Webhook Aktion im Door oder Motion 2 realisieren, ich bin mir da aber nicht sicher, hat zufällig jemand in der Richtung schon sowas realisiert?