Develop and rebuild template sensor to python_script

Continuing the discussion from Heads up! Upcoming breaking change in the Template integration:

since Ha 115 checks for all states mentioned in a template sensor continuously now, below template causes havoc in my system (with a lot of states)

various alternatives were suggested, from leaving it out, cutting my system, or rewriting using an automation and an input_text. The latter would be most suitable were it not that that has a max Character limit of 255,which, obviously isnt near suitable for showing a longer list of entities (that can have long names themselves) in a frontend sensor card. We need to steer away from a sensor template, and a python script seems most appropriate.

Have an automation or script handle running the script, and have that script write to a sensor which can have as many attributes as we need, with as many characters as we need.

Now my original template sensor was this:

sensor:

# https://gist.github.com/jazzyisj/45fce29d825b8f9b29c5974444299d90
# https://community.home-assistant.io/t/sensor-unavailable-offline-detection/147618/10
# https://community.home-assistant.io/t/how-to-list-all-sensors-with-state-unavailable-none-or-unknown/154606

  - platform: template
    sensors:
      entities_unavailable:
#        entity_id:
#          - script.update_entities_uun
#          - automation.check_for_unavailable_entities
        friendly_name: Entities Unavailable
        value_template: >
          {% set ignore_list = ['light.driveway_floodlight','light.garden_backyard_floodlight','light.garden_terrace_floodlight',
                                'light.porch_floodlight','light.parking_light'] if
                                 is_state('binary_sensor.outside_daylight_sensor','on') else [] %}
          {% set unavailable = states|selectattr('state','eq','unavailable')
                                     |rejectattr('entity_id','in',state_attr('group.entity_blacklist','entity_id'))
                                     |rejectattr('entity_id','in',ignore_list)
                                     |rejectattr('domain','eq','media_player')
                                     |list %}
          {{unavailable|count}}

#          {% if states('sensor.entities_unavailable')|int > 0 %} mdi:thumb-down
#          {% else %} mdi:thumb-up
#          {% endif %}

      entities_uun:
#        entity_id:
#          - script.update_entities_uun
#          - automation.check_for_unavailable_entities
        friendly_name: Entities U/U/N
        value_template: >
          {% set ignore_list = ['light.driveway_floodlight','light.garden_backyard_floodlight','light.garden_terrace_floodlight',
                                'light.porch_floodlight','light.parking_light'] if
                                 is_state('binary_sensor.outside_daylight_sensor','on') else [] %}

          {{states|selectattr('state','in',['unavailable','unknown','none'])
                  |rejectattr('entity_id','in',ignore_list)
                  |rejectattr('entity_id','in',state_attr('group.entity_blacklist','entity_id'))
                  |rejectattr('domain','in',['group','media_player'])
                  |list|length}}
        attribute_templates:
          Unknown: >
            {% set unknown = states|selectattr('state','eq','unknown')
                                   |rejectattr('entity_id','in',state_attr('group.entity_blacklist','entity_id'))
                                   |rejectattr('domain','in',['group'])
                                   |map(attribute='entity_id')
                                   |list %}
            {% if unknown|count == 0 %} 0
            {% else %}
            {{unknown|count}}:
            {{'\n' + unknown|join(',\n')}}
            {% endif %}
          Unknown sensors: >
            {% set unknown = states.sensor|selectattr('state','eq','unknown')
                                          |rejectattr('entity_id','in',state_attr('group.entity_blacklist','entity_id'))
                                          |map(attribute='entity_id')
                                          |list %}
            {% if unknown|count == 0 %} 0
            {% else %}
            {{unknown|count}}:
            {{'\n' + unknown|join(',\n')}}
            {% endif %}
          Unavailable: >
            {% set ignore_list = ['light.driveway_floodlight','light.garden_backyard_floodlight','light.garden_terrace_floodlight',
                                  'light.porch__floodlight','light.parking_light'] if
                                   is_state('binary_sensor.outside_daylight_sensor','on') else [] %}
            {% set unavailable = states|selectattr('state','eq','unavailable')
                                       |rejectattr('entity_id','in',state_attr('group.entity_blacklist','entity_id'))
                                       |rejectattr('entity_id','in',ignore_list)
                                       |rejectattr('domain','eq','media_player')
                                       |map(attribute='entity_id')
                                       |list %}
            {% if unavailable|count == 0 %} 0
            {% else %}
            {{unavailable|count}}:
            {{'\n'}}{{unavailable|join(',\n')}}
            {% endif %}
          None: >
            {% set none_ = states|selectattr('state','eq','none')
                                 |map(attribute='entity_id')
                                 |list %}
            {% if none_|count == 0 %} 0
            {% else %}
            {{none_|count}}:
            {{'\n' + none_|join(',\n')}}
            {% endif %}
          Full: >
            {% set full = states|selectattr('state','in',['unavailable','unknown','none'])
                                |map(attribute='entity_id')
                                |list %}
            {{full|count}}:
            {{'\n' + full|join(',\n')}}

