Home Assistant "Text Sensor"

I’m attempting to create a “Text Sensor” in Home Assistant similar to what I use in ESPHome to generate a Text String based on a numeric sensor value.

In ESPHome I use this and it seems to work well:

text_sensor:
- platform: template
  name: "24 Hour AQI Index"
  id: SDS011_PM25_24Hour_AQI_Index
  update_interval: 10min
  icon: mdi:chemical-weapon
  lambda: |-
    if ((id(SDS011_PM25_AQI).state) > 300.0)
    { return {"Hazardous"};
    }
    else if ((id(SDS011_PM25_AQI).state) > 200.0 and (id(SDS011_PM25_AQI).state) <= 300.0)
    { return {"Very Unhealthy"};
    }
    else if ((id(SDS011_PM25_AQI).state) > 150.0 and (id(SDS011_PM25_AQI).state) <= 200.0)
    { return {"Unhealthy"};
    }
    else if ((id(SDS011_PM25_AQI).state) > 100.0 and (id(SDS011_PM25_AQI).state) <= 150.0)
    { return {"Unhealthy for Sensitive Groups"};
    }
    else if ((id(SDS011_PM25_AQI).state) > 50.0 and (id(SDS011_PM25_AQI).state) <= 100.0)
    { return {"Moderate"};
    }
    else
    { return {"Good"};
    }

Apparently Home Assistant doesn’t have the same “Text Sensor” so I’ve tried to set something up using a Template and a Lambda but can’t get it working.

Adding the following to Configuration.yaml, Studio Code Server doesn’t show any errors and the “Check Configuration” states that “Configuration will not prevent Home Assistant from starting!” but some issues show up in the logs.

The first line of the Template is Line 16 in Configuration.yaml.

template:
  - sensor:
      - name: "TextPressureTrend"
        entity_id: sensor.pressure_trend
        id: Pressure_Trend
        icon: mdi:trending-up
        filters:
        - lambda:
            if (sensor.pressure_trend.state) > 0.03)
            { return {"Rising Fast"};
            }
            else if (sensor.pressure_trend.state) > 0.02 and (sensor.pressure_trend.state) <= 0.03)
            { return {"Rising"};
            }
            else if (sensor.pressure_trend.state) > 0.01 and (sensor.pressure_trend.state) <= 0.02)
            { return {"Slowly Rising"};
            }
            else if (sensor.pressure_trend.state) > -0.01 and (sensor.pressure_trend.state) <= 0.01)
            { return {"Steady"};
            }
            else if (sensor.pressure_trend.state) > -0.02 and (sensor.pressure_trend.state) <= -0.01)
            { return {"Slowly Falling"};
            }
            else if (sensor.pressure_trend.state) > -0.03 and (sensor.pressure_trend.state) <= -0.02)
            { return {"Falling"};
            }
            else
            { return {"Falling Fast"};
            }

And here’s the errors from the logs.

Logger: homeassistant.config
Source: config.py:552
First occurred: 9:15:11 AM (1 occurrences)
Last logged: 9:15:11 AM

Invalid config for 'template' at configuration.yaml, line 18: required key 'state' not provided 
Invalid config for 'template' at configuration.yaml, line 19: 'entity_id' is an invalid option for 'template', check: sensor->0->entity_id 
Invalid config for 'template' at configuration.yaml, line 20: 'id' is an invalid option for 'template', check: sensor->0->id 
Invalid config for 'template' at configuration.yaml, line 22: 'filters' is an invalid option for 'template', check: sensor->0->filters

I’ve tried several things to get it working but just can’t figure it out. Am I missing something simple or just way off base here?

In Home Assistant you you have to use templates instead of lamda functions: Templating - Home Assistant
Also make sure your sensor is configured right: Template - Home Assistant

1 Like

How you do things in ESP YAML versus HA YAML is quite different. Your sensor can have a text status, you don’t need a lambda for that (and can’t in this case anyway):

