Created
July 2, 2025 19:28
-
-
Save KrzysztofHajdamowicz/6908099d87959b3a0bfea235dae0cb9d to your computer and use it in GitHub Desktop.
Find cheapest and most expensive electricity hours in Home Assistant to charge your EV or Battery Storage System (BESS)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| template: | |
| - sensor: | |
| - unique_id: 979e14f2-78f9-43bc-9fb9-47e0645419f4 | |
| name: Tesla Model Y Hours to finish charging | |
| device_class: duration | |
| unit_of_measurement: h | |
| state: > | |
| {% set current_battery_soc = states('sensor.tesla_model_y_battery') | int -%} | |
| {% set desired_battery_soc = states('number.tesla_model_y_charge_limit_2') | int -%} | |
| {% set battery_percent_to_charge = [((desired_battery_soc - current_battery_soc)/100),0]|max -%} | |
| {% set battery_capacity_in_kwh = 75 -%} | |
| {% set battery_energy_to_add = battery_percent_to_charge * battery_capacity_in_kwh -%} | |
| {% set charging_phases = 3|int -%} | |
| {% set charging_voltage = 230|int -%} | |
| {% set charging_amps = states('number.tesla_model_y_charging_amps')|float(default=16) -%} | |
| {% set charging_power = (charging_phases*charging_voltage*charging_amps)/1000 -%} | |
| {% set charging_hours = battery_energy_to_add/charging_power -%} | |
| {% set charging_time_left_reported_by_tesla = states('sensor.tesla_model_y_estimated_hours_to_charge_termination')|float(default=0.0) -%} | |
| {% if charging_time_left_reported_by_tesla is not none and charging_time_left_reported_by_tesla > 0 %} | |
| {{ charging_time_left_reported_by_tesla }} | |
| {% else %} | |
| {{ charging_hours }} | |
| {% endif %} | |
| availability: > | |
| {{ | |
| states('sensor.tesla_model_y_battery') | is_number | |
| and states('number.tesla_model_y_charge_limit_2') | is_number | |
| }} | |
| attributes: | |
| source: > | |
| {% set charging_time_left_reported_by_tesla = states('sensor.tesla_model_y_estimated_hours_to_charge_termination')|float -%} | |
| {% if charging_time_left_reported_by_tesla is not none and charging_time_left_reported_by_tesla > 0 %} | |
| Provided by Tesla | |
| {% else %} | |
| Our own calculations | |
| {% endif %} | |
| - binary_sensor: | |
| - unique_id: 911f0a21-48de-438f-90a2-4b46401268b3 | |
| name: Tesla Model Y Charge Car Cheap | |
| device_class: battery_charging | |
| state: > | |
| {% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours -%} | |
| {% set sensor = 'sensor.tge_fixing_1_rate' -%} | |
| {% set start = now() -%} | |
| {% set end = states('input_datetime.tesla_model_y_finish_charging_at') -%} | |
| {% set hours = states('sensor.tesla_model_y_hours_to_finish_charging') -%} | |
| {{ | |
| cheapest_energy_hours( | |
| sensor=sensor, | |
| attr_today='prices_today', | |
| attr_tomorrow='prices_tomorrow', | |
| time_key='time', | |
| value_key='price', | |
| start=start, | |
| end=end, | |
| include_tomorrow=true, | |
| hours=hours, | |
| split=true, | |
| mode='is_now' | |
| ) | |
| }} | |
| availability: > | |
| {{ | |
| states('sensor.tesla_model_y_charging_time_left') | is_number | |
| and states('sensor.tesla_model_y_battery') | is_number | |
| and states('number.tesla_model_y_charge_limit_2') | is_number | |
| and states('number.tesla_model_y_charging_amps') | is_number | |
| and states('sensor.tge_fixing_1_rate') | is_number | |
| }} | |
| attributes: | |
| start: "{{ now() }}" | |
| end: "{{ states('input_datetime.tesla_model_y_finish_charging_at') }}" | |
| hours: "{{states('sensor.tesla_model_y_hours_to_finish_charging')}}" | |
| debug: > | |
| {% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours -%} | |
| {% set sensor = 'sensor.tge_fixing_1_rate' -%} | |
| {% set start = now() -%} | |
| {% set end = states('input_datetime.tesla_model_y_finish_charging_at') -%} | |
| {% set hours = states('sensor.tesla_model_y_hours_to_finish_charging') -%} | |
| {{ | |
| cheapest_energy_hours( | |
| sensor=sensor, | |
| attr_today='prices_today', | |
| attr_tomorrow='prices_tomorrow', | |
| time_key='time', | |
| value_key='price', | |
| start=start, | |
| end=end, | |
| include_tomorrow=true, | |
| hours=hours, | |
| split=true, | |
| mode='all' | |
| ) | |
| }} | |
| - unique_id: phahw3ra8aiShohphaibiegee9ahf6Cu | |
| name: 4 cheapest consecutive hours | |
| device_class: battery_charging | |
| state: > | |
| {% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours -%} | |
| {% set sensor = 'sensor.tge_fixing_1_rate' -%} | |
| {% set start = states('input_datetime.find_cheapest_most_expensive_hours_since') -%} | |
| {% set end = states('input_datetime.find_cheapest_hours_until') -%} | |
| {% set hours = 4 -%} | |
| {{ | |
| cheapest_energy_hours( | |
| sensor=sensor, | |
| attr_today='prices_today', | |
| attr_tomorrow='prices_tomorrow', | |
| time_key='time', | |
| value_key='price', | |
| start=start, | |
| end=end, | |
| include_tomorrow=true, | |
| hours=hours, | |
| split=false, | |
| mode='is_now' | |
| ) | |
| }} | |
| availability: > | |
| {{ | |
| (states('sensor.tge_fixing_1_rate') | is_number) | |
| }} | |
| attributes: | |
| start: "{{ states('input_datetime.find_cheapest_most_expensive_hours_since') }}" | |
| end: "{{ states('input_datetime.find_cheapest_hours_until') }}" | |
| hours: "4" | |
| debug: > | |
| {% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours -%} | |
| {% set sensor = 'sensor.tge_fixing_1_rate' -%} | |
| {% set start = states('input_datetime.find_cheapest_most_expensive_hours_since') -%} | |
| {% set end = states('input_datetime.find_cheapest_hours_until') -%} | |
| {% set hours = 4 -%} | |
| {{ | |
| cheapest_energy_hours( | |
| sensor=sensor, | |
| attr_today='prices_today', | |
| attr_tomorrow='prices_tomorrow', | |
| time_key='time', | |
| value_key='price', | |
| start=start, | |
| end=end, | |
| include_tomorrow=true, | |
| hours=hours, | |
| split=false, | |
| mode='all' | |
| ) | |
| }} | |
| - unique_id: Aesouthaico3ic7oowa4agahiJeeghoo | |
| name: 4 cheapest non-consecutive hours | |
| device_class: battery_charging | |
| state: > | |
| {% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours -%} | |
| {% set sensor = 'sensor.tge_fixing_1_rate' -%} | |
| {% set start = states('input_datetime.find_cheapest_most_expensive_hours_since') -%} | |
| {% set end = states('input_datetime.find_cheapest_hours_until') -%} | |
| {% set hours = 4 -%} | |
| {{ | |
| cheapest_energy_hours( | |
| sensor=sensor, | |
| attr_today='prices_today', | |
| attr_tomorrow='prices_tomorrow', | |
| time_key='time', | |
| value_key='price', | |
| start=start, | |
| end=end, | |
| include_tomorrow=true, | |
| hours=hours, | |
| split=true, | |
| mode='is_now' | |
| ) | |
| }} | |
| availability: > | |
| {{ | |
| (states('sensor.tge_fixing_1_rate') | is_number) | |
| }} | |
| attributes: | |
| start: "{{ states('input_datetime.find_cheapest_most_expensive_hours_since') }}" | |
| end: "{{ states('input_datetime.find_cheapest_hours_until') }}" | |
| hours: "4" | |
| debug: > | |
| {% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours -%} | |
| {% set sensor = 'sensor.tge_fixing_1_rate' -%} | |
| {% set start = states('input_datetime.find_cheapest_most_expensive_hours_since') -%} | |
| {% set end = states('input_datetime.find_cheapest_hours_until') -%} | |
| {% set hours = 4 -%} | |
| {{ | |
| cheapest_energy_hours( | |
| sensor=sensor, | |
| attr_today='prices_today', | |
| attr_tomorrow='prices_tomorrow', | |
| time_key='time', | |
| value_key='price', | |
| start=start, | |
| end=end, | |
| include_tomorrow=true, | |
| hours=hours, | |
| split=true, | |
| mode='all' | |
| ) | |
| }} | |
| - unique_id: yaesat9Phai3wu4eishuThofietoo8Sh | |
| name: 4 most expensive consecutive hours | |
| device_class: battery_charging | |
| state: > | |
| {% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours -%} | |
| {% set sensor = 'sensor.tge_fixing_1_rate' -%} | |
| {% set start = states('input_datetime.find_cheapest_most_expensive_hours_since') -%} | |
| {% set end = states('input_datetime.find_cheapest_hours_until') -%} | |
| {% set hours = 4 -%} | |
| {{ | |
| cheapest_energy_hours( | |
| sensor=sensor, | |
| attr_today='prices_today', | |
| attr_tomorrow='prices_tomorrow', | |
| time_key='time', | |
| value_key='price', | |
| start=start, | |
| end=end, | |
| include_tomorrow=true, | |
| hours=hours, | |
| split=false, | |
| lowest=false, | |
| mode='is_now' | |
| ) | |
| }} | |
| availability: > | |
| {{ | |
| (states('sensor.tge_fixing_1_rate') | is_number) | |
| }} | |
| attributes: | |
| start: "{{ states('input_datetime.find_cheapest_most_expensive_hours_since') }}" | |
| end: "{{ states('input_datetime.find_cheapest_hours_until') }}" | |
| hours: "4" | |
| debug: > | |
| {% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours -%} | |
| {% set sensor = 'sensor.tge_fixing_1_rate' -%} | |
| {% set start = states('input_datetime.find_cheapest_most_expensive_hours_since') -%} | |
| {% set end = states('input_datetime.find_cheapest_hours_until') -%} | |
| {% set hours = 4 -%} | |
| {{ | |
| cheapest_energy_hours( | |
| sensor=sensor, | |
| attr_today='prices_today', | |
| attr_tomorrow='prices_tomorrow', | |
| time_key='time', | |
| value_key='price', | |
| start=start, | |
| end=end, | |
| include_tomorrow=true, | |
| hours=hours, | |
| split=false, | |
| lowest=false, | |
| mode='all' | |
| ) | |
| }} | |
| - unique_id: fuecooPhaizavoh0ShooSeequu8echee | |
| name: 4 most expensive non-consecutive hours | |
| device_class: battery_charging | |
| state: > | |
| {% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours -%} | |
| {% set sensor = 'sensor.tge_fixing_1_rate' -%} | |
| {% set start = states('input_datetime.find_cheapest_most_expensive_hours_since') -%} | |
| {% set end = states('input_datetime.find_cheapest_hours_until') -%} | |
| {% set hours = 4 -%} | |
| {{ | |
| cheapest_energy_hours( | |
| sensor=sensor, | |
| attr_today='prices_today', | |
| attr_tomorrow='prices_tomorrow', | |
| time_key='time', | |
| value_key='price', | |
| start=start, | |
| end=end, | |
| include_tomorrow=true, | |
| hours=hours, | |
| split=true, | |
| lowest=false, | |
| mode='is_now' | |
| ) | |
| }} | |
| availability: > | |
| {{ | |
| (states('sensor.tge_fixing_1_rate') | is_number) | |
| }} | |
| attributes: | |
| start: "{{ states('input_datetime.find_cheapest_most_expensive_hours_since') }}" | |
| end: "{{ states('input_datetime.find_cheapest_hours_until') }}" | |
| hours: "4" | |
| debug: > | |
| {% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours -%} | |
| {% set sensor = 'sensor.tge_fixing_1_rate' -%} | |
| {% set start = states('input_datetime.find_cheapest_most_expensive_hours_since') -%} | |
| {% set end = states('input_datetime.find_cheapest_hours_until') -%} | |
| {% set hours = 4 -%} | |
| {{ | |
| cheapest_energy_hours( | |
| sensor=sensor, | |
| attr_today='prices_today', | |
| attr_tomorrow='prices_tomorrow', | |
| time_key='time', | |
| value_key='price', | |
| start=start, | |
| end=end, | |
| include_tomorrow=true, | |
| hours=hours, | |
| split=true, | |
| lowest=false, | |
| mode='all' | |
| ) | |
| }} | |
| - unique_id: pa1ueCh3neiTahkad0Ohch8eipet4sew | |
| name: 2 most expensive consecutive hours | |
| device_class: battery_charging | |
| state: > | |
| {% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours -%} | |
| {% set sensor = 'sensor.tge_fixing_1_rate' -%} | |
| {% set start = states('input_datetime.find_cheapest_most_expensive_hours_since') -%} | |
| {% set end = states('input_datetime.find_cheapest_hours_until') -%} | |
| {% set hours = 2 -%} | |
| {{ | |
| cheapest_energy_hours( | |
| sensor=sensor, | |
| attr_today='prices_today', | |
| attr_tomorrow='prices_tomorrow', | |
| time_key='time', | |
| value_key='price', | |
| start=start, | |
| end=end, | |
| include_tomorrow=true, | |
| hours=hours, | |
| split=false, | |
| lowest=false, | |
| mode='is_now' | |
| ) | |
| }} | |
| availability: > | |
| {{ | |
| (states('sensor.tge_fixing_1_rate') | is_number) | |
| }} | |
| attributes: | |
| start: "{{ states('input_datetime.find_cheapest_most_expensive_hours_since') }}" | |
| end: "{{ states('input_datetime.find_cheapest_hours_until') }}" | |
| hours: "2" | |
| debug: > | |
| {% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours -%} | |
| {% set sensor = 'sensor.tge_fixing_1_rate' -%} | |
| {% set start = states('input_datetime.find_cheapest_most_expensive_hours_since') -%} | |
| {% set end = states('input_datetime.find_cheapest_hours_until') -%} | |
| {% set hours = 2 -%} | |
| {{ | |
| cheapest_energy_hours( | |
| sensor=sensor, | |
| attr_today='prices_today', | |
| attr_tomorrow='prices_tomorrow', | |
| time_key='time', | |
| value_key='price', | |
| start=start, | |
| end=end, | |
| include_tomorrow=true, | |
| hours=hours, | |
| split=false, | |
| lowest=false, | |
| mode='all' | |
| ) | |
| }} | |
| - unique_id: aeFee0uiM2De1ohquo1eicojiZiekaik | |
| name: 1 most expensive consecutive hour | |
| device_class: battery_charging | |
| state: > | |
| {% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours -%} | |
| {% set sensor = 'sensor.tge_fixing_1_rate' -%} | |
| {% set start = states('input_datetime.find_cheapest_most_expensive_hours_since') -%} | |
| {% set end = states('input_datetime.find_cheapest_hours_until') -%} | |
| {% set hours = 1 -%} | |
| {{ | |
| cheapest_energy_hours( | |
| sensor=sensor, | |
| attr_today='prices_today', | |
| attr_tomorrow='prices_tomorrow', | |
| time_key='time', | |
| value_key='price', | |
| start=start, | |
| end=end, | |
| include_tomorrow=true, | |
| hours=hours, | |
| split=false, | |
| lowest=false, | |
| mode='is_now' | |
| ) | |
| }} | |
| availability: > | |
| {{ | |
| (states('sensor.tge_fixing_1_rate') | is_number) | |
| }} | |
| attributes: | |
| start: "{{ states('input_datetime.find_cheapest_most_expensive_hours_since') }}" | |
| end: "{{ states('input_datetime.find_cheapest_hours_until') }}" | |
| hours: "1" | |
| debug: > | |
| {% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours -%} | |
| {% set sensor = 'sensor.tge_fixing_1_rate' -%} | |
| {% set start = states('input_datetime.find_cheapest_most_expensive_hours_since') -%} | |
| {% set end = states('input_datetime.find_cheapest_hours_until') -%} | |
| {% set hours = 1 -%} | |
| {{ | |
| cheapest_energy_hours( | |
| sensor=sensor, | |
| attr_today='prices_today', | |
| attr_tomorrow='prices_tomorrow', | |
| time_key='time', | |
| value_key='price', | |
| start=start, | |
| end=end, | |
| include_tomorrow=true, | |
| hours=hours, | |
| split=false, | |
| lowest=false, | |
| mode='all' | |
| ) | |
| }} | |
| - unique_id: queevivi4ooleeshu3aekaireeCeeng3 | |
| name: 2 cheapest consecutive hours | |
| device_class: battery_charging | |
| state: > | |
| {% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours -%} | |
| {% set sensor = 'sensor.tge_fixing_1_rate' -%} | |
| {% set start = states('input_datetime.find_cheapest_most_expensive_hours_since') -%} | |
| {% set end = states('input_datetime.find_cheapest_hours_until') -%} | |
| {% set hours = 2 -%} | |
| {{ | |
| cheapest_energy_hours( | |
| sensor=sensor, | |
| attr_today='prices_today', | |
| attr_tomorrow='prices_tomorrow', | |
| time_key='time', | |
| value_key='price', | |
| start=start, | |
| end=end, | |
| include_tomorrow=true, | |
| hours=hours, | |
| split=false, | |
| mode='is_now' | |
| ) | |
| }} | |
| availability: > | |
| {{ | |
| (states('sensor.tge_fixing_1_rate') | is_number) | |
| }} | |
| attributes: | |
| start: "{{ states('input_datetime.find_cheapest_most_expensive_hours_since') }}" | |
| end: "{{ states('input_datetime.find_cheapest_hours_until') }}" | |
| hours: "2" | |
| debug: > | |
| {% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours -%} | |
| {% set sensor = 'sensor.tge_fixing_1_rate' -%} | |
| {% set start = states('input_datetime.find_cheapest_most_expensive_hours_since') -%} | |
| {% set end = states('input_datetime.find_cheapest_hours_until') -%} | |
| {% set hours = 2 -%} | |
| {{ | |
| cheapest_energy_hours( | |
| sensor=sensor, | |
| attr_today='prices_today', | |
| attr_tomorrow='prices_tomorrow', | |
| time_key='time', | |
| value_key='price', | |
| start=start, | |
| end=end, | |
| include_tomorrow=true, | |
| hours=hours, | |
| split=false, | |
| mode='all' | |
| ) | |
| }} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment