Unavailable / Unknown Entity Monitoring - Template Sensor

So as you discovered, the issue here is that when a device is disabled device_entities() doesn’t report any entities.

If it DID, this little hacky template (there is probably a more elegant way to accomplish this) would work and we could utilize it in the unavailable entities template. It would have been a good addition to the template if it did work! But no dice. So I guess my advice above stands. You’ll have to add the entities required manually.

{%- set devices = namespace(device_id=[]) %}
{%- for item in states|map(attribute='entity_id')|list %}
  {%- if device_attr(item,'disabled_by') != none %}
    {%- set devices.device_id = devices.device_id + [device_id(item)] %}
  {%- endif %}
{%- endfor %}
{%- set disabled = devices.device_id|unique|list %}
{% for item in disabled %}
  {{ item }}
  {{ device_attr(item,'name') }}
  {{ device_entities(item) }}
{% endfor %}

Well at least you tried, thanks anyway.

How would I exclude all entity IDs from a specific Integration without adding them to a group ‘Alexa Media Player’ for example? I have over 120+ entity IDs for these.

1 Like

Template and documentation have been updated with new syntax and to exclude new stateless domains (button, scene, event etc.) by default.

3 Likes

Is there anyway just to show entity that’s are unavailable, currently its showing unavailable and unknown entities which isn’t what. I need

Replace this

{% set ignore_seconds = 60 %}
{% set ignored = state_attr('group.ignored_unavailable_entities', 'entity_id') %}
{% set ignore_ts = (now().timestamp() - ignore_seconds) | as_datetime %}
{% set entities = states
    | rejectattr('domain', 'in', ['button', 'event', 'group', 'input_button', 'input_text', 'scene'])
    | rejectattr('last_changed', 'ge', ignore_ts) %}
{% set entities =  entities | rejectattr('entity_id', 'in', ignored) if ignored != none else entities %}
{{ entities | map(attribute='entity_id') | reject('has_value') | list | sort }}

With this

{% set ignore_seconds = 60 %}
{% set ignored = state_attr('group.ignored_unavailable_entities', 'entity_id') %}
{% set ignore_ts = (now().timestamp() - ignore_seconds) | as_datetime %}
{% set entities = states
    | rejectattr('domain', 'in', ['button', 'event', 'group', 'input_button', 'input_text', 'scene'])
    | selectattr('state','eq','unavailable')
    | rejectattr('last_changed', 'ge', ignore_ts) %}
{% set entities =  entities | rejectattr('entity_id', 'in', ignored) if ignored != none else entities %}
{{ entities | map(attribute='entity_id') | list | sort }}
1 Like

I love this sensor however I have just added a device that has added a set of entities beginning with ‘sensor.byte’ which I do not want to know about however when I put '- sensor.byte_* ’ in my ignore entities group they still show. I obviously got the syntax wrong or do i need to add a rejectattr to the sensor code itself.

You can only add complete individual entities to a group.

In this case you can add a match filter to the template since you are matching the beginning of the entity_id. If you wanted to match something in the middle or end you would use a search test instead.

| rejectattr('entity_id','match','sensor.byte_')

There are some examples in the README.

Question, does anyone have an example of how I could get the ‘Detailed persistent notification message’ from the packages example sent via email? I added the following, but get the following error when ran.

expected dict for dictionary value @ data[‘data’]. Got None template value is None for dictionary value @ data[‘message’]. Got None

