The Nightmare Before and During Christmas

Okay, now that the storm is over I can update you on how HestiaPi saved my (basement’s) life during Christmas holidays.

[Ask and comment on the dedicated community forum thread.]

I was working at my basement when I realised there is a leak and drops were coming down from the ceiling. I naturally put a bucket underneath and went ahead to identify the actual problem. About an hour later I had found the cracked pipe but the plumber wouldn’t be coming for a week.

Threat level: Substantial

So I said, oh well, I’ll be emptying the bucket once a day and I can survive. It ended up having to check twice a day as the flow was not regular. One morning I was greeted by water on the floor πŸ™ Not your average holiday morning.

Threat level: Severe

So I did what every hacker does in these situations! Got my electronics parts box out and fired up my favourite code editor! A couple of hours later I had a larger bucket to collect the water, a water level indicator inside it, a threshold and notifications enabled on my phone. Oh and a graph of the level against time.

Network coverage was not great so I colour coded the age of “Last Message” timestamp to spot outdated info.

A NodeMCU was checking the analog value of the water level sensor and sending it to HestiaPi (OpenHAB) via MQTT over WiFi. A few extra lines in items, rules and sitemap file and it was live. I could finally relax by the fireplace… Or so I thought.

Checked level before going to bed. Woke up in the morning to another flooded basement πŸ™ Someone from our building used the washing machine producing a lot of “drops” overnight, overfilling the bucket. You can guess the rest.

Threat level: Critical

It became obvious that notifications were not enough and my system had to react to the water level! I had a little 12V pump for a pond I never used, so adding a relay in the digital pins of NodeMCU, adding one more line of code and subscribing to a different MQTT topic (hestia/flood/pump) I could control the pump from my phone. A hose would send the water out through an airing hole.

Lastly I created a rule to turn the pump on when the level is above the threshold and let me know with a notification on start and end of the pumping. To fine tune it I added another threshold for a min and max level to avoid turning the pump on for a few seconds too often.

The flood level reported is inverted. 102 (aka int(1024/10)) means no water. 0 is fully submerged.

Okay, I am biased but I really loved how quick and easy I could build from scratch such a system. Especially these days of the year that coding and soldering should be left aside.

Here are the file changes needed:

custom.items

Group chart_flood
Number chart_period_flood "Period"
Number FloodLevel "Flood Level [%.0f]" <faucet> (chart_flood) { mqtt="<[mosquitto:hestia/flood/waterlevel:state:REGEX((.*?))]" }
Switch FloodPump "Flood Pump" { mqtt=">[mosquitto:hestia/flood/pump:command:ON:1],>[mosquitto:hestia/flood/pump:command:OFF:0]" }
Number FloodLevelSetpointMax "Flood Level Max[%.0f]" <alarm> (chart_flood)
Number FloodLevelSetpointMin "Flood Level Min[%.0f]" <alarm> (chart_flood)
DateTime FloodLevelLastMessage "Last Message [%1$ta %1$tR]" <time>
String FloodLevelIP "Flood Level IP [%s]" <network> { mqtt="<[mosquitto:hestia/flood/ip:state:REGEX((.*?))]" }

custom.rules

rule "InitialisationCustom"
when
    System started
then
  FloodPump.sendCommand("OFF");
  if(FloodLevel.state == NULL) postUpdate(FloodLevel, 100)
  if(FloodLevelSetpointMin.state == NULL) postUpdate(FloodLevelSetpointMin, 90)
  if(FloodLevelSetpointMax.state == NULL) postUpdate(FloodLevelSetpointMax, 40)
end

rule "FloodSensorCheck"
when
  Item FloodLevelSetpointMin changed or
  Item FloodLevelSetpointMax changed or
  Item FloodLevel changed
then
  if (FloodLevel.state > FloodLevelSetpointMin.state){
    FloodPump.sendCommand("OFF")
  } else if (FloodLevel.state < FloodLevelSetpointMax.state){
    FloodPump.sendCommand("ON")
    sendNotification("myopenhab-account-email-here", "Flood level at: " + FloodLevel.state + " !")
  }
end

rule "FloodSensorTimestamp"
when
  Item FloodLevel received update
then
  FloodLevelLastMessage.postUpdate( new DateTimeType() )
  logInfo("Default","FloodLevelLastMessage updated");
end

rrd4j.persist

Strategies {
  // for rrd charts, we need a cron strategy
  everyMinute : "0 * * * * ?"
  default = everyMinute
}

Items {
  TempSetpointChart,PreviousTempReading,TempMinSetpointChart,TempMaxSetpointChart,HumiSetpointChart,PreviousHumiReading,FloodLevel,FloodLevelSetpointMax,FloodLevelSetpointMin : strategy = everyMinute
}

default.sitemap

  Frame label="Flood Sensor" {
    Text item=FloodLevel valuecolor=[<=40="red",>60="orange",>80="green"]
    Switch item=FloodPump
    Setpoint item=FloodLevelSetpointMax minValue=10 maxValue=110 step=5 icon="alarm"
    Setpoint item=FloodLevelSetpointMin minValue=10 maxValue=110 step=5 icon="alarm"
    Text item=FloodLevelLastMessage valuecolor=[>6000="red",>600="orange",<=600="green"]
    Text item=FloodLevelIP
  }

  Frame label="Flood History" {
    Group item=chart_flood label="Flood Chart" icon="chart" {
      Frame {
        Switch item=chart_period_flood label="Period" mappings=[0="4 Hours", 1="Day", 2="Week"]
        Chart item=chart_flood period=4h refresh=120000 visibility=[chart_period_flood==0, chart_period_flood=="Uninitialized"]
        Chart item=chart_flood period=D refresh=120000 visibility=[chart_period_flood==1]
        Chart item=chart_flood period=W refresh=120000 visibility=[chart_period_flood==2]
      }
    }
  }

 

Ask and comment on the dedicated community forum thread.