Sharing enlightening moments of home automation

Smarter Swimming Pool 3: Water Level

Water disappears from an outdoor swimming pool over time – naturally through evaporation or through a small leak in a pipe that is hard to detect. To some degree rain helps to balance the pool water level, but sometimes you will have to top up manually. If your pool is constructed like mine, then if the water is below a certain level, the pool pump will be unable to pull enough water, and instead you get air into the pipes with unwanted consequences. Filtering water is not working efficiently anymore, the cleaning robot might stop, the pump might be damaged (water cools it down).

So, to avoid having a too low water level, I needed some way to measure the current water level and if too low use that information to take actions.

For this particular purpose I do not actually need to know the exact water level or volume of the pool, but I just wanted to get a reminder when it’s time to refill the pool. Hence my decision fell on a simple water level float switch.

I ended up with a double-switch where the two floats are 5cm apart. That way I could have one switch at a level where I still have a couple of days until the pool pump start pulling in air, and a second switch at the critical water level line where it is almost certain that the pool pump won’t work properly anymore. On sites like ebay you should be able to find plenty of different versions – various different distances between the two floats, plastic vs. metal.

Building the device

In the following you will see how I extend the device that I have previously connected a water temperature sensor to. And again, I am showing how the connectivity looks like on a breadboard, but in reality I have mounted the sensors and the ESP board onto a prototype PCB.

Connecting the switches

The double-switch I bought is actually just two separate reed switches in a single enclosure. Each switch has its own connection cables, and hence each goes onto a separate input pin on the ESP board.

Sensor – Water Level Switches
Water Level SwitchESP
Switch bottomD1
Switch bottomVCC
Switch topD2
Switch topVCC

In addition, mount a 10kΩ resistor between GND and D1, and another 10kΩ resistor between GND and D2. These two resistors are pull-down resistors – one for each switch.

When connecting the switches, make sure you have the direction right. The floats can be removed and turned around if necessary. Since this is a water level switch that is supposed to warn if the water falls to a certain level, I turned the floats around so that each switch turns on when its float reaches its bottom position.

And, remember which switch is connected to which pin – the top switch is reporting a low water level, and the bottom one a critical water level.

Configuring ESPEasy

The general configuration of the device itself and its MQTT connectivity have already been covered in the previous post.

The WEMOS D1 mini Pro does not have a plethora of available digital pins, so I decided that I will need a few more pins for future expansion, but not need to connect I2C sensors. By default ESPEasy allocates pins D1 and D2 for I2C, and if you want to use them for non-I2C the following configuration change is required on the Hardware tab.

ESPeasy I2C configuration

Configuring switches

The water level switches are added as “P001 – Switch input” devices. Pick the right input pin (D2 and D1 in my case) and give each switch a name in the “Values” section at the bottom of the form. Don’t forget to check “Enabled” and “Send to Controller” and hit the “Submit” button.

ESPeasy water level sensor low configuration
ESPeasy water level sensor critical configuration

Make sure the switches work as expected by manually triggering them, or by dipping them into water and slowly pull them out to simulate a decreasing water level.

Once the sensor is reporting its values to the MQTT broker as expected I would also recommend to publish retained messages. That way Home Assistant always has a value to display after restarting. Go to “Tools” → “Advanced”, check the “MQTT Retain Msg” checkbox and click the “Submit” button.

Mounting the water level switches in the pool

Similar to the temperature sensor in the previous post, I used standard parts from a hardware store for the enclosure.

Water level sensor mounted

The top part of the enclosure consists of a piece of 25mm conduit, an elbow bend, a 25mm conduit plug, and a cable gland mounted into a hole drilled into that conduit plug.

The enclosure is held by a conduit mounting clip that is fixed with a screw and ramplug in the pool’s brick coping.

Water level sensor

The bottom holds the water level switch and because the switch is just 32mm wide and the conduit I used before is only available in 32mm, I could not use conduit anymore and had to use a larger pipe. My choice fell onto 40mm PVC pressure pipe that protects the whole switch, a 40x25mm reducing coupling, a 25x20mm PVC reducing bush and a 20mm PVC cap end.

I drilled a hole into the cap end and mounted the water level switch into the cap. The reducing bush just fits into the top end of the reducing coupling, and I used super glue to stick the cap with the switch to that reducing bush through the large end of the coupling.

Because the conduit and the pressure pipe are not really made for each other, I had to use some duct tape around the end of the conduit to make it tightly fit into the pressure pipe, and added a bit of super glue to keep everything together.

Water level sensor bottom

I drilled a couple of small holes into the back of the large pressure pipe to ensure that water can ingress.

The marks on the outside of the pressure pipe indicate the water level at which the switch turns on. This corresponds to the centre seam of the float.

Display switch states in Home Assistant

Setting up the sensors

The two switches are presented to Home Assistant as binary sensors. The state_topic corresponds to the previous configuration. To better distinguish multiple ESPEasy devices and sensors, I am using the entity_namespace reflecting the device’s name. This is combined with the sensor name to form the sensor’s entity ID.

  - platform: mqtt
    entity_namespace: espeasy_01_pool
    state_topic: "espeasy/espeasy-01-pool/waterlevel-low"
    name: "Water Level Low"
    payload_on: "1"
    payload_off: "0"
  - platform: mqtt
    entity_namespace: espeasy_01_pool
    state_topic: "espeasy/espeasy-01-pool/waterlevel-critical"
    name: "Water Level Critical"
    payload_on: "1"
    payload_off: "0"

Avoiding jitter

