How to test when IKEA Tradfri repeater is offline?

I have several IKEA Tradfri Zigbee repeaters. They have worked very well for over a year. Some went offline recently but why is not the question here. My question is about monitoring when these devices are offline.

They show as offline in the Zigbee visualisation page…

Screenshot 2024-02-13 at 12.35.56

… but neither the device nor any entities show up as unavailable in any of the attributes of my Unavailable Devices sensor …

##----------------------------------------------------------------------------------------------------------------------
##
## Unavailable Entities Sensor
##
## 05-Feb-2024 | Andy Symons | created
##
## Credit: based loosely on https://github.com/jazzyisj/unavailable-entities-sensor/blob/main/README.md
##
## The sensor provides lists related to real devices, not internal entities, helpers, automations etc.,
## Entities with state 'unknown' are not counted, because it is possible for a device to have a sub-entity that is
##    unknown while the device itself is available.
##
## The STATE simply gives the count of unavailable entities.
## The long results have to be attributes because the state cannot contain more than 255 characters:
##   ATTRIBUTE 'entity_id_list' contains a list of unavailable entities using their entity ids, which may or may not have been set by the user.
##   ATTRIBUTE 'entity_name_list' contains a list of unavailable entities using their friendly names as assigned by the user.
##   ATTRIBUTE 'device_name_list contains a list of the devices that are unavailable, which is to say having one or more entities that are unavailable,
##      using their friendly names as assigned by the user.
##
##----------------------------------------------------------------------------------------------------------------------

- sensor:
    name: "Unavailable Entities"
    unique_id: unavailable_entities
    icon: "{{ iif(states(this.entity_id)|int(-1) > 0,'mdi:alert-circle','mdi:check-circle') }}"
    state_class: measurement
    unit_of_measurement: entities

    # The entity state is the count of unavailable entites
    state: >
      {{ states
      | selectattr('domain','in',['binary_sensor', 'climate', 'light', 'sensor', 'switch'])
      | selectattr('state', 'in', ['unavailable'])
      | map(attribute='entity_id')
      | unique
      | list 
      | count
      }}

    # The long results have to be attributes because the state cannot contain more than 255 characters.
    attributes:
      ## A list of unavailable entities using their entity ids (which mnay or may not have been set by the user).
      entity_id_list: >-
        {{ states
        | selectattr('domain','in',['binary_sensor', 'climate', 'light', 'sensor', 'switch'])
        | selectattr('state', 'in', ['unavailable'])
        | map(attribute='entity_id')
        | reject('match', 'None')
        | list 
        | sort 
        | join('\n')
        }}

      ## A list of unavailable entities using their friendly names as assigned by the user.
      entity_name_list: >-
        {{ states
        | selectattr('domain','in',['binary_sensor', 'climate', 'light', 'sensor', 'switch']) 
        | selectattr('state', 'in', ['unavailable'])
        | map(attribute='entity_id')
        | map('state_attr', 'friendly_name') 
        | reject('match', 'None')
        | list 
        | sort 
        | join('\n')
        }}

      ## A list of the devices that are unavailable, using their friendly names as assigned by the user.
      device_name_list: >-
        {{ states
        | selectattr('domain','in',['binary_sensor', 'climate', 'light', 'sensor', 'switch'])
        | selectattr('state', 'in', ['unavailable'])
        | map(attribute='entity_id')
        | map('device_attr', 'name_by_user') 
        | reject('match', 'None')
        | unique
        | list 
        | sort 
        | join('\n')
        }}

# HOW THE ATTRIBUTE TEMPLATES WORK
#  -- Taking device_name_list as an example...
#
# {{ states                                                        -- all the states (entities) in the system
#    | selectattr('domain','in',['binary_sensor', 'climate', etc.  -- filter only the entities for real devices
#    | selectattr('state', 'in', ['unavailable'])                  -- filter only entities that are unavailable
#    | map(attribute='entity_id')                                  -- get the entity id from the record
#    | map('device_attr', 'name_by_user')                          -- map the entity id onto the device name
#    | reject('match', 'None')                                     -- take out names 'None' (meaning there is no name, so not a device)
#    | unique                                                      -- take out duplicates (devices usually have several entities)
#    | list                                                        -- make into a list (in the template sense)
#    | sort                                                        -- put them in alphabetical order
#    | join('\n')                                                  -- take out extraneous punctuation for a tidy output
#  }}

If I look up the device in the UI there are only two entities: ‘firmware’ and ‘identify’. So no main device entity?

  1. Am I missing a quirk or something that will give me more entities?
  2. How can I determine in a template that this device is off-line?

There’s a timeout in ZHA before devices report as unavailable, so presumably that’s why they’re not being picked up by your sensor. By default I think it’s set to two hours for mains-powered devices. You can change it, but I don’t know if that’s wise…

