Calculations with historicState of rrd4j

1,093 views
Skip to first unread message

Ivar V

unread,
Apr 3, 2014, 12:50:44 PM4/3/14
to ope...@googlegroups.com
Hi 

I'm trying to make a rule to subtract the historicState of an rrd4j database with the current value. 
If i println the "historic" value, it shows a number like 766.3300000002627 in the debug window, but it throws an error if i try to do a calculations, like in the rule below:
18:46:46.814 ERROR o.o.m.c.i.f.FolderObserver[:105]- An unexpected exception has occured java.lang.NullPointerException: null

My conclusion: the historicState isn't recognized as a number. I have tried defining it as a decimalType, but with no luck. 
Any ideas? 

rule "PWR Consumption"
when
System started or
Time cron "5 * * * * ?"
then

val Number historic = pwrTotal.historicState(now.minusMinutes(30), "rrd4j")
val Number current = pwrTotal.state

postUpdate(pwrHour, current - historic)

end

Thanks
Ivar





Ben Jones

unread,
Apr 3, 2014, 3:29:44 PM4/3/14
to ope...@googlegroups.com
Try;

val Number historic = pwrTotal.historicState(now.minusMinutes(30), "rrd4j").state


Ivar V

unread,
Apr 3, 2014, 3:39:49 PM4/3/14
to ope...@googlegroups.com
Thanks a lot for the effort Ben

Sadly it did not work. Getting this error:
Error during the execution of rule PWR Consumption
java.lang.NullPointerException: cannot invoke method public abstract org.openhab.core.types.State org.openhab.core.persistence.HistoricItem.getState() on null

//Ivar 

Ben Jones

unread,
Apr 3, 2014, 3:42:17 PM4/3/14
to ope...@googlegroups.com
Others will know more, but I have a feeling the historicState() interface doesn't work for rrd persistence, since it is a rolling storage system. Anytime I need to look at specific value back in time I use db4o persistence and it works fine.

Is it worth trying that?

Ivar V

unread,
Apr 3, 2014, 3:56:05 PM4/3/14
to ope...@googlegroups.com
Could try that, but I fear the file would grow big as I'm planning to count the blinks of my Power meter LED.
So my thought was to store the Watt count from the Arduino in the rrd database + the accumulated value to calculate the usage, say per hour.  

In the db4o database i was going to store hourly or maybe weekly usage for persistent storage over time.  

This might not be the optimal approach tho :) 

Thanks again
Ivar

Ben Jones

unread,
Apr 3, 2014, 3:57:25 PM4/3/14
to ope...@googlegroups.com
Might be worth trying it just to see if I am right - and that historicState() isn't supported by rrd. Otherwise you could check the code for the rrd persistence module?

Ivar V

unread,
Apr 4, 2014, 8:50:41 AM4/4/14
to ope...@googlegroups.com
Hello 

Tested with db4o, working as intended then. :) 
Not an optimal solution, as i cant get data to the chart. (at least not using GreentUI)
Guess i have to use both db's in parallel for it to work proper.

Thanks again Ben.

Ivar 

Chris Jackson

unread,
Apr 4, 2014, 9:03:40 AM4/4/14
to ope...@googlegroups.com
I would have expected that the historic item functions would work in rrd since it just uses the 'queryable persistence' interface - the same as db4o. I assume you set the default persistence store appropriately since this is how the persistence extensions decide what store to use (ie persistence:default in the cfg file).