service: notify.email
data_template:
  title: Home Assistant - Unavailable Entities
  message: 
  data: >
    {% set ns = namespace(result=[]) %}
    {% for s in expand(state_attr('sensor.unavailable_entities', 'entity_id')) %}
     {% set ns.result = ns.result + [
         device_attr(s.entity_id, "name") ~ "|" ~ device_id(s.entity_id) ~ "|- **" ~ s.name ~ "**\n"
         ~ "  - *entity_id*: " ~ s.entity_id ~ "\n"
         ~ "  - *state*: " ~ s.state ~ "\n"
       ]
     %}
    {% endfor %}
    
    {% set ns.result = ns.result | sort %}
    {% set lastdev = namespace( id="" ) %}
    {% set tarr = ns.result %}
    {% set ns.result = [] %}
    {% for item in tarr %}
     {% set dev = namespace( id="" ) %}
     {% set entity = namespace( data="" ) %}
     {% set dev.id = item.split("|")[1] %}
     {% set entity.data = item.split("|")[2] %}
     {% if lastdev.id != dev.id %}
       {% if dev.id != 'None' %}
         {% set ns.result = ns.result + [ "**<a href=\"/config/devices/device/" ~ dev.id ~ "\">" ~ device_attr(dev.id, "name") ~ "</a>**" ] %}
       {% else %}
         {% set ns.result = ns.result + [ "**Non-Device Entities**" ] %}
       {% endif %}
       {% set lastdev.id = dev.id %}
     {% endif %}
     {% set ns.result = ns.result + [ entity.data ] %}
    {% endfor %}
    {{ ns.result | join('\n') }}

You’re using a very old format (data_template is now just data) and you put the template under a nested data parameter instead of the message parameter.

Heads up, if you’re using the same trigger as the automation in the package you’re probably going to get a lot of emails. It triggers every time any monitored entity becomes unavailable or not.

service: notify.email
data:
  title: Home Assistant - Unavailable Entities
  message: >
    {% set ns = namespace(result=[]) %}
    {% for s in expand(state_attr('sensor.unavailable_entities', 'entity_id')) %}
     {% set ns.result = ns.result + [
         device_attr(s.entity_id, "name") ~ "|" ~ device_id(s.entity_id) ~ "|- **" ~ s.name ~ "**\n"
         ~ "  - *entity_id*: " ~ s.entity_id ~ "\n"
         ~ "  - *state*: " ~ s.state ~ "\n"
       ]
     %}
    {% endfor %}
    
    {% set ns.result = ns.result | sort %}
    {% set lastdev = namespace( id="" ) %}
    {% set tarr = ns.result %}
    {% set ns.result = [] %}
    {% for item in tarr %}
     {% set dev = namespace( id="" ) %}
     {% set entity = namespace( data="" ) %}
     {% set dev.id = item.split("|")[1] %}
     {% set entity.data = item.split("|")[2] %}
     {% if lastdev.id != dev.id %}
       {% if dev.id != 'None' %}
         {% set ns.result = ns.result + [ "**<a href=\"/config/devices/device/" ~ dev.id ~ "\">" ~ device_attr(dev.id, "name") ~ "</a>**" ] %}
       {% else %}
         {% set ns.result = ns.result + [ "**Non-Device Entities**" ] %}
       {% endif %}
       {% set lastdev.id = dev.id %}
     {% endif %}
     {% set ns.result = ns.result + [ entity.data ] %}
    {% endfor %}
    {{ ns.result | join('\n') }}

That worked. Thanks. So is it possible to get alerts only the triggered entity and not all of them? I like to keep all of them in the persistent notification and get emails of new ones.

To accomplish this I would create an additional sensor like new_unavailable_entities or something like that. This template will return any entities that have become unavailable in the last 5 minutes (300 seconds). Adjust to meet your needs.

{% set check_seconds = 300 %}
{% set ignored = state_attr('group.ignored_unavailable_entities', 'entity_id') %}
{% set check_ts = (now().timestamp() - check_seconds) | as_datetime %}
{% set entities = states
    | rejectattr('domain', 'in', ['button', 'event', 'group', 'input_button', 'input_text', 'scene'])
    | rejectattr('last_changed', 'le', check_ts) %}
{% set entities =  entities | rejectattr('entity_id', 'in', ignored) if ignored != none else entities %}
{{ entities | map(attribute='entity_id') | reject('has_value') | list | sort }}