The water level switches are fairly sensitive to waves. So, if I was just using their on/off state directly to trigger any actions or notifications, a fun hour in the pool could cause the switches to turn on and off all the time and trigger actions more often than I would want. To avoid that I decided to wrap their states into a template sensor each that only turns on/off if the actual switch is on/off for at least 5 minutes.

  - platform: template
        value_template: "{{ is_state('binary_sensor.espeasy_01_pool_water_level_low', 'on') }}"
          minutes: 5
          minutes: 5
        friendly_name: "Water Level Low"
        device_class: safety
        value_template: "{{ is_state('binary_sensor.espeasy_01_pool_water_level_critical', 'on') }}"
          minutes: 5
          minutes: 5
        friendly_name: "Water Level Critical"
        device_class: safety

Hiding the raw data sensors

With the above template sensors in place, the original ones are not required to be displayed in the UI, so they can just be hidden. If you are using packages then the below configuration snippet can go straight into the package file together with all sensors and automations.

      hidden: true
      hidden: true

Display water level state in Home Assistant UI and HADashboard

At this point I can distinguish three water level states – normal, low and critical. The following template sensor definition combines these three states into a single sensor.

  - platform: template
        value_template: '{% if is_state("binary_sensor.pool_water_level_critical", "on") %}critical{% elif is_state("binary_sensor.pool_water_level_low", "on") %}low{% else %}normal{% endif %}'
        icon_template: '{% if is_state("binary_sensor.pool_water_level_critical", "on") %}mdi:close-circle{% elif is_state("binary_sensor.pool_water_level_low", "on") %}mdi:alert-circle{% else %}mdi:check-circle{% endif %}'
        friendly_name: "Water Level"

The below screenshot shows a point in time when the water level was low but not yet critical.

Pool water level panel

On my dashboard I do not need to show the details but just the overall water level state.

  widget_type: sensor
  title: Pool Water Level
  entity: sensor.pool_water_level
  value_style: "font-size: 150%"

I have not yet found a way to display a textual sensor state with an icon, but ideally it would be nice to show a large coloured icon corresponding to the sensor state.

Pool water level dashboard widget


Under normal circumstance I am not expecting to see the water levels changing frequently so I though sending myself a message might be helpful. The following automation sends a notification via Pushover whenever the water level changes. The message just show the textual value and since Pushover supports HTML formatted messages I use text colour to distinguish states.

  - alias: 'Report Pool Water Level'
      platform: state
      entity_id: sensor.pool_water_level
      service: notify.pushover
        message: "Pool Water Level changed to: <font color='{%- if is_state('sensor.pool_water_level', 'normal') -%}#0000ff{%- else -%}#ff0000{%- endif -%}'>{{states.sensor.pool_water_level.state}}</font>."
        title: "Pool Water Level"
          html: 1
Water level critical via Pushover
Water level normal via Pushover

Controlling the pool pump

The switch that is triggered by a critically low water level is at about height where the pool pump will not receive a sufficient amount of water to work efficiently.

A future improvement of my automated pool pump will be to check if the water level is not at a critical level, and if it is to either stop the pump or prevent it from starting.

Refilling the pool

Another future improvement could be to automatically refill the pool. At the moment I am not in a position to automate this task but my high-level idea would be to install an irrigation system that could pump water from a tap or rain water tank into the pool.

Ideally this automation should consider the weather forecast, i.e. if rain is predicted or a very hot sunny day, wait a bit. The other challenge when refilling the pool is – how much or how long? So, I would either need to have another pair of water level switches that indicate the preferred water level and the absolute maximum; or, I would need to measure how much water flows into the pool.


In my next post I will explain how I monitor the level of liquid chlorine remaining in a drum behind my pool that feeds the chlorinator. Please bear with me – this sensor still needs some more time to be mounted and fine-tuned.


At the time of writing this post, I used:

  • Home Assistant 0.57.2 with Python 3.5.1
  • ESPEasy v2.0.0-dev12 (dev_4096 build)
  • Wemos D1 mini Pro

Smarter Swimming Pool Series

  1. Pool Pump
  2. Water Temperature
  3. Water Level
  4. Liquid Chlorine Level
  5. Improvements Under the Surface
  6. Chlorinator Refurbishment
  7. Pool Gate


6 responses to “Smarter Swimming Pool 3: Water Level”

  1. Chris Hettinger Avatar
    Chris Hettinger

    This is fantastic! You truly have a mastery of Home Assistant! I have book marked your pages not just to use for my pool, but for overall learning of Home Assistant. Thank you for taking the time to publish this!

    1. malte Avatar

      Thanks for stopping by. The next article in my pool series is almost finished.

  2. Dave Avatar

    Would be cool to see a youtube on how you put this all together!

    1. malte Avatar

      You are right, that would have been cool. Unfortunately I did not take any videos when I built this sensor, but I’ll consider it for the next project.

  3. SemoTech Avatar

    For refilling the pool, just mount a normally closed solenoid water valve on the pool refill water pipe. Plug it into a smart outlet, and trigger it to open (power on the outlet) and thus allow water to fill the pool. You can setup an automation timer or tie it further with your water level to indicate when the outlet should turn off and thus water stop. I have built this exact thing for my pool, but could use a reliable water level measuring system…

    1. malte Avatar

      Thanks for the suggestion. My water level sensor is still working fine – refilling is still a manual process, but I use the water level sensor to tell me when a refill is needed and when I should stop.

Leave a Reply

Your email address will not be published. Required fields are marked *