If you are using the latest GreenT, then I think this should work with graphing db4o (or any other queryable store) - Pauli changed it before the 1.4 release to support the new charting system (although I've not tested it myself).

Cheers
Chris

Ivar V

unread,
Apr 4, 2014, 9:50:53 AM4/4/14
to ope...@googlegroups.com
Chris

Yes, the "persistence:default=rrd4j" is set properly in the config file. I think it's set by default also. 
Anyways.. I thought declaring the correct service in the rule should be enough? Like this:
"val Number historic = pwrTotal.historicState(now.minusHours(1), "rrd4j").state" 

The chart is not drawing any graph sadly.
I noticed re-enabling logging in my "rrd4j.persist" file, started the graph again, even tho db4o is set in the sitemap like this:
"Chart item=pwr service="db4o" period=h refresh=10000"
So it seems the service setting in sitemap is ignored then? 

Cheers
Ivar

Chris Jackson

unread,
Apr 4, 2014, 10:02:39 AM4/4/14
to ope...@googlegroups.com
Hi Ivar,
> Anyways.. I thought declaring the correct service in the rule should be enough? Like this:
> "val Number historic = pwrTotal.historicState(now.minusHours(1), "rrd4j").state”
Yes, you’re right, this should work. I had a quick look at the source though, and there should be no reason that rrd should not work with the historicState functions (that I can see anyway). It should use the same functions that are used to extract data for charts etc. Personally though, I’ve never used the form you put above - the doc says it works, and the source looks ok, but...


> The chart is not drawing any graph sadly.
> I noticed re-enabling logging in my "rrd4j.persist" file, started the graph again, even tho db4o is set in the sitemap like this:
> "Chart item=pwr service="db4o" period=h refresh=10000"
> So it seems the service setting in sitemap is ignored then?
Maybe this is the case. I have a feeling that this may not be provided by the UIs since before 1.4 this was not used as there was only the ability to graph if you used the rrd4j store. If you only have one store, then this isn’t a problem since the chart service will pick this up correctly (as there is only 1), but since the “service” information must come from the UI, it very much depends on the UI doing the right thing :(

Do you have both the db4o and the rrd JAR in the addons folder, or just the one you are using for each test? Maybe it’s worth removing the one you’re not using if you have them both. The reason is that even if the logging is disabled in the persist file, the service will still be started, and registered in the system, and then when the chart tries to graph, it will have multiple services to try and use, and if there are 2, it will just pick the first one unless the service= is provided by the UI.

Chris

Ivar V

unread,
Apr 4, 2014, 11:04:21 AM4/4/14
to ope...@googlegroups.com
Chris

First, just to be clear... I'm using the latest public builds of both Openhab and Greent available on the openhab.org download site. 

Did some more testing as you suggested, and deleted the rrd JAR and rrd4j.persist file from their corresponding folders.
It's now drawing the graph in GreentUI (Can't test in Habdroid atm) 
So I guess its a bug then if your using more than one storage (at least rrd4j and db4o).

So i guess the setup I was thinking of is out of the question then, rrd for the impulse count and db4o for monthly and yearly statistics. ? 
Any workarounds I haven't thought about? 

Thanks
Ivar  

Chris Jackson

unread,
Apr 4, 2014, 11:17:56 AM4/4/14
to ope...@googlegroups.com

> First, just to be clear... I'm using the latest public builds of both Openhab and Greent available on the openhab.org download site.
Sure - I think the issue is with the UIs in that they probably haven’t been updated to fully support the new graph service that was introduced in 1.4.

> It's now drawing the graph in GreentUI (Can't test in Habdroid atm)
Cool - so this confirms that GreenT doesn’t send back the service when requesting the chart.

> So I guess its a bug then if your using more than one storage (at least rrd4j and db4o).
Yes - the bug is in the UIs. They aren’t supporting the service configuration. There may also be a bug in the persistence extensions if you couldn’t get the version with the service name to work, but I’ve not looked at this so can’t be sure.

> Any workarounds I haven't thought about?
Fix GreenT :)

I’ve just had a quick look, and it should be quite easy to add support for the service= configuration. I’ll take a look at this later...

Chris

Chris Jackson

unread,
Apr 4, 2014, 11:36:31 AM4/4/14
to ope...@googlegroups.com
Please try this version of GreenT. I haven’t checked that this will actually extract the data from the persistence service, but have confirmed that if you add service=“rrd4j” to the end of the chart definition in your sitemap, that this does make it into the chart servlet so I’m pretty sure this will work with multiple services.

Note that to test this you need to run from debug.html - if this works ok I’ll create a proper PR and minify the file...

Let me know if it helps (I hope so).

Chris


app.js

Ivar V

unread,
Apr 4, 2014, 12:01:55 PM4/4/14
to ope...@googlegroups.com
Hi Chris

It works :) 
I set the config back to "persistence:default=rrd4j", added back the rrd jar and rrd4j.persist file. 

