Terrace Misting with a Zigbee Valve in Home Assistant
Our terrace faces south-east and gets full sun from mid-morning, and this summer it turned into a frying pan. The fix wasn’t an awning or a fan — it was a misting line: a row of fine nozzles that throw a fog so light you never feel wet, but the evaporation pulls real heat out of the air. On a 30 °C afternoon it takes the edge off by several degrees, right where you’re sitting.
The nozzles are the boring part. The interesting part is the tap. I didn’t want a system that runs whenever I remember to open a valve, or — worse — one that I forget to close and let dribble onto the patio for three hours. I know myself. So the water goes through a Zigbee valve controlled by Home Assistant, and two small automations do the thinking: one decides when to mist, the other makes sure it can never stay on too long.

The hardware: a battery Zigbee valve, not a mains one
The valve is a SONOFF SWV-ZNE Hydro ONE Lite Zigbee water valve*. A few things made it the right pick for a terrace misting line specifically:
- It’s battery powered (4× AA). No socket, no cable run to a wet outdoor tap. It sits on the garden faucet where mains power was never an option.
- Brass connector, standard garden thread. It screws onto the tap and the misting hose screws onto it. No plumbing.
- It’s a valve, not a “smart plug for a pump”. It opens and closes the water line directly.
- It needs a Zigbee hub — it does not talk WiFi and it does not need the vendor cloud. No account, no app, no weekly quota — a valve that simply answers when HA asks. That is the part that matters to me: the whole point of this site is that the value has to still work in a year, and a device that answers on my own Zigbee mesh will.
One honest limitation up front: the Lite has no flow meter. It can tell you the valve is open; it can’t tell you how many liters went through. For cooling mist that’s fine — I care about time, not volume — but if you want water-usage stats, that’s the wrong model.
In Home Assistant, once it’s paired to your Zigbee coordinator, it shows up as
a plain switch entity. Mine is switch.garden_sonoff_water_valve. That name is
all the misting logic needs — everything below just turns that switch on and
off.

