previousState and persistence

801 views
Skip to first unread message

Michael Pophal

unread,
Jun 16, 2015, 1:36:16 PM6/16/15
to ope...@googlegroups.com
Hi,
I've two persistence services running:
* influxdb for graphing, which is defined as default persistence service in my openhab.cfg.
* mapdb for restoreOnStartup and as previousState store
I need the previousState of some Items in a rule. But this items are persisted via mapdb. How can I retrieve this perviousState?

A test rule like:

rule "Testrule"
when
    Item webserver changed
then
    var tt = webserver.previousState
    logInfo("test", "webserver: "+webserver.state+ " previous:"+tt)
end

returns this messages in openhab.log
2015-06-16 19:28:21.243 [ERROR] [i.i.InfluxDBPersistenceService] - query failed with database error
2015-06-16 19:28:21.244 [ERROR] [i.i.InfluxDBPersistenceService] - database error: Couldn't find series: webserver
2015-06-16 19:28:21.823 [INFO ] [org.openhab.model.script.test ] - webserver: OFF previous:null

which means, that the previousState wants to be fetched from influxdb. How must my variable tt have to look like, to get the state from mapdb?

Greetings,
Michael

Rich Koshak

unread,
Jun 17, 2015, 11:37:43 AM6/17/15
to ope...@googlegroups.com
It can be done according to the wiki page but the short paragraph is a bit vague. By default it will fetch the previous state from the default database. You need to tell it to get the data from the other database explicitly by passing the name of the database in the call. Based on the help from openHAB-designer I think this is what the call should be.

var tt = webserver.previousState(false, "mapdb")

The false indicates that the previous state should be returned even if it hasn't changed and this maps to the behavior of just calling previousState. The true will return the previous state that is different from the current state.

Perhaps an example like this should be added to the wiki.

Rich

Michael Pophal

unread,
Jun 17, 2015, 3:06:37 PM6/17/15
to ope...@googlegroups.com
Hi Rich,
thanks a lot for your assistance!
I used your suggested code in my simple testrule


rule "Testrule"
when
        Item webserver changed
then
    var test = webserver.previousState(false, "mapdb")
    logInfo("test", "previousState:" + test + " State: " + webserver.state)   
end

But unfortunately the result is not the expected:
2015-06-17 21:00:40.495 [INFO ] [org.openhab.model.script.test ] - previousState:17.06.2015 21:00:40: webserver -> ON State: ON
2015-06-17 21:00:43.157 [INFO ] [org.openhab.model.script.test ] - previousState:17.06.2015 21:00:43: webserver -> OFF State: OFF