It’s at the bottom of the network settings (go to the Zigbee coordinator device page then click on “Add devices via this device” and the Network tab.

Thanks for your answer. However, they are recognised as offline by the visualisor, so whatever timeout there is surely must have expired? They have probably been offline for a while; I have not been here recently.

I think the issue is that I am not getting access to all the entities of the repeaters (see screenshot).

BTW there are several and all look the same.

What is shown if you click on ‘+2 entities not shown’ ?
afbeelding

LQI and RSSI. They were both disabled. I enabled them and now they show ‘unavailable’.
Like the other entities, they do not show up in my unavailable entities list.

The router itself is not in this list

But the LQI and RSSI are sensors, so should be

What is the domain of the router? Since I cannot see it in the UI, I cannot see its entity name.

Sorry, you were right. the LQI and RSSI are now showing up in the unavailable entities, and the repeater therefore in the unavailable devices list.

I monitor the “Identify” entity on my Tradfri repeater. When it switches to “Unavailable” I know it has gone offline. Similarly, when it switches from “Unavailable” I know if has come back online.

I am doing the same now. :grinning:

Identify has domain button, so after I added that to my domain list, it was included.

I also added the domain update to my list so that the firmware update entity is now counted too.

In addition, I enabled the LQI and RSSI entities. The domain sensor was already in my list but HA does not count them if they are disabled, as they were by default. They now show up as unknown when the device is online (either the device does not have them or the quirk is not complete), but that is enough to distinguish between the device being unavailable or available.

##----------------------------------------------------------------------------------------------------------------------
##
## Unavailable Devices Sensor
##
## 05-Feb-2024 | Andy Symons | created
## 14-Feb-2024 | Andy Symons | 'button' and 'update' added to the domain lists
##
## The sensor provides lists related to real devices, not internal entities, helpers, automations etc.,
## Entities with state 'unknown' are not counted, because it is possible for a device to have a sub-entity that is
##    unknown while the device itself is available.
##
## The STATE simply gives the count of unavailable devices.
## The long results have to be attributes because the state cannot contain more than 255 characters:
##   ATTRIBUTE 'entity_id_list' (debug aid) contains a list of unavailable entities using their entity ids, which may or may not have been set by the user.
##   ATTRIBUTE 'entity_name_list' (debug aid) contains a list of unavailable entities using their friendly names as assigned by the user.
##   ATTRIBUTE 'device_name_list (the main output) contains a list of the devices that are unavailable, which is to say having one or more entities that are unavailable,
##      using their friendly names as assigned by the user.
##
##----------------------------------------------------------------------------------------------------------------------

- sensor:
    name: "Unavailable Devices"
    unique_id: unavailable_devices
    icon: "{{ iif(states(this.entity_id)|int(-1) > 0,'mdi:alert-circle','mdi:check-circle') }}"
    state_class: measurement
    unit_of_measurement: devices

    # The sensor state is the count of unavailable devices
    state: >
        {{ states
        | selectattr('domain','in', ['binary_sensor', 'button', 'climate', 'light', 'sensor', 'switch', 'update'] ) 
        | selectattr('state', 'in', ['unavailable'])
        | map(attribute='entity_id')
        | map('device_attr', 'name_by_user') 
        | reject('match', 'None')
        | unique
        | list 
        | count
        }}

    attributes:
      ## DEBUG AID: A list of unavailable entities using their entity ids (which mnay or may not have been set by the user).
      entity_id_list: >-
        {{ states
        | selectattr('domain','in', ['binary_sensor', 'button', 'climate', 'light', 'sensor', 'switch', 'update'] )
        | selectattr('state', 'in', ['unavailable'])
        | map(attribute='entity_id')
        | reject('match', 'None')
        | list 
        | sort 
        | unique
        | join('\n')
        }}

      ## DEBUG AID: A list of unavailable entities using their friendly names as assigned by the user.
      entity_name_list: >-
        {{ states
        | selectattr('domain','in', ['binary_sensor', 'button', 'climate', 'light', 'sensor', 'switch', 'update'] ) 
        | selectattr('state', 'in', ['unavailable'])
        | map(attribute='entity_id')
        | map('state_attr', 'friendly_name') 
        | reject('match', 'None')
        | list 
        | sort 
        | unique
        | join('\n')
        }}

      ## MAIN OUTPUT: A list of the devices that are unavailable, using their friendly names as assigned by the user.
      device_name_list: >-
        {{ states
        | selectattr('domain','in', ['binary_sensor', 'button', 'climate', 'light', 'sensor', 'switch', 'update'] ) 
        | selectattr('state', 'in', ['unavailable'])
        | map(attribute='entity_id')
        | map('device_attr', 'name_by_user') 
        | reject('match', 'None')
        | list 
        | sort 
        | unique
        | join('\n')
        }}

# HOW THE ATTRIBUTE TEMPLATES WORK
#  -- Taking device_name_list as an example...
#
# {{ states                                                        -- all the states (entities) in the system
#    | selectattr('domain','in',['binary_sensor', 'climate', etc.  -- filter only the entities for real devices
#    | selectattr('state', 'in', ['unavailable'])                  -- filter only entities that are unavailable
#    | map(attribute='entity_id')                                  -- get the entity id from the record
#    | map('device_attr', 'name_by_user')                          -- map the entity id onto the device name
#    | reject('match', 'None')                                     -- take out names 'None' (meaning there is no name, so not a device)
#    | unique                                                      -- take out duplicates (devices usually have several entities)
#    | list                                                        -- make into a list (in the template sense)
#    | sort                                                        -- put them in alphabetical order
#    | join('\n')                                                  -- take out extraneous punctuation for a tidy output
#  }}


Here is an example dashboard card that uses this sensor

type: vertical-stack
cards:
  - type: custom:mushroom-title-card
    title: Unavailable Devices
  - type: entities
    entities:
      - entity: sensor.unavailable_devices
        name: Count
  - type: markdown
    content: |
      {{ state_attr( 'sensor.unavailable_devices' , 'device_name_list' )  }}

2 Likes