NEWS
Automatische Gartenbewässerung
-
Bei dem trockenem Frühjahr ist Gartenbewässerung ein großes Thema.
Das Skript, dass ich heute vorstelle befasst sich mit der Ansteuerung der Magnetventile. Es enthält keine Regeln, wann die Bewässerung gestartet wird. Ein Ventil anzusteuern ist eigentlich kein Hexenwerk. Auch mehrere dürfte kein Problem sein. Auf meiner Liste standen aber noch mehr Wünsche, die ich bei früheren Skripten nicht bedacht habe. Mehrere Ventile können zu einem Bewässerungskreis zusammengefasst werden. Für jeden Kreis kann eine individuelle Bewässerungszeit festgelegt werden. Die Bewässerung kann jederzeit angehalten oder abgebrochen werden. Außerdem gibt es eine Default-Konfiguration der Bewässerungskreise und die Möglichkeit über eine eine temporäre Konfiguration hiervon abzuweichen. Außerdem gibt es noch einen State, in dem die Restlaufzeit der Bewässerung angezeigt wird.
Bevor man das Skript startet, sollte man die Bewässerungskreise festlegen. Kleiner Tipp: die Bezeichnungen bei der Homematic sind immer etwas kryptisch. Ich habe in einem globalen Skript die Namen der States in Klartext-Variablen gespeichert. Beispiel:
var gartenBwBeetGarage = "hm-rpc.2.IEQ0020480.1.STATE";
Wenn ich das Ventil ansprechen möchte brauche ich nur "gartenBwBeetGarage" übergeben.
Nun müssen wir den Default-Plan der Beregnungskreise anlegen. Es handelt sich um ein Array. Der Aufbau sieht wie folgt aus:
[ [[Ventil1, Ventil2],Zeit1], //Kreis 1 [[Ventil3],Zeit2], //Kreis 2 ... //Folgekreise ]
Man kann zwischen 1 und beliebig vielen Kreisen einrichten. Im obigen Beispiel habe ich zwei Kreise eingerichtet. Kreis 1 besteht aus zwei Ventilen und Kreis 2 aus lediglich einem Ventil. Die Ventile sind in einem Array aufgeführt. Auch nur bei einem Ventil muss dieses als Array aufgelistet werden. Am Ende wird die Bewässerungszeit in Minuten angegeben. In dem Code unten habe ich ein Umfangreiches Beispiel eingepflegt. Da die Array zu "groß" wurden habe ich sie in mehrere aufgeteilt und dann zusammen gefügt.
Immer wenn man die Bewässerung startet, wird dieses "Programm" dann abgearbeitet. Einzige Ausnahme: Man speichert ein temporären Plan ab. Dieses ist auch in dem Code enthalten.
/* How to use: setup states: defaultCircles start watering: set state running=true stop watering: set state running=false pause: set state pause=true, continuing: set state pause=false Todo: skip a circle automatic mode - depending on the need of watering notice: The scheduler runs always on exact minutes. There may be inaccuracies due to the fact that the watering may be started or stopped between the schedules. */ //Declaration of var var statePrefix="garden.watering."; var stateFullPrefix="javascript.0."+statePrefix; var emptyCircle=[[[],0]]; //Creating States //createState(statePrefix+'auto', true); createState(statePrefix+'pause', false); createState(statePrefix+'mode', false); createState(statePrefix+'running', false); createState(statePrefix+'remainingTime', 0); createState(statePrefix+'circles', JSON.stringify(emptyCircle)); createState(statePrefix+'circlesDefault', JSON.stringify(emptyCircle)); createState(statePrefix+'circlesTemp', ""); //Define circleDefault var beete = [ [[gartenBwWein],15], [[gartenBwBeetSandkiste],15], [[gartenBwBeetRosen, gartenBwBeetGarage],7], [[gartenBeetLilie],7], [[gartenBeetKompost,gartenGemueseOben,gartenGemueseUntenLinks,gartenGemueseUntenRechts],15], [[gartenGemueseUntenLinks,gartenGemueseUntenRechts],15], [[gartenBeetTerrasse,gartenBeetMiniGewaechshaus],15], [[gartenBeetWohnzimmer],7] ]; var rasen = [ [[gartenBwRasenSandkiste,gartenBwRasenGarage],20], [[gartenRasen20a,gartenRasenLilie],20], [[gartenRasenSchaf,gartenRasenBuero],20], [[gartenRasenWohnzimmer,gartenRasenKompost],20], [[gartenRasenGewaechshaus],20], ]; var stufenbeete = [ [[gartenBwStufeRhodos,gartenStufeMagnolie,gartenStufeUntenGarage,gartenStufeObenGarage],30] ]; var watering=beete; watering=watering.concat(rasen); watering=watering.concat(stufenbeete); setState(stateFullPrefix+"circlesDefault",JSON.stringify(watering)); //Define circleTemp watering=[ //[[gartenBwRasenSandkiste],0], [[gartenBwRasenGarage],1] ]; setState(stateFullPrefix+"circlesTemp",JSON.stringify(watering)); var circles = emptyCircle; var timer; function startTimer() { timer=schedule("* * * * *", function () { console.log("Timer"); //Check, wether mode is pause or stop or no circles left //if true, just do nothing var status=getState(stateFullPrefix+"mode").val; if((status==="pause") || (status==="stop") || (circles.length===0)){ //do nothing, just return return; } setState('garden.watering.remainingTime',_getRemaningTime()); // Check if remaining time of current circle finished if(circles[0][1]<=0) { _setCurValvesOn(false); //stop valves of current circle circles.shift(); //shift to next circle //if circle left, turn on valves else stop if(circles.length>0) { _setCurValvesOn(true); } else { console.log("#######Stop watering"); setState(stateFullPrefix+"running",false); return; } setState(stateFullPrefix+"circles",JSON.stringify(circles)); } else { circles[0][1]--; //count down remaining time } setState(stateFullPrefix+"circles",JSON.stringify(circles)); }); } //pause routine - alle Ventile an/aus on({id: stateFullPrefix+"pause", val:true}, function (obj) { setState(stateFullPrefix+"mode","pause"); _setCurValvesOn(false); }); on({id: stateFullPrefix+"pause", val:false}, function (obj) { setState(stateFullPrefix+"mode","running"); _setCurValvesOn(true); }); //start on({id: stateFullPrefix+"running", val:true}, function (obj) { setState(stateFullPrefix+"pause",false); setState(stateFullPrefix+"mode","running"); var temp=getState(stateFullPrefix+"circlesTemp").val; if(temp.length>0) { circles=JSON.parse(temp); setState(stateFullPrefix+"circlesTemp",""); } else { circles=JSON.parse(getState(stateFullPrefix+"circlesDefault").val); } _setCurValvesOn(true); setState(stateFullPrefix+'remainingTime',_getRemaningTime()); setState(stateFullPrefix+"circles",JSON.stringify(circles)); startTimer(); }); //stop on({id: stateFullPrefix+"running", val:false}, function (obj) { setState(stateFullPrefix+"pause",false); setState(stateFullPrefix+"mode","stop"); console.log("STOP - alle Ventile aus"); _setCurValvesOn(false); circles=emptyCircle; setState(stateFullPrefix+"circles",JSON.stringify(circles)); setState(stateFullPrefix+'remainingTime',0); clearSchedule(timer); }); function _setCurValvesOn(onOff) { //on=true; off=false //var circles=JSON.parse(getState(stateFullPrefix+"circles").val); if(circles.length>0) { //check if there is a circle left for(var i=0;i