I am having trouble with a value template using multiple criteria. Have been staring at this too long. Any assistance would be appreciated. Sensor keeps coming up as being ‘unavailable’.

As context, I am trying to setup my complex tarrif system for electricity as being “Peak”, “Shoulder”, or “Off-Peak”. This includes time of year, day of week and hour of day.

Cheers

value_template: >-
{% set m = now().month %}
{% set d = now().strftime("%w") %}
{% set h = now().hour %}
{% if m >= 4 and m <= 5 and d <= 5 and h>=7 and h < 14 %} 'S'
{% elif m >= 4 and m <= 5 and d <= 5 and h >= 14 and h < 20 %} 'P'
{% elif m >= 4 and m <= 5 and d <= 5 and h >= 20 and h < 22 %} 'S'
{% elif m >= 4 and m <= 5 and d <= 5 %} 'OP'
{% elif m >= 4 and m <= 5 and h >= 7 and h < 17 %} 'S'
{% elif m >= 4 and m <= 5 %} 'OP'
{% elif m > 5 and m <= 8 and d <= 5 and h>=7 and h < 17 %} 'S'
{% elif m > 5 and m <= 8 and d <= 5 and h >= 17 and h < 21 %} 'P'
{% elif m > 5 and m <= 8 and d <= 5 and h >= 20 and h < 22 %} 'S'
{% elif m > 5 and m <= 8 and d <= 5 %} 'OP'
{% elif m > 5 and m <= 8 and h >= 7 and h < 22 %} 'S'
{% elif m > 5 and m <= 8 %} 'OP'
{% elif m > 8 and m <= 10 and d <= 5 and h>=7 and h < 14 %} 'S'
{% elif m > 8 and m <= 10 and d <= 5 and h >= 14 and h < 20 %} 'P'
{% elif m > 8 and m <= 10 and d <= 5 and h >= 20 and h < 22 %} 'S'
{% elif m > 8 and m <= 10 and d <= 5 %} 'OP'
{% elif m > 8 and m <= 10 and h >= 7 and h < 22 %} 'S'
{% elif m > 8 and m <= 10 %} 'OP'
{% elif d <= 5 and h>=7 and h < 14 %} 'S'
{% elif d <= 5 and h >= 14 and h < 20 %} 'P'
{% elif d <= 5 and h >= 20 and h < 22 %} 'S'
{% elif d <= 5 %} 'OP'
{% elif h >= 7 and h < 22 %} 'S'
{% else %} 'OP'
{% endif %}

Thanks, I assume you mean having if statements within if statements. I started with that but have been debugging to try and get it to work.

As an example: currently we are in month 12 (december) and the day of the week is 4 (thursday). It is 1:36pm where i am, so it should return a value of ‘S’ being shoulder period. The line which should bring this is {% elif d <= 5 and h>=7 and h < 14 %} 'S'

I’m having trouble returning any value. The structure seem to be tripping up and returning unavailable. I would think if the conditions themselves weren’t structured properly, it would at least be returning ‘OP’ via {% else %} 'OP'

now().strftime("%w") returns a string not an integer, so you can’t do mathematical comparisons without converting it first or you can just use now().isoweekday()

{% set m = now().month %}
{% set d = now().isoweekday() %}
{% set h = now().hour %}
{% if 4 <= m <= 5 %}
{% if d <= 5 %}
{% if 14 > h >=7 %} S
{% elif 20 > h >= 14 %} P
{% elif 22 > h >= 20 %} S
{% else %} OP
{% endif %}
{% elif 17 > h >= 7 %} S
{% else %} OP
{% endif %}
{% elif 8 >= m > 5 %}
{% if d <= 5 %}
{% if 17 > h >= 7 %} S
{% elif 21 > h >= 17 %} P
{% elif 22 > h >= 20 %} S
{% else %} OP
{% endif %}
{% elif h >= 7 and h < 22 %} S
{% else %} OP
{% endif %}
...
{% endif %}

Cheers @Didgeridrew that solved it. Here was the final code:

