How to enumerate entities belonging to an integration?

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 }}

yes ofc I tried that, but it errors with:

TypeError: 'NoneType' object is not iterable

hence the if test I added in the for itself

you put it in the wrong spot then

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

indeed:

and change that to my if:

now with your edit, and yes those are identical:

but the |default does not work

that makes no sense, eitehr way don’t use that template anymore. You don’t need namespace.

This template will build a list of your integration, the entities, and the count. Sorted on the count.

{% set ns = namespace(items = []) %}
{% for item in  states | map(attribute='entity_id') | map('device_attr', 'identifiers') | reject('none') | map('first') | select('defined') | map(attribute='0') | unique %}
  {% set entities = integration_entities(item) %}
  {% set ns.items = ns.items + [ { 'integration': item, 'count': entities | count, 'entities': entities } ] %}
{% endfor %}
{{ ns.items | sort(attribute='count', reverse=true) }}

well, dont shoot the messenger, I only showing what’s been returned. moving forward, that counting orde is indeed what I was after, thank you!

no need for the list of entities (now…) so took those out for the moment:

  {% set ns = namespace(items = []) %}
{% for item in  states | map(attribute='entity_id') 
  | map('device_attr', 'identifiers') | reject('none') 
  | map('first') | select('defined') 
  | map(attribute='0') | unique %}

  {% set entities = integration_entities(item) %}
  {% set ns.items = ns.items + [ { 'integration': item, 'count': entities | count} ] %}
{% endfor %}
{{ ns.items | sort(attribute='count', reverse=true) }}

id love the output to be a bit cleaner though, and only show Hue: 474, Wave-js: 394 etc etc so made this

{% for integration in ns.items| sort(attribute='count', reverse=true) %}
  {{integration}}
{% endfor %}

but of course it still uses those dictionaries:

what would be the shortest way to that?

in the main namespace(items = []) or clearing that in the final section

Marius, how else do you get attributes out of dictionaries? You know how to do this, you’ve done it thousands of times before.

I’ve been trying to use the method described above to get information about browser_mod users and I’be been getting a strangely high number. I then came across a different technique that seems to be doing the same thing but gets a strangely low number. Can anyone help me understand what is going on? I believe neither of them is enumerating to a credible number, which by looking browser_mod integation is 16.
Technique 1 from this thread enumerates to 90:

        {%- 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 | default %}
          {%- if ids[0] == 'browser_mod' %}
              {%- set ns.entities = ns.entities + [ids[1]] %}
          {%- endif %}
        {%- endfor %}
        {{ ns.entities |count }}

Technique 2 enumerates to 5:

{{integration_entities('browser_mod')|select('contains','browser_user')|reject('contains','browser_useragent')|list|count }}

The first is finding all entities created by browser mod, the second is finding only entities with a specific enitty_id.

The first method is specifically finding unique devices as well. It’s unnecessary for your application if you’re looking for entities.

{{ integration_entities('browser_mod') }}

Hi all, been following this with interest, yet I noticed that Tasmota seems to be one of those integrations for which entities cannot be enumerated using these templates. Any suggestions on how to reach a similar result with that integration?

I’m using the Tasmota integration so this lists all entities belonging to it:

{{ integration_entities('tasmota') }}

Why does Home Assistant still make it so hard to find the identifier for an integration???

custom:auto-entities allows you to filter by governing integration but that paramater requires the “secret” integration identifier…

The integration’s friendly name can be seen in several places but that is not at all useful.

I shouldn’t have to locate this topic, copy and paste @petro’s magic template into Dev Tools > Template and then visually inspect the list for the correct identifier!

It should be available to easily view from somewhere in the UI like here…
image

or here…

or even here…

:face_exhaling:

You mean apart from the fact that you installed that custom integration in a directory named smartthinq_sensors?

No great secret really.

Yes it is quite a pain in the ass.

It’s not apparent what the domain is. The domain can be different than the name of the integration or even the friendly name of the integration. The selector should accept the friendly name. I’m not sure if @dbrunt tried it, but it would be worth trying to use the friendly name of the integration to see if it works. I’m not sure if it does. Regardless, there does need to be any easier way to get the ‘slug’.

If you’re happy to find it manually, it’s in the URL of that link and its landing page.

And i am supposed to remember that?? :rofl:

I tried it but no go…

Happy? Hmmm. That’s a great tip, and not too difficult to remember! It’ll do for now. Thanks!

image

1 Like