Action on DateTime item age

All -

I’m running the latest OH2. I have two leak sensors that do not provide battery info, but do send a heartbeat 1x/24 hours. So, I’m trying to write a rule that will check this heart beat and if older than 24 hours, warn me that the battery is likely dead.

So I’ve attempted to do this:

  • I have this rule connected to a switch so I can trigger it for testing. I’ll eventually move it to something that automatically gets triggered:

  • This item has a “last heard from” DateTime item that gets updated with the 1x/24 hour heartbeat

  • My method is to take that date time item, add 24 hours to it, and compare that to the current time. If now isAfter the sensor’s last-heard-from-time + 24 hours, then I send a message.

    rule "leak sensor HB check"
    
      when
              Item checkLeak changed to ON
      then
              //Checks for leak sensor heartbeats once per day
    
              val basementLeakLHFExpire = new DateTime((basementLeakLHF.state as DateTimeType).plusHours(24).millis)
    
              if (now.isAfter(basementLeakLHFExpire)){
                      pushover("The Basement Leak Sensor's heartbeat hasn't been detected for >24 hours, please check the battery")
                      logInfo("Basement Leak Sensor","!!!!!!!!!!!!!!!!!!! LHF Check timed out")
                      postUpdate(basementLeakLowBat,"Check")
              } else {
                      logInfo("Basement Leak Sensor","!!!!!!!!!!!!!!!!!!! Heartbeak OK")
                      postUpdate(basementLeakLowBat,"OK")
              }
    
              val hwtankLeakLHFExpire = new DateTime((hwtankLeakLHF.state as DateTimeType).plusHours(24).millis)
    
              if (now.isAfter(hwtankLeakLHFExpire)){
                      pushover("The Hot Water Tank Leak Sensor's heartbeat hasn't been detected for >24 hours, please check the battery"
                      logInfo("HWTANK Leak Sensor","!!!!!!!!!!!!!!!!!!! LHF Check timed out")
                      postUpdate(hwtankLeakLowBat,"Check")
              } else {
                      logInfo("HWTANK Leak Sensor","!!!!!!!!!!!!!!!!!!! Heartbeak OK")
                      postUpdate(hwtankLeakLowBat,"OK")
              }
    
    
      end
    

I am getting the following error:

==> /var/log/openhab2/openhab.log <==

2018-03-13 08:27:52.616 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'leak sensor HB check': 'plusHours' is not a member of 'org.eclipse.smarthome.core.library.types.DateTimeType'; line 1230, column 44, length 53

Now - I have multiple other uses of “plusHours” in other rules, so I don’t think I’m missing some kind of import or something like that. I’m guessing I’m not defining something correctly. Can anyone shed some light on what I’m doing wrong?

Try replacing the plusHours with plusSeconds(86400)

Sorry my bad…
I think the type for plusHours need to be calendar so do:

val basementLeakLHFExpire = new DateTime((basementLeakLHF.state as DateTimeType).calendar.plusHours(24).millis)

You can use one of this.

var DateTime basementLeakLHFExpire = new DateTime((basementLeakLHF.state as DateTimeType).calendar).plusHours(24)
var DateTime basementLeakLHFExpire = new DateTime((basementLeakLHF.state as DateTimeType).calendar.timeInMillis).plusHours(24)
val DateTime basementLeakLHFExpire = new DateTime((basementLeakLHF.state as DateTimeType).getZonedDateTime.toInstant.toEpochMilli).plusHours(24)

The method getCalendar() from the type DateTimeType is deprecated
but i don’t know if

getZonedDateTime.toInstant.toEpochMilli

works before 2.3

pushover("The Hot Water Tank Leak Sensor's heartbeat hasn't been detected for >24 hours, please check the battery"

) is absend
in place of

Item checkLeak changed to ON

you can use cron

.calendar was deprecated with 2.2 already, please use only the latter - works with 2.2.

It would be much much simpler to just use the Expire binding (Design Pattern: Expire Binding Based Timers).

Switch Heartbeat { expire="24h,command=OFF" }
rule "Heartbeat received"
when
    Item HeartBeatSource received update
then
    HeartBeat.sendCommand(ON)
end

rule "Heartbeat timer expired"
when
    Item Heartbeat received command OFF
then
    // code to alert that the device has been offline for too long
end

Depending on how you receive the heartbeat, you could potentially avoid needing to add the new Heartbeat Item and just add the expire to your existing heartbeat.

I use this approach for many of my sensors, though they are mostly MQTT so I don’t need a separate timer Item for the Expire binding.

1 Like

I also use this approach for my sensors - regardless of their binding - MQTT (including LWT) or others…

It’s a little more complex with some other bindings. I wrote that up here: (Design Patterns: Generic Is Alive). Though I need to revisit that DP to take advantage of new stuff like triggeringItem.

Awesome - thanks for all of the help guys! I use the expire binding for other things and never thought about this use case.