Skip to content

Automation examples

These examples use {name} as a placeholder for the name you set during configuration. If your name is Home, replace {name} with home in entity IDs.


Run during cheap hours (rank-based)

The simplest approach: use the rank_acceptable binary sensor to gate an automation. Set your acceptable rank threshold in the Kilowahti options.

alias: Heat water during cheap hours
trigger:
  - platform: state
    entity_id: binary_sensor.kilowahti_{name}_rank_acceptable
    to: "on"
action:
  - action:switch.turn_on
    target:
      entity_id: switch.water_heater
trigger_variables: {}

To stop the device when the window ends:

alias: Stop water heater when hours no longer cheap
trigger:
  - platform: state
    entity_id: binary_sensor.kilowahti_{name}_rank_acceptable
    to: "off"
action:
  - action:switch.turn_off
    target:
      entity_id: switch.water_heater

Run when price is below threshold

Use price_acceptable when you care about the absolute price rather than relative rank. Set your threshold in Kilowahti options.

alias: EV charging when price is acceptable
trigger:
  - platform: state
    entity_id: binary_sensor.kilowahti_{name}_price_acceptable
    to: "on"
action:
  - action:switch.turn_on
    target:
      entity_id: switch.ev_charger

You can also combine both conditions using price_or_rank_acceptable:

trigger:
  - platform: state
    entity_id: binary_sensor.kilowahti_{name}_price_or_rank_acceptable
    to: "on"

Schedule appliance at cheapest upcoming window

Use the kilowahti.cheapest_hours service to find the cheapest consecutive block ahead of time and schedule your appliance to start then. Requires an input_datetime helper — create one via Settings → Devices & Services → Helpers → Create helper → Date and/or time (e.g. input_datetime.cheapest_window_start).

Automation 1 — Find the window (runs daily at 17:00):

alias: Find cheapest 3-hour overnight window
trigger:
  - platform: time
    at: "17:00:00"
action:
  - action:kilowahti.cheapest_hours
    data:
      start: "{{ now().isoformat() }}"
      end: "{{ (now() + timedelta(hours=15)).isoformat() }}"  # 15 hours is the window from 17:00 → 08:00 next morning
      hours: 3
    response_variable: result
  - action:input_datetime.set_datetime
    data:
      timestamp: "{{ result['start'] }}"
    target:
      entity_id: input_datetime.cheapest_window_start

Automation 2 — Start the appliance at the scheduled time:

alias: Start dishwasher at cheapest window
trigger:
  - platform: time
    at: input_datetime.cheapest_window_start
action:
  - action:switch.turn_on
    target:
      entity_id: switch.dishwasher

Proportional control (thermostat / climate)

Use control_factor_price to modulate a setpoint rather than switching on/off. 1.0 = cheapest slot, 0.0 = most expensive.

This example adjusts a thermostat setpoint between 19 °C (expensive) and 22 °C (cheap) using 0.5 °C steps:

alias: Adjust thermostat by price
trigger:
  - platform: state
    entity_id: sensor.kilowahti_{name}_control_factor_price
action:
  - action:climate.set_temperature
    data:
      temperature: >
        {{ (19 + (states('sensor.kilowahti_{name}_control_factor_price') | float) * 3) | round(0, "half") }}
    target:
      entity_id: climate.living_room

For a ±1 bipolar input (e.g. to feed a PID controller), use sensor.kilowahti_{name}_control_factor_price_bipolar instead.

Note

The control factor shape (linear or sinusoidal) and scaling exponent are configurable in Kilowahti options. Sinusoidal gives a gentler response near the extremes.

Tip

Home Assistant ships an improved version of Jinja's round filter — including the "half" method used above, which rounds to the nearest 0.5. See Home Assistant's round documentation.


Scale EV charging current by price

Rather than switching an EV charger on or off, use control_factor_price to continuously scale the charging current between a minimum and maximum. 1.0 = cheapest slot (full current), 0.0 = most expensive slot (minimum current).

This example scales between 6 A and 16 A using 1 A steps:

alias: Scale EV charging current by price
trigger:
  - platform: state
    entity_id: sensor.kilowahti_{name}_control_factor_price
action:
  - action:number.set_value
    target:
      entity_id: number.ev_charger_current
    data:
      value: >
        {{ (6 + (states('sensor.kilowahti_{name}_control_factor_price') | float) * 10) | round(0) | int }}

Adjust 6 (minimum current) and 10 (spread: maximum minus minimum) to your charger's supported range. Check your charger's integration documentation for the correct entity and accepted values.


Charge and discharge a battery by quartile

Use price_quartile to drive a home battery: charge in the cheapest 25% of slots (Q1), discharge in the most expensive 25% (Q4), and leave it on automatic otherwise.

alias: Battery charge/discharge by price quartile
trigger:
  - platform: state
    entity_id: sensor.kilowahti_{name}_price_quartile
action:
  - choose:
      - conditions:
          - condition: state
            entity_id: sensor.kilowahti_{name}_price_quartile
            state: "1"
        sequence:
          - action:select.select_option
            target:
              entity_id: select.battery_mode
            data:
              option: charge
      - conditions:
          - condition: state
            entity_id: sensor.kilowahti_{name}_price_quartile
            state: "4"
        sequence:
          - action:select.select_option
            target:
              entity_id: select.battery_mode
            data:
              option: discharge
    default:
      - action:select.select_option
        target:
          entity_id: select.battery_mode
        data:
          option: auto

Replace select.battery_mode and the option values with the entities and modes your battery integration exposes.


Notify when tomorrow's prices are available

Tomorrow's prices are published in the early afternoon (around 13:00 CET; later in some markets). Trigger on tomorrow_available turning on to send a push notification with the day's price range.

alias: Notify when tomorrow's prices arrive
trigger:
  - platform: state
    entity_id: binary_sensor.kilowahti_{name}_tomorrow_available
    to: "on"
action:
  - action:notify.mobile_app_your_phone
    data:
      title: "Tomorrow's electricity prices"
      message: >
        Min {{ states('sensor.kilowahti_{name}_tomorrow_spot_min') }},
        avg {{ states('sensor.kilowahti_{name}_tomorrow_spot_avg') }},
        max {{ states('sensor.kilowahti_{name}_tomorrow_spot_max') }}
        {{ state_attr('sensor.kilowahti_{name}_tomorrow_spot_min', 'unit_of_measurement') }}

Replace notify.mobile_app_your_phone with your notification service.


Alert when spot price exceeds today's average

Send a notification whenever the current slot price rises above today's average — useful as an early warning to delay discretionary loads.

alias: Alert when price exceeds today's average
trigger:
  - platform: template
    value_template: >
      {{ states('sensor.kilowahti_{name}_spot_price') | float(0) >
         states('sensor.kilowahti_{name}_today_spot_avg') | float(0) }}
action:
  - action:notify.mobile_app_your_phone
    data:
      message: >
        Electricity price {{ states('sensor.kilowahti_{name}_spot_price') }}
        is above today's average {{ states('sensor.kilowahti_{name}_today_spot_avg') }}
        {{ state_attr('sensor.kilowahti_{name}_spot_price', 'unit_of_measurement') }}.