Rule help: persistence, rrd4j (gas/water smart metering)

Hi, I am not a software developer, therefore need some support from you. Many thanks in advance…

I have a hooked up a gas and water sensor to a binary actuator (KNX).
The scalings are:

  • water: each Impulse represents one liter consumption
  • gas: each Impulse represents 0.01m³ consumption
  • Platform information:

    • Hardware: pine64
    • OS: Ubuntu 16.04.4 LTS (openHABian)
    • Java Runtime Environment: openjdk version “1.8.0_152”
    • openHAB version: openHAB 2.3.0 Build #1241
  • configurations

rrd4j.persist

Strategies {
    everyMinute : "0 * * * * ?"
    everyHour   : "0 0 * * * ?"
    everyDay    : "0 0 0 * * ?"
    default = everyChange
}

Items {
    Gas_pulse    : strategy = everyChange, restoreOnStartup
    Gas_scale    : strategy = everyChange, restoreOnStartup

    Water_pulse    : strategy = everyChange, restoreOnStartup
    Water_scale    : strategy = everyChange, restoreOnStartup
}

knx.items


Group         gGas

Number        Gas_pulse       "Gas (Impuls=0.01m³) [%.0f Imp]"    <gas> (gGas)        { channel="knx:device:bridge:binaryinput2:Gas" }
Number        Gas_scale       "Gas [%.3f m³]"                     <gas> (gGas)
Number        Gas_Last_H      "Gas letzte Stunde [%.3f m³]"       <gas> (gGas)
Number        Gas_Last_3H     "Gas letzten 3 Stunde [%.3f m³]"    <gas> (gGas)
Number        Gas_Last_D      "Gas letzter Tag [%.3f m³]"         <gas> (gGas)
Number        Gas_meter       "Gas Zählerstand[%.3f m³]"          <gas> (gGas)
Number        Gasprice        "Gaspreis"                          <gas> (gGas)
DateTime      Gas_LastTime    "Letzter Gas Vebrauch [%1$td.%1$tm.%1$tY %1$tT]" <time>


Group         gWater

Number        Water_pulse    "Wasser (Impuls=1l) [%.0f Imp]"      <water> (gWater)    { channel="knx:device:bridge:binaryinput2:Wasser" }
Number        Water_scale    "Wasser [%.3f m³]"                   <water> (gWater)
Number        Water_Last_H   "Wasser letzte Stunde [%.3f m³]"     <water> (gWater)
Number        Water_Last_3H  "Wasser letzten 3 Stunden [%.3f m³]" <water> (gWater)
Number        Water_Last_D   "Wasser letzter Tag [%.3f m³]"       <water> (gWater)
Number        Water_meter    "Wasser Zählerstand [%.3f m³]"       <water> (gWater)
Number        Waterprice     "Wasserpreis"                        <water> (gWater)
DateTime      Water_LastTime "Letzter Wasser Vebrauch[%1$td.%1$tm.%1$tY %1$tT]" <time>

knx.sitemap

sitemap knx label="KNX Schmart Mäter" {
  Frame label="Gas" {
    Text   item=Gas_pulse
    Text   item=Gas_scale
    Text   item=Gas_Last_H
    Text   item=Gas_Last_3H
    Text   item=Gas_Last_D
    Text   item=Gas_meter
    Text   item=Gas_LastTime
    Chart  item=Gas_scale period=4h refresh=300
  }

   Frame label="Wasser" {
    Text   item=Water_pulse
    Text   item=Water_scale
    Text   item=Water_Last_H
    Text   item=Water_Last_3H
    Text   item=Water_Last_D
    Text   item=Water_meter
    Text   item=Water_LastTime
    Chart  item=Water_scale period=4h refresh=300
  }  

}


gas.rules

rule "Gas smart metering" //divide by 100, because each impuls=0.01m3, add also offset
    when   
       Item Gas_pulse changed
    then
        Gas_scale.postUpdate(Gas_pulse.state as Number / 100)
        logInfo("Rules", "Gas impuls scaled in m³: " + Gas_scale.state)

        Gas_meter.postUpdate(Gas_pulse.state as Number / 100 + 16685.299)
        logInfo("Rules", "Gas meter value in m³" + Gas_meter.state)

        Gas_LastTime.postUpdate(new DateTimeType())
        logInfo("Rules", "Gas last update" + Gas_LastTime.state)
   
        Gas_Last_H.postUpdate(Gas_pulse.deltaSince(now.minusHours(1),"rrd4j") / 100)
        logInfo("Rules", "Gas last hour scaled to: " + Gas_Last_H.state)

        Gas_Last_3H.postUpdate(Gas_pulse.deltaSince(now.minusHours(3),"rrd4j") / 100)
        logInfo("Rules", "Gas last 3 hours scaled to: " + Gas_Last_3H.state)

        Gas_Last_D.postUpdate(Gas_pulse.deltaSince(now.minusDays(1),"rrd4j") / 100)
        logInfo("Rules", "Gas day scaled to: " + Gas_Last_D.state)
        
    end

