Develop and rebuild template sensor to python_script

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…

you mean the card_mod style doesn’t work? If not we have to find out how to get it to work (again), style the fold_entity_row header…it did before… see: How to style the fold-entity-row head? - #9 by Mariusthvdb

about the alignment: as said, in my case, all is well (aligned to the left side of the top thumbs, except for the header alignement, which is shifted too far to the right:

yours are all shifted right :wink:

btw, I’ve taken the card out of the top entities card, which allows for one less card_mod too:

type: custom:hui-element
card_type: entities
title: Unavailable Unknown None
show_header_toggle: false
style: |
  ha-card {
    box-shadow: none;
  }
  .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

alignment is solved, it was as easy as adding padding: 0 to the top fold… how I could have missed that. Had to adjust the other styles for the left side shift to -8px because of that:

  - type: custom:fold-entity-row
    head:
      type: section
      label: Details
    padding: 0
    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 -8px;
              }
            content: |
              Count: {{state_attr('sensor.uun_ordered','unknown_count')}}
              {{state_attr('sensor.uun_ordered','unknown_entities')}}

for all folds. and makes it looks perfect:

only thing left is to style the fold heads, can’t stand this is so difficult to find out…

1 Like

Hi Marius,

Would you happen to have this issue as well? Each time I open a new HA instance or that I refresh, I’m getting this…

Refreshing 2-3 times, sometimes needs to clear cache (Ctrl+F5), but it eventually comes back to working good

That’s an old issue indeed. From the top of my head you can solve that using the hui-element custom card by Thomas loven and then add the markdown card in that

1 Like

Explanation:

You can also use the card-preloader to fix this.

1 Like

You were right… Here’s for posterity

Use this

- type: custom:hui-element
  card_type: markdown

Instead of:

- type: custom:hui-markdown-card

Thanks :slight_smile:

card-preloaded caused issues still, or maybe put differently, didnt solve it all.
added to that is seemed to do so in a ‘hacky’ way, and not always, seemed a bit flaky. While hue-element solved all red cards, never seen a red card since using that. And so easy.

see this post from Thomas why probably: https://github.com/home-assistant/frontend/issues/4984#issuecomment-610781709