Send an email that lists the time an item state has changed every 2 hours

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:

  1. the persistence strategy is such that everyChange is used
  2. the timing is OK (i.e. the door state doesn’t change exactly when the rule runs); lastChange returns null 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.

  1. Make sure you have JS Scripting installed
  2. 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.
  3. Navigate to Add-on Store → Automation → Rule Templates → Threshold Alert and Open Reminder and add the rule tempalte
  4. Add the Door Item to a Group (we’ll call if AllDoors)
  5. 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
  1. Navigate to Settigns → Rules → +
  2. Enter the rule metadata (name, ID, etc)
  3. Select Threshold Alert under “Templates”
  4. 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.

1 Like