Calculate time between two rules firing (time door is open)


Simple question, however I haven’t found a definite (working) answer yet after searching on the community.
I have a door sensor, which posts updates (1 = closed, 0 = open) to a Number item Voordeur. I want to know the time that passed between the door opening (event 1) and the door closing (event 2).

Attached is the attempt that I made. Unfortunately, when testing, the rules do not fire. When commenting out the doorOpen and timeDoorOpen lines, the rules do fire.

Can you help me?

Thanks, Michiel.

import org.openhab.core.library.types.*
import org.openhab.core.persistence.*
import org.openhab.model.script.actions.*

var DateTime doorOpen = null

rule "Door open"
	Item Voordeur changed from 1 to 0
	logInfo("Voordeur OPEN: ", Voordeur.state.toString())

	doorOpen = now
	sendHttpGetRequest("" + Voordeur.state)

rule "Door closed"
	Item Voordeur changed from 0 to 1
	var DateTime timeDoorOpen = now.millis - doorOpen.millis
	doorOpen = null

	logInfo("Voordeur state DICHT, millis open: ", timeDoorOpen)

	sendHttpGetRequest("" + timeDoorOpen)

It is much easier to read code when you use the forum’s code formatting. There are several ways but the easiest is to put three backticks before and after the code.

code goes here

What do you see in your logs?

Some thoughts after a quick scan.

If you are on OH 1.8.x you need to import org.joda.time.* in order to use the DateTime class.

Hi Rich,

Thanks for your response. I have editted the post. Thanks.
I’m actually not sure which version I’m using. I think 1.7.1. How can I check easily?

Do I need to import the time package as well for that version?
Does the code seem to be correct?

Logs do not show strange things, just the state change of the Number item.

Thanks again,


If you are running 1.7.1 I recommend upgrading to 1.8.3. You can tell by looking at the names of the jar files in the addons folder or by looking at the first few lines of the openhab.log file when it starts.

Yes, you do need to import the org.joda.time.* for all versions of OH 1.

The code otherwise looks correct.

In the events.log file do you see Voordeur actually changing from 1 to 0 and from 0 to 1 or does it have some state in between? If there is some other state in there you may need to relax your triggers to

Item Voordeur changed to 0

Item Voordeur changed to 1

That will disregard whatever state it was before, which I think would still be correct in this case.

I’m frankly grasping at straws.

Hi Rich,

Strange… I did import org.joda.time.* and relaxed the rule a bit, however no results :frowning:
I added some logInfo calls, which are not showing. It looks like the rules are ignored altogether. While, when removing the doorOpen / timeDoorOpen code, they ARE fired.

The logfile does not show a thing, except the runtime busevents related to the change of the door:

Voordeur state updated to 0
Voordeur state updated to 1

Upgrading is indeed a good idea (I confirmed that I’m on 1.7.1), however I would not expect this problem to be caused by an old version of openHAB.

Is there any (simple) way, by which I can get more info on why the rules are not firing? Increase loglevels or something? Or is there another way to accomplish the same goal?

Thanks again for helping me.


DOH! While writing below I found at least one major error.

var DateTime timeDooropen = now.millis - doorOpen.millis

This makes no sense. millis is a long, not a DateTime and while the Rules DSL does a bunch of stuff for you, it can’t convert a long to a DateTime. You must create a DateTime (i.e. new DateTime(now.millis - doorOpen.millis)) but that doesn’t really make sense because that will likely give you a DateTime sometime around 00:05 1970 January 1, not “five minutes” which is what you really want.

You need to convert the millis to minutes yourself:

val timeOpenMillis = now.millis - doorOpen.millis
val timeOpenMin = timeOpenMillis / 1000 / 60

I also notice that I don’t think you understand how logInfo works. logInfo and all the other log actions take two Strings, the first is the name of the logger (this appears in the brackets of the log statements). The second String is your actual log statement.

For example, a logInfo("nest", "Setting Nest to " + Presence.state.toString) when Presence is set to “AWAY” would appear in the logs as:

2016-07-08 10:18:07.070 [INFO ] [org.openhab.model.script.nest ] - Setting Nest to AWAY

There is a limit to the number of characters that gets printed in the brackets so your log statements above will be truncated which I’m sure is not what you want.

My original ideas below.

Things to try:

  • Upgrade to the latest. There probably isn’t something but knowing you are on the newest eliminates hundreds of bugs which may or may not be relevant.

  • Just create a rule with a logInfo in it that fires on any update to Voordeur

rule "Voordeur updated"
    Item Voordeur received update
    logInfo("Voordeur", "Received update " + Voordeur.state.toString)

If that fires gradually build up from there and experiment.

  • Use Designer and see if it is highlighting any syntax errors

  • Use persistence to calculate the open time:

Configure Voordeur to save everyChange in your .persist file.

rule "Door changed"
    Item Voordeur changed
    if(Voordeur.state == 0){
        logInfo("Voordeur OPEN: ", Voordeur.state.toString)
    else {
        val lastOpen = Voordeur.previousState(true).timestamp.time
        val totalTime = now.millis - lastOpen
        val totalTimeMin = totalTime / 1000 / 60
        logInfo("Voordeur", "Voordeur state DICHT, minutes open: ' + totalTimeMins)
        sendHttpGetRequest("https://api..." + totalTimeMin)

Hi Rich,

Thanks for your reply. Sorry for not responding earlier (busy busy busy).
I tried the proposed changes without upgrading (sorry for that), and it still didn’t work. I did not yet check the structural approach that you suggested (gradually building up the rules). Will do so at a later stage, but time pressure from other things hinders me at this moment.

The suggestion on logInfo did work. Thanks for that, I misunderstood the syntax.

Regarding upgrading, how difficult/easy is that? Is there a good place for me to visit to see what steps to need to be taken?

Regards, Michiel.

If you are on a debian based linux (e.g. raspbian, ubuntu) you should reinstall using apt-get.

NOTE: this will put things in different locations from what you may be used to. The big important locations are:

  • /etc/openhab - configurations
  • /usr/share/openhab - binaries, addons, and webapps folder
  • /var/log/openhab - log files
  • /var/lib/openhab - persistence, zwave files, openhab user’s home directory

The advantages will be from this point upgrading the software will just be an apt-get upgrade command away. Also, it configures openHAB to run as a service under a non-privileged user and sets up all the file permissions appropriately for you.

If you are not on a debian based linux, just make a make a backup of your openHAB installation directory, install the newest version using the appropriate instructions, and copy your <openhab home>/configurations and <openhab home>/addons folders from the backup to the new version.

Hi Rich,

this rule make this error:

16:10:58.510 [ERROR] [o.o.c.s.ScriptExecutionThread :50 ] - Error during the execution of rule ‘Wie lange war das Fenster offen’: rrd4j does not allow querys without a begin date, unless order is descending and a single value is requested

My persist file:

Items {
        // persist all items once a day and on every change and restore them from the db at startup
        * : strategy = everyChange, everyDay, restoreOnStartup

What can i do? I use openHab 1.8.3.

rrd4j has a hard time when you do not store a value at heart every minute. Try an every minute strategy and see if that makes the error go away. If not, search around the forum. I think I remember some posts about a similar problem a few months ago but don’t remember the resolution. It may have been a bug.

ok, i add

azFensterKontakt: strategy = everyMinute

an the same error :frowning:

I search …

Would this be possible to do it in one line as well? like

val timeOpenMin = (now.millis - doorOpen.millis) / 1000 / 60

Yes. That would work.