template:
  - sensor:
      - name: "TextPressureTrend"
        unique_id: 471cbe8e-5fc3-4597-9064-47e57295d25c
        icon: mdi:trending-up
        state: >-
            {% if float(sensor.pressure_trend.state, 0) > 0.03 %}
            	{{ "Rising Fast" }}
            {% elif float(sensor.pressure_trend.state,0) > 0.02 and float(sensor.pressure_trend.state,0) <= 0.03 %}
            	{{ "Rising" }}
            {% endif %}

Just continue the logic for the rest of your states.

A bit of both.

You mistakenly assumed that the coding technique used in one open-source project (ESPHome) works in another open-source project (Home Assistant). As you have discovered empirically, it doesn’t.

Home Assistant uses Jinja2. What you are attempting to achieve can be done with a long chain of if-elif statements (similar to how you did in ESPHome) or, more concisely, using a map (a.k.a. dictionary lookup).

template:
  - sensor:
      - name: "Text Pressure Trend"
        unique_id: text_pressure_trend
        icon: mdi:trending-up
        state: >-
          {% set p = states('sensor.pressure_trend') | float(0) %}
          {% set m = { p > 0.03: "Rising Fast",
              0.02 < p <= 0.03: "Rising",
              0.01 < p <= 0.02: "Slowly Rising",
             -0.01 < p <= 0.01: "Steady",
             -0.02 < p <= -0.01: "Slowly Falling",
             -0.03 < p <= -0.02: "Falling" } %}
          {{ m.get(true, 'Falling Fast') }}
2 Likes

You don’t need the curly brackets for text:

template:
  - sensor:
      - name: "TextPressureTrend"
        unique_id: 471cbe8e-5fc3-4597-9064-47e57295d25c
        icon: mdi:trending-up
        state: >-
            {% if float(sensor.pressure_trend.state, 0) > 0.03 %}
              Rising Fast
            {% elif float(sensor.pressure_trend.state,0) > 0.02 and float(sensor.pressure_trend.state,0) <= 0.03 %}
              Rising
            {% endif %}

Old habits… :slight_smile:

Thanks all. We’ve made some progress with the following.

template:
  - sensor:
    - name: "TextPressureTrend"
      unique_id: TextPressureTrend
      icon: mdi:trending-up
      state: >-
        {% if float(sensor.pressure_trend.state, 0) > 0.03 %}
          Rising Fast
        {% elif float(sensor.pressure_trend.state, 0) > 0.02 and float(sensor.pressure_trend.state, 0) <= 0.03 %}
          Rising
        {% elif float(sensor.pressure_trend.state, 0) > 0.01 and float(sensor.pressure_trend.state, 0) <= 0.02 %}
          Slowly Rising
        {% elif float(sensor.pressure_trend.state, 0) > -0.01 and float(sensor.pressure_trend.state, 0) <= 0.01 %}
          Steady
        {% elif float(sensor.pressure_trend.state, 0) > -0.02 and float(sensor.pressure_trend.state, 0) <= -0.01 %}
          Slowly Falling
        {% elif float(sensor.pressure_trend.state, 0) > -0.03 and float(sensor.pressure_trend.state, 0) <= -0.02 %}
          Slowly Rising
        {% else %}
          Falling Fast
        {% endif %}

No errors reported anywhere and the new Sensor shows up as an Entity but has a value of “Unavailable” while the numeric Pressure Trend sensor shows a value of -0.01
image

You aren’t trapping that, so you could do:

            {% else %}
              No Change
            {% endif %}

Because there’s an error in that needlessly long template. sensor.pressure_trend.state is invalid. You’ll need to change all ten instances of it or just replace the entire template with what I suggested above.

Wouldn’t

{% else %}
    Falling Fast
{% endif %}

cover all values less than -0.03 since the ‘if’ covers all values greater than 0.03 and all the ‘elif’ statements cover all values in between?

As already mentioned, your template is failing because it uses an invalid reference, not because there’s any problem with the else.

Your post must have showed while I was trying the other solution and I didn’t see until now. This does seem to work. Thanks
image

1 Like