value_template: >-
{% set m = now().month %}
{% set d = now().isoweekday() %}
{% set h = now().hour %}
{% if 4 <= m <= 8 and d <= 5 and 0 <= h < 7 %} OP
{% elif 4 <= m <= 8 and d <= 5 and 7 <= h < 14 %} S
{% elif 4 <= m <= 5 and d <= 5 and 14 <= h < 20 %} P
{% elif 4 <= m <= 5 and d <= 5 and 20 <= h < 22 %} S
{% elif 4 <= m <= 8 and d <= 5 and 22 <= h < 24 %} OP
{% elif 4 <= m <= 5 and d >= 6 and 0 <= h < 7 %} OP
{% elif 4 <= m <= 5 and d >= 6 and 7 <= h < 17 %} S
{% elif 4 <= m <= 5 and d >= 6 and 17 <= h < 24 %} OP
{% elif 5 < m <= 8 and d <= 5 and 0 <= h < 7 %} OP
{% elif 5 < m <= 8 and d <= 5 and 7 <= h < 17 %} S
{% elif 5 < m <= 8 and d <= 5 and 17 <= h < 21 %} P
{% elif 5 < m <= 8 and d <= 5 and 21 <= h < 22 %} S
{% elif 5 < m <= 8 and d <= 5 and 22 <= h < 24 %} OP
{% elif 5 < m <= 8 and d >= 6 and 0 <= h < 7 %} OP
{% elif 5 < m <= 8 and d >= 6 and 7 <= h < 22 %} S
{% elif 5 < m <= 8 and d >= 6 and 22 <= h < 24 %} OP
{% elif 8 < m <= 10 and d <= 5 and 0 <= h < 7 %} OP
{% elif 8 < m <= 10 and d <= 5 and 7 <= h < 14 %} S
{% elif 8 < m <= 10 and d <= 5 and 14 <= h < 20 %} P
{% elif 8 < m <= 10 and d <= 5 and 20 <= h < 22 %} S
{% elif 8 < m <= 10 and d <= 5 and 22 <= h < 24 %} OP
{% elif 8 < m <= 10 and d >= 6 and 0 <= h < 7 %} OP
{% elif 8 < m <= 10 and d >= 6 and 7 <= h < 22 %} S
{% elif 8 < m <= 10 and d >= 6 and 22 <= h < 24 %} OP
{% elif m < 4 or m >= 11 and d <= 5 and 0 <= h <= 7 %} OP
{% elif m < 4 or m >= 11 and d <= 5 and 7 <= h < 14 %} S
{% elif m < 4 or m >= 11 and d <= 5 and 14 <= h < 20 %} P
{% elif m < 4 or m >= 11 and d <= 5 and 20 <= h < 22 %} S
{% elif m < 4 or m >= 11 and d <= 5 and 22 <= h <= 24 %} OP
{% elif m < 4 or m >= 11 and d >= 6 and 0 <= h < 7 %} OP
{% elif m < 4 or m >= 11 and d >= 6 and 7 <= h < 22 %} S
{% elif m < 4 or m >= 11 and d >= 6 and 22 <= h < 24 %} OP
{% endif %}

Because the issue and solution was related to using now().isoweekday() rather than now().strftime("%w"). The code looks different as i prefer to not use nested if statements, whereas Didgeridrew’s code did use nested if statements.

The only difference between the two is that one indexes weekdays from 0 to 6 and the other from 1 to 7. Both are equally effective at reporting the day of the week. However, I suspect you didn’t know that when you created the template and so everywhere you used d <= 5 you assumed it meant Monday (1) to Friday (5) when it actually meant Sunday (0) to Friday (5).

What you referred to as a “complex template” isn’t actually complex, just needlessly bloated. Didgeridrew simplified it by removing all the duplicated and unnecessary logic.

Anyway, it’s the featured Solution post so, hopefully, it will steer other users in the right direction.

What I was saying was to nest it, but nest it intelligently. Right now your doing elif and covering every possibility when you can reorganize and have proper fallbacks with nesting. For example, always check peak first. Then shoulder next. Then everything else falls outside that and you don’t need to provide the timerange. If you check peak first, you don’t have to define 2 time ranges for shoulder. Just check the whole thing because peak would have already been hit.

and reduce it to something readable, then copy/paste and adjust numbers.

{% if 4 <= m <= 5 %}
{% if d <= 5 %}
{% if 14 <= h < 20 %}P
{% elif 7 <= h < 22 %}S
{% else %}OP
{% endif %}
{% else %}
{% if 17 <= h < 21 %}P
{% elif 7 <= h < 22 %}S
{% else %}OP
{% endif %}
{% endif %}
... add elifs here...

You can even make a macro because shoulder looks like it’s always between 7 and 22 for all months, you simply just need to define peak.