rather large, I admit, but it was very useful. Have it run after a delayed startup, check any red flags, fix if possible, run again to see if things got better, and where to look for issues (imagine a weather integration not initializing or whatever other integration) If alright, dont look back and leave alone.

Previously that could be done by setting the entity_id in the sensors config, as you can see above, now commented.

@VDRainer already started with a bare python_script, which does what the bottom attribute Full in my template sensor does, write the full unfiltered list :

count = 0
attributes = {}

for entity_id in hass.states.entity_ids():
    state = hass.states.get(entity_id).state
    if state in ['unavailable','unknown','none']:
        attributes[entity_id] = state
        count = count + 1

attributes['friendly_name'] = 'Unavailable Entities'
attributes['icon'] = 'mdi:message-alert-outline'

hass.states.set('sensor.unavailable_entities', count, attributes)

which runs alright.
I would love to expand on that by at least having the states ‘none’, ‘unavailable’, and ‘unknown’ in their own ordered lists (attributes).

further more, we really need the ignore_list and black_list filtering, along with a few domain rejectors :wink:

Not really knowing where to start here, I turn to the community for assistance, please have a look if you can help me out here?

would be much appreciated! thanks


1 Like

Give him the small finger and he want’s the whole hand. :slightly_smiling_face:

OK, here’s something to play with

Don’t forget, i’m also only a trial & error scripter, and that’s all i can

friendly_name = 'NUU Ordered'
icon = 'mdi:message-alert-outline'

# excludes
exclude_entities = ['binary_sensor.ir01_dvd_power', 'switch.sonoff02_basic_relay']
exclude_groups = ['group.my_lights', 'group.windows']
exclude_domains = ['media_player', 'automation']

# some variables
count_all = 0
count_none = 0
count_unavailable = 0
count_unknown = 0
list_none = []
list_unavailable = []
list_unknown = []
attributes = {}

# add groups entities to exclude_entities list
for group in exclude_groups:
    for entity_id in hass.states.get(group).attributes['entity_id']:
        exclude_entities.append(entity_id)

# iterate over all entities
for entity_id in hass.states.entity_ids():
    domain = entity_id.split('.')[0]
    if entity_id not in exclude_entities and domain not in exclude_domains:
        state = hass.states.get(entity_id).state
        if state in ['none', 'unavailable', 'unknown']:        
            count_all = count_all + 1
            if state == 'none':
                count_none = count_none + 1
                list_none.append(entity_id)
            if state == 'unavailable':
                count_unavailable = count_unavailable + 1
                list_unavailable.append(entity_id)
            if state == 'unknown':
                count_unknown = count_unknown + 1
                list_unknown.append(entity_id)

# build the attributes
if count_all > 0:
    if count_none > 0:
        attributes['none_count'] = count_none
        attributes['none_entities'] = sorted(list_none)
    if count_unavailable > 0:
        attributes['unavailable_count'] = count_unavailable
        attributes['unavailable_entities'] = sorted(list_unavailable)
    if count_unknown > 0:
        attributes['unknown_count'] = count_unknown
        attributes['unknown_entities'] = sorted(list_unknown)

attributes['friendly_name'] = friendly_name
attributes['icon'] = icon

# set the sensor
hass.states.set('sensor.nuu_orderd', count_all, attributes)

1 Like

cool! thank you so much!!

this will get things running indeed.
Immediately see why this is so handy to use, and only needs 1 go: listing 2 integrations not working as they are expected to, (illustrating the need for more than 255 characters
)


giving me the opportunity to check:


right,

reload integration:

bam! hit run script once more to see, and yes, all weather bits are gone!

got to get the other hand too
:
how can we use the condition on the list:

exclude_entities = ['light.driveway_floodlight','light.garden_backyard_floodlight','light.garden_terrace_floodlight',
                                'light.porch_floodlight','light.parking_light'] if
                    hass.states.get('binary_sensor.outside_daylight_sensor').state == 'on' else []

