> It's apparently possible to track a washing machine's progress with a smart switch that monitors power draw;

Can confirm, it's what I do. I can even detect which part of the cycle it is in using plain Home Assistant template sensors.

It's crude but it works. Detecting washing vs not is trivial, but I went the extra mile, looking at the power history and analysed the thing visually to get the general profile of each part, taking into account peaks, throughs, noise to have some unambiguous rules. Some are wrong if taken in isolation but taking the order of priority into account, flattening the result with if/elif in a single state sensor it becomes correct. That strategy is also very easy to debug visually with a entity history list in the dashboard.

I could probably also detect error states (which I had a few, like filter clogged with lint preventing water drain) as in this case the panel stays lit with the error code basically forever VS a normal cycle has it lit but ultimately it shuts down to deeper sleep states once it's done.

I really enjoy making dumb devices smart, it's a nice decoupling too and means I can just change e.g washing machine if it dies, adjust a few values below, and be all the merrier.

(nixos config, but it's a 1:1 to YAML and you get the idea)

services.home-assistant = {
#...

config = {
#...
template = [
# washing machine
# 5-6W: on (idle, panel lit)
# 4-5W: off (sleep after on, panel unlit)
# 0.1-1W: off (deep sleep)
# 2100-2200W: water heating
# noisy 8-100W, trough 10W: washing
# ramp-up 15-500W, plateau 300-500W, noisy 100W: spin dry
# 1300-1500W, trough 40W-150W: tumble dry
# 7.5-8W 240s, peak 95-105W, 20-25W 30s: cooldown
{
sensor = [
{
name = "washing_machine_power";
unit_of_measurement = "W";
state_class = "measurement";
state = "{{ states('sensor.shellyplusplugs_80646fc7bb4c_switch_0_power') }}";
}
{
name = "washing_machine_state";
state = ''
{% if is_state('binary_sensor.washing_machine_heating', 'on') %}
heating
{% elif is_state('binary_sensor.washing_machine_drying', 'on') %}
drying
{% elif is_state('binary_sensor.washing_machine_spinning', 'on') %}
spinning
{% elif is_state('binary_sensor.washing_machine_cooling', 'on') %}
cooling
{% elif is_state('binary_sensor.washing_machine_washing', 'on') %}
washing
{% elif is_state('binary_sensor.washing_machine_idle', 'on') %}
idle
{% elif is_state('binary_sensor.washing_machine_sleeping', 'on') %}
sleeping
{% elif states('sensor.washing_machine_power') | float(default=0) < 0.01 %}
off
{% endif %}
'';
}
];
binary_sensor = [
{
name = "washing_machine_active";
state = ''
{{ states('sensor.washing_machine_power') | int(default=0) > 30 }}
'';
delay_on = { minutes = 2; };
delay_off = { minutes = 2; };
}
{
name = "washing_machine_heating";
state = ''
{{ states('sensor.washing_machine_power') | int(default=0) > 1900 }}
'';
delay_on = { seconds = 5; };
delay_off = { seconds = 10; };
}
{
name = "washing_machine_drying";
state = ''
{{ states('sensor.washing_machine_power') | int(default=0) > 1000 and states('sensor.washing_machine_power') | int(default=0) < 1600 }}
'';
delay_on = { seconds = 5; };
delay_off = { seconds = 120; };
}
{
name = "washing_machine_washing";
state = ''
{{ states('sensor.washing_machine_power') | int(default=0) > 30 and states('sensor.washing_machine_power') | int(default=0) < 150 }}
'';
delay_on = { seconds = 120; };
delay_off = { seconds = 45; };
}
{
name = "washing_machine_spinning";
state = ''
{{ states('sensor.washing_machine_power') | int(default=0) > 150 and states('sensor.washing_machine_power') | int(default=0) < 500 }}
'';
delay_on = { seconds = 5; };
delay_off = { seconds = 5; };
}
{
name = "washing_machine_cooling";
state = ''
{{ states('sensor.washing_machine_power') | int(default=0) > 6 and states('sensor.washing_machine_power') | int(default=0) < 30 }}
'';
delay_on = { seconds = 90; };
delay_off = { seconds = 60; };
}
{
name = "washing_machine_idle";
state = ''
{{ states('sensor.washing_machine_power') | int(default=0) > 1 and states('sensor.washing_machine_power') | int(default=0) < 6 }}
'';
delay_on = { seconds = 1; };
delay_off = { seconds = 1; };
}
{
name = "washing_machine_sleeping";
state = ''
{{ states('sensor.washing_machine_power') | float(default=0) > 0.01 and states('sensor.washing_machine_power') | int(default=0) < 1 }}
'';
delay_on = { seconds = 1; };
delay_off = { seconds = 1; };
}
];
}
];