historicState with RRD4j in OH3 returns null

I’ve just noticed that my historicstate always return ‘null’ instead of the value after the upgrade to OH3. Default is the persistence set to RRD4J. I tried also to change the rrd4j to influxdb and mapdb. But these gave me other errors. fe:

rule:

rule "Test"
when
        Item TestKnop1 changed
then
        var Light111 = Light_AT_BureauStock.historicState(now.minusSeconds(1), "rrd4j")
        logInfo("TTEST", "Test Result: " + Light111 )
end

rrd4j:

2021-01-24 12:34:35.087 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'TestKnop1' changed from ON to OFF
2021-01-24 12:34:35.090 [INFO ] [org.openhab.core.model.script.TTEST ] - Test Result: null

2021-01-24 12:34:40.640 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Light_AT_BureauStock' changed from OFF to ON

2021-01-24 12:34:46.003 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'TestKnop1' changed from OFF to ON
2021-01-24 12:34:46.007 [INFO ] [org.openhab.core.model.script.TTEST ] - Test Result: null

2021-01-24 12:34:50.078 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Light_AT_BureauStock' changed from ON to OFF

2021-01-24 12:34:53.528 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'TestKnop1' changed from ON to OFF
2021-01-24 12:34:53.531 [INFO ] [org.openhab.core.model.script.TTEST ] - Test Result: null

mapdb:

2021-01-24 12:39:26.513 [INFO ] [org.openhab.core.model.script.TTEST ] - Test Result: Jan 24, 2021, 12:34:50 PM: Light_AT_BureauStock -> OFF

influxdb:

2021-01-24 12:40:09.858 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'test-1' failed: Cannot format given Object as a Date in test




ps I noticed some other topics that touched simular issues, but not completely the same, therefor a new topic. :blush:

What are you actually expecting to see here?
By default, rrd4j will be recording every minute. 99 times you run this, there won’t be any -1s record at all.
Really, historicState() should then search backwards to next youngest record, on the assumption that that state continued, but that might not be working when you’re on the most recent record.

More importantly, historicState() returns an object, an historic state object to be precise, see docs.

Try

logInfo("TTEST", "Test Result: " + Light111.state.toString )
logInfo("TTEST", "Test Result: " + Light111.getTimestamp.toString )

I want to check the status of the light, right before the switch push.

And you’re right. When I put 65 seconds, I’m getting proper results.
Of course not ideal if somebody pushes the switch several times in 1 minute. That’s the reason why I want to check it right in front of the push.

It also seems that ‘tostring’ gives the best result to check the state with rrd4j.

2021-01-24 13:47:12.615 [INFO ] [org.openhab.core.model.script.TTEST ] - Test Result1: 1/24/21, 1:46 PM: Light_AT_BureauStock -> OFF
2021-01-24 13:47:12.615 [INFO ] [org.openhab.core.model.script.TTEST ] - Test Result2: OFF
2021-01-24 13:47:12.616 [INFO ] [org.openhab.core.model.script.TTEST ] - Test Result3: 2021-01-24T13:46:07+01:00[Europe/Brussels]

Have you seen previousState implicit variable?
Not applicable in every use case, but would serve the purpose in the example rule given.

Yes, but isn’t this just ON/OFF in my case (=switch)?
The opposite from the ‘now state’?

ye-es, unless it was NULL or UNDEF by chance.

So what’s the rule for? If it triggers on change, and state can only be ON/OFF, then it’s (almost!) certain that the state a second ago was the opposite?

If the switch (KNX) is pushed, it triggers a lights (KNX GA).
Openhab isn’t aware about the GA status, only of the light address.
I want to trigger something through openHAB, but I need to know if somebody enters (light ON) or leaves (light OFF).

Another solution would maybe be to build in a delay, and check then the status?
fe

 Thread::sleep(100)
 if ( Light_AT_BureauStock.state == ON ) {
   logInfo("TEST", "Test Result: ")
   }

I don’t want to make the Thread to big, so I won’t have bid delays.

ps I’m just afraid that openHAB is faster then the status of the KNX light. :blush:

Ah yes, I was overlooking toggle switch.

A few hundred mS sleep should be no problem, you’ll not be running the rule that often as it’s triggered by manual action.
If in doubt, make it a timer instead.

EDIT - I had a play (in OH2.5) and confirm that historicState() has a null return if it’s looking in the “gap” between most recent record and ‘now’.
i.e. -1 sec nearly always fails, -65 sec always works, -30sec might or might not with an everyMinute strategy.
I think this is a minor bug, and it should return next-youngest record always.

1 Like

A lot of these persistence calls in rrd4j behave unexpectedly, due to the nature of rrd4j. For example, if you call previousState, you will never get a timestamp on the HistoricItem greater than one minute ago. That’s because it goes to the most recent entry in the database and returns that entry’s timestamp. Assuming you have the persistence set to save on everyChange in addition to everyUpdate, previousState(true) will similarly work by giving you the first entry that is different from the Item’s current state, which will be at most one minute away from when the Item changed to it’s current state.

This isn’t limited to rrd4j. It applies when ever any periodic strategy is used. It’s just that rrd4j requires a periodic strategy.

One way to work around this limitation would be to not use a persistence based approach. I would create a DateTime Light111_Lastupdate Item linked to the same Channel as Light111 but using the Timestamp Profile. So any time Light111 changes Light111_Lastupdate will be set with a timestamp. Then in your rule you just need to

if((Light111_Lastupdate.state as DateTimeType).getZonedDateTime.isBefore(now.minusSeconds(1)))
1 Like