Showing posts with label Home Automation. Show all posts
Showing posts with label Home Automation. Show all posts

Wednesday, May 1, 2024

Monitoring and controlling the swimming pool water level

Ever since I became owner of a swimming pool, a whole new set of chores and responsibilites were unlocked. Some are the repeating manual tasks of keeping the pool and the water clean for human use, while others are more technical and infrastructure related tasks that go along with keeping this very special reservoir of water that so much importance acquires in the hot days of summer.

While in a typical swimming pool some basic features are automated (for example controlling th pH, running the filtration or generating the correct amount of chlorine to disinfect the water), there are many others which by default are left to the intervention of a human.

One of the aspects that got me particularly concerned was the maintenance of the correct water level not being an automated process. Especially during the summer, a substantial amount of water is lost every day (at least 5 mm per day - depending on the environmental temperature and humidity). The water level dropping too much is problematic, because as the level approaches the bottom of the skimmer opening, it will cause the pump to ingest air, cavitate and unprime. If this persists for too long the pump will get damaged as its seals and bearings will seize in the absence of water.

With that in mind, I tried to come up with a solution with the following aspects in mind:

  • simple design without many failure modes;
  • be as much as possible based on off-the-shelf and easy to replace components;
  • possible to monitor and remotely control if necessary;
  • integrate with home automation;
  • physically discrete and without any aesthetical impact to the swimming pool and its surroundings;
  • not very expensive to implement and maintain.
While there are different types of solutions that one way or another cover the water level control aspect, these are in general either expensive, limited in terms of integration with other home automation platforms, or impossible to control remotely.

As such I decided to call for my ingenuity, and put together a custom solution that would tick all the boxes.

So basically the solution needed two components: a sensor installed in the swimming pool to detect the low level, and an automatic valve to inject tap water.

The sensor

Because I had good experience with Zigbee devices for their long battery life and ease of integration with home automation platforms, I decided to go for a very particular approach in respect to the sensor: retrofit a Aqara water leak sensor the serve the opposite purpose - detect lack of water instead of presence:

While ideally I would be looking for a proportional indication of the water level, so that for example I could also detect an excessively high water level (which will occur when it rains heavily), I could not readily find a solution that would not imply much more complexity and eventually custom parts.

The simplest approach would be to place this sensor inside the swimming pool, and have it setup so that when it would not detect water, the home automation would kick in and activate a valve. This would be the most basic approach . However it would have some implications: first, even though the Aqara sensor is waterproof, it is likely not designed to be permanently in contact with the water, and especially not water containing a certain concentration of chlorine and other chemicals. Also placing the sensor practically at the water level would seriously degrade the Zigbee signal strength. Lastly, as the water oscillates most of the time, debouncing logic would have to be added to ignore the false positives.  This would also carry the implication that battery life would probably plummet, as the device would have to transmit much more often than normal.

This led me to think about a slightly more sophisticated approach. First, as I did not trust the sensor to be robust enough to tolerate being in contact with the water, I went for designing a custom enclosure where the Aqara sensor could be mounted inside and stay safe and dry all the time.

Because I became accustomed with modelling 3D objects for functional purposes since I bought a 3D printer, it proved to be a no brainer approach to create this enclouse myself and print it.

And so it was. The idea was to use a float switch connected to the Aqara sensor electrodes, so that when the water level would be low, the switch would close and trigger the sensor. For convenience and for keeping it visually discrete, the most logical choice was to put the device inside the skimmer cavity, supported under its cover:

Soon I learned that leaving the float sensor directly exposed to the water surface would lead to a lot of detection events, even while the water level was still substantially high.

This first version was still not based on 3D printed parts but rather on off the shelf parts cobbled together. Soon I found that the plastic enclosure was not a good solution as it would crack and let water in.

That is when I decided to make a 3D printed enclosure from scratch.

This enclosure would solve the excess events issue by measuring the water level not directly from the pool surface, but from the level of water inside a cup that would be part of the bottom of this enclosure:

This cup forms a kind of low pass filter for water waves: as the water is only be allowed in via small orifices, it takes some time for the level to rise and lower, effectively providing a damping behaviour to the variations in the water level as observed in the surface of the swimming pool.

So far, the resin material of the enclosure did not show any signs of wear due to the water or the chemicals present in it, and proved effective at keeping the sensor protected from water ingress. At the top cover right at the end of the threading, I have added a rubber seal, which is essential for keeping the enclosure water tight.

The actuator

