Impuls counting: Time critical & double counting

I use volkszaehler to detect some of my consumption and send the data via mqtt to openhab. I plan to put a tutorial in when finished as it is not working out of the box.

For the gas sensor, I only have an impuls based sensor, this means I get a mqtt message each time 0.01 m3 gas are consumed. The mqtt message contains the timestamp as well as 1 as value. I currently have a rule to add the gas consumption each time I receive such a value but experience that counting goes not correct even after a few hours already. My questions: Any better ideas?


Type number : GasImpuls "Gaszaehler Impuls" [ stateTopic="vzlogger/data/chn14/raw",  transformationPattern="JSONPATH:$.value"]


Number   Gaszaehler_Impuls  "Gas Impuls" (gGaszaehler){channel="mqtt:topic:Volkszaehler_Zaehlerstand:GasImpuls"}
Number   Gaszaehler_Zaehlerstand  "Gas Zählerstand [%.2f m3]" (gGaszaehler)["Measurement","Gas"]


rule     "Gaszähler Impulsupdate"
    Item Gaszaehler_Impuls changed to 1
    // Impuls resetten
    // Zählerstand erhöhen
    Gaszaehler_Zaehlerstand.sendCommand((Gaszaehler_Zaehlerstand.state as Number) + 0.01)

   // More Code for other purpose

I also thought if too much code might be the reason as I also do some additional calculations to calculate the consumption. What happens if such a rule takes too long and several impulses are received in the meanwhile? Nevertheless, I also observed the value of the counter (Zählerstand) being higher then the real one, which would mean somehow impulses have been counted twice. I also thought about using expire for the item but not sure about the right way. Another idea is to use the timestamp as I could at least distinguish between the values.

I believe there is a smarter way and look forward to your ideas, thanks!

Are you sure? MQTT can be configured for how hard it tries to deliver a message, see “QoS”.

OH3 in general runs only one pass through a rule at a time, and will queue up triggering events to cause new passes when the first is complete.
Beware that asynchronous actions fired by the rule - like updating Items - may not have completed by the time of the second pass.

For MQTT, you can use the “post command” option on your incoming channel, which will cause the message to trigger an openHAB command event on the Item, instead of a state change. That way you won’t have to mess about with setting its state back to 0. (because that might not have finished yet when the second pass comes along.) Trigger your rule from command.

In fact, I’d go further and use the sent timestamp as the command - by comparing “last” with “new” you’ll be able to check that you haven’t got a duplicate message. (which can happen with some MQTT QoS settings)

Within your rule, if you want to update your total Item, then update it. Don’t send it a command, which adds delay and overhead.

That is all about improving your chances - there are some things openHAB will never cope well with, it is not a real time data acquisition system. How quickly do your pulses come, at worst?
Look in your events.log and you’ll be able to see what is happening better.

I configured QoS = 2 on vzlogger (sender) as well as openhab (receiver). What I meant with “I get a mqtt message each time”: every time I consume 0.01 m3 gas, I get a message sent out. This is the behaviour as expected from an impulse sensor.

Good to know. queuing to run through the rule is a good thing in this case. Nevertheless, for fast updates it might happen that the update to the item storing the count has not taken place yet. Any idea how to avoid this?

It took me a while and reading through rules and mqtt binding documentation to understand what you wrote.

I changed the ting to

Type number : GasImpulsTimestamp "Gaszaehler Impuls Timestamp" [ stateTopic="vzlogger/data/chn14/raw",  transformationPattern="JSONPATH:$.timestamp",postCommand=true]

Item has not changed and is not needed yet. Comparing the timestamps is on the list for the second update then seeing the effect of this change.

The full rule looks like this with changed trigger and deactivated first command as well as postUpdate instead of sendCommand:

var DateTimeType time1 = 0
var DateTimeType time2 = 0
var Number timediffSeconds = 0
var Number timediffDays = 0
var Number result = 0

