Label Management (find low-use and orphaned labels)

I have a lot of labels, I have used them to power/simplify automations, create more flexible and ‘dynamic’ groups, reduce dependency on HACS components, and to help me have a more fine-grained control over my home assistant setup.

… Too many Labels - Not easy to manage

There is no built-in way (AFAIK) to be able to see at a glance how I am using all of these labels, so …

  • I wrote a little jinja macro that helps me out with aggregating that data.
  • I store the labels data in a template sensor which updates periodically, and when labels are added or removed.
  • I present the output in a Flex-Tale Card in my system dashboard.

Custom components used:

This is what it looks like in the browser:

  • Being a flex-table, it is a nice sortable table.


This is the jinja macro
File: /custom_templates/labels.jinja

{%- macro labels_usage() -%}

    {%- set ns            = namespace(labels=[]) -%}
    {%- set labels_sorted = labels() | sort  -%}
    {%- for id in labels_sorted -%}

        {%- set entities = label_entities(id) -%}
        {%- set devices  = label_devices(id) -%}
        {%- set areas    = label_areas(id) -%}

        {%- set count_entities     = entities | count | default(0) -%}
        {%- set count_devices      = devices  | count | default(0) -%}
        {%- set count_areas        = areas    | count | default(0) -%}
        {%- set count_automations  = entities | select('match', '^automation\.')       | list | count | default(0) -%}
        {%- set count_scripts      = entities | select('match', '^script\.')           | list | count | default(0) -%}
        {%- set count_sensors      = entities | select('match', '^(binary_)?sensor\.') | list | count | default(0) -%}
        {%- set count_helpers      = count_entities - ( count_automations + count_scripts + count_sensors ) -%}
        {%- set count_total        = count_entities + count_devices + count_areas -%}

        {%- set row = dict(
            label_id          = id,
            label_name        = label_name(id),
            count_entities    = count_entities,
            count_devices     = count_devices,
            count_areas       = count_areas,
            count_automations = count_automations,
            count_scripts     = count_scripts,
            count_sensors     = count_sensors,
            count_helpers     = count_helpers,
            count_total       = count_total,
        ) -%}

        {%- set ns.labels = ns.labels + [row] -%}

    {%- endfor -%}
    {{- ns.labels | to_json(pretty_print=true) -}}
{%- endmacro -%}

This is the YAML for the template sensor.

# ########################################################################
# Updates: Every hour
# Updates: When label is created, deleted, and (unfortunately updated)
# ########################################################################
template:
- trigger:

  - platform: time_pattern
    hour: /1
    id: every_hour
    alias: Every Hour
  - platform: event
    event_type: label_registry_updated

  sensor:
  - name: labels_usage
    unique_id: labels_usage
    state: >
      {{- labels() | count -}}
    attributes:
      labels_usage: >
        {%- from "labels.jinja" import labels_usage -%}
                {{- labels_usage() -}}
    icon: mdi:label-percent-outline

This is the YAML for the user interface component.

# ############################################################################
# Flex Table configuration
# ############################################################################
- type: 'custom:flex-table-card'
  entities:
    include:
      sensor.labels_usage
  title: Labels Usage
  clickable: false
  columns:

  - name: Name
    data: labels_usage
    align: left
    modify: x.label_name

  - name: ID
    data: labels_usage
    align: left
    modify: x.label_id

  - name: Total
    modify: >-
      let count_total = parseInt(x.count_total, 10);
      if(count_total > 5 ){
          count_total
      }
      else{
        (count_total === 0)
          ? '<div class="0-negative" style="color:red;">' + count_total + '</div>'
          : '<div class="1-negative" style="color:green;">' + count_total + '</div>'
      }
    <<: &numeric_column
      data: labels_usage
      align: right

  - name: Devices
    modify: x.count_devices
    <<: *numeric_column

  - name: Entities
    modify: x.count_entities
    <<: *numeric_column

  - name: Areas
    modify: x.count_areas
    <<: *numeric_column

  - name: Automations
    modify: x.count_automations
    <<: *numeric_column

  - name: Script
    modify: x.count_scripts
    <<: *numeric_column

  - name: Sensors
    modify: x.count_sensors
    <<: *numeric_column

  - name: Helpers
    modify: x.count_helpers
    <<: *numeric_column

  # -----------------------------------------------------------------------------------
  # https://github.com/custom-cards/flex-table-card/blob/0f0260f170660309906358254b8bb1ed7c301f63/docs/example-cfg-css.md
  # -----------------------------------------------------------------------------------
  css:
    table+: 'padding-top: 5px;'
    'tbody tr+': 'user-select: text'
    'tbody tr:nth-child(even)': 'background-color: #a2542f6;'
    'th': 'padding: 0px 0px 10px 3px; background-color: #eeeeee;'
    'td': 'padding: 10px 10px 10px 10px'
    'td:nth-child(1)': 'font-weight: 700;'
    'td:nth-child(2)': 'color: #999999;font-style:italic;'
    'td:nth-child(7)': 'color: #999999;font-style:italic;'
    'td:nth-child(8)': 'color: #999999;font-style:italic;'
    'td:nth-child(9)': 'color: #999999;font-style:italic;'
    'td:nth-child(10)': 'color: #999999;font-style:italic;'

9 Likes