Automating pool pump / filter on/off that changes according to the season


  • I have a pool pump that I can control via Tasmota

  • a solar panel that reports:

    • how much power it’s generating
    • how much power I’m using
    • how much it is drawing from (positive number) or “exporting” back to the grid (negative number, i.e. the excess usage).
  • I live in a mild 4 season area. In winter we are told to run the pump only for 3 hrs a day, but in summer 8hrs a day

  • As much as possible, I want to run the pool pump only when my solar panels are generating enough excess power.

Additionally, I have set Tasmota:

  • Not to power on automatically: PowerOnState 0
  • As a fail safe, to turn on the pool pump at 10am every day. I assume that openhab rule will turn it on before this time and not turn it off before this time
  • With “PulseTime” of 8 hours, so the maximum amount of time the pump will run is 8 hours and it will automatically turn off by itself even if Openhab happens to be down.
  • Another fail safe, have another schedule to turn off the pump at 6pm. This is because when the pump is turned off due to cloudy conditions and turned back on, pulsetime will reset for another 8hrs. This is just in the event of openhab losing connection with Tasmota after turning off/on. Thanks to @powerpolly for pointing this out.


  • Don’t forget to set the time on your Tasmota:
Time 0
TimeZone +10
TimeDST / TimeSTD as appropriate

So for now I’m using the following simple rules to turn the pump on/off:

sun_elevation_threshold = 34
solar_grid_threshold = -2000

@rule("Pool pump ON")
# don't want to turn it on too early regardless of solar power / sun elevation
@when("Time cron 0 */30 8-16 ? * * *")
def pool_pump_on(event):
    if items.Pool_Pump == ON:

    if items.Sun_Elevation.intValue() < sun_elevation_threshold:

    # Solar_Grid_Power is negative when exporting the excess power
    if items.Solar_Grid_Power.intValue() < solar_grid_threshold or isinstance(items.Solar_AC_Power, UnDefType):"Turning on the Pool Pump via cron rule")
        events.sendCommand("Pool_Pump", "ON")

@rule("Pool pump OFF")
@when("Time cron 0 */30 14-18 ? * * *")
def pool_pump_off(event):
    if items.Pool_Pump == OFF:

    # Turn it off when the solar power is low (cloudy?) or the sun is low
    if items.Solar_Grid_Power.intValue() > solar_grid_threshold or items.Sun_Elevation.intValue() < sun_elevation_threshold:"Turning off the Pool Pump via cron rule")
        events.sendCommand("Pool_Pump", "OFF")

This is a very simplistic rule, and I haven’t really tested how it goes. No doubt it will need some tweaking.

  • Even in summer, the pump won’t turn on when it’s very cloudy that the solar panels aren’t generating much power. At the latest, Tasmota will turn it on at 10am.
  • Even in summer, if it gets cloudy at 2pm, it will turn it off. However, what if it happens to be cloudy just when the cron rule kicked in but otherwise not cloudy after that? The “Pump ON” rule will kick in 30 minutes later.
  • The power threshold of 2000 (2kW) is arbitrary and it would depend on how much your system normally generates of course. It would need tweaking.
  • I’ve chosen the sun elevation threshold of 34 which seems to be suitable for my location. I derived this number by experimentation with the help of

Comments / Suggestions?

Nothing to add. It looks good. My only suggestion, which I did myself, was to move this to the Tutorials & Examples: Solutions category. Thanks for posting!

just two thoughts:
1.) if your Solar Power drops because a cloud came by, your rule powers OFF your pump. Take care about the PulseTime setting. If your pump ran already 6 hours when Power drops below 2kW but came back again, your pulsetimer will start again for a 8h runtime…

you could calculate the remaining pool runtime and adjust the tasmota pulsetime with openhab rules.

