Is it not possible to concatenate some text in a template sensor with nested ifs and show it correctly in a markdown card?

Make a list of dictionaries instead to keep the data together

That is what I would expect from other programming languages.
In other programming languages each key value pair is created one by one and effectively overwriting the previous with key 0.

1 Like

You’re right, that’s exactly what it’s doing when the value of av[i] is 0.

I think the simplest solution is to reverse the order of the keys:


Try this version. The order of the dictionary’s keys has been reversed in order to correctly report GESLOTEN, instead of VENTI, when a cover’s ventilation position is 0.

  - sensor:
      - name: "Rolluiken_status"
        state: >
          {%- macro staat(a, av, plaats, naam) -%}
          {%- set x = a | average -%}
          {%- if x in [0,100] -%}
          {{ plaats }} **{{'OPEN' if x == 100 else 'GESLOTEN'}}**.
          {%- elif a == av -%}
          {{ plaats }} **VENTILATIE**.
          {%- else -%}
          {%- set ns = namespace(s=[]) -%}
          {%- for i in range(0, a | length) -%}
          {%- set ns.s = ns.s + ['{}: **{}**'.format(naam[i], {av[i]:'VENTI', 100:'OPEN', 0:'GESLOTEN' }.get(a[i], (100 - a[i]) ~ '%'))] -%}
          {%- endfor -%}
          {{ ns.s | join(' / ') }}
          {%- endif -%}
          {%- endmacro -%}

          {% set alle = [
              states.cover.master_bedroom, states.cover.voorraam_klein, states.cover.voorraam_groot,
              states.cover.computer_kamer, states.cover.hal_1e_etage, states.cover.zijraam,
              states.cover.badkamer, states.cover.logeerkamer, states.cover.achterdeur, states.cover.achterraam ]
              | selectattr('attributes.current_position', 'defined')
              | map(attribute='attributes.current_position') | map('int', 0) | list %}

          {% set alle_ventilatie = [
              states.input_number.master_bedroom_cover_ventilatie_positie, states.input_number.voorraam_klein_cover_ventilatie_positie, states.input_number.voorraam_groot_cover_ventilatie_positie,
              states.input_number.computer_kamer_cover_ventilatie_positie, states.input_number.hal_1e_etage_cover_ventilatie_positie, states.input_number.zijraam_cover_ventilatie_positie,
              states.input_number.badkamer_cover_ventilatie_positie, states.input_number.logeerkamer_cover_ventilatie_positie,
              states.input_number.achterdeur_cover_ventilatie_positie, states.input_number.achterraam_ventilatie_positie ]
              | map('int', 0) | list %}

          {%- set x = alle | average -%}
          {%- if x in [0,100] -%}
          Alle rolluiken zijn **{{'OPEN' if x == 100 else 'GESLOTEN'}}**.
          {%- else -%}
          {{ staat(alle[0:3], alle_ventilatie[0:3], 'Voorkant', ['Master', 'Klein', 'Groot']) }}
          {{ staat(alle[3:6], alle_ventilatie[3:6], 'Westkant', ['Computerkr', 'Hal', 'Zijraam']) }}
          {{ staat(alle[6:], alle_ventilatie[6:], 'Acterkant', ['Badkamer', 'Logeerkamer', 'Achterdeur', 'Achterraam']) }}
          {%- endif -%}

It seems to be working fine now. I’ll keep an eye on it for the next few days.

Thanks a lot!

1 Like

@123 Hi Taras,