water.rules

rule "Water smart metering" //divide by 1000, because each impuls=0.001m3, add also offset
    when   
       Item Water_pulse changed
    then
        Water_scale.postUpdate(Water_pulse.state as Number / 1000)
        logInfo("Rules", "Water impuls scaled in m³: " + Water_scale.state)

        Water_meter.postUpdate(Water_pulse.state as Number / 1000 + 399.955 - 0.005)
        logInfo("Rules", "Water meter value in m³" + Water_meter.state)

        Water_LastTime.postUpdate(new DateTimeType())
        logInfo("Rules", "Water last update" + Water_LastTime.state)
   
        Water_Last_H.postUpdate(Water_pulse.deltaSince(now.minusHours(1),"rrd4j") / 1000)
        logInfo("Rules", "Water last hour scaled to: " + Water_Last_H.state)

        Water_Last_3H.postUpdate(Water_pulse.deltaSince(now.minusHours(3),"rrd4j") / 1000)
        logInfo("Rules", "Water last 3 hours scaled to: " + Water_Last_3H.state)

        Water_scale_D.postUpdate(Water_pulse.deltaSince(now.minusDays(1),"rrd4j") / 1000)
        logInfo("Rules", "Water day scaled to: " + Water_scale_D.state)
        
    end

  • logs
[ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Water smart metering': null
[ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Gas smart metering': null

-----

2018-03-26 09:54:22.952 [INFO ] [eclipse.smarthome.model.script.Rules] - Gas impuls scaled in m³: 28.84000000
2018-03-26 09:54:22.971 [INFO ] [eclipse.smarthome.model.script.Rules] - Gas meter value in m³16714.14900000
2018-03-26 09:54:22.981 [INFO ] [eclipse.smarthome.model.script.Rules] - Gas last update2018-03-26T09:54:06.813+0200
2018-03-26 09:54:22.997 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Gas smart metering': null
==> /var/log/openhab2/events.log <==
2018-03-26 09:54:22.923 [vent.ItemStateChangedEvent] - Gas_pulse changed from 2884.0 to 2885.0
2018-03-26 09:54:22.947 [vent.ItemStateChangedEvent] - Gas_scale changed from 28.84000000 to 28.85000000
2018-03-26 09:54:22.967 [vent.ItemStateChangedEvent] - Gas_meter changed from 16714.13900000 to 16714.14900000
2018-03-26 09:54:23.007 [vent.ItemStateChangedEvent] - Gas_LastTime changed from 2018-03-26T09:54:06.813+0200 to 2018-03-26T09:54:22.974+0200

  • Issues
  1. not getting a value for:
        Water_Last_3H.postUpdate(Water_pulse.deltaSince(now.minusHours(3),"rrd4j") / 1000)
        logInfo("Rules", "Water last 3 hours scaled to: " + Water_Last_3H.state)

and

        Water_scale_D.postUpdate(Water_pulse.deltaSince(now.minusDays(1),"rrd4j") / 1000)
        logInfo("Rules", "Water day scaled to: " + Water_scale_D.state)

I assume, there is an error with my rrd4j persistence, because the chart in the sitemap does not show all values.

In addition to this post,

  • I would like to extend both rules with calculations of gas/water pricing.
  • I would like to have a chart, where the gas/water will be reseted, if lets say no consumption for 5 minutes exists. The chart should then identify consumption by peaks (like an impulse) to see for example the toilet flush needs 9l water and the short press only 4l or the washing machine needs 25l.
    … but this can be developed later on, by help of all of you. :wink:

…maybe there are already some usable code snippets for that…

thanks for any reply…

rrd4j Needs a strategy everyMinute in order to work correctly!

I would expect the chart to show nothing, confirm you do see values on the chart.

Well,
regarding the strategy “everyMinute”, I have changed it to:

Strategies {
    everyMinute : "0 * * * * ?"
    everyHour   : "0 0 * * * ?"
    everyDay    : "0 0 0 * * ?"
    default = everyChange
}

Items {
    Gas_pulse    : strategy = everyMinute, restoreOnStartup
    Gas_scale    : strategy = everyMinute, restoreOnStartup

    Water_pulse    : strategy = everyMinute, restoreOnStartup
    Water_scale    : strategy = everyMinute, restoreOnStartup
}

is it correct any recommendations?

The chart shows:

Due to that Statement:

I understood your Chart were not showing all values.

It looks to me as if you are lacking the .deltaSince values only. I’m actually not using those, therefor I have to look a bit deeper into them.

[Edit:]
In addition to your actual problems, how do you intend to use the persisted data in longer terms? By selecting rrd4j, you have selected a never growing database. Older data gets compresed (the default setup does hold a value for every minute only for the last 8 houres!). If you are not comfortable with that, you can change this setup.