Finding Cheapest window over 7 days to charge EV on Octopus Agile

My goal is to charge my car at the cheapest possible price given the predicted electricity prices over the next 7 days. We are not daily commuters so we can happily keep our car between 30%-50% knowing it will meet our needs.

I’m on an Octopus Agile tariff where the electricity price changes every 30 minutes. The energy provider tells us what the next 24 hours are going to be from 4pm the previous day. However I’ve recently added an API that provides predictions for the next 7 days. (setup as sensor.agile_predict_forecast below)

Right now I manually look ahead to see if there is going to be a cheaper part in the week. I then have to manually wait until that day, confirm the prices and then set a scheduled charging window for my car. This is something I’d like to automate.

Setup:
HomeAssistant-OctopusEnergy integration by bottlecap dave
Custom sensor that pulls in predicted prices of the next 7 days in 30 min windows
EV integration to tell my car when to start and stop charging.

Has anybody already got something that can help me achieve this? I did think that perhaps the target rate sensor in the octopus integration could help

Perhaps something like the below might work, using next_cheapest_start as a trigger to start charging.

template:
  - sensor:
      - name: "Tesla Cheapest Charge Slots"
        unique_id: tesla_cheapest_charge_slots
        icon: mdi:flash-auto
        state: "{{ now().isoformat() }}" # State value doesn't matter, it's just a timestamp
        attributes:
          cheapest_slots: >
            {% set required_slots = 4 %}
            {% set all_rates = state_attr('sensor.agile_predict_forecast', 'prices') %}
            {% set cheapest = all_rates | sort(attribute='value_inc_vat') | list %}
            
            {% set charge_times = [] %}
            {% for slot in cheapest[0:required_slots] %}
              {% set charge_times = charge_times + [
                {
                  'start': slot.valid_from, 
                  'end': slot.valid_to,
                  'price': slot.value_inc_vat
                }
              ] %}
            {% endfor %}
            
            {{ charge_times | sort(attribute='start') }}

          next_cheapest_start: >
            {% set required_slots = 4 %}
            {% set all_rates = state_attr('sensor.agile_predict_forecast', 'prices') %}
            {% set cheapest = all_rates | sort(attribute='value_inc_vat') | list %}
            
            {% set earliest_slot = cheapest[0:required_slots] | sort(attribute='valid_from') | first %}
            
            {{ earliest_slot.valid_from if earliest_slot is defined and earliest_slot is not none else 'unknown' }}

I can’t help but wonder though if I’m really overcomplicating this and other smart people here have already figured out a better way to do this.

1 Like