Sensor - display last known value instead of 'unavailable'

This seems to be working great for MQTT. Does anyone know of a solution that works with sensors that don’t get their value via MQTT?

Same problem here, but I have an idea:

  • Create one template sensor which takes the value of a template sensor below it in sensor.yaml
  • Create the lower template sensor which updates itself only when the referenced entity is not in [‘unavailable’, ‘unknown’], otherwise takes the value of the template sensor above
  • If template sensors are updated in series then there will be no circular reference. No idea if this is true, but I will try it.

You could probably do this with an automation that conditionally stores a value in an input_number helper, but that seems less elegant, and I already have too many automations as it is.

Sounds promising. Let us know how it goes.

Updated 29-12-2021

Ok, I’ve implemented the below in sensor.yaml (or configuration.yaml if you don’t have a sensor.yaml set up yet) and it works for my use case. In my case, I’m trying to send the last known uptime in a mobile notification when my router goes down (it’s going down a lot lately), and there’s only a brief period where my notification automation must be triggered by the data source entity going unavailable and then reporting its previously known value.

How it works:

  • Consists of:

    1. Data source entity whose last known value should be sent in a notification the moment it becomes unavailable
    2. Template sensor (lets call it primary) that uses if/else logic to take the value of the data source entity, or to take a secondary template sensor value when the data source entity becomes unavailable
    3. Secondary template sensor that just always takes the state of the primary template sensor
  • When home assistant reboots, the template sensors are reloaded with a none value that causes both template sensors to take the value “unknown” while the data source entity is “unavailable” (see here). If you don’t care about this temporary state at home assistant reboot, then this solution should still work for you.

  • When the data source entity initially becomes available after HA reboot, the template sensors start working as expected. Both primary and secondary template sensors keep the last known value of the data source entity when the data source entity becomes unavailable, and revert back to the value of the data source entity when it becomes available again.

Here is a generic version of the above:

# Store last known value of data source entity while it is unavailable
- platform: template
  sensors:
    primary_template_sensor:
      friendly_name: "Place to store last known value of DATA SOURCE ENTITY while it is unavailable"
      value_template: >-
        {% set data_source = states('INSERT DATA SOURCE ENTITY HERE') %}
        {% if data_source in ['unavailable', 'unknown'] %} 
          {{states('sensor.secondary_template_sensor')}}
        {% else %}
          {{data_source}}
        {% endif %}
    secondary_template_sensor:
      friendly_name: "Placeholder to avoid circular reference in primary_template_sensor if/else logic"
      value_template: >-
        {{states('sensor.primary_template_sensor')}}

Here is my implementation: Note that I’ve combined a solution for keeping the previously known uptime value with some extras for converting the uptime in seconds to a readable text string as discussed here. I also needed to filter uptime with the int() function when I set seconds in the value_template of rax_uptime_verbose in order to do the math operations below it without an error.

# Store last known RAX120 uptime when sensor becomes unavailable
- platform: template
  sensors:

    rax120_uptime_verbose:
      friendly_name: "Human-readable RAX120 uptime"
      icon_template: mdi:clock-start
      value_template: >-
        {% set uptime = states('sensor.rax120v2_gateway_uptime_2') %}
        {% if uptime in ['0', 'unavailable', 'none', 'unknown'] %} 
          {{states('sensor.rax120_uptime_placeholder')}}
        {% else %}
          {% set seconds = uptime|int %}
          {% set minutes = (seconds // 60)|int %}
          {% set hours = minutes // 60 %}
          {% set days = hours // 24 %}
          {% set minutes = minutes % 60 %}
          {% set hours =  hours % 24 %}
          {% set days = days % 7 %}
          {% macro phrase(value,name) %}
            {%- set value = value %}
            {%- set end = 's' if value > 1 else '' %}
            {{- '{} {}{}'.format(value,name,end) if value|int > 0 else '' }}
          {%- endmacro %}
          {% set text = [phrase(days,'day'),phrase(hours,'hour'),phrase(minutes,'min')]|select('!=','')|list|join(', ') %}
          {% set last_comma = text.rfind(',') %}
          {% if last_comma != -1 %}
            {% set text = text[:last_comma] + ' and' + text[last_comma + 1:] %}
          {% endif %}
          {{text}}
        {% endif %}

    rax120_uptime_placeholder:
      friendly_name: "Place to store RAX120 uptime when unavailable"
      icon_template: mdi:clock-start
      value_template: >-
        {{states('sensor.rax120_uptime_verbose')}}

If you really need the last known value of the data source entity to persist through a HA reboot (or the HA uptime entity is your data source entity), then you can use an automation and an input_text, input_number or input_date helper in place of the primary and secondary template sensors above. In this case, create the appropriate type of input sensor for your datatype via “helpers” in the HA configuration settings and use its respective set_value service call in your automation. The automation could look like the below with as many conditions as you desire (or a fancy combined template condition :stuck_out_tongue:):

alias: 'DATA SOURCE ENTITY persistent storage'
description: 'Update INPUT NUMBER to match DATA SOURCE ENTITY state unless unavailable or unknown'
mode: single
trigger:
  - platform: state
    entity_id: INSERT DATA SOURCE ENTITY
    id: Data source state updated
condition:
  - condition: and
    conditions:
      - condition: not
        conditions:
          - condition: state
            entity_id: INSERT DATA SOURCE ENTITY
            state: unavailable
      - condition: not
        conditions:
          - condition: state
            entity_id: INSERT DATA SOURCE ENTITY
            state: unknown
action:
  - service: input_number.set_value
    target:
      entity_id: INSERT INPUT NUMBER ENTITY

This automation will only update the value of the helper entity when the the data source entity is not unavailable and not unknown, and the helper entity should persist through a reboot. Note that the helper entity will be updated with the value of the data source entity when it becomes available again. I chose not to use this implementation because my data source entity updates every few seconds, and I didn’t want to use an automation that runs so frequently and clogs up my logs. But, perhaps this will do the job for others, especially if your data source entity changes states infrequently.

1 Like

Few options that pop to mind.

  1. Have an automation that posts a sensor value to an mqtt topic unless it’s unavailable / unknown. Make sure you set the retain flag on. Have a template sensor that pulls from the mqtt topic unless it’s unavailable / unknown
  2. Use the Var custom component
1 Like

Sorry for reviving an old topic, but I’m encountering this now. The answers below seemed rather complicated for such a silly small problem. The solution I’m using is to just publish “Online” to the LWT topic that published “Offline”. HA then switches from all relevant entities being “unavailable” to whatever data they last received.

So, in my case, tasmota goes into deep sleep, publishes it’s “tele/tasmota_xxxxxx/LWT Offline” message and HA sets all entities for that device to unavailable. I made a simple automation with the trigger mqtt topic “tele/tasmota_xxxxxx/LWT” payload “Offline”. The action is call service, MQTT publish topic “tele/tasmota_xxxxxx/LWT” payload “Online”. HA now thinks the device is online and displays whatever the last values each entity had.

2 Likes

@demondreamer : Thanks. Meets the need. I use Tasmota, and this seems to be the simplest way to make the values retained. If I ever wonder if the sensor is still working, I can check to see when the automation last ran. Good idea.

I tried this method because I have a temperature sensor for my pool that gets shutdown at this time of year. I’d like the dashboard to reflect the last known temp but instead I get the “Entity is currently unavailable:” message instead.
After creating and running the automation the dashboard still shows the same message. I’m using Guage card for this. Am I correct to think that by publishing the Online payload when it sees “Offline” that the gauge card would still show with the last known temp (before going offline)? I think I followed the process correctly, I saw the new payload “Offline” in the mqtt logs. I did not include the quotes ("") in the automation for either the payload or topic. Appreciate any thoughts here. Thanks!

Here’s a better way to show the last known value of a sensor:

Create a Trigger-based Template Sensor (the NOTE section of this post)

3 Likes

That’s spot on!
I wish it was marked as a solution right away, so there’s no need to read the whole thread.

@ros could you maybe mark this as the solution?

1 Like