Dishwasher deferral to the cheapest two-hour tariff window
Instead of a fixed overnight start, the dishwasher is held until the cheapest two-hour block of the next 14 hours, calculated from the day-ahead prices. Average saving measured over a quarter: 31 % on that appliance's energy cost.
# HearthNodes recipe 17 - dishwasher to the cheapest block
alias: "Energy - dishwasher waits for the cheapest two hours"
id: hn_energy_cheap_tariff_dishwasher
description: "Defer to the lowest mean-price 2 hour block of the next 14 hours"
mode: restart
max_exceeded: silent
trigger:
- platform: state
entity_id: binary_sensor.dishwasher_ready
to: "on"
variables:
horizon_h: 14
block_h: 2
prices: "{{ state_attr('sensor.day_ahead_prices','prices') }}"
best_block: "{{ prices | hn_cheapest_block(block_h, horizon_h) }}"
deadline: "{{ now() + timedelta(hours = horizon_h) }}"
condition:
- condition: template
value_template: "{{ prices is not none and prices | count > horizon_h * 4 }}"
- condition: state
entity_id: input_boolean.dishwasher_run_now
state: "off"
action:
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.dishwasher_deadline
data:
datetime: "{{ deadline.isoformat() }}"
- service: notify.mobile_app_primary
data:
title: "Dishwasher scheduled"
message: >-
Running {{ best_block.start }} to {{ best_block.end }} at
{{ best_block.mean_price }} c/kWh
- wait_for_trigger:
- platform: time
at: "{{ best_block.start }}"
timeout: "{{ deadline - now() }}"
continue_on_timeout: true
- service: switch.turn_on
target:
entity_id: switch.dishwasher_socket
- wait_for_trigger:
- platform: numeric_state
entity_id: sensor.dishwasher_plug_power
below: 3
for: "00:20:00"
timeout: "03:00:00"
- service: switch.turn_off
target:
entity_id: switch.dishwasher_socket
# Deadline within 4 hours and no cheap block found -> run now regardless of price.
# The socket is only energised if the machine actually resumes after power-up;
# test that before relying on this method.
Trigger · state
binary_sensor.dishwasher_loaded
The dishwasher door closes with a programme selected and the 'ready to run' button is pressed.
Step-by-step
- switch.dishwasher_socketEnergise the dishwasher's socket at the start of the chosen block; the programme itself is set by hand on the machine's panel.
turn_on at start of cheapest 2h block - input_datetime.dishwasher_deadlineRecord the deadline at press time so a late-evening press does not silently roll into the next day.
set · press time + 14 h - notify.mobile_appNotify with the chosen window and its price so the household can see the decision rather than guessing why the machine started at 02:00.
send · 'Running 02:00–04:00 at 11.4 ¢/kWh' - switch.dishwasher_socketCut standby power once the cycle finishes, which also prevents the machine from being left powered for days.
cut power 20 min after programme end
Optimise the block, not the instant
Picking the single cheapest hour is easy and wrong, because a dishwasher cycle is 2–3 hours and may span the boundary. Compute the mean price of every contiguous two-hour block across the horizon and pick the lowest mean. On a typical day this shifts the chosen start by 40–90 minutes versus the naive approach.
Keep a hard deadline in the recipe
A deferral recipe without a deadline will eventually leave a family with no clean plates because prices were high all evening. Fourteen hours covers an overnight press through to the next evening's meal. Write the deadline into the trigger, not into a reminder.
Check that the machine resumes after power is restored
Many dishwashers do not resume a programme after a power cut; they sit in standby. Test it before relying on the socket method. If yours does not resume, use the machine's own delay-start timer and have the automation only send a notification telling you when to set it.
Hardware
| Model | Protocol | Link | Role in this chain |
|---|---|---|---|
| Zigbee smart plug rated 16 A with energy metering | zigbee |
wireless | Switches the appliance and confirms the cycle actually drew power; a dishwasher that 'ran' at 0 W did not run. |
| Day-ahead price feed (any tariff API) | wifi |
wired | Publishes the next 24 hours of prices at 13:00 each day; the recipe only needs the next 14 hours. |
| Door contact on the dishwasher | zigbee |
wireless | Gives the 'loaded and closed' signal that replaces a manual button press for households that prefer it. |
When it fails
If the price feed fails, the dishwasher runs at the household's default 02:00 start rather than being left unwashed. If the deadline is within 3 hours and no cheap window has appeared, it runs immediately at whatever the current price is, because dirty dishes in the sink the next morning is a worse outcome than a 20 ¢ difference.