Good afternoon. I’m a complete newbie to openhab and I’m strugging to get my first project off the ground. My goal is to get my alexa to sound an alarm/say something when a contact sensor attached to my front door has detected that the door has been left open for 10 seconds. I’m using a Tuya contact sensor which I have correctly configured with openHAB thanks to the users here, and I’ve also correctly configured alexa using the appropriate channels + links.
My issue is when creating the rule I can’t make the appropriate timer work. The contact sensor is an item called Tuya_test, where an ON state means the door is open. This is the config of my rule so far using the GUI:
triggers:
- id: "1"
configuration:
itemName: Tuya_Test
state: ON
previousState: OFF
type: core.ItemStateChangeTrigger
conditions:
- inputs: {}
id: "3"
configuration:
type: application/javascript
script: |-
var Timer timer = null
rule "timer"
when
Item Tuya_Test.state === ON //Use whatever trigger
then
(if timer === null) {
timer = createTimer(now.plusSeconds(10)), [ |
if (Tuya_Test.state === ON) {
output = 1
} //Do the timer stuff
timer = null // cancel the timer
])
}
end
type: script.ScriptCondition
actions:
- inputs: {}
id: "2"
configuration:
itemName: ThomassEchoDot_Speak
command: The door is open
type: core.ItemCommandAction
If I remove the conditions section then alexa talks whenever the door is opened, but crucially I want the condition to test that the door has been opened continuously for 10 seconds and only then to do the action. I’m sorry if this has already been covered somewhere but I’ve been trying to make a sense of related posts with no luck for the past few days.
I’m happy to try either approach (.rules or JS) but I’m lost as to where to start. Is there a good example of a .rules file I could use as a template perhaps?
Thanks for your help rossko - I’ve managed to come up with a javascript solution. In case its helpful for anyone else who stumbles on this thread I’ll post my (noob-friendly) solution, i.e., the rule I created using the openHAB GUI (note the proximity door sensor and alexa were already set up with their required channels - don’t forget to check advanced to see them all!).
The Rule will detect then the proximity door sensor is triggered to “ON” (and thus open), and if this state persists for 10 seconds, a function defined in this rule will be triggered that sends various commands to my Alexa Echo (change to max volume, say a predefined sentence). This will then repeat until the door is closed again/the proximity sensor is seen to be ‘OFF’.
The below code was put into an ECMAscript (javascript) under the ‘Then’ section of the Rules UI
var mytimer = (mytimer === undefined) ? null : mytimer; // this defines the timer variable
var ScriptExecution = Java.type("org.openhab.core.model.script.actions.ScriptExecution");
var ZonedDateTime = Java.type("java.time.ZonedDateTime"); // two required javascript functions to be loaded
var event
myObj = ir.getItem(event.itemName) // fetches the event relevant to the rule (in my case the proximity door sensor set in the 'When' section of the UI.
function warnOpenDoor() {
myObj = ir.getItem(event.itemName)
//events.sendCommand("ThomassEchoDot_Speak", myObj.getState()) //debug
//events.sendCommand("ThomassEchoDot_Speak", "test speaking") // debug
var EchoDotVolume = ir.getItem("ThomassEchoDot_Volume")
//events.sendCommand("ThomassEchoDot_AlarmSound","ECHO:system_alerts_alarming_03")
while (myObj.getState() == ON) {
events.sendCommand("ThomassEchoDot_Volume", "100")
//events.sendCommand("ThomassEchoDot_AlarmSound","ECHO:system_alerts_rhythmic_02")
events.sendCommand("ThomassEchoDot_Speak", "Warning: Front Door Open. Beware of the cats.")
events.sendCommand("ThomassEchoDot_Volume", EchoDotVolume.state)
java.lang.Thread.sleep(10000)
}
mytimer = null
}
var now = ZonedDateTime.now()
if (myObj.getState() == ON) {
//events.sendCommand("ThomassEchoDot_Speak", "Open") // debug
mytimer = ScriptExecution.createTimer(now.plusSeconds(10), warnOpenDoor)
}
else {
//events.sendCommand("ThomassEchoDot_Speak", "Close") // debug
if (mytimer != undefined) {
mytimer.cancel();
mytimer = undefined;
}
}
That’s for posting your code. The more examples we have the better. I’ve a few comments though which might make the code posted even better.
When posting a rule to the forum, consider whether it makes sense to post just the Script Action or to post the entire rule. You can access the code for the whole rule from the Code tab of the Rule Designer page.
JavaScript is a bit loosey-goosey in what it will allow you to get away with. But in general I’ve seen it recommended to always close your lines of code with a ;.
var event: what is this line doing? event should already exist in the rule as one of the variables that gets inserted into the context when the rule is triggered. You don’t need to redeclare it.
In the function warnOpenDoor, you redefine and populate myObj. myObj should already be available in that function but if it’s not, pass it as an argument to the function. Avoid duplicate lines of code.
function warnOpenDoor(myObj) {
You can use createTimerWithArgument or you can use a function generator which would look like:
`function warnOpenDoorGenerator(myObj){
return function(){
// your existing code goes here
}
}
This is more of a style thing, but I prefer to use the items dict to get an Item’s state. It makes for shorter and clearer code over all. Also, the items dict gets updated as the Items change states. I’m not sure the Item Object you’ve pulled from the ItemRegistry get’s updated the same way.
var EchoDotVolume = items["ThomassEchoDot_Volume"];
function warnOpenDoor() {
while(items[event.itemName] == ON) {
...
events.sendCommand("ThomassEchoDot_Volume", EchoDotVolume);
java.lang.Thread.sleep(10000);
}
myTimer = null;
}
Use the identity comparison when comparing to undefined.