How to enumerate entities belonging to an integration?

EDIT: device_entities() only exists in 2021.10.0+ or the current beta. So you’ll need to be on the latest.

You can only find entities in an integration if the integration is implemented through the ui. But first, you’ll need to find the integration identifier. Then use that identifier to list the entities.

Here’s a template that will find you the identifiers for each integration that’s implemented in the UI.

{% set devices = states | map(attribute='entity_id') | map('device_id') | unique | reject('eq',None) | list %}
{%- set ns = namespace(integrations = []) %}
{%- for device in devices %}
  {%- set ids = device_attr(device, 'identifiers') | list | first %}
  {%- if ids and ids | length == 2 %}
    {%- set integration, something_unique = ids %}
    {%- if integration not in ns.integrations %}
      {%- set ns.integrations = ns.integrations + [ integration ] %}
    {%- endif %}
  {%- endif %}
{%- endfor %}
{{ ns.integrations }}

If the integration you desire is not listed in the output, then you cannot get the list of entities.

e.g.

Then, take a listed integration and paste it into the following tempalte. For example, I’m pulling hyperion entities.


{%- set find_integration = 'hyperion' %} 
{%- set devices = states | map(attribute='entity_id') | map('device_id') | unique | reject('eq',None) | list %}
{%- set ns = namespace(entities = []) %}
{%- for device in devices %}
  {%- set ids = device_attr(device, 'identifiers') | list | first %}
  {%- if ids and ids | length == 2 and ids[0] == find_integration %}
    {%- set ns.entities = ns.entities + device_entities(device) %}
  {%- endif %}
{%- endfor %}
{{ ns.entities }}

e.g.

EDIT2: If you don’t want to wait for 2021.10, this will work currently:

{%- set find_integration = 'hyperion' %} 
{% set entities = states | map(attribute='entity_id') | list %}
{%- set ns = namespace(entities = []) %}
{%- for entity_id in entities %}
  {%- set ids = device_attr(entity_id, 'identifiers') %}
  {%- if ids %}
    {%- set ids = ids | list | first %}
    {%- if ids and ids | length == 2 and ids[0] == find_integration %}
      {%- set ns.entities = ns.entities + [ entity_id ] %}
    {%- endif %}
  {%- endif %}
{%- endfor %}
{{ ns.entities }}

EDIT3: 1 liner in current version of HA for list of UI integrations:

{{ states | map(attribute='entity_id') | map('device_id') | reject('eq',None) | map('device_attr', 'identifiers') | map('list') | map(attribute='0') | map('list') | reject('eq', []) | map(attribute='0') | unique | sort }}
9 Likes

Very nice work (and I’ll amend my post above)! :+1:

FYI
device_entities exists in 2021.9.7 and I can confirm your example containing it does in fact work with it.

From here:

huh, I thought it was skipped in the beta this month :man_shrugging: Maybe I’m remember a different macro

Got to say that this made me do a double-take. device_id is a filter?!? Why yes, yes it is.

map(attribute='entity_id') | map('device_id')

FWIW, I had taken notice of area_id and area_name but skimmed over the device-related ones. Looks like I need to review them because it opens new doors for templating.

Yah, it does but it also doesn’t make it easy. For loops and/or namespace are pretty much required at all times.

Also, here’s a zwave one that’s pretty useful

1 Like

Thanks for the link! I swapped zwavejs with upb and it cranked out a table listing my UPB entities.

Yes, there is! This should give you a list of entities belonging to the SmartThings integration:

{{ integration_entities('smartthings') }}

Changed to lowercase. It appears some integrations will accept the upper, but the lower seems to work with most if not all integrations. Although for some strange reason, “Sonos” returned a larger list than “sonos”.

I think it should be lowercase, ie
{{ integration_entities('smartthings') }}

Very good, I will amend my post to reflect that.

I did some more digging and it turns out the Sonos example I had based my reply on was a fluke. For a proper list of integration identifiers, I suggest you check out petro’s post:

They all appear to be lowercase, as nickrout pointed out (heh, I’m a poet). Helpful in case the integration name in the UI does not match the actual integration identifier (e.g. Steam = steam_online)

1 Like

Hi guys.

What if I want to filter specific type of entity? I want to get all switches on my Google wifi to block internet access for a period of time. I get all swtiches and trackers using:
{%- set devices = states.switch | map(attribute='entity_id') | map('device_id') | unique | reject('eq',None) | list %}