2.) I don`t see how you adjust the runtime between seasons eg limit runtime to 3hrs in winter.

I’m also controlling my pool pump runtime with tasmota, but based on the temperature of the water. the purpose for this is just to save energy and I do not have any kind of water heating.

the tasmota flashed sonoff I use to switch pump and lights is just at the edge of my wifi router and often loosing the connection followed by reboots which also resets the “PulseTime”. So, to get a maximum of reliability I created three tasmota-rules which power ON/OFF the pump at specific times. openhab just reads the temperature and selects tasmota-rules by issuing MQTT actions. by this, my pool should survive a multi-week openhab outage.
my future task: tasmota rules are IF THEN ELSE capable since some time, so I could completely trigger the pool runtime within tasmota. => winter-project :slight_smile:

val mqttActions = getActions("mqtt","mqtt:broker:myBroker")
var Number tasmotarule = 2 

rule "Pool Temp changes"
        Item Pool_Temp changed or 
        Item Pool_season changed    //an administrative switch item that tells if pool is operation (we empty the pool in winter)
        var currenttmp = Pool_Temp.state as DecimalType 
        var yesterdaytmp = Pool_Temp.historicState(now.minusHours(24)).state as DecimalType 
        var proz = Math::round(((currenttmp * 100 / yesterdaytmp) - 100).floatValue())
        var String tmp = (currenttmp + " °C gestern: " + yesterdaytmp + " °C " + "Diff: " + proz + "%")
        logInfo("Pool Temp changes", tmp)
        if (Pool_season.state == OFF && tasmotarule !== 0) {
            mqttActions.publishMQTT("cmnd/Pool/Rule1", "OFF")
            mqttActions.publishMQTT("cmnd/Pool/Rule2", "OFF")
            mqttActions.publishMQTT("cmnd/Pool/Rule3", "OFF")
            tasmotarule = 0
            sendNotification("", "Sonoff Rules deactivated")
            logInfo("Pool Temp changes", "Sonoff Rules deactivated")
        else if (Pool_season.state == ON && Pool_Temp.averageSince(now.minusHours(12)) <= 17 && tasmotarule !== 1) {
            mqttActions.publishMQTT("cmnd/Pool/Rule1", "ON")
            mqttActions.publishMQTT("cmnd/Pool/Rule2", "OFF")
            mqttActions.publishMQTT("cmnd/Pool/Rule3", "OFF")
            tasmotarule = 1
            sendNotification("", "Sonoff Rule1 activated")
            logInfo("Pool Temp changes", "Sonoff Rule1 activated")
        else if (Pool_season.state == ON && Pool_Temp.averageSince(now.minusHours(12)) >= 19 && Pool_Temp.averageSince(now.minusHours(12)) <= 24 && tasmotarule !== 2) {
            mqttActions.publishMQTT("cmnd/Pool/Rule1", "OFF")
            mqttActions.publishMQTT("cmnd/Pool/Rule2", "ON")
            mqttActions.publishMQTT("cmnd/Pool/Rule3", "OFF")
            tasmotarule = 2
            sendNotification("", "Sonoff Rule2 activated")
            logInfo("Pool Temp changes", "Sonoff Rule2 activated")
        else if (Pool_season.state == ON && Pool_Temp.averageSince(now.minusHours(12)) >= 26 && tasmotarule !== 3) {
            mqttActions.publishMQTT("cmnd/Pool/Rule1", "OFF")
            mqttActions.publishMQTT("cmnd/Pool/Rule2", "OFF")
            mqttActions.publishMQTT("cmnd/Pool/Rule3", "ON")
            tasmotarule = 3
            sendNotification("", "Sonoff Rule3 activated")
            logInfo("Pool Temp changes", "Sonoff Rule3 activated")

tasmota rules are looking like this:
stat/Pool/RESULT = {"Rule2":"OFF","Once":"OFF","StopOnError":"OFF","Length":258,"Free":253,"Rules":"on Time#Minute=0 do Power1 1 endon on Time#Minute=360 do Power1 1 endon on Time#Minute=540 do Power1 1 endon on Time#Minute=720 do Power1 1 endon on Time#Minute=900 do Power1 1 endon on Time#Minute=1080 do Power1 1 endon on Time#Minute=1380 do Power1 1 endon"}

Thanks for your thoughts and suggestions.

I don’t want to change the pulsetime because I want it to be completely independent. Imagine if I changed pulsetime to 3hrs then openhab is down then it will remain having a pulsetime of 3hrs.

However, you do have a point there. In order to avoid the extra 8hr runtime, I’ll add another schedule on Tasmota to turn it off at 6pm, as a worst case / last resort.

I was thinking that the Sun_Elevation (an item from the astro binding) would automatically do that. In winter, the sun goes down earlier than in summer. I don’t know the exact threshold for Sun_Elevation, although there are web sites that does the calculation, e.g.

So I tried it for my lat/long: in July (Winter here) it looks like the sun (elevation) never goes above 40. Planetcalc has a nice interface to let me know the sun elevation at any time of the day by moving the mouse pointer.

This probably won’t work for me, because a) I have no idea how the water temperature relates to how long the pump should run, b) I have a salt water pool with a chlorinator, so the pump does need to run a certain amount of time to generate enough chlorine.

However, I’m curious how you’re getting the pool temperature data?

I’d like to be able to get the pool water level and control an automatic top up system, but I haven’t figured out what to use for the water level sensor that would look nice.

A quick playing around with planetcalc seems to give me an approximate sun elevation threshold of 34 which should work for my location.

  • In winter (July), the sun elevation goes below 34 at 1:30pm
  • in summer (january), the sun elevation goes below 34 at 4pm
  • I’ll have to check the sun elevation in the ON rule too - the sun needs to be above 34° for it to start.

I have never been able to reproduce it, but several people have reported that something will sporadically cause this method of accessing Item states to stop working. It is a neat bit of code, but it doesn’t really do anything but confuse people, because there are already a couple ways to get Item states. The other scripting languages also do not have this implemented, and not not be able to. For these reasons, I’ve considered removing this functionality, and I recommend getting Item states using…

if items["Pool_Pump"] == ON:

As for the rest, if the rules function for you, and you understand them, then they’re good! Personally though, I’d rework them to trigger on events from the Solar_Grid_Power Item rather than using cron, which would allow them to collapse into one rule. I’d also compare QuantityType to QuantityType, rather than stripping units.

All my scripts use this syntax! Could you point me to the topics discussing the issue please? I’m just curious to see if I could reproduce it. I can’t recall ever having a mystery related to it.

This issue comes up quite often in many situations. I chose cron because it would only fire a limited number of times, whereas Solar_Grid_Power would change every 5 seconds, 24 hours a day. I figured the cron approach reduces the load on openhab. What do you think?

there are online tools to calculate the runtime of your pump. someone told you to vary between 3hrs in winter and 8hrs in summer, so that are the ranges you can play with. In my case I was experimenting a bit, when water got green, I added another hour of runtime per day. I do have a ph dispenser, that is powered together with the pump and I vary between 4, 7 and 10 hours a day. works great for my pool setup.

I use a Sonoff Dual to control the pump on one relay and poollights with the other. I attached a DS18B20 to on of the free GPIOs and attached the sensor on the outside of my pool, adding a thick layer of styrofoam to isolate against air temperature

Every 5 seconds for a rule like this is probably fine, but you could easily use a global variable to drop out of the rule except for one in x times to limit the load. Better yet, reduce the frequency of power meter reports.

I’m sure there were more discussions about this, but…

Maybe this sensor is something your usecase.

I use it to monitor our cistern.