NEWS
Zustandsautomat (State Machine) Skript
-
Hallo,
mit dem clearSchedule von BlueFox habe ich ein Zustandsautomat Skript implementiert. Dieses Skript ändert um gewiesen Zeitpunkten ein Zustands-variable. Ich Benutze die, um aktionen wie Rollanden, Heizung, Wecker, etc zu steuern. Die Zeitpunkte sind in eigene Variablen definiert, die ich später via VIS konfigurierbar machen will
Es ist ein erstes Version und da meine Erfahrung mit Javascript außerhalb von iobroker null ist wird es vermutlich noch Anpassungen brauchen aber vielleicht hilft es schon jemand.
Update: version 1.1
- State times werden jetzt in einem Baumstruktur definiert.
// iobroker state machine v 1.1 // // Features: // - update state variable at times defined in extra variables // - update a preview state variable (usefull to adjust heating in advance) // - use diferent times for free days and work days // - this requires another script // // Changelog // 1.0 Initial version // 1.1 Store variables in tree structure (easier to display in iobroker.admin) // //Id of the javascript adaptor instance where variables should be created/read var JAVASCRIPT_INSTANCE_ID = "javascript.0"; //Variable name where state is stored to var STATE_VAR_NAME = "homeState"; //Variable name where state preview is stored to var STATE_VAR_PREVIEW_NAME = "homeStatePreview"; //Number of hours the the state preview changes before state does var PREVIEW_DELTA_HOURS = 1; //Bool variable where external script writes if today is a freeday var IS_FREEDAY_TODAY_VARNAME="isFreeDay.today"; //Bool variable where external script writes if tomorrow is a freeday var IS_FREEDAY_TOMORROW_VARNAME="isFreeDay.tomorrow"; //Bool variable where external script writes if yesterday was a freeday var WAS_FREEDAY_YESTERDAY_VARNAME="isFreeDay.yesterday"; //Local cache of state information var allStateChanges = {}; //************************************************************ // STATE DEFINITIONS //************************************************************ //Define work states addState("sleeping", 0 /*stateNumber*/, false /*isFreeday*/, "22:00:00" /*initValue*/); addState("awakeBeforeWork", 1 /*stateNumber*/, false /*isFreeday*/, "07:00:00" /*initValue*/); addState("empty", 2 /*stateNumber*/, false /*isFreeday*/, "09:00:00" /*initValue*/); addState("awake", 3 /*stateNumber*/, false /*isFreeday*/, "18:30:00" /*initValue*/); //Define freeday states addState("sleeping", 0 /*stateNumber*/, true /*isFreeday*/, "23:30:00" /*initValue*/); addState("awake", 3 /*stateNumber*/, true /*isFreeday*/, "09:00:00" /*initValue*/); //************************************************************ // IMPLEMENTATION //************************************************************ function addState(stateName, stateNumber, isFreeday, initValue){ //Define variable name to store the timer value var stateFullName = JAVASCRIPT_INSTANCE_ID+".stateTime." + ((isFreeday)?"freeDay":"work") + "." + stateName; //When we use it as key, we need to replace . with _ var stateFullNameFlat = stateFullName.replace(/\./g,"_"); //common object for state var common = {"role": "homeStates", "type": "string", "desc": "Time to change state to "+stateName+"("+initValue+")."}; //Create variable createState(stateFullName, initValue, false, common); //Function used to (re-)schedule the state changes. var sch; var schPreview; function registerState(obj){ //Delete old schedules (if any) if (sch) clearSchedule(sch); if (schPreview) clearSchedule(schPreview); //get current date var schDateObj = obj ? obj.newState : getState(stateFullName); var schDateStr = schDateObj ? schDateObj.val : initValue /*first time*/; var schDate = addTime(schDateStr); log("Scheduling state change(number="+stateNumber+", freeDay="+isFreeday+") at "+schDate); //Remember this state allStateChanges[stateFullNameFlat] = { dateStr: schDateStr, stateNumber: stateNumber, isFreeday: isFreeday }; //Schedule for state changes sch = schedule({hour: schDate.getHours(), minute: schDate.getMinutes(), second: schDate.getSeconds()},cb(function(){ if (isTodayFreeDay() === isFreeday) { log(STATE_VAR_NAME+" CHANGE: "+stateNumber); setState(STATE_VAR_NAME, stateNumber); } })); //One hour before we want to update a previewState variable schDate.setHours(schDate.getHours()-PREVIEW_DELTA_HOURS); log("Scheduling statePreview change("+stateNumber+") at "+schDate); //Schedule for preview state changes schPreview = schedule({hour: schDate.getHours(), minute: schDate.getMinutes(), second: schDate.getSeconds()},cb(function(){ if (isTodayFreeDay() === isFreeday) { log(STATE_VAR_PREVIEW_NAME+" CHANGE: "+stateNumber); setState(STATE_VAR_PREVIEW_NAME, stateNumber); } })); //If the state change variable was updated, update the current and preview states if (obj) { //This is an update updateState(); } } //Register with current timer registerState(); //Register again if the timer changes on(stateFullName, cb(registerState)); log("Subscribed to "+stateFullName); } function updateState(){ //current state var currentDate = new Date(); var stateNumber = getCurrentState(currentDate); setState(STATE_VAR_NAME, stateNumber); log(STATE_VAR_NAME + " set to " + stateNumber); //preview state var previewDate = currentDate; previewDate.setHours(previewDate.getHours() + PREVIEW_DELTA_HOURS /*One hour in the future*/); stateNumber = getCurrentState(previewDate); setState(STATE_VAR_PREVIEW_NAME, stateNumber); log(STATE_VAR_PREVIEW_NAME + " set to " + stateNumber); } function getCurrentState(currentDate) { var isTodayFreeDay_l = isTodayFreeDay(); var wasYesterdayFreeDay_l = wasYesterdayFreeDay(); var isTomorrowFreeDay_l = isTomorrowFreeDay(); //log("getCurrenState for "+JSON.stringify(currentDate.getHours())); var stateNumber2set; var largestDate; function checkCandidate(candidateDate, stateNumber){ //log("Checking "+JSON.stringify(candidateDate)); if (candidateDate <= currentDate){ //This is a valid state candidate if ((largestDate === undefined) || (candidateDate > largestDate)){ //Better candidate stateNumber2set = stateNumber; largestDate = new Date(candidateDate); } } } var candidateDate; for (var stateChangeName in allStateChanges) { if (allStateChanges.hasOwnProperty(stateChangeName)) { //log("Element: "+JSON.stringify(allStateChanges[stateChangeName])); //Check elements candidateDate = addTime(allStateChanges[stateChangeName].dateStr); //Check today if (allStateChanges[stateChangeName].isFreeday === isTodayFreeDay_l) { checkCandidate(candidateDate, allStateChanges[stateChangeName].stateNumber); } //Check yesterday if (allStateChanges[stateChangeName].isFreeday === wasYesterdayFreeDay_l) { candidateDate_yesterday = candidateDate; candidateDate_yesterday.setDate(candidateDate_yesterday.getDate() - 1); checkCandidate(candidateDate_yesterday, allStateChanges[stateChangeName].stateNumber); } //Check tomorrow if (allStateChanges[stateChangeName].isFreeday === isTomorrowFreeDay_l) { candidateDate_tomorrow = candidateDate; candidateDate_tomorrow.setDate(candidateDate_tomorrow.getDate() + 1); checkCandidate(candidateDate_tomorrow, allStateChanges[stateChangeName].stateNumber); } } } return stateNumber2set; } function isTodayFreeDay(){ createState(IS_FREEDAY_TODAY_VARNAME,true); return getState(IS_FREEDAY_TODAY_VARNAME).val; } function wasYesterdayFreeDay(){ createState(WAS_FREEDAY_YESTERDAY_VARNAME,true); return getState(WAS_FREEDAY_YESTERDAY_VARNAME).val; } function isTomorrowFreeDay(){ createState(IS_FREEDAY_TOMORROW_VARNAME,true); return getState(IS_FREEDAY_TOMORROW_VARNAME).val; } //Create home state (in case it does not exists) createState(STATE_VAR_NAME); createState(STATE_VAR_PREVIEW_NAME); //Create variable that groups the state change times createState(JAVASCRIPT_INSTANCE_ID+".stateTime", null,false,{"role": "homeStates","desc":"Time to change variables"}); createState(JAVASCRIPT_INSTANCE_ID+".stateTime.freeDay",null,false,{"role": "homeStates","desc":"Time to change variables for free days"}); createState(JAVASCRIPT_INSTANCE_ID+".stateTime.work", null,false,{"role": "homeStates","desc":"Time to change variables for work days"}); //Set current state updateState();
-
Update: version 1.1
- State times werden jetzt in einem Baumstruktur definiert.
![](</s><URL url=)<link_text text="http://forum.iobroker.net/download/file ... 50bb7c0f49">http://forum.iobroker.net/download/file.php?mode=view&id=2455&sid=610e0fb156af1e900f038c50bb7c0f49</link_text>" />