With the sensor aspect resolved, it was time to cover the other aspect of the solution: how to automatically inject water into the swimming pool when needed?

Slightly overwhelmed with the idea of messing around with the swimming pool hardware, at first I considered using a modified sprinkler to send a jet of water to the swimming pool directly. But this idea seemed a bit cumbersome and would inevitably make the solution less discrete than desirable.

That is when I realized that it would not be such a big challenge to tap into the PVC pipes initially desiged for the installation of a heat pump:

With these I could effectively inject water into the swimming pool in a very discrete manner. Because the public water supply has a much superior pressure compared to the pool filtering pump (4 + bars compared to less than 1 bar for the latter), there should be positive flow even when the pump is running.

As so it was. I had to study a bit of plumbing in order to determine what fittings I had to buy and how to glue PVC-U piping parts together, but at the end it was a success:

Basically I had to add a 2" pipe  to 3/4" inch reduction fitting, followed by a 3/4" elbow, followed by a retention valve (I wanted to make sure it would not be possible to have water from the swimming pool flowing towards the water supply - however unlikely that would be because of the pressure differences). Lastly the most important bit, the electronic valve that would open the water for injection.

For that I have chosen the GiEX QT06 Zigbee solenoid valve. This valve is normally used for garden irrigation, and it has the interesting feature of having a flow sensor that measures the injected water. Very useful for this application as well.

Before this valve I am also using a motorized ball valve which acts as a safety valve which I can close when not injecting water into the pool or having the irrigation running from the public water supply:

The integration of this valve is a bit more custom and uses a ESP8266 Wifi controller running Tasmota.