Use this new sensor to trigger your email notification. I would also suggest changing the trigger for your automation to a time pattern trigger equivalent to whatever time period your sensor is checking for to avoid multiple emails in a short time period.

In addition to the valid number condition, you will also need a condition to prevent the automation from firing if the sensor has gone to 0 to prevent “blank” email notifications.

condition: numeric_state
entity_id: sensor.new_unavailable_entities
above: 0

Another note, you will always get an email after a restart if you have any unavailable entities even if they were unavailable before the restart as the last_changed attribute always resets on a restart. You can use the following condition if you have enabled the uptime sensor to prevent this email after a restart, but if there are also any new unavailable entities you won’t get notified of them. Don’t forget to change the time in this condition if you adjust the template.

condition: template
value_template: "{{ now() - states('sensor.uptime') | as_datetime > timedelta(minutes=5) }}"

Hi,

I have added the integration exclusion as specified in the doco GitHub - jazzyisj/unavailable-entities-sensor: Unavailable entities template sensor for Home Assistant.

but doesn’t seem to be working showing more entities unavailable rather than less.
I added the text in the red box to the code in the packages file:

When I show the unavailable entities in the UI using the method mentioned in the readme it shows up fine without my additions to the package yaml. Once I add the code above though it goes from about 200 items to thousands. Assuming I am doing something wrong. Any ideas?

I am currently only restarting with quick reload (load new YAML).

Before and after screenshots below
image

You have placed your additions to the template after the closing bracket for the statement in the template that should have contained them.

Had you put your actual code in your comment instead of a screenshot I could have put a corrected version up for you to use.

Instead here is an example from my config for you.
          {% set ignore_seconds = 60 %}
          {% set ignored = state_attr('group.ignored_unavailable_entities', 'entity_id') %}
          {% set ignore_ts = (now().timestamp() - ignore_seconds) | as_datetime %}
          {% set entities = states
              | rejectattr('domain', 'in', ['button', 'device_tracker', 'event', 'group', 'input_button', 'input_text', 'scene'])
              | rejectattr('entity_id', 'in', integration_entities('browser_mod'))
              | rejectattr('entity_id', 'in', integration_entities('hassio'))
              | rejectattr('entity_id', 'in', integration_entities('dlna_dmr'))
              | rejectattr('entity_id', 'contains', 'jason_laptop_media_player')
              | rejectattr('entity_id', 'contains', 'jason_phone_media_player')
              | rejectattr('entity_id', 'contains', 'jason_tablet_media_player')
              | rejectattr('entity_id', 'contains', 'charlie_crate_camera')
              | rejectattr('entity_id', 'contains', 'living_room_camera')
              | rejectattr('entity_id', 'search', 'jphone_app|jtablet_app|jlaptop_chrome|jwork_chrome
                |_dlna|_timers|_alarms|_next_alarm|sensor.daily_energy_consumption')
              | rejectattr('last_changed', 'ge', ignore_ts) %}
          {% set entities =  entities | rejectattr('entity_id', 'in', ignored) if ignored != none else entities %}
          {{ entities | map(attribute='entity_id') | reject('has_value') | list | sort }}

You also should test your templates in Developer Tools template editor to see if they evaluate as expected before putting them in your configuration.

Additionally, if you are only editing a template, only need to reload templates. You don’t need to reload your entire YAML config.

image

Hope this all helps!

1 Like

Currently i use a group of entities i want to ignore. Is there also a way to ignore all entities of a device in a different defined group?

Excluding all entities from a device.

thats i already red but here i need one line per device or? Thats why i asked to use a group of devices?

You’ll need to give more details then. How many devices are you talking about here? Are all the devices you want to exclude part of the same integration? If so, you can just exclude the entire integration.

I have a bunch of devices (from different integrations) i want to exclude these. So my idea was to create a group with these device ids that should be excluded.