within the last weeks I have installed openhab 3.2 on my OMV-Server, where it runs within an docker container. So far so good. But to switch off my currently used openHabian, I have to transfer my rules to the new OpenHab instance. For this I tried to use blockly and “recode” the rules grafically … and now I run into problems.
What should the rule do? Our guest toilet has a switch and a motion detector. The aim is, that the light will go off automaticaly (when switch on befor by switch or motion detection) by either switch or timeout (time where no motion or presence was detected).
var defaultBirghntness, autoOffTime, currentBrightness;
if (typeof this.timers === 'undefined') {
this.timers = [];
}
var zdt = Java.type('java.time.ZonedDateTime');
var logger = Java.type('org.slf4j.LoggerFactory').getLogger('org.openhab.rule.' + ctx.ruleUID);
var scriptExecution = Java.type('org.openhab.core.model.script.actions.ScriptExecution');
defaultBirghntness = 75;
autoOffTime = 1 * 20;
currentBrightness = itemRegistry.getItem('HUEWC_Helligkeit').getState();
if (typeof this.timers['timeout_Timer'] !== 'undefined' && this.timers['timeout_Timer'].isRunning()) {
if (itemRegistry.getItem('HuemotionsensorWC_Bewegung').getState() == 'OFF') {
events.sendCommand('HUEWC_Helligkeit', '0');
if (typeof this.timers['timeout_Timer'] !== 'undefined') {
this.timers['timeout_Timer'].cancel();
this.timers['timeout_Timer'] = undefined;
}
} else {
if (typeof this.timers['timeout_Timer'] !== 'undefined') { this.timers['timeout_Timer'].reschedule(zdt.now().plusSeconds(autoOffTime)); }
}
} else {
if (currentBrightness == '0') {
logger.error('WC Light ON');
events.sendCommand('HUEWC_Helligkeit', defaultBirghntness);
}
if (typeof this.timers['timeout_Timer'] === 'undefined' || this.timers['timeout_Timer'].hasTerminated()) {
this.timers['timeout_Timer'] = scriptExecution.createTimer(zdt.now().plusSeconds(autoOffTime), function () {
logger.error('Timeout Timer retriggered?');
if (itemRegistry.getItem('HuemotionsensorWC_Bewegung').getState() == 'OFF') {
events.sendCommand('HUEWC_Helligkeit', '0');
if (typeof this.timers['timeout_Timer'] !== 'undefined') {
this.timers['timeout_Timer'].cancel();
this.timers['timeout_Timer'] = undefined;
}
} else {
if (typeof this.timers['timeout_Timer'] !== 'undefined') { this.timers['timeout_Timer'].reschedule(zdt.now().plusSeconds(autoOffTime)); }
}
})
}
}
What works is, that the light will be sitched on by switch or motion detector and will go off after the timeout time (currently for test purpose only 20s). What not work is to switch of the light befor the timeout will be reached.
An other problem I’ve discovered is, that the log messages will no appear within the events.log file …
Has anyone an idear, where the mistake is?
Thanks, best regards and stay healthy
Stef
After reading the timer manual again I come to the conflusion that it is not possible to create someting similar to the following code with the blockly interface
rule "WC_LightON"
when
Item HueSensMotion2 changed to ON or
Item LCN_WC_Relay_HUE_WC_Switch changed from ON or
Item LCN_WC_Relay_HUE_WC_Switch changed from OFF
then {
logInfo("WC-Rule","Triggered")
val currBrightness = HueWCLight.getStateAs(PercentType) as Number // get the brightness
if (WC_Auto_OFF_Timer === null || WC_Auto_OFF_Timer.hasTerminated() ) {
if (HueWCLight.state == 0) {
sendCommand(HueWCLight, WC_WC_Brightness_Default)
logInfo("WC-Rule", "switched ON by either switch or BWM.")
}
WC_Auto_OFF_Timer = createTimer(now.plusSeconds(AutoOffTime), [|
if (HueSensMotion2.state == OFF) {
sendCommand(HueWCLight, OFF)
WC_Auto_OFF_Timer = null
logInfo("WC-Rule", " switch light OFF, because timer has finished.")
} else {
WC_Auto_OFF_Timer.reschedule(now.plusSeconds(AutoOffTime))
logInfo("WC-Rule","ReSchedule Timer, because WC still occupied.")
}
])
} else {
logInfo("WC-Rule", "retrigger path.")
if (triggeringItem.name == "LCN_WC_Relay_HUE_WC_Switch") {
sendCommand(HueWCLight, OFF)
WC_Auto_OFF_Timer.cancel
WC_Auto_OFF_Timer = null
logInfo("WC-Rule","OFF by switch.")
}
else {
WC_Auto_OFF_Timer.reschedule(now.plusSeconds(AutoOffTime))
logInfo("WC-Rule","ReSchedule Timer because of presence.")
}
}
}
end
If someone has an idear how to map this code with blockly it would be fine toi share this.
Thanks and best regards
Stef
thanks for your support. The 3rd szenario you mentioned is implemented in the “else if” pass, because … if the motion detector has not fired (off) then the other trigger have fired and the other triggers are the switch (relaized by a state toggle).
Maybe I’m wrong, but this was the idear behind this implementation.
Thanks and best regards
Stef
PS: Don’t be confused about the trigger for the switch. The switch is an LCN module, where I just toggle the state of an relay, when the switched ist pressed short.
Maybe just add some logging before the if block of your relevant items state and within reach part of the if block to see what’s happening and see if the IF, ELSE IF or ELSE block is executed.
Also you could use received command and triggering item variables to better react on each scenario
var defaultBirghntness, autoOffTime, currentBrightness, dummy;
var scriptExecution = Java.type('org.openhab.core.model.script.actions.ScriptExecution');
var zdt = Java.type('java.time.ZonedDateTime');
if (typeof this.timers === 'undefined') {
this.timers = [];
}
var logger = Java.type('org.slf4j.LoggerFactory').getLogger('org.openhab.rule.' + ctx.ruleUID);
defaultBirghntness = 75;
autoOffTime = 1 * 20;
currentBrightness = itemRegistry.getItem('HUEWC_Helligkeit').getState();
if (itemRegistry.getItem('HUEWC_Helligkeit').getState() < '5') {
events.sendCommand('HUEWC_Helligkeit', defaultBirghntness);
if (typeof this.timers['timeout_Timer'] === 'undefined' || this.timers['timeout_Timer'].hasTerminated()) {
this.timers['timeout_Timer'] = scriptExecution.createTimer(zdt.now().plusSeconds(autoOffTime), function () {
if (itemRegistry.getItem('HuemotionsensorWC_Bewegung').getState() == 'OFF') {
events.sendCommand('HUEWC_Helligkeit', '0');
if (typeof this.timers['timeout_Timer'] !== 'undefined') {
this.timers['timeout_Timer'].cancel();
this.timers['timeout_Timer'] = undefined;
}
} else {
if (typeof this.timers['timeout_Timer'] !== 'undefined') { this.timers['timeout_Timer'].reschedule(zdt.now().plusSeconds(autoOffTime)); }
}
})
}
} else if (itemRegistry.getItem('HuemotionsensorWC_Bewegung').getState() == 'OFF') {
events.sendCommand('HUEWC_Helligkeit', '0');
if (typeof this.timers['timeout_Timer'] !== 'undefined') {
this.timers['timeout_Timer'].cancel();
this.timers['timeout_Timer'] = undefined;
}
} else {
if (itemRegistry.getItem('HUEWC_Helligkeit').getState() >= '0') {
logger.info('ReTrigger by motion detection');
dummy = itemRegistry.getItem('HUEWC_Helligkeit').getState();
events.sendCommand('HUEWC_Helligkeit', (dummy - 1));
}
if (typeof this.timers['timeout_Timer'] !== 'undefined') { this.timers['timeout_Timer'].reschedule(zdt.now().plusSeconds(autoOffTime)); }
}
From my point of view the rule will not be triggered after started once … but … if I retrigger the motion detection, while the light is on, the rule will be retriggered. But this can also happend within the code that should be executed, when the timer ist finished …
The Docker container does not support the port 9001 to show an logging windows … this is another problem that I have to solve.
But … I demystified the problem … f**k … If you take a look on my first post you can see the “But only if” clause … this prevents the rule from being retriggered, while the light is on … damned.
In my original rule I used on openhabian I used if (triggeringItem.name == …) to distinguish which trigger triggers the rule. Within Blockly I can’t find someting similar. So I can switch off the light manualy only after the motion detector hast released his “motion detected” state …
Do you know how to fuild something like if (triggeringItem.name == …) ?
Thanks, best regards, happy new year and stay healthy
Stef
That’s part of openHABian, not openHAB. It’s a separate third party service called Frontal that outbidded the logs in the browser capability. If not using ooenHABian (e.g. rubbing on Docker), it’s up to you to install and configure Frontal.
There is an “event” block that includes all the JSR223 equivalents to implicit variables. In this case event.itemName.