Im stuck in how to put all that in a group so I can switch it on and off

You can’t send a list of device_id’s to any service. You have to use the entity_id. Also, the only way to create dynamic groups is by using group.set but keep in mind, that is a legacy group and it’s functions are limited.

It’s probably best if you just make a switch group instead.

Hi all,

strange but I don’t get ANY output from the template.
Of course I have plenty of integrations set up by UI.

The only output I get when pasting the template into the UI is

UndefinedError: No first item, sequence was empty.

Any help would be appreciated :slight_smile:

you either:

  • don’t have devices for the integration
  • spelled the integration incorrectly.

Sorry Petro, my reference was possibly wrong.

I’m trying to use the first template in your post from Oct.21 that should find the identifiers for each integration implemented in the UI.

From THAT template I don’t get any output.

I also give a try of that:

{% set devices = states | map(attribute='entity_id') | map('device_id') | unique | reject('eq',None) | list %}
{%- set ns = namespace(integrations = []) %}
{%- for device in devices %}
  {%- set ids = device_attr(device, 'identifiers') | list | first %}
  {%- if ids and ids | length == 2 %}
    {%- set integration, something_unique = ids %}
    {%- if integration not in ns.integrations %}
      {%- set ns.integrations = ns.integrations + [ integration ] %}
    {%- endif %}
  {%- endif %}
{%- endfor %}
{{ ns.integrations }}

And also get the error reported by @RalfP.
Then I change this line:

  {%- set ids = device_attr(device, 'identifiers') | list | first %}

to that:

  {%- set ids = device_attr(device, 'identifiers') | list | first | default('unknown')% }
1 Like

Thanks Adorem, that change is giving the desired results :slight_smile:

1 Like

does this still work? I cant get any output, other than a

TypeError: 'NoneType' object is not iterable

this is with the edit above

taking it apart a bit shows that:

{% set devices = states | map(attribute='entity_id') 
                        | map('device_id') | unique 
                        | reject('eq',None) | list %}

{{devices}}

{% for device in devices %}
  
  {{device_attr(device, 'manufacturer')}}
  {{device_entities(device)}}
{% endfor %}

all works, but adding

{{device_attr(device, 'identifiers')|list|first }}

caused the error UndefinedError: No first item, sequence was empty.

so there seem to be devices that dont have any.

Guarding that line with

if device_attr(device, 'identifiers') 

returns the list of integrations:

{% set devices = states | map(attribute='entity_id') | map('device_id') | unique | reject('eq',None) | list %}
{%- set ns = namespace(integrations = []) %}
{%- for device in devices if device_attr(device, 'identifiers') %}
  {%- set ids = device_attr(device, 'identifiers') | list | first %}
  {%- if ids and ids | length == 2 %}
    {%- set integration, something_unique = ids %}
    {%- if integration not in ns.integrations %}
      {%- set ns.integrations = ns.integrations + [ integration ] %}
    {%- endif %}
  {%- endif %}
{%- endfor %}
{{ ns.integrations }}

as I came here looking for a template to list all integrations, and expand that to a template that lists all integrations, and their entity count, I now end up with:

{% set devices = states | map(attribute='entity_id') | map('device_id') | unique | reject('eq',None) | list %}
{%- set ns = namespace(integrations = []) %}
{%- for device in devices if device_attr(device, 'identifiers') %}
  {%- set ids = device_attr(device, 'identifiers') | list | first %}
  {%- if ids and ids | length == 2 %}
    {%- set integration, something_unique = ids %}
    {%- if integration not in ns.integrations %}
      {%- set ns.integrations = ns.integrations + [ integration ] %}
    {%- endif %}
  {%- endif %}
{%- endfor %}
{% for integration in ns.integrations %}
  {{integration}}:  {{integration_entities(integration)|count }}
{% endfor %}

which works fine, without yet sorting the list according to the number of entities.

would love some feedback how to maybe get that done.

Just add a | default. Standard procedure anytime you use first and it returns nothing.

EDIT: This filter does everything that the for loop used to do. It’s also more accurate. The previous template filtered out integrations that had less than 2 identifiers. This does not.

{{ states | map(attribute='entity_id') | map('device_attr', 'identifiers') | reject('none') | map('first') | select('defined') | map(attribute='0') | unique | list }}