Rule for leakage notification when water is constantly consumed

  • Platform information:
    • Hardware: Raspberry Pi 4 Model B Rev 1.2 (4GB RAM); SDD WDC_WDS500G1R0B-68A4Z0
    • OS: Raspbian GNU/Linux 10 (buster)
    • Java Runtime Environment: openjdk version “11.0.11” 2021-04-20 LTS
    • openHAB version: openHAB 2.5.12 Release Build

Dear Community,
I am tracking our water consumption of our water meter in the basement with a WeMos D1 Mini flashed with Tasmota and a proximity sensor in order to visualize our water consumption in Grafana. I am doing this like this (picture is from google but basically this is my setup and it works great):

Every time the metal plate gets detected by the blue tip of the sensor is equal to 1l water consumption. I am sending this information via MQTT to openHAB2.

Required Usecase:
Today I noticed that our toilet cistern is leaking and it wasted ~60l for a short period of time, visible in Grafana:

I would like to have a rule which sends me a notification if the consumption value is adding up (changing) frequently for a certain amount of time. How can I do this? Here are my two items to check the water flow and a proxy item to see when water was consumed the last time:

Number MQTT_Wasser_Zaehler "Wasser Durchfluss [%.0f l]" <flow> (gWasseruhr, gMQTT, gNumber,gCharts) {channel="mqtt:topic:MQTT_Bridge:MQTT_Wasser:MQTT_Wasser_Zaehler"}
DateTime Wasser_LetzteWasserentnahme "Wasser letzte Entnahme [%1$td.%1$tm.%1$tY %1$tH:%1$tM]" <time> (gWasseruhr, gVirtual, gDateTime,gHistory)

With this rule I Update Wasser_LetzteWasserentnahme:

rule "Wasserentnahme"
    Item MQTT_Wasser_Zaehler changed
    if (MQTT_Wasser_Zaehler.state > 0) {
        Wasser_LetzteWasserentnahme.postUpdate( new DateTimeType() )
    else if (MQTT_Wasser_Zaehler.state == 0 ) {
        Wasser_LetzteWasserentnahmeReset.postUpdate( new DateTimeType() )

Item MQTT_Wasser_Zaehler is persited with influxdb for now. I also use mapdb persistence service.

Any idea how to do this?

1 Like

Quite an interesting puzzle, what to check for. Presumably you may consume water in fairly large amounts for a short time, e.g. run a bath, so a simple average won’t do. Maybe the thing to look for is a few spot-checks to see if it is ever zero. Perhaps start a timer from a zero=to=positive transition, if it doesn’t return to zero in the next X minutes/hours, ring a bell.

1 Like

I’d try something like the following.

  • Trigger the rule on changed.
  • Take the absolute value of the difference between the previousState and the newState.
  • If the difference is positive set a timestamp.
  • If the timestamp becomes beyond a certain point in the past you know that the water usage has been going up and down for at least that long without any period of zero usage.
  • Once the difference returns to 0 (maybe a few zeros in a row) reset the date time to null or something to indicate no leak was detected.

From there you may need to tune it. For example, use a running average from persistence or something like that.


Dear folks,

sorry for the delayed response but thanks for your reply. I tried to take your input into my next steps and I think I got a little bit further but my approach is not working. Maybe you can give me another hint. Let me set some assumptions before:

  • I don’t receive zeros from the WeMos D1 via MQTT, always the absolut number for MQTT_Wasser_Zaehler
  • I don’t need to check at the absolute number change of MQTT_Wasser_Zaehler, I am more looking for the constant change of this value
  • The measurements are taken from the fresh water pipe, hence ice-cold water. Taking longer showers wont directly impact the measurements because the warm water comes from the heating boiler. No one takes cold showers here :blush:

I tried to get closer with my rule adjustments, taking your input into account:

  • Work with an additional counter Entnahme_count
  • Try to compare the updated Wasser_LetzteWasserentnahme.state with Wasser_LetzteWasserentnahme.previousState but I run into an error in the logs.

This is my new modified rule including comments for what I want to achieve in every step:

var int Entnahme_count = 0

rule "Wasserentnahme"
  Item MQTT_Wasser_Zaehler changed
  val val_Wasser_LetzteWasserentnahme_Neu = new DateTime(Wasser_LetzteWasserentnahme.state.toString)            //get DateTime of recent change
  val val_Wasser_LetzteWasserentnahme_Alt = new DateTime(Wasser_LetzteWasserentnahme.previousState.toString)    //get DateTame of previous change before
  if (MQTT_Wasser_Zaehler.state > 0) {
    Wasser_LetzteWasserentnahme.postUpdate( new DateTimeType() )                                                //update Wasser_LetzteWasserentnahme if water was consumed
    logInfo("Wasser", "Letzte Entnahme aktualisiert")
    if (val_Wasser_LetzteWasserentnahme_Neu.minusMinutes(10) > val_Wasser_LetzteWasserentnahme_Alt) {           //if new consumption minus 10 minutes is **greater** than the previous consumption, reset the counter
      Entnahme_count = 0
      logInfo("Wasser", "Entnahme_count reset")
    if (val_Wasser_LetzteWasserentnahme_Neu.minusMinutes(10) < val_Wasser_LetzteWasserentnahme_Alt) {           //if new consumption minus 10 minutes is **less** than the previous consumption, add +1 to the counter
      Entnahme_count = Entnahme_count  + 1
      logInfo("Wasser", "Entnahme_count addiert")
    if (Entnahme_count > 10) {                                                                                  //if counter reaches 11 or more, broadcast a push notification (yes, every change from now until the time span increases)
      sendBroadcastNotification("Auffällige Wasserentnahme", "faucet", "Wasser")
      logInfo("Wasser", "Auffällige Wasserentnahme")
  if (MQTT_Wasser_Zaehler.state == 0 ) {
    Wasser_LetzteWasserentnahmeReset.postUpdate( new DateTimeType() )

Unfortunately, somethings seems to be wrong regarding the to val of Wasser_LetzteWasserentnahme. This is what I get from the logs if the rule is fired:

2021-12-16 22:06:02.844 [vent.ItemStateChangedEvent] - MQTT_Wasser_Zaehler changed from 306 to 307
2021-12-16 22:06:02.853 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Wasserentnahme': cannot invoke method public java.lang.String java.lang.Object.toString() on null

Can you enlight me what might be wrong? Is there another approach to check the difference between the new DateTime Wasser_LetzteWasserentnahme and the previous Wasser_LetzteWasserentnahme?

Thanks and best regards,

The Item doesn’t have a simple previousState method. You can’t make syntax up; looking at examples you’ll find two separate similarly named functions:
An implicit variable, derived from the event that triggered the rule

A persistence query function - thisreturns a record including timestamp info, as well as state.

If it were me, I’d take a step back here. You are likely to find a “flowrate” value generally useful, not least because you can chart it while working out strategies to work with it.

So create a “Current Flowrate” Item, and design a calculation to populate it. That’s a function of time and your ‘absolute’ meter reading, as I understand it?
Does your reading come at regular intervals? That makes it easier. Else you must examine time since last reading, as well as previous reading, to work it out.

Once that’s done, it is separate business to act on it.