Smart Control for Clean Water and Lower Energy Bills
Pool maintenance doesn’t have to be expensive or time-consuming. One of the biggest power consumers in any pool setup is the pump. While it’s essential to circulate water and distribute chemicals, many people run their pumps longer than necessary, especially on cooler days. Because the filter requirement is dependent on the temperature – the higher it is, the more filtration and circulation is needed.
So, instead of setting a fixed runtime, I use this rule of thumb:
Run the pool pump for one third of the maximum daily temperature (in °C) in hours.
For example:
- On a 30°C day → 10 hours of runtime
- On a 21°C day → 7 hours of runtime
- On a 15°C day → 5 hours is enough
This strikes a great balance between hygiene and efficiency: on hotter days, you prevent algae and bacterial growth; on cooler days, you save electricity without compromising cleanliness.
I’ve automated this using Home Assistant with a few template sensors and a single automation. Let’s break it all down.
Step 1: Perquisites
I use two helper variables and one integration in the below integration. Make sure they are available in your Home Assistant instance as well:
- A schedule helper called “poolpump_schedule” that I set to the desired maximum run times of the pump. The end value in the schedule defines when the pump will always shut down and the start value defines the earliest time the pump will start running.
- An imput boolean helper called “poolpump_automation” which controls if the automation is on or off.
- A weather forecast integration to give me the maximum temperature for that specific day. I use the integration AccuWeather. The sensor called “home_realfeel_temperature_max_0d” in below examples. If your integration has an other sensor for this, change the name accordingly.
Step 2: Create a Sensor to Calculate Pump Runtime
We start by calculating the runtime in hours, based on the daily maximum temperature forecast and adding a new template sensor to the configuration.yaml file. I use the add-on “file editor” to edit the configuration.yaml file.
template:
- sensor:
- name: PoolMaxTemp
unique_id: "PoolMaxTemp"
state: >-
{{ ((states('sensor.home_realfeel_temperature_max_0d'))|int(0) / 3) | round(0) }}
What it does:
- Input:
sensor.home_realfeel_temperature_max_0d
– this should be your weather integration’s forecast for today’s maximum temperature. - Logic: We divide that value by 3 to get the desired number of hours the pump should run. If you want your pump to run longer or shorter (depending on pool size, climate, sun, filter and chemicals) adjust the value accordingly (the smaller the number the longer to pump runs daily)
- Output: A rounded integer value (e.g., 30 for a 30.2°C forecast).
Step 3: Calculate How Many Hours Before 10 PM the Pump Must Start
The pump should run within a fixed time window — in my case, from 6 AM to 10 PM (a 16-hour window) set in the schedule. This next sensor determines how far back we need to count from 10 PM to ensure we get the required runtime. Because we aim to start the pump as late as possible and always shut it down at 10 PM (or whenever the schedule ends).
This sensor also gets added to the configuration.yaml:
- sensor:
- name: PumpDelayTime
unique_id: "PumpDelayTime"
state: >-
{% set pool_temp = states('sensor.PoolMaxTemp') | int(0) %}
{% set start_time = state_attr('schedule.poolpump_schedule', 'start') %}
{% set end_time = state_attr('schedule.poolpump_schedule', 'end') %}
{% if start_time and end_time %}
{% set duration = (as_timestamp(end_time) - as_timestamp(start_time)) / 3600 %}
{% if pool_temp <= duration %}
{{ (duration - pool_temp) | round(2) }}
{% else %}
0
{% endif %}
{% else %}
0
{% endif %}
What it does:
- Input: The number of runtime hours from the previous sensor “sensor.PoolMaxTemp”.
- Logic: We need to find out the time we have to wait after the schedule start time to make sure we start the pump as late as possible to shut it down at the end time of the schedule. Therefore we need to calculate the duration of the schedule (end time minus start time) and subtract the number of hours we plan to run the pump from that. This will give us the waiting time we have to wait after the begin of the schedule.
- Failsafe: If somehow the runtime is more than the difference in hours from the schedule (e.g. a forecast bug or general shorter schedule or longer run times), it defaults to 0 (start right at the schedule time without delay – but also not earlier).
Example:
If the Schedule is from 6 AM to 10 PM and the runtime is 10 hours (because max temp will be 30°C) and the end of the schedule is at 10 PM – 10 hours = 12 PM
So this sensor outputs 6, meaning “start 6 hours after 6 AM”.
Step 4: Automation to Control the Pump
Once all sensors are in place, we build an automation that controls the switch based on a schedule and the calculated start time.
Trigger: Trigger automation when schedule starts and stops
alias: Poolpump
description: "Control pool pump based on daily maximum temperature"
mode: single
triggers:
- entity_id:
- schedule.poolpump_schedule
from: null
to: null
trigger: state
What it does:
- The automation is triggered by the poolpump_schedule entity (in my case a schedule helper that defines the 6:00 to 22:00 availability window). The schedule makes it very easy to change the hours or have different hours on the weekends.
- It triggers when at every status change of the schedule – so, at the beginning and at the end.
Condition: Enable Automation Only if Allowed
conditions:
- condition: state
entity_id: input_boolean.poolpump_automation
state: "on"
This input boolean lets you manually override automation. Turn it off if you want to temporarily control the pump manually or perform maintenance. I added this as switch on my dashboard.
Actions: Wait Until Start Time, Then Turn On Pump
Because the automation is triggered at the minimum start time, we now have to wait for the actual start time. We calculated the waiting time in the “sensor.PumpDelayTime” sensor.
actions:
- alias: TurnOn
if:
- condition: state
entity_id: schedule.poolpump_schedule
state: "on"
then:
- delay: >-
{{
'{:02}:00:00'.format(states('sensor.PumpDelayTime')
| int) }}
- if:
- condition: state
entity_id: input_boolean.poolpump_automation
state: "on"
then:
- type: turn_on
device_id: -yourdeviceID-
entity_id: -yourentityID-
domain: switch
Here’s how it works:
- Delay: Waits until the desired number of hours have passed since 6 AM.
- Double check override: Verifies that the pump automation is still allowed. This is, just in case you disabled the automation during the time the automation already triggered and was waiting for the delay.
- Turns on the switch that controls the pool pump.
The turn-off is then automatically handled by the schedule in the same automation:
- alias: TurnOff
if:
- condition: state
entity_id: schedule.poolpump_schedule
state: "off"
then:
- type: turn_off
device_id: -yourdeviceID-
entity_id: -yourentityID-
domain: switch
Final Thoughts
By combining weather-based logic and time-restricted control, you create an intelligent pump automation that:
- Saves energy
- Adapts to daily conditions
- Runs during the warmest part of the day and the period you are most likely to use the pool
- Requires zero manual input once set up
If you’re ready to go even further, you can:
- Notify yourself when the pump is running
- Display start and stop times in a dashboard card for monitoring