I only need to exclude these under the condition posted, but this errors.

Thought I was on the wrong forum for a second there


if hass.states.get('binary_sensor.outside_daylight_sensor').state == 'on':
    exclude_entities = ['light.driveway_floodlight','light.garden_backyard_floodlight','light.garden_terrace_floodlight', 'light.porch_floodlight','light.parking_light']
else:
    exclude_entities = []

yes, thanks works!
I have 2 more additions to make
1 for the full unfiltered list, being the original this started with. And a filtered list, but only for the domain sensor (including the filters of the blacklist and exclude entities

so, I added

count_full = 0
count_sensors = 0
list_full = []
list_sensors = []

to the variables, and,

    if count_full > 0:
        attributes['full_count'] = count_full
        attributes['full_entities'] = sorted(list_full)

to the attributes builder.
for the full list, I tried an additional for, but this errors on

  File "uun.py", line 54, in <module>
TypeError: 'NoneType' object is not callable

code:

for entity_id in hass.states.entity_ids():
    state = hass.states.get(entity_id).state
    if state in ['none', 'unavailable','unknown']:
        count_full = count_all + 1
        list_full = list_full.append(entity_id). #< being line 54 now

didn’t start with the sensors yet, 1 step at the time

btw, if a sensor counts 0, what happens? Won’t the attribute be built at all? Would be nice to have a value state: ‘All ok’ or something like that, as a positive feedback the count in fact = 0.

as a touch of beauty, it would be nice if the produced list would be presented nicely in Lovelace. Right now, displaying the attribute in a fold-entity-row, this shows as a list with ugly quotes and brackets :wink:
Could this be ‘unlisted’?

ok, found the way


count_all = 0
count_none = 0
count_unavailable = 0
count_unknown = 0
count_sensors = 0
list_all = []
list_none = []
list_unavailable = []
list_unknown = []
list_sensors = []

attributes = {}

# add groups entities to exclude_entities list
for group in exclude_groups:
    for entity_id in hass.states.get(group).attributes['entity_id']:
        exclude_entities.append(entity_id)

# iterate over all entities
for entity_id in hass.states.entity_ids():
    domain = entity_id.split('.')[0]
    if entity_id not in exclude_entities and domain not in exclude_domains:
        state = hass.states.get(entity_id).state
        if state in ['none', 'unavailable', 'unknown']:
            count_all = count_all + 1
            list_all.append(entity_id)
            if state == 'none':
                count_none = count_none + 1
                list_none.append(entity_id)
            if state == 'unavailable':
                count_unavailable = count_unavailable + 1
                list_unavailable.append(entity_id)
            if state == 'unknown':
                count_unknown = count_unknown + 1
                list_unknown.append(entity_id)
            if domain == 'sensor':
               count_sensors = count_sensors + 1
               list_sensors.append(entity_id)

# build the attributes
if count_all > 0:
    if count_none > 0:
        attributes['none_count'] = count_none
        attributes['none_entities'] = sorted(list_none)
    if count_unavailable > 0:
        attributes['unavailable_count'] = count_unavailable
        attributes['unavailable_entities'] = sorted(list_unavailable)
    if count_unknown > 0:
        attributes['unknown_count'] = count_unknown
        attributes['unknown_entities'] = sorted(list_unknown)
    if count_sensors > 0:
        attributes['sensors_count'] = count_sensors
        attributes['sensors_entities'] = sorted(list_sensors)
    if count_all > 0:
        attributes['all_count'] = count_all
        attributes['all_entities'] = sorted(list_all)

only need to re-format the lists, and check what happens in the 0 scenario.

Do you think you will ever get there? :slightly_smiling_face:

if count_all > 0:
    ...
else:
    count_all = 'All OK'

Then the state of the sensor should be ‘All OK’.
or

if count_all > 0:
    ...
else:
    attributes['nuu_entities'] = 'All OK'

then the state will be 0 with an attribute nuu_entities: All OK

Sorry, no clue how to format the output of the attributes.

haha, well, we’re close! thanks to you fundamental perseverance on my questions

got to admit this is very nice to have back:

open a folded row:

a more-info:


and working so quickly, without the system giving in to it.
cool

about the formatting: maybe Petro can come to the rescue :wink: will try and find a way to not-tag him

must be something like

', '.join(list)

https://www.decalage.info/en/python/print_list

Yes, that was is!

# build the attributes
if count_all > 0:
    if count_none > 0:
        attributes['none_count'] = count_none
        attributes['none_entities'] = ', '.join(sorted(list_none))
    if count_unavailable > 0:
        attributes['unavailable_count'] = count_unavailable
        attributes['unavailable_entities'] = ', '.join(sorted(list_unavailable))
    if count_unknown > 0:
        attributes['unknown_count'] = count_unknown
        attributes['unknown_entities'] = ', '.join(sorted(list_unknown))
    if count_sensors > 0:
        attributes['sensors_count'] = count_sensors
        attributes['sensors_entities'] = ', '.join(sorted(list_sensors))
    if count_all > 0:
        attributes['all_count'] = count_all
        attributes['all_entities'] = ', '.join(sorted(list_all))

this must be possible wit a dash in front of each item, but I have a déjà vu of difficulties with that


ok, one more question


Ive made an extra filter for unconditional entities (just like the original in fact, always leave out these entities_id’s)

if entity_id not in exclude_entities and entity_id not in exclude_conditional_entities and domain not in exclude_domains:

I tried to write that as

    if entity_id not in [exclude_entities,exclude_conditional_entities] and domain not in exclude_domains:

but that simply does nothing, not even an error


can’t we list several lists in a list like that to select from?

Found this:

thanks! unfortunately we cant import libraries like they mention there, give the fact we have a sandboxed python environment in HA.

made we want to try this though:

if hass.states.get('binary_sensor.outside_daylight_sensor').state == 'on':
    exclude_conditional_entities = ['light.parking_light']
else:
    exclude_conditional_entities = []
exclude_entities = ['group.battery_sensors','group.github_repos_in_use',
                    'group.github_repos_not_in_use','group.indoor_temp_sensors',
                    'group.iungo_switches_actueel','group.philips_temp_sensors']

excludes = exclude_conditional_entities + exclude_entities

and

if entity_id not in excludes and domain not in exclude_domains:

which seems to work as hoped for.
So, thanks for the pointer :wink:

edit

small change:

for group in exclude_groups:
    for entity_id in hass.states.get(group).attributes['entity_id']:
        excludes.append(entity_id)

otherwise the entities from the external group weren’t taken into account in the addition of the 2 lists.
Now we can add the entities of that external group, and the conditional excludes and fixed excluded entities.

just to be able to see the unfiltered entities for the ['none', 'unavailable', 'unknown'] states, functional to be able to fine tune the filtering, I re-added the original small section.

also, I de-tabbed the attribute building, because I didn’t want these to be none and build under all circumstances, if only to be able to display that nicely in the Lovelace Frontend.

Also, I added some customization (
) on the main All sensor, to have an immediate place if all is ok. (we can’t customize entities in Ha Customize, that are created in Python scripts)

Below, I post the script and the Lovelace card. The external group and script to call this python script are all you need in HA config to get this going.

Hope this is of use for the community, have fun.

Python script

##########################################################################################
# Python script to replace formely used template sensor, which causes havoc in HA 115
# https://community.home-assistant.io/t/develop-and-rebuild-template-sensor-to-python-script/228699
# thanks to @VDRainer for providing most of the code here, and persevering my thoughts and
# questions
# 23 sep 2020 @mariusthvdb
##########################################################################################

# excludes based on certain conditions
if hass.states.get('binary_sensor.outside_daylight_sensor').state == 'on':
    exclude_conditional_entities = ['light.parking_light']
else:
    exclude_conditional_entities = []

exclude_entities = ['group.battery_sensors','group.github_repos_in_use',
                    'group.github_repos_not_in_use','group.indoor_temp_sensors',
                    'group.iungo_switches_actueel','group.philips_temp_sensors',
                    'sensor.theboss',
                    'sensor.openweathermap_forecast_precipitation',
                    'sensor.openweathermap_forecast_temperature_low']

excludes = exclude_conditional_entities + exclude_entities

exclude_groups = ['group.entity_blacklist'] # configured in HA group outside this python script
exclude_domains = ['media_player','automation','geo_location']

# some variables
count_unfiltered = 0
count_all = 0
count_none = 0
count_unavailable = 0
count_unknown = 0
count_sensors = 0

list_unfiltered = []
list_all = []
list_none = []
list_unavailable = []
list_unknown = []
list_sensors = []


attributes = {}

# create unfiltered list to fine-tune filtering
for entity_id in hass.states.entity_ids():
    state = hass.states.get(entity_id).state
    if state in ['none', 'unavailable', 'unknown']:
         list_unfiltered.append(entity_id)
         count_unfiltered = count_unfiltered + 1

# add groups entities to exclude_entities list
for group in exclude_groups:
    for entity_id in hass.states.get(group).attributes['entity_id']:
        excludes.append(entity_id)

# iterate over all entities
for entity_id in hass.states.entity_ids():
    domain = entity_id.split('.')[0]
    if entity_id not in excludes and domain not in exclude_domains:
        state = hass.states.get(entity_id).state
        if state in ['none','unavailable','unknown']:
            count_all = count_all + 1
            list_all.append(entity_id)
            if state == 'none':
                count_none = count_none + 1
                list_none.append(entity_id)
            if state == 'unavailable':
                count_unavailable = count_unavailable + 1
                list_unavailable.append(entity_id)
            if state == 'unknown':
                count_unknown = count_unknown + 1
                list_unknown.append(entity_id)
            if domain == 'sensor':
               count_sensors = count_sensors + 1
               list_sensors.append(entity_id)

# build the attributes
if count_all > 0:
    icon = 'mdi:thumb-down'
    icon_color = 'red'
    attributes['all_count'] = count_all
    attributes['all_entities'] = ', '.join(sorted(list_all))
else:
    icon = 'mdi:thumb-up'
    icon_color = 'green'
    attributes['all_count'] = count_all
    attributes['all_entities'] = 'All entities OK!'

if count_none > 0:
    attributes['none_count'] = count_none
    attributes['none_entities'] = ', '.join(sorted(list_none))
else:
    attributes['none_count'] = count_none
    attributes['none_entities'] = 'No None entities'

if count_unavailable > 0:
    attributes['unavailable_count'] = count_unavailable
    attributes['unavailable_entities'] = ', '.join(sorted(list_unavailable))
else:
    attributes['unavailable_count'] = count_unavailable
    attributes['unavailable_entities'] = 'No Unavailable entities'

if count_unknown > 0:
    attributes['unknown_count'] = count_unknown
    attributes['unknown_entities'] = ', '.join(sorted(list_unknown))
else:
    attributes['unknown_count'] = count_unknown
    attributes['unknown_entities'] = 'No Unknown entities'

if count_sensors > 0:
    attributes['sensors_count'] = count_sensors
    attributes['sensors_entities'] = ', '.join(sorted(list_sensors))
else:
    attributes['sensors_count'] = count_sensors
    attributes['sensors_entities'] = 'All sensors Ok'

if count_unfiltered > 0:
    attributes['unfiltered_count'] = count_unfiltered
    attributes['unfiltered_entities'] = ', '.join(sorted(list_unfiltered))
else:
    attributes['unfiltered_count'] = count_unfiltered
    attributes['unfiltered_entities'] = 'All and Unfiltered Ok'


attributes['friendly_name'] = 'UUN Ordered'
attributes['icon'] = icon
attributes['icon_color'] = icon_color

# set the sensor
hass.states.set('sensor.uun_ordered', count_all, attributes)

#How it all started
# count = 0
# attributes = {}
#
# for entity_id in hass.states.entity_ids():
#     state = hass.states.get(entity_id).state
#     if state in ['unknown']:
#         attributes[entity_id] = state
#         count = count + 1
#
# attributes['friendly_name'] = 'Unavailable Entities'
# attributes['icon'] = 'mdi:message-alert-outline'
#
# hass.states.set('sensor.unavailable_entities', count, attributes)

Lovelace card:

type: entities
entities:

  - type: custom:hui-element
    card_type: entities
    title: Unavailable Unknown None
    show_header_toggle: false
    style: |
      ha-card {
        box-shadow: none;
        margin: 0px -16px 0px -16px;
      }
      .card-header {color: var(--primary-color);font-weight: bold;}
      .:
      "#states > div:nth-child(n+1) > fold-entity-row":
        $:
         "#head > entity-row-maker > hui-section-row":
           $: |
             div.divider {height: 0px;}
             div.label {font-weight: bold;}
    entities:
      - sensor.uun_ordered
      - entity: script.update_entities_uun
        secondary_info: last-triggered
        action_name: Update

      - type: custom:fold-entity-row
        head:
          type: section
          label: Unknown entities
        entities:
          - type: custom:hui-markdown-card
            style: |
              ha-card {
                box-shadow: none;
                margin: -16px -16px -16px -26px;
              }
            content: |
              Count: {{state_attr('sensor.uun_ordered','unknown_count')}}
              {{state_attr('sensor.uun_ordered','unknown_entities')}}

      - type: custom:fold-entity-row
        head:
          type: section
          label: Unknown sensors
        entities:
          - type: custom:hui-markdown-card
            style: |
              ha-card {
                box-shadow: none;
                margin: -16px -16px -16px -26px;
              }
            content: |
              Count: {{state_attr('sensor.uun_ordered','sensors_count')}}
              {{state_attr('sensor.uun_ordered','sensors_entities')}}

      - type: custom:fold-entity-row
        head:
          type: section
          label: Unavailable
        entities:
          - type: custom:hui-markdown-card
            style: |
              ha-card {
                box-shadow: none;
                margin: -16px -16px -16px -26px;
              }
            content: |
              Count: {{state_attr('sensor.uun_ordered','unavailable_count')}}
              {{state_attr('sensor.uun_ordered','unavailable_entities')}}

      - type: custom:fold-entity-row
        head:
          type: section
          label: None
        entities:
          - type: custom:hui-markdown-card
            style: |
              ha-card {
                box-shadow: none;
                margin: -16px -16px -16px -26px;
              }
            content: |
              Count: {{state_attr('sensor.uun_ordered','none_count')}}
              {{state_attr('sensor.uun_ordered','none_entities')}}

      - type: custom:fold-entity-row
        head:
          type: section
          label: Full list filtered
        entities:
          - type: custom:hui-markdown-card
            style: |
              ha-card {
                box-shadow: none;
                margin: -16px -16px -16px -26px;
              }
            content: |
              Count: {{state_attr('sensor.uun_ordered','all_count')}}
              {{state_attr('sensor.uun_ordered','all_entities')}}

      - type: custom:fold-entity-row
        head:
          type: section
          label: Full list unfiltered
        entities:
          - type: custom:hui-markdown-card
            style: |
              ha-card {
                box-shadow: none;
                margin: -16px -16px -16px -26px;
              }
            content: |
              Count: {{state_attr('sensor.uun_ordered','unfiltered_count')}}
              {{state_attr('sensor.uun_ordered','unfiltered_entities')}}

2 Likes

This script IS AMAZING :smiley:

Providing my touch if you don’t mind
 Getting one item per line is more beautiful :stuck_out_tongue:

Python script

##########################################################################################
# Python script to replace formely used template sensor, which causes havoc in HA 115
# https://community.home-assistant.io/t/develop-and-rebuild-template-sensor-to-python-script/228699
# thanks to @VDRainer for providing most of the code here, and persevering my thoughts and
# questions
# 23 sep 2020 @mariusthvdb
##########################################################################################

# excludes based on certain conditions
# if hass.states.get('binary_sensor.outside_daylight_sensor').state == 'on':
#     exclude_conditional_entities = ['light.parking_light']
# else:
#    exclude_conditional_entities = []

exclude_conditional_entities = []

# exclude_entities = ['group.battery_sensors','group.github_repos_in_use',
#                     'group.github_repos_not_in_use','group.indoor_temp_sensors',
#                     'group.iungo_switches_actueel','group.philips_temp_sensors',
#                     'sensor.theboss',
#                     'sensor.openweathermap_forecast_precipitation',
#                     'sensor.openweathermap_forecast_temperature_low']

exclude_entities = [
                    'sensor.chance_of_precip', 
                    'sensor.condition', 
                    'sensor.humidex', 
                    'sensor.icon_code', 
                    'sensor.rain_count', 
                    'sensor.visibility', 
                    'sensor.wind_chill', 
                    'sensor.wind_gust',
                    'sensor.octoprint_current_state', 
                    'sensor.octoprint_time_elapsed', 
                    'sensor.octoprint_time_remaining'
                    ]

excludes = exclude_conditional_entities + exclude_entities

exclude_groups = [] # configured in HA group outside this python script
exclude_domains = ['media_player','automation','geo_location']
    
# some variables
count_unfiltered = 0
count_all = 0
count_none = 0
count_unavailable = 0
count_unknown = 0
count_sensors = 0

list_unfiltered = []
list_all = []
list_none = []
list_unavailable = []
list_unknown = []
list_sensors = []


attributes = {}

# create unfiltered list to fine-tune filtering
for entity_id in hass.states.entity_ids():
    state = hass.states.get(entity_id).state
    if state in ['none', 'unavailable', 'unknown']:
         list_unfiltered.append(entity_id)
         count_unfiltered = count_unfiltered + 1

# add groups entities to exclude_entities list
for group in exclude_groups:
    for entity_id in hass.states.get(group).attributes['entity_id']:
        excludes.append(entity_id)

# iterate over all entities
for entity_id in hass.states.entity_ids():
    domain = entity_id.split('.')[0]
    if entity_id not in excludes and domain not in exclude_domains:
        state = hass.states.get(entity_id).state
        if state in ['none','unavailable','unknown']:
            count_all = count_all + 1
            list_all.append(entity_id)
            if state == 'none':
                count_none = count_none + 1
                list_none.append(entity_id)
            if state == 'unavailable':
                count_unavailable = count_unavailable + 1
                list_unavailable.append(entity_id)
            if state == 'unknown':
                count_unknown = count_unknown + 1
                list_unknown.append(entity_id)
            if domain == 'sensor':
               count_sensors = count_sensors + 1
               list_sensors.append(entity_id)

# build the attributes
if count_all > 0:
    icon = 'mdi:thumb-down'
    icon_color = 'red'
    attributes['all_count'] = count_all
    attributes['all_entities'] = ',\n'.join(sorted(list_all))
else:
    icon = 'mdi:thumb-up'
    icon_color = 'green'
    attributes['all_count'] = count_all
    attributes['all_entities'] = 'All entities OK!'

if count_none > 0:
    attributes['none_count'] = count_none
    attributes['none_entities'] = ',\n'.join(sorted(list_none))
else:
    attributes['none_count'] = count_none
    attributes['none_entities'] = 'No None entities'

if count_unavailable > 0:
    attributes['unavailable_count'] = count_unavailable
    attributes['unavailable_entities'] = ',\n'.join(sorted(list_unavailable))
else:
    attributes['unavailable_count'] = count_unavailable
    attributes['unavailable_entities'] = 'No Unavailable entities'

if count_unknown > 0:
    attributes['unknown_count'] = count_unknown
    attributes['unknown_entities'] = ',\n'.join(sorted(list_unknown))
else:
    attributes['unknown_count'] = count_unknown
    attributes['unknown_entities'] = 'No Unknown entities'

if count_sensors > 0:
    attributes['sensors_count'] = count_sensors
    attributes['sensors_entities'] = ',\n'.join(sorted(list_sensors))
else:
    attributes['sensors_count'] = count_sensors
    attributes['sensors_entities'] = 'All sensors Ok'

if count_unfiltered > 0:
    attributes['unfiltered_count'] = count_unfiltered
    attributes['unfiltered_entities'] = ',\n'.join(sorted(list_unfiltered))
else:
    attributes['unfiltered_count'] = count_unfiltered
    attributes['unfiltered_entities'] = 'All and Unfiltered Ok'


attributes['friendly_name'] = 'UUN Ordered'
attributes['icon'] = icon
attributes['icon_color'] = icon_color

# set the sensor
hass.states.set('sensor.uun_ordered', count_all, attributes)

#How it all started
# count = 0
# attributes = {}
#
# for entity_id in hass.states.entity_ids():
#     state = hass.states.get(entity_id).state
#     if state in ['unknown']:
#         attributes[entity_id] = state
#         count = count + 1
#
# attributes['friendly_name'] = 'Unavailable Entities'
# attributes['icon'] = 'mdi:message-alert-outline'
#
# hass.states.set('sensor.unavailable_entities', count, attributes)

And only one line when not checking them

Lovelace card:

        - type: custom:hui-element
          card_type: entities
          title: Unavailable Unknown None
          show_header_toggle: false
          style: |
            ha-card {
              box-shadow: none;
              margin: 0px -16px 0px -16px;
            }
            .card-header {color: var(--primary-color);font-weight: bold;}
            .:
            "#states > div:nth-child(n+1) > fold-entity-row":
              $:
              "#head > entity-row-maker > hui-section-row":
                 $: |
                  div.divider {height: 0px;}
                  div.label {font-weight: bold;}
          entities:
            - type: custom:fold-entity-row
              head: sensor.uun_ordered
              entities:
                #- sensor.uun_ordered
                - entity: script.update_entities_uun
                  secondary_info: last-triggered
                  action_name: Update
            
                - type: custom:fold-entity-row
                  head:
                    type: section
                    label: Unknown entities
                  entities:
                    - type: custom:hui-markdown-card
                      style: |
                        ha-card {
                          box-shadow: none;
                          margin: -16px -16px -16px -26px;
                        }
                      content: |
                        Count: {{state_attr('sensor.uun_ordered','unknown_count')}}
                        {{state_attr('sensor.uun_ordered','unknown_entities')}}
            
                - type: custom:fold-entity-row
                  head:
                    type: section
                    label: Unknown sensors
                  entities:
                    - type: custom:hui-markdown-card
                      style: |
                        ha-card {
                          box-shadow: none;
                          margin: -16px -16px -16px -26px;
                        }
                      content: |
                        Count: {{state_attr('sensor.uun_ordered','sensors_count')}}
                        {{state_attr('sensor.uun_ordered','sensors_entities')}}
          
                - type: custom:fold-entity-row
                  head:
                    type: section
                    label: Unavailable
                  entities:
                    - type: custom:hui-markdown-card
                      style: |
                        ha-card {
                          box-shadow: none;
                          margin: -16px -16px -16px -26px;
                        }
                      content: |
                        Count: {{state_attr('sensor.uun_ordered','unavailable_count')}}
                        {{state_attr('sensor.uun_ordered','unavailable_entities')}}
            
                - type: custom:fold-entity-row
                  head:
                    type: section
                    label: None
                  entities:
                    - type: custom:hui-markdown-card
                      style: |
                        ha-card {
                          box-shadow: none;
                          margin: -16px -16px -16px -26px;
                        }
                      content: |
                        Count: {{state_attr('sensor.uun_ordered','none_count')}}
                        {{state_attr('sensor.uun_ordered','none_entities')}}
           
                - type: custom:fold-entity-row
                  head:
                    type: section
                    label: Full list filtered
                  entities:
                    - type: custom:hui-markdown-card
                      style: |
                        ha-card {
                          box-shadow: none;
                          margin: -16px -16px -16px -26px;
                        }
                      content: |
                        Count: {{state_attr('sensor.uun_ordered','all_count')}}
                        {{state_attr('sensor.uun_ordered','all_entities')}}
          
                - type: custom:fold-entity-row
                  head:
                    type: section
                    label: Full list unfiltered
                  entities:
                    - type: custom:hui-markdown-card
                      style: |
                        ha-card {
                          box-shadow: none;
                          margin: -16px -16px -16px -26px;
                        }
                      content: |
                        Count: {{state_attr('sensor.uun_ordered','unfiltered_count')}}
                        {{state_attr('sensor.uun_ordered','unfiltered_entities')}}

that’s what I have too?

Nope
 you do because names are long enough to not allow a second one to start on the same line, like my sensor.pond_control_box_humidity and the next one is too long to fit

If you have two short names, they’ll show more than one on a row

Untitled

yes, you’re right, I see it now, will adapt :wink:

btw, I like it better like this, to conform with my other sensors:

as a side note, the card_mod of the headers per fold_entity_row did work once, but have lost their functionality:

      .:
      "#states > div:nth-child(n+1) > fold-entity-row":
        $:
         "#head > entity-row-maker > hui-section-row":
           $: |
             div.divider {height: 0px;}
             div.label {font-weight: bold;}

would you know how tp get that to work?

also, the fold titles are to far to the right, and need a mod still, while the padding: 0 setting wrks fine for the entities in the fold:

using this now:

    entities:
      - sensor.uun_ordered
      - entity: script.update_entities_uun
        secondary_info: last-triggered
        action_name: Update

      - type: custom:fold-entity-row
        head:
          type: section
          label: Details
        entities:
          - type: custom:fold-entity-row
            head:
              type: section
              label: Unknown entities
            padding: 0
            entities:
              - type: custom:hui-markdown-card
                style: |
                  ha-card {
                    box-shadow: none;
                    margin: -16px -16px -16px -26px;
                  }
                content: |
                  Count: {{state_attr('sensor.uun_ordered','unknown_count')}}
                  {{state_attr('sensor.uun_ordered','unknown_entities')}}

Have you tried clearing cache? any errors in the log?

No nothing really. Does it work on your side then?

No, everything seems aligned to the title though