Plant template sensor

Hello,
I wrote a (plant) template sensor, but it won’t get updated in a button card.
It is updated in the developers tool, states window, but not in the card.
¿What I am missing?

The template is in a yaml file which is included in the configuration.yaml

Thanks in advanced.

This is the code of the sensor…

- sensor:
    - name: "Citronela del jardín"
      unique_id: citronela_02
      icon: mdi:sprout
      variables:
        h: >
          {{states('sensor.sensor_humedad_03_humedad')}}
        t: >
          {{states('sensor.sensor_humedad_03_temperatura')}}
        b: >
          {{states('sensor.sensor_humedad_03_battery')}}
        hmin: >
          {{30}}
        hmed: >
          {{50}}
        tmin: >
          {{13}}
        tmed: >
          {{30}}
        bmin: >
          {{4}}
        bmed: >
          {{20}}
      state: >
        {% set estados = [] %}
        {% set u = h %}
        {% set h = h | float %}

        {% if u == 'unavailable' %}
          {% set estados = estados +['unavailable'] %}
        {% elif h > hmed %}
          {% set estados = estados +['humedo'] %}
        {% elif h < hmin %}
          {% set estados = estados +['seco'] %}
        {% else %}
          {% set estados = estados +['ok'] %}
        {% endif %}

        {% set u = t %}
        {% set t = t | float %}
        {% if u == 'unavailable' %}
          {% set estados = estados +['unavailable'] %}
        {% elif t > tmed %}
          {% set estados = estados +['caliente'] %}
        {% elif h < tmin %}
          {% set estados = estados +['frio'] %}
        {% else %}
          {% set estados = estados +['ok'] %}  
        {% endif %}

        {% set u = b %}
        {% set b = b | float %}
        {% if u == 'unavailable' %}
          {% set estados = estados +['unavailable'] %}
        {% elif b > bmed %}
          {% set estados = estados +['ok'] %}
        {% elif b < bmin %}
          {% set estados = estados +['batería baja'] %}
        {% else %}
          {% set estados = estados +['batería normal'] %}  
        {% endif %}      
        {% set estados = estados | reject("in", ["unavailable", "ok"]) | list %}
        {{estados | join(', ')}}

      attributes:
        ahora: "{{ now().minute }}"
        humedad: >
          {{h}}
        temperatura: >
          {{t}}
        autor: >
          {{"Jorge Arias"}}
        pila: >
          {{b}}
        hmin: >
          {{hmin}}
        hmed: >
          {{hmed}}
        tmin: >
          {{tmin}}
        tmed: >
          {{tmed}}
        bmin: >
          {{bmin}}
        bmed: >
          {{bmed}}

This is the code of the card…

type: custom:button-card
template: plantilla_planta_2
variables:
  entidad: sensor.cipres_2
  imagen: /local/cipres.jpeg

And this is the code of the template (in the raw configuration editor)…

