Laundry done, and emptied
A power-metering smart plug and a door sensor on the washer and dryer, so Home Assistant knows running, done and emptied, and nags until it's unloaded.
- Difficulty
- Easy
- Parts cost
- Two power-metering smart plugs and two door sensors
- Build time
- An evening, then a few loads to check the numbers
- Skills
- Home Assistant, Zigbee
The problem
I wanted the house to tell us when the washing’s done, and keep telling us until someone empties it.
Knowing a machine has finished is the easy half. A smart plug that measures power shows it straight away: the watts go up when it starts and drop when it stops. The hard half is knowing it’s been emptied. Without that, the reminder either stops too early or never stops. So each machine also gets a door sensor, and opening the door after a load counts as “emptied”.
How it works
Each machine sits in one of three states: Idle, Running or Done. Home Assistant moves it along using the power reading from the plug, and moves it back to Idle when someone opens the door. If the door sensor isn’t fitted yet, or plays up, there’s an Emptied button that does the same job. Starting the next load also clears it, because nobody starts a load on top of wet washing.
The door only counts while the machine says Done. Open the lid mid-wash to throw in a sock, or open it to load up, and nothing changes. Ours is a top-loader, so its “door” is the lid.
The washer and dryer need different numbers. The washer drops under 10 W when it finishes. The dryer keeps tumbling every so often after the cycle (anti-crease, so the clothes don’t set in creases), at about 170 W. So its “finished” line sits at 200 W, above those tumbles.
Done shows on the screen we have in the living area: a little laundromat panel with photos of our two machines, and the finished one blinks DONE ✔ COLLECT until someone deals with it. Any Home Assistant dashboard can do the same job, and a phone message is optional (code below).
What you need
- Two Zigbee smart plugs with power metering, one per machine. They must be rated for the machine’s load (see below).
- Two Zigbee door/window sensors, the cheap kind with a magnet.
- Home Assistant with a working Zigbee setup. I use Zigbee2MQTT.
- Somewhere to show it: a dashboard, a wall screen, or the Home Assistant phone app.
Check the plug rating, especially for the dryer. A dryer is one of the biggest loads in the house. Over 11 days of logging, my dryer peaked at 2245 W and the washer at 1353 W. A 10 A plug at 240 V is good for 2400 W, so the dryer runs close to the limit. Check the rating on the plug itself against the nameplate on your machine. Plug it straight into the wall, not through a power board or extension lead.
Wiring
There’s no wiring. It’s all plug-in:
| Machine | Smart plug | Door sensor |
|---|---|---|
| Washer | Between the wall socket and the washer’s plug | Sensor on the body, magnet on the lid (or door), lined up so they sit together when it’s shut |
| Dryer | Between the wall socket and the dryer’s plug | Same again on the dryer door |
Keep the plug somewhere dry and out of the way of the hoses. Stick the door sensor where you can still get at its battery.
Firmware and config
No firmware. Pair the plugs and sensors like any other Zigbee device and give them sensible names. The examples below use these entity IDs:
sensor.washer_powerandsensor.dryer_power(the plugs’ power readings)binary_sensor.washer_doorandbinary_sensor.dryer_door(onmeans open)
If yours come out with different IDs, rename them in Settings → Entities, or change the YAML.
First the helpers: a dropdown per machine to hold its state, and an Emptied button for each. You can
make the dropdowns in the UI instead (Settings → Devices & services → Helpers → Dropdown) with the
options Idle, Running and Done.
# configuration.yaml
input_select:
washer_state:
name: Washer
icon: mdi:washing-machine
options: [Idle, Running, Done]
dryer_state:
name: Dryer
icon: mdi:tumble-dryer
options: [Idle, Running, Done]
script:
washer_emptied:
alias: "Washer emptied"
icon: mdi:basket-check
sequence:
- event: laundry_emptied
event_data:
machine: washer
dryer_emptied:
alias: "Dryer emptied"
icon: mdi:basket-check
sequence:
- event: laundry_emptied
event_data:
machine: dryer
Leave out initial: on the dropdowns. Without it Home Assistant puts back the last state after a
restart, so a load that was Done is still Done.
Then one automation per machine. This is the washer:
# automations.yaml
- id: laundry_washer
alias: "Laundry: washer running → done → emptied"
mode: queued
triggers:
- trigger: numeric_state
entity_id: sensor.washer_power
above: 20
for: "00:01:00"
id: start
- trigger: numeric_state
entity_id: sensor.washer_power
below: 10
for: "00:05:00"
id: stop
- trigger: state
entity_id: binary_sensor.washer_door
to: "on"
id: emptied
- trigger: event
event_type: laundry_emptied
event_data:
machine: washer
id: emptied
# A restart throws away a half-finished "for 5 minutes" timer. This catches it.
- trigger: homeassistant
event: start
id: boot
actions:
- choose:
# Drawing power for a minute: a load has started (this also clears an old Done)
- conditions:
- condition: trigger
id: start
sequence:
- action: input_select.select_option
target:
entity_id: input_select.washer_state
data:
option: Running
# Quiet for 5 minutes after running: finished
- conditions:
- condition: trigger
id: [stop, boot]
- condition: state
entity_id: input_select.washer_state
state: Running
- condition: numeric_state
entity_id: sensor.washer_power
below: 10
sequence:
- action: input_select.select_option
target:
entity_id: input_select.washer_state
data:
option: Done
# Door opened or Emptied pressed, but only once it's finished
- conditions:
- condition: trigger
id: emptied
- condition: state
entity_id: input_select.washer_state
state: Done
sequence:
- action: input_select.select_option
target:
entity_id: input_select.washer_state
data:
option: Idle
For the dryer, copy it and change four things: every washer becomes dryer, the start line becomes
above: 300, both “finished” lines become below: 200, and the finished wait becomes "00:03:00".
Those numbers came from one day’s power history on our machines. Yours will be different, so check yours before you copy mine (see Testing).
A dashboard card that only shows up when there’s something to do, plus the buttons:
type: vertical-stack
cards:
- type: conditional
conditions:
- condition: state
entity: input_select.washer_state
state: Done
card:
type: markdown
content: "## Washer DONE. Empty me!"
- type: conditional
conditions:
- condition: state
entity: input_select.dryer_state
state: Done
card:
type: markdown
content: "## Dryer DONE. Empty me!"
- type: entities
entities:
- input_select.washer_state
- input_select.dryer_state
- script.washer_emptied
- script.dryer_emptied
And if you want the phone told as well: one message when a machine finishes, which comes off the phone
by itself once the machine is emptied. The tag ties the two together. Add a condition on
person.example if you only want it sent while that person is home.
- id: laundry_phone
alias: "Laundry: tell the phone"
mode: queued
triggers:
- trigger: state
entity_id:
- input_select.washer_state
- input_select.dryer_state
to: Done
id: done
- trigger: state
entity_id:
- input_select.washer_state
- input_select.dryer_state
from: Done
id: cleared
actions:
- choose:
- conditions:
- condition: trigger
id: done
sequence:
- action: notify.mobile_app_example_phone
data:
title: "Laundry"
message: "The {{ trigger.to_state.name | lower }} is done. Please empty it."
data:
tag: "laundry_{{ trigger.to_state.object_id }}"
- conditions:
- condition: trigger
id: cleared
sequence:
- action: notify.mobile_app_example_phone
data:
message: clear_notification
data:
tag: "laundry_{{ trigger.to_state.object_id }}"
Step by step
- Put the plugs in and pair them. Leave them for a few loads with no automation at all.
- Open History for each plug’s power and look at a full load. Note what it draws while running, what it drops to when it’s finished, and any quiet patches mid-cycle (a soak, or the dryer’s anti-crease tumbles at the end).
- Pick your numbers: a “started” line well above standby, and a “finished” line and wait that a quiet patch mid-cycle won’t cross.
- Add the helpers and the two automations. You don’t need the door sensors yet: the Emptied buttons do the job until they arrive. I ran it that way for a day.
- Fit the door sensors. Before you stick them down, check in Developer tools → States that each one
reads
offwith the door properly shut andonwhen it’s open. - Add the dashboard card, and the phone message if you want it.
- Hide the plugs’ on/off switches from any voice assistant and keep them off your dashboards. Nobody should be able to turn the washer off mid-load by accident.
Testing it
- Don’t switch the plug off to test anything. It cuts power to the machine. Test with real loads, or by setting states.
- To check the card or the phone message without a load, pick
Donein the Washer dropdown on the dashboard card, then open the door or press Emptied and watch it go back toIdle. If you didn’t test the door, put the dropdown back toIdleyourself. - Then watch real loads. Our washer runs about 41 minutes a load, and the dryer about 65 minutes at around 1.55 kW. The moment it shows Done should line up with the machine actually stopping.
- If a load shows Done halfway through, the “finished” wait is shorter than a quiet patch in the cycle. Make it longer.
- Open the automation’s Traces to see which branch ran on any change you didn’t expect.
Lessons learnt
The dryer keeps going after it’s finished. After the cycle it tumbles now and then, at about 170 W, so the clothes don’t crease. A line low enough for the washer would see those tumbles as the dryer still running. Look at a full load in History before you pick your numbers, especially the tail end.
A restart can lose the “finished” timer. A “below 10 W for 5 minutes” trigger only fires after
the power drops and then stays down. If Home Assistant restarts while the timer’s counting, the timer is
gone and nothing re-arms it, so the machine sits on Running forever. This bit me on a lighting
automation once: a 45-minute timer never fired and a setting stayed stuck for about 22 hours. That’s
why the automation checks again at start-up. Also, after a restart the Zigbee plugs read unknown for
a minute or two. They only report when something changes. That’s not a fault.
A door sensor is only as good as the door. Another door sensor in our house reads open when the door is shut, because that door sits badly on its rollers. On a washer or dryer a door sensor that reads wrong either clears the reminder before anyone’s touched the washing, or never clears it. Check it reads shut with the door shut before you stick it down, and keep the Emptied button for when it plays up.
We turned the phone pushes off the same day. The first version sent a message to phones when a load finished. We took that off on day one and left it on the board, which stays lit until someone empties the machine. Try the board on its own first. You can always add the phone later.