Since you only care about when the door changed to the current state I think using persistence or a separate Item would be less complicated.
Using Items in Rules DSL (assumes the Item doesn’t update except when it changes):
- create a DateTime Item linked to the same Channel as the door sensor Channel and apply the timestamp profile
rule “Main door is opened 01”
when
Item GF_Entry_Door changed from CLOSED to OPEN
then
logInfo(“RULES”, “Main door was opened”)
end
rule “Main door is opened 02”
when
Time cron "0 0 0/2 ? * * *"
then
if(now.getHour() > 16 && now.getHour() < 8) return;
if(GF_Entry_Door.state == OPEN) return;
val mailActions = getActions(“mail”,“mail:smtp:samplesmtp”)
mailActions.sendHtmlMail(“my_email@gmail.com”, “OH Alert - Main door log”, “Entry door was opened at ” + GF_Entry_Door_Timestamp.state.toString)
logInfo(“RULES”, “eMail of main door status change was sent” )
end
If the Item does update and you cannot use the timestamp profile you can use your OPEN rule.
rule “Main door is opened 01”
when
Item GF_Entry_Door changed from CLOSED to OPEN
then
logInfo(“RULES”, “Main door was opened”)
GF_Entry_Door_Timestamp.postUpdate(now)
end
You have a few more Items with this approach but much less complexity in the rules.
You could also use the cache which would be slightly less complicated than keeping track of the timestamps manually.
rule “Main door is opened 01”
when
Item GF_Entry_Door changed from CLOSED to OPEN
then
logInfo(“RULES”, “Main door was opened”)
sharedCache.put("GF_Entry_Door_Timestamp", now)
end
rule “Main door is opened 02”
when
Time cron "0 0 0/2 ? * * *"
then
if(now.getHour() > 16 && now.getHour() < 8) return;
if(GF_Entry_Door.state == OPEN) return;
val mailActions = getActions(“mail”,“mail:smtp:samplesmtp”)
mailActions.sendHtmlMail(“my_email@gmail.com”, “OH Alert - Main door log”, “Entry door was opened at ” + sharedCache.get("GF_Entry_Door_Timestamp"))
logInfo(“RULES”, “eMail of main door status change was sent” )
end
The persistence approach gets a bit complicated depending on the database used and strategies used to save values. I don’t think we can just get all the entries in the past two hours becuase the door may have opened more than two hours ago.
Thankfully there is now a lastChange
persistence extension which should work so long as:
- the persistence strategy is such that everyChange is used
- the timing is OK (i.e. the door state doesn’t change exactly when the rule runs);
lastChange
returnsnull
if the current state of the Item is different from the most recent value in the database
rule “Main door is opened 01”
when
Item GF_Entry_Door changed from CLOSED to OPEN
then
logInfo(“RULES”, “Main door was opened”)
end
rule “Main door is opened 02”
when
Time cron "0 0 0/2 ? * * *"
then
if(now.getHour() > 16 && now.getHour() < 8) return;
if(GF_Entry_Door.state == OPEN) return;
var openedAt = GF_Entry_Door.lastChange
if(openedAt === null) {
logError("door open", "Timing error")
return;
}
val mailActions = getActions(“mail”,“mail:smtp:samplesmtp”)
mailActions.sendHtmlMail(“my_email@gmail.com”, “OH Alert - Main door log”, “Entry door was opened at ” + openedAt)
logInfo(“RULES”, “eMail of main door status change was sent” )
end
Having done all that, there is another option if you change your requirements just a little bit. You can install and use Threshold Alert and Open Reminder [4.0.0.0;4.9.9.9] to get an alert every two hours that a door is left open.
- Make sure you have JS Scripting installed
- Install OHRT; if you are on openHABian this can be done from openhabian-config, if not run
npm install openhab_rules_tools
from the$OH_CONF/automation/js
folder. - Navigate to Add-on Store → Automation → Rule Templates → Threshold Alert and Open Reminder and add the rule tempalte
- Add the Door Item to a Group (we’ll call if
AllDoors
) - Create a rule to send the alert. All the tracking logic is handled by the rule template so all you need to do is send the email. The rule ID will be the name of the .rules file and the number of the rule in that file. For example, if this is the third rule in a file named “foo.rules” the rule ID will be
foo-3
.
rule "Main door is opened"
when
// no triggers, this rule will be called from threshold alert
then
val mailActions = getActions(“mail”,“mail:smtp:samplesmtp”)
mailActions.sendHtmlMail(“my_email@gmail.com”, “OH Alert - Main door log”, “Entry door has been open for a long time”)
logInfo(“RULES”, “eMail of main door status change was sent” )
end
- Navigate to Settigns → Rules → +
- Enter the rule metadata (name, ID, etc)
- Select Threshold Alert under “Templates”
- Fill out the properties as follows (if not listed here leave the property at the default):
a. Triggering Group: AllDoors
b. Threshold State: OPEN
c. Alert Delay: PT5M
d. Reminder Period: PT2H
e. Alert Rule: Select the rule created above
f. Do not disturb start time: 16:00
g. Do not disturb end time: 08:00
The rule that gets created will work as follows:
- When any member of AllDoors remains in the OPEN state for five minutes, it will call the Alert Rule.
- If the door closes before the five minutes nothing happens.
- If the door remians open for two hours after that initial alert, the Alert Rule is called again.
- If the call to the alert rule would happen between 16:00 and 08:00, the call to the alert rule is delayed until 08:00. Of course, if the door closes between 16:00 and 08:00, no call to the alert rule will occur.
It’s really pretty straight forward. I was overly explicit in the steps above so it looks like a lot more work than it really is.