Sensor template help please

Hello, I do need some help with this template sensor. It is throwing the error:

  • Invalid config for ‘sensor’ from integration ‘template’ at sensor.yaml, line 16: invalid template (TemplateSyntaxError: expected token ‘end of statement block’, got ‘if’) for dictionary value ‘sensors->electricity_price->value_template’, got ‘{% if now().hour() >= 23 %}0.04 {% elif now().hour() >= 7 %}0.04 {% elif now().month() >= 5 \n and now().month() <9\n if now().weekday() < 5 \n if now().hour() >= 14 \n and now().hour() <=19%}.30 \n {%else%}.12\n {%else%}.12\n{%else%}.12 {% endif %}"\n’, please check the docs at Template - Home Assistant
- platform: template
  sensors:
    electricity_price:
      friendly_name: Electricity price
      unit_of_measurement: USD
      value_template: >
        {% if now().hour() >= 23 %}0.04
        {% elif now().hour() >= 7 %}0.04
        {% elif now().month() >= 5 
            and now().month() <9
              if now().weekday() < 5 
                if now().hour() >= 14 
                and now().hour() <=19%}.30 
              {%else%}.12
            {%else%}.12
        {%else%}.12
        {% endif %}"

Those docs are not easy to consume. Any tips?

I’m trying to codify this logic:

Super Off-peak
Every day of the year from 11 p.m. – 7 a.m. It’s cheapest for Georgia Power to produce electricity during these hours so the savings are passed on to you. About 33% of the hours in a year fall in the Super Off-peak time period and it’s the lowest price. : .04

Off-peak
All hours of the year not identified as On-Peak or Super Off-peak From June to September, weekdays from 7 a.m. to 2 p.m. and 7 p.m. to 11 p.m., and during weekends from 7 a.m. to 11 p.m. For October to May, this period is from 7 a.m. to 11 p.m. Prices during this period are higher than the Super Off-peak time period, but much lower than the On-peak time period. The majority of the hours in a year (62%) fall in the Off-peak time period. :.12

On-peak
Period from June to September, weekdays 2 p.m. to 7 p.m. represents the time when it’s the most expensive for Georgia Power to produce electricity. Although the On-peak period has the highest prices, only about 5% of the hours during a year fall in this period. :.30

I’m not quite understanding the logic, but this example may point you in the right direction

 {% set a= now().hour  %}
 {% set b= now().month %}
 {% set c= now().weekday() %}
 {% if ( a >= 23 or a <= 7) %} .04
 {% elif ((a > 7 and a <= 14 or a >=19 and a <= 23) and b >=6 and b <=9  and c <5) %} .12
 {% elif (a >= 14 and a <= 19 and b >=6 and b <= 9 and c < 5) %} .30
 {% else %} .04
 {% endif %}

EDIT…you’ll have to test the logic. I continued this more for my education and questioned my method after staring at numbers too long today. I always refer to Taras’s logic when appropriate.

De-wording the explanation, I think it’s

  • 23:00 – 07:00: $0.04
  • June – September 14:00 – 19:00 weekdays: $0.30
  • Everything else: $0.12

Here’s the template to build that into a modern-format template sensor (under template:) rather than the legacy-format you have (under sensor:) — or even easier, by creating a template sensor Helper via the UI:

{% set h, w, m = now().hour, now().weekday(), now().month %}
{% if h == 23 or h < 7 %}
  0.04
{% elif (6 <= m <= 9) and (14 <= h < 19) and (w < 5) %}
  0.3
{% else %}
  0.12
{% endif %}
Expand for modern-format sensor
template:
  - sensor:
      - name: "Electricity price"
        unit_of_measurement: USD
        device_class: monetary
        state: >
          {% set h, w, m = now().hour, now().weekday(), now().month %}
          {% if h == 23 or h < 7 %}
            0.04
          {% elif (6 <= m <= 9) and (14 <= h < 19) and (w < 5) %}
            0.3
          {% else %}
            0.12
          {% endif %}

Notes:

  • “June to September” includes all of the month of September, so “<= 9
  • “2pm to 7pm” stops at 19:00, excluding all of the “7:something pm” hour, so “< 19

Syntax errors with your original template:

  • throughout: hour and month are properties of now() not methods, so it’s now().hour not now().hour() — but it is now().weekday().
  • lines 5, 6: should be and not if
  • lines 8, 9: not needed: I assume you’re trying to match your ifs from lines 5 & 6
  • line 10: remove closing double quote

…and logic errors, before making any of the line adjustments from above:

  • line 2: should be < 7: yours is after 7am.
  • line 3: should be > 5 or >= 6: yours also selects May
  • line 7: should be < 19: slot finishes as soon as the hour turns to 19.

With those corrections and with the formatting tidied up, yours looks like this:

{% if now().hour >= 23 %}
  0.04
{% elif now().hour < 7 %}
  0.04
{% elif now().month >= 6 
        and now().month <= 9
        and now().weekday() < 5 
        and now().hour >= 14 
        and now().hour < 19 %}
  0.30 
{% else %}
  0.12
{% endif %}

When you’re working on a template, use Developer Tools / Template which is far easier than putting it into a sensor, reloading and seeing what errors it throws.

Expand for sequence of error-finding updates

Your original, complaining about the inline ifs:

Fixing the ifs to ands, it’s now moaning about the superfluous elses:

Removing the elses. Might have needed help with this error, but it’s complaining about now().hour() and now().month():

Hooray, it works without error! Just that errant double-quote, then the logic errors as above:

First one is obvious if it’s after 7am when you’re checking: it’s reporting the low tariff due to the second line.

3 Likes

Wow, thank you.

Very concise, and works great.

1 Like