Rrd4j only stores one datapoint

Hey Togetrher,

I tried to solve this by searching the community for one day now but didnt made it.
I want to store a Number value in rrd4j to get the previous state in my rules.

My rrd4j.persist

Strategies {
    everyMinute : "0 * * * * ?"
}

Items {
   Media_Aktion: strategy = everyChange, everyMinute
}

My Item:

Number Media_Aktion

My Rule:

rule "Medienauswahl"
when Item Media_Aktion received command
then switch Media_Aktion.state {
	case 1: {//gVm.allMembers.forEach [ item | item.sendCommand(OFF)]
			logInfo("TEST ", "Mediaaktionprev "+Media_Aktion.previousState(false,"rrd4j").state)
			logInfo("TEST ", "Mediaaktion "+Media_Aktion.state)
			}
	case 2: {//Fernsehen.sendCommand(ON)
			//Musik.postUpdate(OFF)
			//Dvd.postUpdate(OFF)
			logInfo("TEST ", "Mediaaktionprev "+Media_Aktion.previousState(false,"rrd4j").state)
			logInfo("TEST ", "Mediaaktion "+Media_Aktion.state)
            }
	case 3: {//Musik.sendCommand(ON)
			//Fernsehen.postUpdate(OFF)
			//Dvd.postUpdate(OFF)
			logInfo("TEST ", "Mediaaktionprev "+Media_Aktion.previousState(false,"rrd4j").state)
			logInfo("TEST ", "Mediaaktion "+Media_Aktion.state)
            }
	case 4: {//Dvd.sendCommand(ON)
			//Musik.postUpdate(OFF)
			//Fernsehen.postUpdate(OFF)
			logInfo("TEST ", "Mediaaktionprev "+Media_Aktion.previousState(false,"rrd4j").state)
			logInfo("TEST ", "Mediaaktion "+Media_Aktion.state)
            }
}
end

all the commands are // cause of testing.

The Value is set through an Selection in my Sitemap:

Selection item=Media_Aktion
 mappings=[1="Aus", 2="Fernsehen", 3="Musik", 4="DVD"]

When I get the presistence values through RestApi:

{
  "name": "Media_Aktion",
  "datapoints": "1",
  "data": [
    {
      "time": 1572604184212,
      "state": "2"
    }
  ]
}

there is only one Datapoint…I already deleted everything regarding to rrd4j and reinstalled it but dosn´t change everything.
Here the Log:

2019-11-01 11:29:36.732 [DEBUG] [sistence.rrd4j.internal.RRD4jService] - Stored 'Media_Aktion' with state '1' in rrd4j database

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

2019-11-01 11:29:36.737 [vent.ItemStateChangedEvent] - Media_Aktion changed from 3 to 1

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

2019-11-01 11:29:40.776 [INFO ] [eclipse.smarthome.model.script.TEST ] - Mediaaktionprev 1.0

2019-11-01 11:29:40.782 [INFO ] [eclipse.smarthome.model.script.TEST ] - Mediaaktion 1

The Value is also stored every minute, so this is working but only one Datapoint…
As you can see, the .state and .previousstate is the same,

I also tried it with my SQL and MapDb by the way with the same config…same result…
Here the Log from MapDB:

2019-11-01 11:49:41.725 [ome.event.ItemCommandEvent] - Item 'Media_Aktion' received command 3

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

2019-11-01 11:49:41.746 [DEBUG] [pdb.internal.MapDBPersistenceService] - store called for Media_Aktion

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

2019-11-01 11:49:41.756 [vent.ItemStateChangedEvent] - Media_Aktion changed from 1 to 3

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

2019-11-01 11:49:41.766 [DEBUG] [pdb.internal.MapDBPersistenceService] - Stored 'Media_Aktion' with state '3' in mapdb database

2019-11-01 11:49:41.773 [INFO ] [eclipse.smarthome.model.script.TEST ] - Mediaaktionprev 3

2019-11-01 11:49:41.784 [DEBUG] [pdb.internal.MapDBPersistenceService] - store called for Media_Aktion

2019-11-01 11:49:41.791 [INFO ] [eclipse.smarthome.model.script.TEST ] - Mediaaktion 3

2019-11-01 11:49:41.792 [DEBUG] [pdb.internal.MapDBPersistenceService] - Stored 'Media_Aktion' with state '3' in mapdb database


Anybody any Idea, i want to prevent setting u a new setup cause of some stupid error i made.
As mentioned, always only one datapoint is created :frowning:

Greetings and many thanks in advantage
Andy

MapDBPersistenceService
MapDB only stores 1 data
You need to specify what DB you want to use or chage your default DB

Hey Vincent,
thanks for the superfast answer.
I have MapDB as Default DB.
In my rules i specified rrd4j when I tried to use it (see Code in my previous post) and left empty when I tried to use it with MapDB (see Code below).
But I Always get the same value for state and .previousstate

for Mapdb as Default DB it Looks like:

logInfo("TEST ", "Mediaaktionprev "+Media_Aktion.previousState(false).state

hope this is what you ment?
Unfortunately it is not working.

greetings
Andy

Let me take as guess:
When you tried to get data out of the rrd4j database it was not running for more then a couple of minutes (less then 4).
You did not specify the timeframe of the REST-call, hence a 24 houre request was generated., which would show only one value for very four minutes (caused by the default setup). A REST-call for less then 8 houses would yield in values for every minute.

A REST-call on mapDB will always show a single valuebecause this db stores one value only ( as stated by @vzorglub).

Hi Jürgen,
the Setup was running over night but no datapoints visible in REST API.
The single value from MapDB is ok for me, but I Need the previus not te actual, shouldnt be this possible? In my case its Always the same.

thanks for your efforts
greetings
Andy

Then use the implicit variable previousState instead of the persistence method
Your rule trigger with the one item so there shouldn’t be ant confusion

See: https://www.openhab.org/docs/configuration/rules-dsl.html#implicit-variables-inside-the-execution-block

still the same:
mapdb.persist:

Media_Aktion : strategy = everyChange

rule:

rule "Medienauswahl"
when Item Media_Aktion received command
then switch Media_Aktion.state {
	case 1: {//gVm.allMembers.forEach [ item | item.sendCommand(OFF)]
			logInfo("TEST ", "Mediaaktionprev "+Media_Aktion.previousState.state)
			logInfo("TEST ", "Mediaaktion "+Media_Aktion.state)
			}
	case 2: {//Fernsehen.sendCommand(ON)
			//Musik.postUpdate(OFF)
			//Dvd.postUpdate(OFF)
			logInfo("TEST ", "Mediaaktionprev "+Media_Aktion.previousState.state)
			logInfo("TEST ", "Mediaaktion "+Media_Aktion.state)
            }
	case 3: {//Musik.sendCommand(ON)
			//Fernsehen.postUpdate(OFF)
			//Dvd.postUpdate(OFF)
			logInfo("TEST ", "Mediaaktionprev "+Media_Aktion.previousState.state)
			logInfo("TEST ", "Mediaaktion "+Media_Aktion.state)
            }
	case 4: {//Dvd.sendCommand(ON)
			//Musik.postUpdate(OFF)
			//Fernsehen.postUpdate(OFF)
			logInfo("TEST ", "Mediaaktionprev "+Media_Aktion.previousState.state)
			logInfo("TEST ", "Mediaaktion "+Media_Aktion.state)
            }
}
end

log:

2019-11-01 15:25:39.396 [ome.event.ItemCommandEvent] - Item 'Media_Aktion' received command 1

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

2019-11-01 15:25:39.421 [DEBUG] [pdb.internal.MapDBPersistenceService] - store called for Media_Aktion

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

2019-11-01 15:25:39.434 [vent.ItemStateChangedEvent] - Media_Aktion changed from 4 to 1

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

2019-11-01 15:25:39.460 [DEBUG] [pdb.internal.MapDBPersistenceService] - Stored 'Media_Aktion' with state '1' in mapdb database

2019-11-01 15:25:39.463 [DEBUG] [pdb.internal.MapDBPersistenceService] - store called for Media_Aktion

2019-11-01 15:25:39.465 [INFO ] [eclipse.smarthome.model.script.TEST ] - Mediaaktionprev 1

2019-11-01 15:25:39.477 [INFO ] [eclipse.smarthome.model.script.TEST ] - Mediaaktion 1

2019-11-01 15:25:39.487 [DEBUG] [pdb.internal.MapDBPersistenceService] - Stored 'Media_Aktion' with state '1' in mapdb database

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

2019-11-01 15:25:48.950 [ome.event.ItemCommandEvent] - Item 'Media_Aktion' received command 2

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

2019-11-01 15:25:48.963 [DEBUG] [pdb.internal.MapDBPersistenceService] - store called for Media_Aktion

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

2019-11-01 15:25:48.971 [vent.ItemStateChangedEvent] - Media_Aktion changed from 1 to 2

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

2019-11-01 15:25:48.981 [DEBUG] [pdb.internal.MapDBPersistenceService] - Stored 'Media_Aktion' with state '2' in mapdb database

2019-11-01 15:25:48.985 [DEBUG] [pdb.internal.MapDBPersistenceService] - store called for Media_Aktion

2019-11-01 15:25:48.989 [INFO ] [eclipse.smarthome.model.script.TEST ] - Mediaaktionprev 2

2019-11-01 15:25:48.994 [DEBUG] [pdb.internal.MapDBPersistenceService] - Stored 'Media_Aktion' with state '2' in mapdb database

2019-11-01 15:25:49.000 [INFO ] [eclipse.smarthome.model.script.TEST ] - Mediaaktion 2

so both (.state and .previousstate.state) got the same value.

thanks for your efforts so far
greetings
Andy

According to this example from @rlkoshak your call should look like:

logInfo("TEST ", "Mediaaktionprev "+previousState)

1 Like

i used:

logInfo("TEST ", "Mediaaktionprev "+ triggeringItem.state + triggeringItem.previousState.state)

but still Returns same value for both

I have the same running with some ON OFF values (switch item) and it works well… could be the Number item which is triggered by my sitemap selection be the issue?

Let’s assume that rrd4j has multiple points. There are two reason presented here for why you might only get one value mentioned in this thread so far.

  • Don’t ignore Vincent’s suggestion. You can very easily change the Rule trigger and solve this problem using a changed trigger and the previousState implicit variable

  • This Rule is triggered by a command. Commands do not directly change the state of an Item. So while this Rule is running, either the binding or the autoupdate module is working in the background to update Media_Aktion to what ever state results from the command. So, in short, depending on timing, Media_Aktion.state will sometimes be the “previousState” as it hasn’t been updated as a result of the command yet. This is another reason why a received update or a changed trigger would be more appropriate for this. In both cases, the event doesn’t occur until after the Item actually gets the new state.

  • Because MapDB is your default, the call to Media_Aktion.previousState is going to use MapDB. You need to tell it to use rrd4j like you did in your first version of the code.

  • Even if you change the rule trigger to received update or changed, the actual processing of the event by persistence will still be going on in the background. Again, it’s all up to the luck of the timing to determine whether or not the latest state is actually stored in the database or not which will change the result. So you probably need a short Thread::sleep (100 to 300 should be sufficient) to give persistence time to actually save the latest event.

Timing is going to forever be a problem for you in this Rule with this approach. If there is any way you can move to a changed Rule trigger instead that will solve all of your timing problems and eliminate the need to go out to the database to get the previousState.

Hi Rich,

thanks for your awesome and really detailed Reply.
i hope this is what you ment by changing the trigger:

rule "Medienauswahl"
when Item Media_Aktion changed
then switch Media_Aktion.state {
	case 1: {               if( Media_Aktion.state==2 ) {
					Fernsehen.sendCommand(OFF)
					}
				if( Media_Aktion.state==3 ) {
					Musik.sendCommand(OFF)
					}
				if( Media_Aktion.state==4 ) {
					Dvd.sendCommand(OFF)
					}
					Thread::sleep(300)
					logInfo("TEST ", "Mediaaktionprev "+ Media_Aktion.state + Media_Aktion.previousState.state)
			}
	case 2: {	Thread::sleep(300)
				logInfo("TEST ", "Mediaaktionprev "+ Media_Aktion.state + Media_Aktion.previousState.state)rule "Medienauswahl"
when Item Media_Aktion changed
then switch Media_Aktion.state {
	case 1.0: {if( Media_Aktion.state==2 ) {
					Fernsehen.sendCommand(OFF)
					}
				if( Media_Aktion.state==3 ) {
					Musik.sendCommand(OFF)
					}
				if( Media_Aktion.state==4 ) {
					Dvd.sendCommand(OFF)
					}
					Thread::sleep(300)
					logInfo("TEST ", "Mediaaktionprev "+ Media_Aktion.state + Media_Aktion.previousState.state)
			}
	case 2: {	Thread::sleep(300)
				logInfo("TEST ", "Mediaaktionprev "+ Media_Aktion.state + Media_Aktion.previousState.state)

but still both are the same value.

BTW, the reason why i wanted to use the rrd4j database and .perviousState(false,“rrd4j”).state is cause I want to use the previous state of my item in some other rules too whichh execute after this one.
I also had a look in the RestAPI and could not find any datapoints for my item

{
  "name": "Media_Aktion",
  "datapoints": "1",
  "data": [
    {
      "time": 1572604184212,
      "state": "2"
    }
  ]
}

but there is also no hint if it Shows rrd4j or mapdb.

That because just changing the trigger is not sufficient. You also need to replace all of your Media_Aktion.previousState.state calls with just previousState.

But even if that were not the case, there are number of other changes I mentioned you had to make that you did not make.

Did you tell it to search rrd4j? If not it searches the default.

Similarly, as I mentioned above, you are not telling previousState to use “rrd4j” so it’s using your default.

sorry, that was my fault, I forgot the database in RestAPI…bad mistake.
Also the previous state is workin in my Switch case rule, thanks for that.

But in my other rules wher I wanted to use rrd4j i got the following:
rule:

rule "Teufel_Amp_ON"
when Item harmony_activity changed
then logInfo("TEST", "prev" + Media_Aktion.previousState(true, "rrd4j").state)
 }
end

i want to get the last different state to the state it has now.

log:

2019-11-01 17:28:52.890 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Teufel_Amp_ON': rrd4j does not allow querys without a begin date, unless order is descending and a single value is requested

Had the same in the beginning an thougt it was an Problem of the “missing” datapoints…sorry
i also searched some old post About that but cant find a solution for this.

thanks for all your efforts in this case.
greetings Andy

I don’t use rrd4j and I’ve never seen this error before. You may need to file an issue. See How to file an Issue on https://github.com/openhab/openhab1-addons.

I just did a test on an item that I do persist with rrd4j.
Using this code:

rule "TestpreviousState"
when
Item RunTime changed
then
logInfo("Test", "aktuell: {}", CPU_Load.state)
logInfo("Test","previous: {}", CPU_Load.previousState().state)
end

I only got different results for “aktuell” and “previous” if the time-intervall for no data-reports was 60 seconds or better less then that. Since rrd4j stores every minute, the previous state is mostly the same as the actual if the time-intervall is more then a minute (IMHO!)

1 Like

Very good point. openHAB is not smart enough to recognize the difference between storing an update from storing a value periodically. So rrd4j is really useless for reliably getting the previousState unless you always provide true (i.e. get the previous state that is different from the current state). And even that only works if the value of the state always changes and never is the same state twice in a row.

I would be ready to start an argument about that, because IMHO the previousState is the previously stored state (being it the same value or string as the actual or not).
In case of the implicit rules variable the state will always be different because the rule was triggered by that change.
In case of the persistence extension (without the true) just a historic item is to be returned, which can be different or not.
Using the true as an argument should start a search backwards for the first state different to the actual one. However this call on a rrd4j database yields the already reported error.

1 Like

When one wants to call previuosState, they want the previous state of the Item. Consider this scenario. Item changes state which gets saved. Two minutes pass. Now I want to know what the state before the current state was even if it was the same. But I can’t know that. If I call previousState(true) it will skip the previous state of it was the same as the current state and go before the previous state. If I use previodState, when it returns the same state as the Item’s current state, I can’t know if that is the actual previous state or the current state saved in the past minute. It’s impossible to determine if the previous state was the same as the current state (i.e. received update to the same state). There is no way to tell if the value returned came from an update or just the usual every minute saved value.

It’s also impossible to determine how long it’s been since the last update you an item since there is no way to tell the difference between an update to the same state or one of the every minute saves.

Both are calls and useful use cases that are impossible with rrd4j.

1 Like

Hey together,

thanks for the support in this case and all the lessions learned for me trough Rich, Jürgen and Vincents Posts. Thats why I love using OpenHAB, the support is awesome.

In my case I now Setup MySQL and trough some short test it Looks like it should work.

I also will file an issue cause of the strange error Messages in rrd4j requests.

again thanks for your time
Greetings
Andy