A 'starter' template sensor for per-hour energy tarrifs

Happy HA release day, all!

I was beyond stoked to see that energy monitoring is now a first-class citizen!
If you have a whole-home energy monitoring system in place, go check it out… you’ll notice that there is support for tracking energy costs too.

That is, Home Assistant keeps track of the energy used in an hour and then multiples the used energy by some value that you provide.

I was waiting for some code to compile at work so I started to create a template sensor that would work with my utility company rate plans. I am sharing this w/ y’all to save some of you the trouble of having to craft your own.

Below is what I came up with. If you can spot an optimization, let me know!

{##
My power company does not have the most complicated tarrif schedule, but it's not a flat rate, either!
Rates change by the season and day and hour.

They define summer as June 1 - September 30.
Weekends have consistent pricing; each hour is the same fee.
Weekdays have variable pricing to disencentivise peak useage.

Native datetime() function is not available in jinja, apprently, so strptime() to the rescue!
Use https://strftime.org/ for help on building your own format strings.

##}
{% set fmt_str = "%Y-%m-%d" %}

{# Can't do datetime(hour=now().hour ...) so we format, then parse :/ #}
{% set today = strptime(now().strftime(fmt_str), fmt_str) %}

{# Provide your own list here or leave empty #}
{% set holidays = [
  strptime("2021-08-04", fmt_str)
] %}
{% set summer_months = [6,7,8,9] %}

{# ISO weekday: https://docs.python.org/3/library/datetime.html#datetime.date.isoweekday #}
{% set weekend_days = [6,7] %}

{% set summer_rates = {
  0: 0.1277,
  1: 0.1277,
  2: 0.1277,
  3: 0.1277,
  4: 0.1277,
  5: 0.1277,
  6: 0.1277,
  7: 0.1277,
  8: 0.1277,
  9: 0.1277,
  10: 0.1277,
  11: 0.1277,
  12: 0.1765,
  13: 0.1765,
  14: 0.1765,
  15: 0.1277,
  16: 0.1765,
  17: 0.3105,
  18: 0.3105,
  19: 0.3105,
  20: 0.1765,
  21: 0.1765,
  22: 0.1765,
  23: 0.1765,
} %}

{% set non_summer_rates = {
  0: 0.1082,
  1: 0.1082,
  2: 0.1082,
  3: 0.1082,
  4: 0.1082,
  5: 0.1082,
  6: 0.1082,
  7: 0.1082,
  8: 0.1082,
  9: 0.1082,
  10: 0.1082,
  11: 0.1082,
  12: 0.1082,
  13: 0.1082,
  14: 0.1082,
  15: 0.1082,
  16: 0.1082,
  17: 0.1494,
  18: 0.1494,
  19: 0.1494,
  20: 0.1082,
  21: 0.1082,
  22: 0.1082,
  23: 0.1082,
} %}


{## If today is a holiday, return the cheapest rate (0th hour) for the season ##}
{%- if today in holidays %}

  {% if now().month in summer_months -%}
    {## weekends have consistent rate all day, same price as weekday off peak hours ##}
    {# Summer: Weekend&Holiday Rate for {{now().hour}} is {{summer_rates[0]}} #}
    {{summer_rates[0]}}
  {%- else -%}
    {# NonSummer: Weekend&Holiday Rate for {{now().hour}} is {{non_summer_rates[0]}} #}
    {{non_summer_rates[0]}}
  {%- endif %}

{%- elif now().month in summer_months -%}
  {% if now().day in weekend_days -%}
    {## weekends have consistent rate all day, same price as weekday off peak hours ##}
    {# Weekend. Rate for {{now().hour}} is {{summer_rates[0]}} #}
    {{summer_rates[0]}}
  {%- else -%}
    {# Weekday. Rate for {{now().hour}} is {{summer_rates[now().hour]}} #}
    {{summer_rates[now().hour]}}
  {%- endif %}

{%- else -%}
  {## In non-summer months, we still have a split between weekdays and weekends##}

  {% if now().day in weekend_days -%}
    {## weekends have consistent rate all day, same price as weekday off peak hours ##}
    {# Weekend. Rate for {{now().hour}} is {{non_summer_rates[0]}} #}
    {{non_summer_rates[0]}}
  {%- else -%}
    {# Weekday. Rate for {{now().hour}} is {{non_summer_rates[now().hour]}} #}}
    {{non_summer_rates[now().hour]}}
  {%- endif %}
{%- endif %}



{# uncomment if you want to test that your list of holidays is working
Today is {{today}}...
{%- if today in holidays %}
...and that is a holiday
{%- endif %}
#}

Hope that helps somebody!

EDIT: Updated template to actually use holiday list; I pasted the incomplete version first time!

3 Likes