EasyESP counter for utility metering

Hi all,

I have a water meter and gas meter that I want to integrate into OH2. For a start I have a reed switch on the gas meter connected to a nodemcu running ESPEasy R120. The reed switch is configured as pulse counter, and sends data to mosquitto (verified with mosquitto_sub).

What is the best way to get this data into OH2 and influxdb? ESPEasy can give either the number of pulses since last report, or the total accumulated pulses. If using the number of pulses, how should these be summed (in an OH2 rule or in influxdb)? Or if using the accumulated values, how to handle when the ESPEasy is occasionally reset (counter restarts).

My end goals are:

  1. graph of consumption, e.g. per hour.
  2. Accumulation (I would like to preset it to the value shown on the mechanical meter, in order to have a “calculated meter reading”

If someone has an example (OH2 configuration and/or rules), I believe that would be very helpful. Thank you

1 Like

It seems you have the comms part figured out. Use the MQTT binding to receive the info from the microcontrollers.

I think it really depends on what you want to do with these values.
What information are you hoping to get out of these pulses?
What do the pulses represent (e.g a certain volume of gas consumed per click)?
How do you want to chart the data (e.g. a line that goes up then resets to zero at the end of the month, bar chart showing daily usage, etc.)?
What sort of math do you intend to do on the data (e.g. average use per day, total use per day, total use per month, etc)?

Speaking generically I think receiving the number of pulses since the last report gives you the most flexibility in terms of what you can do with that information. You can then use Rules and persistence calls to, for example, get sumSince(now.minusHours(1)) to get the total number of pulses in the past hour and assign that to a separate Item to store, graph, and display if you so choose. If you graph using Grafana there are all sorts of accumulation strategies you can use to generate a chart to show the info you need. You can keep a running total on another accumulation Item as well using a rule.

Thanks for the reply, Rich.

The gas meter gives me 100 pulses per m^3 (i.e. one pulse per 10L).
For starters, a bar graph showing daily consumption would be fine (I have grafana set up as well).

I guess what I am having difficulties with is if I use the MQTT binding to assign the delta count (i.e. the number of pulses since last report, which is perhaps 1 minute ago), I will get that as a number. But in the examples I find of OH rules and item definitions, number is usually a measurement (temperature, humidity, etc.), where summing makes no sense (hence no examples), whereas other forms of aggregation, like “average” does.

A separate item used for running total seems like a good idea. I guess that could be persisted via mapdb. Any suggestions for how to manually “preset” the accumulation to a value read from the physical meter?

A few examples of item definitions and/or rules would be really helpful.

Thanks in advance

I’m using Flukso for this. https://www.flukso.net/

It’s a stand alone device that connects to water, electricity and gas meter in my case (works great with Belgian gas and water meters). It also submits mqtt messages (both gauge as well as absolute values) which I just capture in OH.

For graphing purposes I just persist in MySQL.

It’s a fairly hassle free solution as the flukso device deals with the connections, the calculations and transitions.

Write a System started rule that does a postUpdate on the Item. Make sure the Item is persisted with restoreOnStartup and then you can remove the System started rule.

Browse the Tutorials and Examples section for tons of examples.

See the MQTT binding readme for MQTT info.

I also have a ESP with a reed contact attached to the gas utility meter. Mine also sends 100 pulses per m^3. Note that I normalize the pulses to m^3 on the ESP by applying the formula “%value%/100” to the value before sending it by mqtt.

These are my items:

Number gGaszaehlerCount "Gaszähler Count [%.2f m3]" {mqtt="<[snapp:/ESP1/Gaszaehler/Count:state:default]"} 
Number gGaszaehlerTotal "Gaszähler Total [%.2f m3]"  
Number gGaszaehlerLastHour "Gasverbrauch letzte Stunde [%.2f m3]" 
Number gGaszaehlerCounter0h
Number gGaszaehlerYesterday "Gasverbrauch gestern [%.2f m3]" 
Number gGaszaehlerToday "Gasverbrauch heute [%.2f m3]" 

My rules are JSR223 Rules that are using Steve Bate’s openhab2-jython library:

@rule
class ProcessGasTicks(object):
    def __init__(self):
        self.log.info('ProcessGasTicks')

    def getEventTriggers(self):
        return [ ItemStateUpdateTrigger('gGaszaehlerCount', None, 'gGaszaehlerCount')
        ]

    def execute(self,modules, inputs):
        total=float(str(items.gGaszaehlerTotal))  
        current=float(str(items.gGaszaehlerCount))
        events.postUpdate('gGaszaehlerTotal',str(total+current))

@rule
class GasLastHour(object):
    def __init__(self):
        self.log.info('GasLastHour')

    def getEventTrigger(self):
        return [ CronTrigger("0 0 * * * ?"),
        ]

    def execute(self,modules,inputs):
        gasCounterNow=float(str(items.gGaszaehlerTotal))
        gasCounter1hrAgo=float(str(pe.historicState( ir.getItem("gGaszaehlerTotal"), DateTime.now().minusHours(1)).state))
        if items.gGaszaehlerCounter0h != 'NULL':
            gasCounter0h=float(str( items.gGaszaehlerCounter0h))
        else:
            gGaszaehler0h=gasCounterNow
        events.postUpdate('gGaszaehlerLastHour',str(gasCounterNow-gasCounter1hrAgo))
        events.postUpdate('gGaszaehlerToday',str(gasCounterNow-gasCounter0h))

@rule
class GasYesterday(object):
    def __init__(self):
        self.log.info('GasYesterday')

    def getEventTrigger(self):
        return [ CronTrigger("0 59 23 * * ?")
        ]

    def execute(self,modules,inputs):
        gasConsumptionNow=float(str(items.gGaszaehlerTotal))
        gasConsumption24hrAgo=float(str(pe.historicState( ir.getItem("gGaszaehlerTotal"), DateTime.now().minusHours(24)).state))
        events.postUpdate('gGaszaehlerYesterday',str(gasConsumptionNow-gasConsumption24hrAgo))
        events.postUpdate('gGaszaehlerCounter0h',str(gasConsumptionNow))

Thank you @ralle. That looks useful.

Below is what I have come up with so far (just a total so far), in case anyone searches for something like this. As this is entirely uncharted territory for me, if you have any suggestions for improvements, please post them.

I ended up using the Total from ESPEasy, and keeping track of the last value. This should prevent any problems if the ESPEasy is offline for some time.

For presetting the total, I added a separate MQTT topic, which I can post to using mosquitto_pub on the command line.

items/gascounter.items:

Number GasCounterValue "MQTT [%.2f m³]" {mqtt="<[mosquitto:/gasmeter/gas/Total:state:default]"}
Number GasCounterPreset {mqtt="<[mosquitto:/gasmeter/preset:state:default]"}
Number GasCounterTotal "Gas total [%.2f m³]"

rules/gascounter.rules:

var Number gasCounterLastValue = 0

rule "Gas meter update"
when
        Item GasCounterValue changed
then
        //logInfo("gasmeter", "GasCounterValue = " + GasCounterValue.state.toString())

        if (gasCounterLastValue == 0) {
                // First update, do not add delta to total
                logInfo("gasmeter", "reset to " + GasCounterValue.state.toString())
        } else {
                var Number delta = (GasCounterValue.state as DecimalType) - gasCounterLastValue
                if (delta > 0) {
                        // logInfo("gasmeter", "Delta=" + delta.toString())
                        if (GasCounterTotal.state == NULL) {
                                GasCounterTotal.postUpdate(delta)
                        } else {
                                GasCounterTotal.postUpdate(delta + GasCounterTotal.state)
                        }
                } else if (delta < 0) {
                        // ESPEasy total is lower, maybe ESPEasy was power cycled
                        logInfo("gasmeter", "Negative delta " + delta.toString() + " Value=" + GasCounterValue.state.toString())
                }
        }
        gasCounterLastValue = GasCounterValue.state as DecimalType
end


rule "Gas meter total preset"
when
        // Preset the total by mosquitto_pub -h localhost -t /gasmeter/preset -m "1116.17" 
        Item GasCounterPreset received update
then
        GasCounterTotal.postUpdate(GasCounterPreset.state as DecimalType)
        logInfo("gasmeter", "GasCounterTotal preset to " + GasCounterPreset.state.toString())
end
1 Like