Because I am using Home Assistant as the "brains" of the house, and multiple Tasmota and other devices that communicate via MQTT messages, for integrating with these Zigbee devices I resorted to using a Sonoff Zigbee bridge flashed with Tasmota ( and Zigbee2Tasmota (on the Zigbee coordinator chip).

Then with all the hardware prepared and the Zigbee devices paired to the bridge (very simple procedure, some information can be found here -, this is where all the fun begins. 

Configuring Home Assistant

On HA we need to define the entities that correspond to the Zigbee devices we are adding. In this case the level sensor and the valve.

For the valve I defined the following MQTT switch in the HA configuration.yaml file:

    - name: swimming_pool_water_injection
      state_topic: 'tele/zbbridge/SENSOR'
      value_template: >
        {% for key, value in value_json.ZbReceived.items() %}
          {% if 'Name' in value and value.Name == 'valve' %}
            {% if 'WaterState' in value %}
              {{ value.WaterState }}
            {% endif %}
          {% endif %}
        {% endfor %}
      command_topic: 'cmnd/zbbridge/zbsend'
      qos: 1
      payload_on: '{"device":"valve","Write":{"WaterState":1}}'
      payload_off: '{"device":"valve","Write":{"WaterState":0}}'
      state_on: '1'
      state_off: '0'
        - topic: "stat/zbbridge/RESULT"
          payload_available: true
          payload_not_available: false
          value_template: "{{ (value_json['ZbStatus3'] | selectattr('Name', 'eq', 'valve') | map(attribute='LastSeen') | first | int) < 14000 }}"
      retain: false

This implies that we first gave the valve a friendly name on the Zigbee bridge, via the ZBName command. For example in the Tasmota console:

zbname 0x2916,valve

Regarding the sensor, I have defined the following MQTT binary_sensor:

    - name: swimming_pool_level_low
      state_topic: "tele/zbbridge/SENSOR"
      value_template: >
        {% for key, value in value_json.ZbReceived.items() %}
          {% if 'Name' in value and value.Name == 'level-sensor' %}
            {% if 'Water' in value %}
              {{ value.Water }}
            {% elif 'ZoneStatusChange' in value  %}
              {{ value.ZoneStatusChange }}
            {% endif %}
          {% endif %}
        {% endfor %}
      device_class: problem
      payload_on: '1'
      payload_off: '0'
        - topic: "stat/zbbridge/RESULT"
          payload_available: true
          payload_not_available: false
          value_template: "{{ (value_json['ZbStatus3'] | selectattr('Name', 'eq', 'level-sensor') | map(attribute='LastSeen') | first | int) < 3300 }}"

This exposes the Zigbee level sensor as a binary sensor in Home Assistant, allowing it to be used in monitoring and automations.

For the automation I considered important to add some hysteresis (not trying to compensate the water level on every received event), and alert and give up if it tries to compensate too often:

- id: swimming_pool_water_level_low
  alias: swimming_pool_water_level_low
    - platform: numeric_state
      entity_id: sensor.total_swimming_pool_level_low
      above: 3
    condition: and
      - condition: template
        value_template: "{{ (as_timestamp(now()) - as_timestamp(state_attr('automation.swimming_pool_water_level_low', 'last_triggered')) | float) / 3600 >= 24 }}"
      # Data is only valid if it is being updated through the Zigbee gateway. If it is down, we cannot trust the sensors:
      - condition: template
        value_template: "{{ states('sensor.zbbridge_wifi_connect_count') != 'unavailable' }}"
      - condition: numeric_state
        entity_id: sensor.level_sensor_last_seen
        below: 3100
    - service: script.multi_notification
        title: "Swimming pool level low!"
        message: "Swimming pool level low! Compensating level."
    # Set the zigbee valve to track the water quantity:
    - service: mqtt.publish
        topic: "cmnd/zbbridge/zbsend"
        payload: '{"device":"valve","write":{"WaterMode":1}}'
    - delay:
        seconds: 4
    # Set the desired water quantity:
    - service: mqtt.publish
        topic: "cmnd/zbbridge/zbsend"
        payload: >-
          {% set target_volume =  states('input_number.swimming_pool_water_injection_amount') %}
          {{ {"device":"valve","write":{"IrrigationTarget":target_volume}} | tojson }}
    - delay:
        seconds: 4
    - service: switch.turn_on
        entity_id: switch.swimming_pool_water_injection
    - service: switch.turn_on
        entity_id: switch.garden_valve

This automation will only starting injecting water if the level is low for more than 3 hours. Also it will refuse to compensate if the last time it injected water was less than 24 hours ago. Because this Zigbee valve has a flow sensor, we are able to tell it exactly how much water (in 1 liter increments) we want to add to the swimming pool.

Once all of this is setup I can monitor everything from the distance of a web browser and a comfortable chair:


With this solution I was able to monitor the water level, have Home Assistant inject water automatically and have one less thing to worry about especially in the Summer where this solution is most necessary as I am physically away from the site to be able to inject water manually.

In the future I plan to also support the opposite, which is to be able to remove excess water when the level is above the skimmer opening. This is also an important addition because in the most rainy periods of the year water will regularly rise above the skimmer port and render it ineffective at colecting debris. Also there is the risk of water infiltrating behind the liner, causing problems to the adhesion between the latter and the pool walls, ultimately leading to its detachment.

Sunday, November 22, 2020

Continuing with the Kiosk project

It is fairly interesting that just as with other "things" that I have equipped my house with, this Kiosk and other IoT gadgetry proved to be of relevance not just for my geek person, but for my family as well. For example my wife likes to keep track of the vacuum cleaner progress. Having its map and progress show up automatically when it starts cleaning, proved to be quite useful in this sense:

Sunday, October 18, 2020

Improving an RPI 2 based Home Assistant server for reliability and performance

For some time I have been using the same Raspberry Pi 2 v1.1 as the infrastructure for my instance. It proved to perform quite reliably over the approximately 18 months I have been using it 24x7. From that time during approximately 1 year I used the same SanDisk Ultra XC I 64 GB MicroSD card:

Just for precaution I have later switched to a similar card, a SanDisk Ultra HC I 32 GB, and moved my installation onto it:

Monday, April 27, 2020

Building a kiosk for Home Assistant from scrap parts - Part 2

With a project of this type, the hardware preparation is just the tip of the iceberg. It was thoroughly explained in the last post, despite one last change still being pending. What lacks is basically the addition of a resistive touch panel to the front of the screen, in order not to depend on the mouse as a pointer/input device. The panel is still somewhere between China and my location..

The first aspect that I found important to cover, now that I had this Android based kiosk up and running, was the ability to remote control it and launch arbitrary applications and services on startup.

Saturday, April 4, 2020

Building a kiosk for Home Assistant from scrap parts

It is great to have automation in the house providing increments of comfort such as eliminating manual tasks like cleaning the floor, or to aid in managing the energy consumption by turning off lights and appliances which are not in use, or in the safety side, by providing intrusion detection or monitoring the presence of gas leaks or other hazards, and executing the adequate actions.

Sunday, March 22, 2020

Tasmota-based multi-channel air quality sensor station

The sense of smell is an amazing function in vertebrate animals. Even the human nose, which is not particularly notable in comparison with other animals, is fascinating in its sensitivity to trace amounts of a large variety of substances. It has a level of selectivity and capability of distinguishing between different kinds of smells, which is very difficult to match by even the most sophisticated artificial sensors.

Having as the main motivation the enrichment of the IoT gadgetry sitting around in my house (and eventually fill up an entire network address range), I found that (after the motion and entrance detection device), an interesting device to invest time on would be something capable of sensing multiple air quality parameters at the same time.

Sunday, December 29, 2019

Ghost switching can be a bitch if your switch is your main circuit breaker

On my way to eat my own dog food, I learned the hard way that ghost switching is kind of the default problem most people will stumble upon when setting up their MQTT switch for the first time.This is not a big deal when you are configuring a single light switch or some other not so critical appliance. But when your switch is in series with your main circuit breaker, ghost switching suddenly gains a whole different level of importance.

Sunday, December 22, 2019

ZMAi-90 (or SMTONOFF WDS688) DIN rail meter/switch - more details on GPIOs and configuration

As an update to the previous post where I have shared the details on how to "Tasmotize" this device, I am adding more detail on what is the physical assignement of GPIO pins from the ESP8266, to other components in this device.

Given the pins from the ESP8266 microcontroller that are exposed in its breakout board (which in turn is SMD soldered to the main PCB):

Saturday, December 14, 2019

Intrusion / motion / door opening detector using a NodeMCU, some sensors, and Tasmota

The Espressif Systems chip manufacturer kind of created a revolution by opening the door to the creation of dirt cheap chips for building IoT devices. Its low cost led to introduction in the market, of many types of home automation devices, such as switches, light dimmers, smart bulbs, HVAC systems and what not.

On par with that, the open source community quickly became an interested party as well, and this led to the introduction of tools for quickly allowing developers to write interesting applications for practically anything based on these chips. It is the case of the Arduino core for the ESP8266 chip - This allowed for Arduino IDE accustomed developers, to write their own code, and either replace the original firmware on commercial devices featuring the ESP8266, or use open-source board designs such as NodeMCU and build their own custom devices.

Friday, November 22, 2019

Attempting to reverse engineer a home automation oriented smart-meter - Part 1

In my quest to make my house smarter, but still looking forward to keep having control over it, I have been doing some additions which I plan to further document here, in the short term.

In the meantime I thought it would be more relevant to share my findings in regard to a device a bit more "exhotic" than the Sonoff boxes we are all used to. This device is a sort of a miniature smartmeter that fits in a DIN rail next to the circuit breakers.

Just like the Sonoff modules, it also pairs with your WLAN, and connects to a cloud service. Instead of the eWeLink cloud to which Sonoff devices connect to, in this case it connects to another relatively popular cloud service called Tuya.

Wednesday, October 30, 2019

Waking up devices in (Home Assistant)

This is a quick post on a challenge I had to overcome while integrating my SmartTV (an LG TV 55UJ620V) with

I wanted to be able to turn on the TV (as such allowing automations to be built on top of it, or for example turning it on through a voice command via Google Assistant). As such I first resorted to using the Home Assistant Wake on LAN built in integration ( It kind of worked, but was not very reliable (perhaps 2 out of 5 times it would work).

I knew that by definition, the way that (Wake-up On LAN) WOL is implemented is inherently unreliable: essentially the target (dormant) device is expecting a frame with a specific pattern of bytes. If it receives that frame, it wakes up the host, otherwise nothing happens. The device will normally scan for that pattern of bytes in the frame regardless of the type of transport level protocol it may be on top of. In the case of WiFi in particular, there is the probability (high or low, depending on the network conditions) of that single frame not reaching the destination. This probability increases with the more hops we have in between.

With this implementation I was requiring the magic packet to be sent from a host (the Raspberry Pi where I keep running) that is in a separate router vlan, from where the TV is (these are connected via Ethernet and WiFi respectively):

Monday, October 28, 2019

Building a kick-ass home automation by reflashing the Sonoff devices with Tasmota and getting it all working with

For some time I have been gradually bringing more devices to my house, which are either designed or having features allowing these to be integrated to a home automation system.

In spite of all the concerns that can arise from bringing smart/connected devices to the place where you expect personal privacy to exist, the convenience of having these ends up speaking louder overall..

It all started with having a set of unrelated devices in the house, each featuring connectivity and some cloud-based features provided by the vendor. This is the case for the Xiaomi Rockrobo vacuum cleaner, the Sonoff switches, the multimedia devices such as the TV set (an LG smartTV), and also the Google Chromecast and Assistant devices.