How to count compressor cycles of my heating pump?

What exactly is “not working”?

Check your events.log if there is a change in HeatPump_state_compressor1
Do some logInfo(“TEST”;"Count: "+HeatPump_compressor_count.intValue) in your rule.
Is there anything in the openhab.log? Coming up with an error?

It seems, that the rule gets not triggered??? I made a logging on first position after the “then”-part. But since this time, compressor was off.

Count is alway 0. Formerly it was “-” , but i made a rule (and removed it afterwards) to send “0” as initial value to the item.

The problem is: I get “Compressor ON” every minute. Also if “Compressor” is not initiated and i get command “on”, i will get 1 count. (Maybe on openhab startup)

But i only want to get a count, when compressor was “off” and changes to"on".

I don´t think, there is any error in the log-files.

I changed the rule to this:

postUpdate(HeatPump_compressor_count, HeatPump_compressor_count.state as DecimalType + 1)

Now it seems to work…

.state as DecimalType

and not .intValue

Thank you for your help.

Which database is the right one to persist this counts? I dont´want to install an external database like mySQL.

So i can use db4o - is this right?

rrd4j is no good choice, because the values will get rounded.
mapDB will only store the last value.

What´s the difference between .intValue and .state as DecimalType???

There is no longer support for db4o in OH 2. If you ever want to generate nice charts I would highly recommend InfluxDB and Grafana. Short of that I’d look into SQLite.

ItemName.state is how you get the current state of your Item.

Each type of Item has its own type of state. A Number Item has a DecimalType for its state whereas a DateTime Item will have a DateTimeType. When you want to do math with an Item’s state, you need to tell the Rules that the state is a DecimalType (as DecimalType).

.intValue is a method on DecimalType which returns the value of the state as a primitive int.

1 Like

But for InfluxDB and SQLite i need to install an external database?

No longer all in openhab-directory like mapDB, rrd4j and 4dbo?

SQLite is an embedded database that I think stores its data in the OH directory. Influx is an external DB.

I use rrd4j for all charting this (Must!) and it is not rounding (or didn’t I get your point?).
So use this, but I would prefer mysql so you can do your own sql statements to check things. Calculation within rules would be the same.

rrd4j “compresses” the data as it gets older by taking several near by values and replacing them all with a single average of those values. So as your data gets older the values become more and more spare and less and less precise.

Therefore, for example, you may have a value every minute but once the data becomes a couple of days old you will have one value every ten minutes which is the average of the once per minute values in that ten minute period.

This is what @halloween means by rounding.

In practice for many if not most use cases this isn’t a problem because the precision of data a week, month, year or older doesn’t have to be as high as recent data. But some use cases do require all the precision for this older data.

That´s exactly the point, why i use different persitence services.

rrd4j for most things.

MapDB for only to keep last value, when restarting openhab.

db4o only for things, where i need the exact values, even they are some days old. (for example minimum/maximum temperature of a given time period).

I made a second rule to count the starts of today, but this rule is not working.

Error-Message from the log:

2017-01-10 09:05:19.581 [ERROR] [o.o.c.s.ScriptExecutionThread ] - Error during the execution of rule 'Kompressor Starts zählen 2': The name '<XMemberFeatureCallImplCustom>.state' cannot be resolved to an item or type.

Here is my rule:

rule "Kompressor Starts zählen 2"
		Item HeatPump_state_compressor1 received update
		postUpdate(HeatPump_counts_today, (HeatPump_compressor_count.deltaSince(now.toDateMidnight, "db4o").state as DecimalType)

I changed my rule a little bit and now it seems working…

rule "Kompressor Starts zählen 2"
		Item HeatPump_compressor_count received update
		var count_today = HeatPump_compressor_count.deltaSince(now.toDateMidnight, "db4o")

Is there a way to show values of last day? What other things are possible? Can you give me a link to a manual or table with all possible values for this two things (deltaSince, …) and (now.toDateMidnight, …)?


I try to do the same on my openhab2 but it doesn`t work. I got the following error message:


2018-01-14 11:59:50.794 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Impulse z�hlen Waermepumpe': Could not cast NULL to org.eclipse.smarthome.core.library.types.DecimalType; line 6, column 35, length 42
rule "Impulse zählen Waermepumpe"
	Item Imp_StrZ changed from OPEN to CLOSED
	postUpdate(HeatPump_Stromzaehler, HeatPump_Stromzaehler.state as DecimalType + 1.0)
	logInfo("Hinweise", "Zähler Wärmepumpe: " + HeatPump_Stromzaehler.state.toString )


Contact	Imp_StZ				"Impuls Wasserzähler [%s]"		<switch>		(KG_HAR)		{ knx="5/6/1" }

/* Wärmepumpe */
Number HeatPump_Stromzaehler					"Wärmepumpe Stromzaehler [%d Impulse]"		<energy>		(KG_HAR,Status)	

Which line is “Line 6” of your rule? Is this the one with the logging? If yes, then try to remove the “.to.String” from the logging.

Your item is a number item and no string.

Is the shown item the right one? In your rule you write “Imp_StrZ” and your item is called “Imp_StZ” without the “r”. But it is called “Impuls Wasserzähler”, so is this the right one?

Line 6 is the postupdate line. The item ist the right one. I posted the wrong line of the item file.

Hm, I would make a helper rule and send a value to the number item one time. I think the item is empty (NULL). But it should be 0.

Ok, I will test it tonigth

dear halloween,

I did a test with your hint and it works fine. Thanks a lot.

1 Like

The error is caused by the fact that HeatPump_Stromzaehler is NULL (i.e. uninitialized). You can’t cast NULL to a DecimalType nor can you add 1.0 to NULL.

You may need to test for NULL before calling the postUpdate if the error persists.

just yesterday I discovered, that my onewire counter for my gas meter nulled for some reason.
Then I remembered to have set the real counter for some reason two months ago (at the start of heating Season - as I’m lucky to only need gas from mid-November till Mid-February). But whats more important here:

  1. I have an old gas meter (not smart), which I count via an S0-reader
    (see here my original post: Gas consumption, adding the offset from the meter)
  1. it works kind of - for some reason the S0counter gets nulled, and therefore my Approach to tell the Offset in a static variable was lost
  2. So I changed the Approach - and as I use persistence, this one comes in Handy

I guess @Halloween, @Timo_Horn , you could adapt this one to your needs as well. This rule just counts the offset between the last two cycles and adds that one to the overall consumption counter.

in my script I use those items:

  • Sensoren_Leist_Gas => Actual Count of the S0-Reader (would be a compressor cycle)
  • Sensoren_Status_Gas => Overall consumption Counter (that one on my BK4 - would be your Counter)
    as my BK4 Counts 1/100 of a m3 in one count, I have to calculate this.

I also had some troubles casting the right types for calculating and item updates. What I found out was quite confusing: Sensoren_Leist_Gas.sendCommand(value) didn’t update the value, only postUpdate did. As this one is an item without a binding, I am confused. Second one was Sensoren_Status_Gas.postUpdate(Sensoren_Status_Gas.previousState().state) didn’t work, I had to use a variable for the update-command for the argument. Same for the overall consumption, I had to use a variable for this…

So here’s my code, looks a bit ugly and rough.

rule "Gaszähler"
		Item Sensoren_Leist_Gas changed
		if (Sensoren_Leist_Gas != UNDEF) {
			// calculate the Delta since the last update
			var Number newCounter = (Sensoren_Leist_Gas.state as Number - previousState as Number)
			// NULL abfragen
			if (newCounter < 0) { 
				// This was my concern, if the S0 was nulled, use just the counter (it would be 1)
				newCounter = Sensoren_Leist_Gas.state 
			if (Sensoren_Status_Gas.state == NULL) {
				//  I experienced even with .restoreOnStartup the state wasn't restored - so do it manually
				var Number oldConsumption = Sensoren_Status_Gas.previousState().state
				Thread::sleep(10) // not sure, if needed, but somehow I suspected the script to be too fast sometimes

			// now calculate the consumption and assign it to the counter
			var Number newConsumption = newCounter/100 
			newConsumption += Sensoren_Status_Gas.state

this one works for now! :wink: just wanted to share with you guys.

1 Like