Could it be that there is some breaking changes in last versions of Home Assistant. It was working perfect, but i noticed that the ‘ventilation states’ are not working anymore.

  - sensor:
      - name: "rolluiken_status_macro"
        state: >
          {%- macro staat(a, av, plaats, naam) -%}
          {%- set x = a | average -%}
          {%- if x in [0,100] -%}
          {{ plaats }} **{{'OPEN' if x == 100 else 'GESLOTEN'}}**.
          {%- elif a == av -%}
          {{ plaats }} **VENTILATIE**.
          {%- else -%}
          {%- set ns = namespace(s=[]) -%}
          {%- for i in range(0, a | length) -%}
          {%- set ns.s = ns.s + ['{}: **{}**'.format(naam[i], {av[i]:'VENTI', 100:'OPEN', 0:'GESLOTEN' }.get(a[i], (100 - a[i]) ~ '%'))] -%}
          {%- endfor -%}
          {{ ns.s | join(' / ') }}
          {%- endif -%}
          {%- endmacro -%}

          {% set alle = [
              states.cover.master_bedroom, states.cover.voorraam_klein, states.cover.voorraam_groot,
              states.cover.computer_kamer, states.cover.hal_1e_etage, states.cover.zijraam,
              states.cover.badkamer, states.cover.logeerkamer, states.cover.achterdeur, states.cover.achterraam ]
              | selectattr('attributes.current_position', 'defined')
              | map(attribute='attributes.current_position') | map('int', 0) | list %}

          {% set alle_ventilatie = [
              states.input_number.master_bedroom_cover_ventilatie_positie, states.input_number.voorraam_klein_cover_ventilatie_positie, states.input_number.voorraam_groot_cover_ventilatie_positie,
              states.input_number.computer_kamer_cover_ventilatie_positie, states.input_number.hal_1e_etage_cover_ventilatie_positie, states.input_number.zijraam_cover_ventilatie_positie,
              states.input_number.badkamer_cover_ventilatie_positie, states.input_number.logeerkamer_cover_ventilatie_positie,
              states.input_number.achterdeur_cover_ventilatie_positie, states.input_number.achterraam_ventilatie_positie ]
              | map('int', 0) | list %}
          
          {%- set x = alle | average -%}
          {%- if x in [0,100] -%}
          Alle rolluiken zijn **{{'OPEN' if x == 100 else 'GESLOTEN'}}**.
          {%- else -%}
          {{ staat(alle[0:3], alle_ventilatie[0:3], 'Voorkant', ['Master', 'Klein', 'Groot']) }}<br>
          {{ staat(alle[3:6], alle_ventilatie[3:6], 'Westkant', ['Computerkr', 'Hal', 'Zijraam']) }}<br>
          {{ staat(alle[6:], alle_ventilatie[6:], 'Achterkant', ['Badkamer', 'Logeerkamer', 'Achterdeur', 'Achterraam']) }}
          {%- endif -%}



          {{ alle_ventilatie }}

This results now in this:

- sensor:
      - name: "rolluiken_status_macro"
        state: >

          Voorkant **OPEN**.<br>
          Westkant **OPEN**.<br>
          Badkamer: **89%** / Logeerkamer: **89%** / Achterdeur: **OPEN** / Achterraam: **OPEN**[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Two covers are at the moment in ventilation state:

One is the ‘Badkamer’ cover and you see that the input helper has a value of 11 (input_number.badkamer_cover_ventilatie_positie)

The input helpers don’t report the correct state anymore:
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

The covers are reporting the states correctly (you see 2 times the 11 == ventilation state)
[100, 100, 100, 100, 100, 100, 11, 11, 100, 100]

I think I have found it:

      {% set alle_ventilatie = [
          states.input_number.master_bedroom_cover_ventilatie_positie.state, 

After the input number there muste be .state and then it works again. So it is something that is changed in some previous version.

That’s what it will report if it cannot find any of the input_number helpers listed in the variable alle_ventilatie.

Copy-paste this into the Template Editor. If it reports a list containing nothing but zeros then it means it cannot find any of the input_number helpers.

{% set alle_ventilatie = [
   states.input_number.master_bedroom_cover_ventilatie_positie, states.input_number.voorraam_klein_cover_ventilatie_positie, states.input_number.voorraam_groot_cover_ventilatie_positie,
   states.input_number.computer_kamer_cover_ventilatie_positie, states.input_number.hal_1e_etage_cover_ventilatie_positie, states.input_number.zijraam_cover_ventilatie_positie,
   states.input_number.badkamer_cover_ventilatie_positie, states.input_number.logeerkamer_cover_ventilatie_positie,
   states.input_number.achterdeur_cover_ventilatie_positie, states.input_number.achterraam_ventilatie_positie ]
   | map('int', 0) | list %}
{{ alle_ventilatie }}

Go to Developer Tools → States and confirm the spelling of the listed input_numbers.


EDIT

While I was typing, you already figured out the problem; good work!

When I entered this in the developer tools:

{{ states.input_number.badkamer_cover_ventilatie_positie }}

I get this:

<template TemplateState(<state input_number.badkamer_cover_ventilatie_positie=11.0; initial=None, editable=False, min=0.0, max=100.0, step=1.0, mode=slider, friendly_name=Badkamer rolluik ventilatie positie @ 2022-05-17T15:25:31.741030+02:00>)>

Then I tried adding .state and coincidentally it worked again :slight_smile:

To avoid surprises like this in the future, I suggest you use the states() function to get each input_number’s state value.

          {% set alle_ventilatie = [
              states('input_number.master_bedroom_cover_ventilatie_positie'), states('input_number.voorraam_klein_cover_ventilatie_positie'), states('input_number.voorraam_groot_cover_ventilatie_positie'),
              states('input_number.computer_kamer_cover_ventilatie_positie'), states('input_number.hal_1e_etage_cover_ventilatie_positie'), states('input_number.zijraam_cover_ventilatie_positie'),
              states('input_number.badkamer_cover_ventilatie_positie'), states('input_number.logeerkamer_cover_ventilatie_positie'),
              states('input_number.achterdeur_cover_ventilatie_positie'), states('input_number.achterraam_ventilatie_positie') ]
              | map('int', 0) | list %}


Thanks! I have changed it and it still works perfect.