rule     "Gaszähler Impulsupdate"
    Channel "mqtt:topic:Volkszaehler_Zaehlerstand:GasImpulsTimestamp" triggered
    // Impuls resetten
    // Zählerstand erhöhen
    Gaszaehler_Zaehlerstand.postUpdate((Gaszaehler_Zaehlerstand.state as Number) + 0.01)

    // Verbrauch berechnen
    if (Gaszaehler_lastupdate.state != NULL && Gaszaehler_lastlastupdate.state != NULL) {
        time2 = (Gaszaehler_lastupdate.state as DateTimeType).getZonedDateTime() 
        time1 = (Gaszaehler_lastlastupdate.state as DateTimeType).getZonedDateTime() 
        if (time1 != time2)
            timediffSeconds = Duration.between(time1, time2).toSeconds()
            timediffDays = timediffSeconds / 86400.0
            result = 0.01 / (timediffDays)
            //logInfo("Gas", "Timediff Seconds: " + timediffSeconds.toString + "; Timefiff Days: " + timediffDays.toString )
            if (result != 0 && result != NULL)
                Gaszaehler_Verbrauch.postUpdate( result)
    // Letzte Aktion: Last Update für den nächsten Impuls speichern
    Gaszaehler_lastlastupdate.sendCommand(Gaszaehler_lastupdate.state as DateTimeType)

Clear! In fact I would say worst case 1 per second as an assumption. It’s hard to see the worst case as this is really rare. I tried to derive from measurements which would be even every 2 seconds.


Not sure your mystery timestamp format will fit into a number channel/Item.
If you don’t care what it is (just if it is different) use a string type.

There is no real fix for this. It’s not likely to happen - your events.log will show you the time from trigger to update- but problem would be hidden in your events.log because update-to-same are not logged.

You could maintain your count in a ‘global’ variable, which the rule would handle synchronously, and copy that to your totals Item. You can initialize your variable at system startup from the restore-on-startup Item.

It’s a timestamp as a real number (integer). The current solution works fine with some slight modifications. I had to add trigger=true to the Channel in the items file.
Currently no timestamp comparison implemented yet - I want to see how good it will be without first. Still playing around a bit to see how it behaves but need time to see any drift from the real value.

That does something completely different, and generates a trigger event that will be visible in your events.log. This is unrelated to Item states and commands.

Sure on that? I thought I have observed without the rule was not firing.

During my research I also found this: MQTT Things and Channels - Bindings | openHAB
trigger: If true, the state topic will not update a state, but trigger a channel instead.

Also some log output not showing any unwanted / unnecessary item change:

2022-01-26 20:08:29.454 [INFO ] [openhab.event.ChannelTriggeredEvent ] - mqtt:topic:Volkszaehler_Zaehlerstand:GasImpulsTimestamp triggered 1643224108851
2022-01-26 20:08:29.467 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Gaszaehler_Zaehlerstand' changed from 1852.01 to 1852.02
2022-01-26 20:08:29.473 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Gaszaehler_lastupdate' changed from 2022-01-26T20:07:10.459176+0100 to 2022-01-26T20:08:29.463465+0100
2022-01-26 20:08:29.483 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Gaszaehler_lastlastupdate' changed from 2022-01-26T20:07:10.459176+0100 to 2022-01-26T20:08:29.463465+0100


That’s right - here it is in your log -
(I’m not convinced that it stops the usual update of a linked Item state. If you really didn’t want that, you just wouldn’t need to link an Item to a triggering channel at all)

There’s nothing to stop you using that to trigger your rule, if you wish.
It is less convenient than an Item because you would have to use some other method to store “last” trigger, if you wanted the old/new comparison.

That’s good news then, all worry about nothing?

Although do remember that if your rule did double-update the total to the same value twice in succession, you would not see that in events.log as the second time is not a change.
But if you cannot see double triggers, for whatever your rule is triggering off of now, then that isn’t going to happen.

If in doubt, log it out. Put logging in your rule to observe triggering and start conditions.

I did several tests how to get data best from Volkszaehler. I have a cyble v2 sensor and actually the sensor / volkszaehler already introduces an error I could / would need to fix. This is about 0.2 m3 per day.

Interesting fakt: The most precise result within openhab was counting the impulses I receive via mqtt qos 2 from volkszaehler. There is also a http interface I could pull the results regularly but this has dramatically higher errors (around 1 m3 per day error). Probably this would get better if I pull less often but this would introduce a much reduced time resolution.

Probably I play around within volkszaehler to see how I can get accuracy of impulse counting correct but regarding openhab interface if anybody wants to do something similar: my observation: mqtt impulse counting is the most accurate interface.

This topic was automatically closed 41 days after the last reply. New replies are no longer allowed.