button_card_templates:
  plantilla_planta_2:
    variables:
      entidad: sensor.citronela_del_jardin
      triggers_update:
        - sensor.citronela_del_jardin
      imagen: /local/CitronelaJardin.jpg
      nombre: '[[[ return states[variables.entidad].attributes.friendly_name ;]]]'
      h_icon: mdi:water-percent
      t_icon: mdi:thermometer
      temperatura: '[[[ return states[variables.entidad].attributes.temperatura ;]]]'
      humedad: '[[[ return states[variables.entidad].attributes.humedad ; ]]]'
      h_max: '[[[ return states[variables.entidad].attributes.hmed; ]]]'
      h_med: '[[[ return states[variables.entidad].attributes.hmin; ]]]'
      t_med: '[[[ return states[variables.entidad].attributes.tmin; ]]]'
      t_max: '[[[ return states[variables.entidad].attributes.tmed; ]]]'
      eh: '[[[ return states[variables.entidad].attributes.humedad ; ]]]'
      et: '[[[ return states[variables.entidad].attributes.temperatura ;]]]'
      pila:
        force_eval: true
        value: '[[[ return states[variables.entidad].attributes.pila ;]]]'
    entity: '[[[ return variables.entidad ]]]'
    name: '[[[return variables.nombre]]]'
    aspect_ratio: 2/1
    section_mode: false
    show_state: false
    show_units: false
    show_icon: false
    show_entity_picture: false
    custom_fields:
      b: |
        [[[return 'Batería: ' + variables.pila + ' %']]]
      h:
        card:
          type: custom:button-card
          name: |
            [[[ 
              if (variables.eh == 'unavailable') return '- -' + " %"
              else return variables.eh + " %" 
            ]]]
          icon: '[[[ return variables.h_icon]]]'
          show_icon: true
          show_name: true
          show_status: true
          styles:
            grid:
              - grid-template-areas: '''i n'''
              - grid-template-columns: 1fr 1fr
              - grid-template-rows: min-content
            card:
              - height: 100%
              - border-radius: 20%
              - background-color: |
                  [[[
                    
                    if (variables.eh == 'unavailable') return "rgba(255,0,0,0.06)";
                    if (variables.eh < variables.h_med) return "rgba(255,0,0,0.1)";
                    else if (variables.eh > variables.h_max) return "rgba(0,180,255,0.1)";
                    else return "rgba(0,200,0,0.06)";
                  ]]]
              - box-shadow: |
                  [[[
                    
                    if (variables.eh == 'unavailable') return  "0px 0px 6px 2px rgb(255,0,0)";
                    if (variables.eh < variables.h_med) return "0px 0px 6px 2px rgb(255,0,0)";
                    else if (variables.eh > variables.h_max) return "0px 0px 6px 2px rgb(0,180,255)";
                    else return "0px 0px 6px 2px rgb(0,200,0)";
                  ]]] 
            icon:
              - animation: |
                  [[[
                    if (variables.eh < variables.h_med) return "blink 2s ease infinite";
                  ]]]
              - color: |
                  [[[
                    
                    if (variables.eh == 'unavailable') return "rgb(255,0,0)";
                    if (variables.eh < variables.h_med) return "rgb(255,0,0)";
                    else if (variables.eh > variables.h_max) return "rgb(0,180,255)";
                    else return "rgb(0,200,0)";
                  ]]]
            name:
              - color: |
                  [[[
                    
                    if (variables.eh == 'unavailable') return "rgb(255,0,0)";
                    if (variables.eh < variables.h_med) return "rgb(255,0,0)";
                    else if (variables.eh > variables.h_max) return "rgb(0,180,255)";
                    else return "rgb(0,200,0)";
                  ]]]
              - animation: |
                  [[[
                    
                    if (variables.eh == 'unavailable') return "blink 2s ease infinite";
                    if (variables.eh < variables.h_med) return "blink 2s ease infinite";
                  ]]]
      t:
        card:
          type: custom:button-card
          name: |
            [[[ 
              
              if (variables.et == 'unavailable') return '- -' + " °C"
              else return variables.et + " °C" 
            ]]]
          icon: mdi:thermometer
          show_icon: true
          show_name: true
          show_status: true
          styles:
            grid:
              - grid-template-areas: '''i  n'''
              - grid-template-columns: 1fr 1fr
              - grid-template-rows: min-content
            card:
              - height: 100%
              - border-radius: 20%
              - background-color: |
                  [[[
                    if (variables.et == 'unavailable') return "rgba(255,0,0,0.1)";
                    if (variables.et < variables.t_med) return "rgba(0,180,255,0.1)";
                    else if (variables.et > variables.t_max) return "rgba(255,0,0,0.1)";
                    else return "rgba(0,200,0,0.06)";
                  ]]]
              - box-shadow: |
                  [[[
                    
                    if (variables.et == 'unavailable') return "0px 0px 6px 2px rgb(255,0,0)";
                    if (variables.et < variables.t_med) return "0px 0px 6px 2px rgb(0,180,255)";
                    else if (variables.et > variables.t_max) return "0px 0px 6px 2px rgb(255,0,0)";
                    else return "0px 0px 6px 2px rgb(0,200,0)";
                  ]]]
            icon:
              - animation: |
                  [[[
                    if (variables.et > variables.t_max) return "blink 2s ease infinite";
                  ]]]
              - color: |
                  [[[
                    if (variables.et == 'unavailable') return "rgb(255,0,0)";
                    if (variables.et < variables.t_med) return "rgb(0,180,255)";
                    else if (variables.et > variables.t_max) return "rgb(255,0,0)";
                    else return "rgb(0,200,0)";
                  ]]]
            name:
              - color: |
                  [[[
                  if (variables.et == 'unavailable') return "rgb(255,0,0)";
                    if (variables.et < variables.t_med) return "rgb(0,180,255)";
                    else if (variables.et > variables.t_max) return "rgb(255,0,0)";
                    else return "rgb(0,200,0)";
                  ]]]
              - animation: |
                  [[[
                    
                    if (variables.et == 'unavailable') return "blink 2s ease infinite";
                    if (variables.et < variables.t_med) return "blink 2s ease infinite";
                  ]]]
      f:
        card:
          type: custom:button-card
          entity_picture: '[[[return variables.imagen ]]]'
          show_entity_picture: true
          show_name: false
          show_icon: false
          color: transparent
          size: 100%
          styles:
            card:
              - background-color: transparent
              - padding: 0%
              - box-shadow: |
                  [[[
                    if (variables.et < variables.t_med) return "0px 0px 4px 1px rgb(0,180,255)";
                    else if (variables.et > variables.t_max) return "0px 0px 4px 1px rgb(255,0,0)";
                    else return "0px 0px 4px 1px rgb(0,200,0)";
                  ]]]
    styles:
      custom_fields:
        b:
          - color: red
          - font-size: 12px
          - justify-self: start
          - padding-left: 5%
      grid:
        - grid-template-areas: '''n . f'' ''b . f '' ''h . f'' ''t . f'' '
        - grid-template-columns: 60% 1fr 35%
        - grid-template-rows: min-content min-content 30% 30%
      card:
        - padding: 1% 1% 1% 2%
        - box-shadow: |
            [[[
              if (variables.eh == 'unavailable') return "0px 0px 8px 1px rgb(255,0,0)";
              if (variables.eh < variables.h_med) return "0px 0px 4px 0px rgb(255,0,0)";
              else if (variables.eh > variables.h_max) return "0px 0px 4px 0px rgb(0,180,255)";
              else return "0px 0px 4px 0px rgb(0,200,0)";
            ]]] 
      name:
        - font-size: 130%
        - justify-self: start
        - padding-left: 5%
        - padding-top: 0%
        - color: |
            [[[
              if (variables.eh == 'unavailable') return "rgba(255,200,0,0.7)";
              return "rgba(0,200,0,0.7)"
            ]]]

In state-based Template entities the variables only update when the integration reloads, so they are fine for static values, but not for dynamic values. It can be done with a few changes:

State-Based
- sensor:
    - name: "Citronela del jardín"
      unique_id: citronela_02
      icon: mdi:sprout
      variables:
        hmin: 30
        hmed: 50
        tmin: 13
        tmed: 30
        bmin: 4
        bmed: 20
      state: >      
        {% set h = states('sensor.sensor_humedad_03_humedad') | float('unavailable') %}
        {% set t = states('sensor.sensor_humedad_03_temperatura') | float('unavailable') %}
        {% set b = states('sensor.sensor_humedad_03_battery') | float('unavailable') %}

        {% if h != 'unavailable' %}
          {% if h > hmed %}
            {% set h = 'humedo' %}
          {% elif h < hmin %}
            {% set h = 'seco' %}
          {% else %}
            {% set h = 'ok' %}
        {% endif %}{% endif %}

        {% if t != 'unavailable' %}
          {% if t > tmed %}
            {% set t = 'caliente' %}
          {% elif t < tmin %}
            {% set t = 'frio' %}
          {% else %}
            {% set t = 'ok' %}
        {% endif %}{% endif %}

        {% if b != 'unavailable' %}
          {% if b > bmed %}
            {% set b = 'ok' %}
          {% elif b < bmin %}
            {% set b = 'batería baja' %}
          {% else %}
            {% set b = 'batería normal' %}
        {% endif %}{% endif %}
        {{ [h,t,b] | reject('in', ['unavailable', 'ok']) | list | join(', ') | default('todo bien',1) }}
      attributes:
        ahora: "{{ now() }}"  
        #The ahora attribute will not reflect updates of the sensor, it will just update every minute
        humedad: "{{ states('sensor.sensor_humedad_03_humedad') }}"
        temperatura:  "{{ states('sensor.sensor_humedad_03_temperatura') }}"
        pila: "{{ states('sensor.sensor_humedad_03_battery') }}"
        autor: Jorge Arias
        hmin: "{{hmin}}"
        hmed: "{{hmed}}"
        tmin: "{{tmin}}"
        tmed: "{{tmed}}"
        bmin: "{{bmin}}"
        bmed: "{{bmed}}"

A better option would be to use a trigger-based Template Sensor:

Trigger-Based
- triggers:
    - trigger: state
      entity_id: 
        - sensor.sensor_humedad_03_humedad
        - sensor.sensor_humedad_03_temperatura
        - sensor.sensor_humedad_03_battery
      to: ~
  variables:
    h: "{{ states('sensor.sensor_humedad_03_humedad') | float('unavailable') }}"
    t: "{{ states('sensor.sensor_humedad_03_temperatura') | float('unavailable') }}"
    b: "{{ states('sensor.sensor_humedad_03_battery') | float('unavailable') }}"
    hmin: 30
    hmed: 50
    tmin: 13
    tmed: 30
    bmin: 4
    bmed: 20
  sensor:
    - name: "Citronela del jardín"
      unique_id: citronela_02
      icon: mdi:sprout
      state: >
        {% if h != 'unavailable' %}
          {% if h > hmed %}
            {% set h = 'humedo' %}
          {% elif h < hmin %}
            {% set h = 'seco' %}
          {% else %}
            {% set h = 'ok' %}
        {% endif %}{% endif %}

        {% if t != 'unavailable' %}
          {% if t > tmed %}
            {% set t = 'caliente' %}
          {% elif t < tmin %}
            {% set t = 'frio' %}
          {% else %}
            {% set t = 'ok' %}
        {% endif %}{% endif %}

        {% if b != 'unavailable' %}
          {% if b > bmed %}
            {% set b = 'ok' %}
          {% elif b < bmin %}
            {% set b = 'batería baja' %}
          {% else %}
            {% set b = 'batería normal' %}
        {% endif %}{% endif %}
        {{ [h,t,b] | reject('in', ['unavailable', 'ok']) | list | join(', ') | default('todo bien',1) }}
      attributes:
        ahora: "{{ now() }}"
        humedad: "{{ h }}"
        temperatura:  "{{ t }}"
        pila: "{{ b }}"
        autor: Jorge Arias
        hmin: "{{ hmin }}"
        hmed: "{{ hmed }}"
        tmin: "{{ tmin }}"
        tmed: "{{ tmed }}"
        bmin: "{{ bmin }}"
        bmed: "{{ bmed }}"
1 Like

Thank you so much!!!
Both appoaches worked flawlessly.