The idea: short bursts on a duty cycle, not a garden hose
The mistake would be to open the valve and leave it open. You’d soak the terrace, waste water, and the cooling doesn’t actually improve — past a certain point the air is as humid as it’s going to get and the rest just runs off the furniture.
What works is a duty cycle: a short burst, a pause, another short burst. The fog stays in the air, evaporates, cools, and the pause lets it clear before the next one. My starting point is 2 minutes on, every 10 minutes — and only while it’s genuinely hot and sunny.
Automation 1: mist when it’s sunny and above 28 °C
This is the whole cooling logic. It runs on a time pattern, checks the weather, and pulses the valve:
alias: "Atomizer misting - sunny and above 28C"
description: >-
Garden atomizer cooling. Every 10 minutes, if the weather is sunny and
outdoor temperature is above 28C, run the SONOFF Zigbee water valve for
2 minutes then close it. Duty cycle (2 min on / 10 min interval) is a
starting point - adjust the delay and the time_pattern to suit the misting
nozzles. Only fires while 'sunny', so it is inherently daytime-only.
triggers:
- trigger: time_pattern
minutes: "/10"
conditions:
- condition: state
entity_id: weather.forecast_home
state: "sunny"
- condition: numeric_state
entity_id: weather.forecast_home
attribute: temperature
above: 28
actions:
- action: switch.turn_on
target:
entity_id: switch.garden_sonoff_water_valve
- delay:
minutes: 2
- action: switch.turn_off
target:
entity_id: switch.garden_sonoff_water_valve
mode: single
A few deliberate choices in there:
- The trigger is time, the weather is a condition. The automation wakes up every 10 minutes regardless, then asks “is it sunny and over 28 °C?” and only mists if both are true. That’s cleaner than trying to trigger off the temperature crossing a threshold.
weather.forecast_homeprovides both checks. Thesunnystate keeps it daytime-only for free — at night the state isn’tsunny, so nothing fires, no separate sun-elevation condition needed. Itstemperatureattribute is the current outdoor reading. If you have a real outdoor temperature sensor, point the numeric condition at that instead — it’ll be more accurate than a forecast.mode: single. If a run is somehow still going when the next tick arrives, don’t stack a second one on top.
That’s it. Sit on the terrace, and every ten minutes you get a two-minute whisper of fog while the sun’s out.
Automation 2: the failsafe that stops it flooding
Here’s the part I’d argue matters more than the cooling itself. A valve on a
water line is a small liability: if it’s ever left open, it doesn’t beep or
warn you — it just keeps running, patiently, until somebody notices. HA could restart mid-cycle (right after the
turn_on, before the turn_off), someone could flip the switch by hand in the
app, or a future edit to automation 1 could leave a path where the close never
fires.
So there’s a second, independent automation whose only job is: if the valve is on for 5 minutes straight, force it shut.
alias: "Atomizer failsafe - close water valve if open too long"
description: >-
Safety net for the garden atomizer. The misting automation opens the valve
for 2 minutes at a time, so the valve should never be open for 5 minutes
straight. If it is (HA restarted mid-cycle, manual toggle, stuck
automation), force it closed to prevent flooding and water waste.
triggers:
- trigger: state
entity_id: switch.garden_sonoff_water_valve
to: "on"
for:
minutes: 5
actions:
- action: switch.turn_off
target:
entity_id: switch.garden_sonoff_water_valve
mode: single
The logic is deliberately dumb, and that’s the point. It doesn’t know about the weather, the duty cycle, or why the valve is open. It knows one fact — the normal burst is 2 minutes, so anything past 5 minutes is wrong — and it acts on it. Because it triggers on the switch’s own state, it catches every cause at once: crash, manual toggle, buggy edit. It’s the cheapest insurance you’ll ever write.
A note on unattended water. Any automation that opens a water valve should have a hard stop like this. A misting line is low-pressure and low-volume, so the worst case is a wet patio and a water bill — but the same pattern on a bigger valve is the difference between “oops” and a flooded room. Build the failsafe first, then the fun part.
Automation 3: standing water in the hose
Someone pointed this out to me only after a few weeks, and it’s the thing I would most likely have overlooked: the misting line is a thin black hose that lies in the sun all day. On a cool day the first automation never opens — and then lukewarm water sits in a warm line for days. That’s exactly the environment legionella and biofilm like. When you mist, you breathe the stuff in as an aerosol. No need to dramatise it, but don’t ignore it either.
My fix is deliberately simple: every night at 23:00, flush for two minutes, whether or not it misted during the day.
alias: "Atomizer hygiene flush - nightly"
triggers:
- trigger: time
at: "23:00:00"
actions:
- if:
- condition: state
entity_id: switch.garden_sonoff_water_valve
state: "unavailable"
then:
- action: notify.send_message
target:
entity_id: notify.renes_iphone_2
data:
title: "💧 Atomizer flush skipped"
message: "The garden water valve is unavailable, so the nightly hygiene flush could not run."
- stop: "valve unavailable, notified"
- action: switch.turn_on
target:
entity_id: switch.garden_sonoff_water_valve
- delay:
minutes: 2
- action: switch.turn_off
target:
entity_id: switch.garden_sonoff_water_valve
mode: single
Two decisions worth explaining:
- No “only if it didn’t mist today” condition. I first built that on
last_changedand threw it out again: Home Assistant re-stampslast_changedon every restart, so the check would have silently skipped flushes. Two minutes of extra water is the cheaper failure. - The
unavailablebranch sends a push notification. If the Zigbee valve happens to be unreachable, that’s precisely the night the water stays put — I want to know, not find it in the log later.
Honest limit: this is a flush, not a drain. The line stays full afterwards, just with fresh water. Actually draining it means tap off, open the end, by hand. And for winter you switch the automation off, otherwise it opens a dry valve every night.
What I’d tune before you copy it
The two automations are solid, but the numbers are specific to my terrace and my nozzles. Before you settle in:
- Burst length and interval. 2-on / 10-off is conservative. Fine nozzles in
dry heat can take shorter, more frequent bursts; coarser ones need longer
gaps or they drip. Watch the terrace for an afternoon and adjust the
delayand the/10time pattern. - The temperature threshold. 28 °C is where I start wanting it. Humid climates get less cooling from evaporation, so you might raise it; very dry climates could drop it.
- Swap the forecast for a real sensor.
weather.forecast_homeis convenient because it ships with HA, but a €15 outdoor Zigbee temperature sensor in the shade will beat a forecast every time. Keep thesunnycondition for the daytime gate, move the numeric check to your sensor. - Winterise it. A battery valve on an outdoor tap does not enjoy frost. When the season ends, disable automation 1, close and drain the line, and bring the valve in. The failsafe can stay armed — it does no harm.
Where I landed
The nozzles cost less than a round of drinks. The thing that turned them into an actual appliance — one that cools the terrace on its own on the hot afternoons and stays firmly shut the rest of the time — is a battery Zigbee valve* and about forty lines of YAML. One automation to run it, one to make sure it can never run away. That second one is what lets me leave the house without wondering whether I left the water on.