Everytime, when I switch the item, the previousState is the same as the current state :-(
Do you know, what's going wrong?

Kind regards,
Michael

Rich Koshak

unread,
Jun 17, 2015, 4:03:26 PM6/17/15
to ope...@googlegroups.com
I've not played with multiple DBs before so I'm making educated guesses here. Based on the limited documentation, I'm guessing that previousState just retrieves the most recent value saved to the DB before the item was set to its current state. If your persistence strategy is set to something fast like every second you might be seeing the current state being saved more than once before you get to your rule. Your strategy might be such that each change gets saved multiple times. previousState returns a HistoricState object which has a timestamp value you can check to see when the value was saved to the DB. That might give you some insight into what is going on. Note that it is a Date object, not a Joda DateTime object so the methods will be a little different.

item.previousState(false, "mapdb").timestamp

However, it isn't clear what you are trying to accomplish but in your example above it seems like you would want to use previousState(true, "mapdb") so instead of retrieving the most recent saved value it looks for the most recent saved value that is different from the current state.

Frankly I have no idea whether either of these persistence quirks are possible or what is really happening under the covers. I'm only inferring how it works. My only direct experience is with rrd4j and using previousState(true) as I really only care about when the state changed in my rules and don't care about what the previous state actually was. I can usually infer what the previous state was based on the current state (Switches and Contacts only have two possible states, three if you count Undefined) anyway.

Rich

herr...@gmail.com

unread,
Jun 18, 2015, 3:25:10 AM6/18/15
to ope...@googlegroups.com
Hello all,

as far as I know Openhab, I think that what's going on is that your persistence strategy is to store every change. So whenever the state of your item 'webserver' changes, that is stored. Then your rules are executed and it retrieves the last state from your persistence store (as Rich indicated).
Rich also hinted me in the right direction to give a possible answer (with the timestamp). You actually want to know the value of the penultimate value stored in your persistence store.

So here's what I think you can do:
- retrieve the last store item/value (via previousState - which in your case actually is the currentState)
- and via historicState (and a timestamp) retrieve the state that precedes this previousState (aka 'currentState' in your case).

You should get something like this:

var test = webserver.historicState(webserver.previousState(false, "mapdb").timestamp, "mapdb")

Let us know if it works.

 Erwin

Michael Pophal

unread,
Jun 18, 2015, 10:35:45 AM6/18/15
to ope...@googlegroups.com
Hi Erwin, hi Rich,

thanks for your efforts helping me. Your thoughts are very clever but unfortunately they didn't change the result. But first of all I have to let you know, that I'm no programmer. I'm just copying code snippets from everywhere to create my rules, therefore I fear I'm no adequate sparring partner in discussing such issues.
The result of Erwins suggestion resulted in error messages like

2015-06-18 16:10:05.336 [ERROR] [o.o.c.s.ScriptExecutionThread ] - Error during the execution of rule 'Testrule': Could not invoke method: org.openhab.core.persistence.extensions.PersistenceExtensions.historicState(org.openhab.core.items.Item,org.joda.time.base.AbstractInstant,java.lang.String) on instance: null
2015-06-18 16:10:05.342 [INFO ] [org.openhab.model.script.test ] - previousState:18.06.2015 16:10:05: webserver -> ON State: ON

I tried this procedure also on an influxdb persisted item, with the same result. I need to explain, that mapdb persisted items just store the very last items status. Normally it's used for restoreOnStartup method. Therefore I fear, that there is no historicState method available. What I wanted to have, is the very last status of an item. Not the current state, but the previous state. But it seems, that
webserver.previousState(false, "mapdb") and
webserver.state
have the same result, which makes me wonder for the sense of previousState.
It seems there is always the current state stored before the rules are called (as you already mentioned), so that never the previousState will result. Furthermore the state before the previousState should be the previousState, which would make sense for me.

Well, I will find a workaround in my rule, so that I appreciate your effort, but don't want to waste your time.
Maybe it's worth to update the wiki if someone finds the correct meaning and usage of previousState method.

Thanks a lot and greetings from Germany,
Michael

Rich Koshak

unread,
Jun 18, 2015, 12:38:45 PM6/18/15
to ope...@googlegroups.com
Ah, now the pieces are becoming clear. If your persistence strategy is to only save only the item's most recent status to support reload on startup it explains everything. As soon as the state changes it gets saved to the DB and wipes out the old state so previousState will always return the current state no matter what. This is the only way to guarantee that the current value gets restored on a restart as opposed to the value before the current one.

To get the behavior you really want you need to save every change, not just the most recent change. If you are worried about the DB getting too large, you can use rrd4j which is a fixed size DB that doesn't grow. Instead it thins out old data (e.g. you may have every minute for a week but it drops to every hour , then every day as the data gets older and older. It is what I use and I go ahead and save every change to everything and save every minute those things I want to chart.

I think what you are seeing is a rare edge case. I suspect that most people save more than just the most recent value for their items and in those cases previousState works as you would expect. In your case, since you are saving only the current value it is defaulting to return that one value rather than generate an error which is making previousState perform in an unexpected manner.

Good luck!

Rich

Michael Pophal

unread,
Jun 18, 2015, 3:53:20 PM6/18/15
to ope...@googlegroups.com
Just to clarify a maybe missunderstanding. I also tried to get the previousState from a influxdb persisted item, which ist stored on every change and on every minute. This DB growths endless and it definitly has a previousState stored. But I didn't get the previousstate either. The behaviour between mapdb (which stores just one state) and influxdb (which stores endlessly states) is absolute identical. That's why I'm wondering about the sense of previousState.
BTW, I know about rrd4j and decided to use influxdb. For some analytic reasons, I need uncompessed data.

Rich Koshak

unread,
Jun 18, 2015, 6:31:09 PM6/18/15
to ope...@googlegroups.com
I did some quick looking in the source code but not enough to answer the question. I need to set up a dev environment because I have a few other burning questions I want answered that I should be able to find in the code.

Have you tried to run is on influx which is saving all the states using true? I.e.

var tt = webserver.previousState(true, "influx")

If this still produces the same problem, it might be worthwhile posting to the influx and/or mapdb parts of the forum and see if the experts can figure out what is going on. I know from my experience with previousState(true) that it will return the previousState that was actually different, which I think is what you are going after anyway.

Rich

Michael Pophal

unread,
Jun 19, 2015, 11:11:53 AM6/19/15
to ope...@googlegroups.com
Here are the results for
var tt = Gaeste.previousState(true, "influx")

2015-06-19 16:53:26.672 [INFO ] [org.openhab.model.script.test ] - previousState:19.06.2015 00:00:00: Gaeste -> ON State: OFF
2015-06-19 16:53:33.954 [INFO ] [org.openhab.model.script.test ] - previousState:19.06.2015 16:53:25: Gaeste -> OFF State: ON
2015-06-19 16:54:25.027 [INFO ] [org.openhab.model.script.test ] - previousState:19.06.2015 16:53:33: Gaeste -> ON State: OFF

After that I changed the rule back to
var tt = Gaeste.previousState(false, "influx")

The results are quite confusing for me:
2015-06-19 16:55:10.642 [INFO ] [org.openhab.model.script.test ] - previousState:19.06.2015 16:55:10: Gaeste -> ON State: ON
2015-06-19 16:55:13.778 [INFO ] [org.openhab.model.script.test ] - previousState:19.06.2015 16:55:10: Gaeste -> ON State: OFF
2015-06-19 16:55:20.222 [INFO ] [org.openhab.model.script.test ] - previousState:19.06.2015 16:55:20: Gaeste -> ON State: ON
2015-06-19 16:55:26.208 [INFO ] [org.openhab.model.script.test ] - previousState:19.06.2015 16:55:26: Gaeste -> OFF State: OFF
2015-06-19 16:55:32.634 [INFO ] [org.openhab.model.script.test ] - previousState:19.06.2015 16:55:32: Gaeste -> ON State: ON
2015-06-19 16:55:43.767 [INFO ] [org.openhab.model.script.test ] - previousState:19.06.2015 16:55:43: Gaeste -> OFF State: OFF

I would have expected everytime the same state for previousState and currentState. But the second logline thows different values. Hmmm, no idea, what this means.
I'm also not quite sure, if I now understand the meaning for "true" and "false". "true" means, the last different value is fetched. The only sense could be to have the timestamp of this event, otherwise I can quite sure predict the last different value ;-)
"false" means that the very last value is fetched, which means it is the curentState. The only explanation for the second line phenomenon could be, that I was to fast for the persistence service, as the events seems to be happend in the same second.
While writing this lines I did some additional tests, to verify my thoughts. Even with a few seconds in between, I could reproduce this behaviour:
2015-06-19 17:04:52.774 [INFO ] [org.openhab.model.script.test ] - previousState:19.06.2015 17:04:52: Gaeste -> ON State: ON
2015-06-19 17:04:55.240 [INFO ] [org.openhab.model.script.test ] - previousState:19.06.2015 17:04:55: Gaeste -> OFF State: OFF
2015-06-19 17:04:56.619 [INFO ] [org.openhab.model.script.test ] - previousState:19.06.2015 17:04:55: Gaeste -> OFF State: ON
2015-06-19 17:04:57.241 [INFO ] [org.openhab.model.script.test ] - previousState:19.06.2015 17:04:57: Gaeste -> OFF State: OFF
2015-06-19 17:05:00.524 [INFO ] [org.openhab.model.script.test ] - previousState:19.06.2015 17:04:57: Gaeste -> OFF State: ON
2015-06-19 17:05:01.393 [INFO ] [org.openhab.model.script.test ] - previousState:19.06.2015 17:05:00: Gaeste -> ON State: OFF
2015-06-19 17:05:02.100 [INFO ] [org.openhab.model.script.test ] - previousState:19.06.2015 17:05:01: Gaeste -> OFF State: ON
2015-06-19 17:05:04.152 [INFO ] [org.openhab.model.script.test ] - previousState:19.06.2015 17:05:02: Gaeste -> ON State: OFF
2015-06-19 17:05:04.978 [INFO ] [org.openhab.model.script.test ] - previousState:19.06.2015 17:05:04: Gaeste -> OFF State: ON
2015-06-19 17:05:07.754 [INFO ] [org.openhab.model.script.test ] - previousState:19.06.2015 17:05:04: Gaeste -> ON State: OFF
2015-06-19 17:05:09.255 [INFO ] [org.openhab.model.script.test ] - previousState:19.06.2015 17:05:07: Gaeste -> OFF State: ON
2015-06-19 17:05:10.634 [INFO ] [org.openhab.model.script.test ] - previousState:19.06.2015 17:05:09: Gaeste -> ON State: OFF
2015-06-19 17:05:12.033 [INFO ] [org.openhab.model.script.test ] - previousState:19.06.2015 17:05:10: Gaeste -> OFF State: ON
2015-06-19 17:05:13.430 [INFO ] [org.openhab.model.script.test ] - previousState:19.06.2015 17:05:11: Gaeste -> ON State: OFF
2015-06-19 17:05:17.284 [INFO ] [org.openhab.model.script.test ] - previousState:19.06.2015 17:05:13: Gaeste -> OFF State: ON
2015-06-19 17:05:18.663 [INFO ] [org.openhab.model.script.test ] - previousState:19.06.2015 17:05:18: Gaeste -> OFF State: OFF
2015-06-19 17:05:20.289 [INFO ] [org.openhab.model.script.test ] - previousState:19.06.2015 17:05:20: Gaeste -> ON State: ON
2015-06-19 17:05:21.769 [INFO ] [org.openhab.model.script.test ] - previousState:19.06.2015 17:05:20: Gaeste -> ON State: OFF
2015-06-19 17:05:23.614 [INFO ] [org.openhab.model.script.test ] - previousState:19.06.2015 17:05:21: Gaeste -> OFF State: ON
2015-06-19 17:05:25.299 [INFO ] [org.openhab.model.script.test ] - previousState:19.06.2015 17:05:23: Gaeste -> ON State: OFF

Look at orange line: 2 seconds in between and the states are different.
Look at red line: also 2 seconds in between and the states are equal.
I really don't understand this behaviour. Maybe you can find some hints in the code. Maybe there is a bug, in every case, the documentation should be adapted to explain this behaviour.

Good luck
Michael
Reply all
Reply to author
Forward
0 new messages