Thanks allot!
At least I can use two storages with charts again :) 

So now I'll try to get the historicState work with rrd4j. The db4o i building up quite fast, almost 2MB already after 2 days of testing. 

Have a nice weekend!
Cheers 
Ivar

Chris Jackson

unread,
Apr 4, 2014, 12:26:59 PM4/4/14
to ope...@googlegroups.com
Brilliant - thanks. I’ll create a PR for this…

Cheers
Chris


--
You received this message because you are subscribed to the Google Groups "openhab" group.
To unsubscribe from this group and stop receiving emails from it, send an email to openhab+u...@googlegroups.com.
To post to this group, send email to ope...@googlegroups.com.
Visit this group at http://groups.google.com/group/openhab.
For more options, visit https://groups.google.com/d/optout.

helmut....@ingenieurbuero-mbi.de

unread,
Apr 4, 2014, 1:20:41 PM4/4/14
to ope...@googlegroups.com
Hi, at least for me it works like this :
rule "taeglichen Gasverbrauch ermitteln"
when
    Time cron "59 59 23 * * ?"
then
  var Number currGas = Z_Gas.state as DecimalType
  prevGas = Z_Gas.historicState(now().minusHours(24)).state as DecimalType
  var Number diff = currGas - prevGas
  var String msg = "Gestriger Verbrauch : "+ diff.floatValue.toString + " m3"
  sendXMPP( addr , msg)
end

cheers,
Flipper

Ivar V

unread,
Apr 4, 2014, 3:06:50 PM4/4/14
to ope...@googlegroups.com
Hi 

Thank you for sharing :) 
Modified my script a bit with the missing parts from your script. 

So I got it working now finally!

And I didn't really do anything to fix it.
It seems when I start the script it can't sync up with the rr database for after like 3 - 5 minutes.
Then it suddenly gets correct values. Error code for the first minutes:
"Error during the execution of rule 'PWR Consumption': cannot invoke method public abstract org.openhab.core.types.State org.openhab.core.persistence.HistoricItem.getState() on null"

I've tried to change the time in "historicState(now().minusMinutes(60)" back and forth, and every time its the same error as above at first. 
My theory is that either the rrd4j has to "adjust" to get the correct timestamps to match or it just syncs up somehow. But I don't know really :)

Heres the working rule:
rule "PWR Consumption"
when
Time cron "0 0 * * * ?" //Every Hour
then

val Number historic = pwrTotal.historicState(now().minusMinutes(60), "rrd4j").state as DecimalType
val Number current = pwrTotal.state as DecimalType



postUpdate(pwrHour, current - historic)
end 
 

Cheers
Ivar

helmut....@ingenieurbuero-mbi.de

unread,
Apr 4, 2014, 6:07:18 PM4/4/14
to ope...@googlegroups.com
You are welcome,

glad it works now

Flipper

Carsten

unread,
Oct 6, 2014, 12:36:04 AM10/6/14
to ope...@googlegroups.com
Hi,

I had the same error message when starting implementing historicstate functionality. After a 2 days it started working without any change. My assumption is that the rrdj database engine is producing this error if no data is available for the requested historic period. Question is if this behavior is desired or should be changed (e.g. not giving back an error but a "0" if a value is not found).

C.

Thomas E.-E.

unread,
Oct 6, 2014, 5:33:19 AM10/6/14
to ope...@googlegroups.com
Hi,

the behaviour of the binding should be return a HistoricState if there is any. If there is no matching state nothing can be returned which is indicated by the NullPointer. In order to circumvent this you could change your rule and introduce a null check:


rule "taeglichen Gasverbrauch ermitteln"
when
   
Time cron "59 59 23 * * ?"
then
 
var Number currGas = Z_Gas.state as DecimalType

 
var State histState = Z_Gas.historicState(now().minusHours(24))
 
if (histState != null) {
    prevGas
= histState.state as DecimalType

   
var Number diff = currGas - prevGas
   
var String msg = "Gestriger Verbrauch : "+ diff.floatValue.toString + " m3"
    sendXMPP
( addr , msg)
 
}
end


Hope this helps,

Thomas E.-E.
Reply all
Reply to author
Forward
0 new messages