Clever way to define multiple nearly identical entities (just different names) in configuration?

Huh.

That worked - thank you!

Re the YAML - that’s a clever trick. I had thought “<<: &…” was effectively one thing, but actually it is two. “<<:” says insert the following indented parts (map) after it at that point, and there just happens to be a separate “&” anchor sitting there as well marking the following indented parts (map) for later re-use.

Interesting that I don’t see that sort of usage in very many YAML explainers.

Also interesting that HA complains about duplicate keys when given a ‘typical’ example of anchor usage such as:

default: &default-person
    name: Bill
    height: 175
    age: 5

person1:
    <<: *default-person
    age: 20

Anyways, learn something new every day. Thanks for your help!

1 Like

For anyone interested, final configuration here.

By using references to the state object & YAML anchors, aliases, and overrides we can declare a complex entity once, and then use that as a template for multiple additional entities.

Note, you’ll need to separately declare the required input boolean, text, and number entities as well.

This file (fans-config.yaml) is included with fan: !include fans-config.yaml in configuration.yaml:

- platform: template
    fans:
      master_bedroom_fan:
        friendly_name: "Master Bedroom Fan"
        unique_id: master_bedroom_fan
        <<: &hunter-fan-definition
          speed_count: 6

          value_template: "{{ states('input_boolean.' ~ this.object_id ~'_state') }}"

          turn_on:
            - service: fan.set_percentage
              target:
                entity_id: '{{ this.entity_id }}'
              data:
                percentage: "{{ states('input_number.' ~ this.object_id ~'_percentage') }}"

          turn_off:
            - service: input_boolean.turn_off
              target:
                entity_id: 'input_boolean.{{this.object_id}}_state'
            - service: remote.send_command
              target:
                entity_id: remote.linknlink01
              data:
                device: '{{ this.object_id }}'
                num_repeats: 1
                delay_secs: 0.4
                hold_secs: 0
                command: turn_off

          direction_template: "{{states('input_text.' ~ this.object_id ~'_direction')}}"

          set_direction:
            - service: input_text.set_value
              target:
                entity_id: 'input_text.{{this.object_id}}_direction'
              data:
                value: "{{direction}}"
            - service: remote.send_command
              target:
                entity_id: remote.linknlink01
              data:
                device: '{{ this.object_id }}'
                num_repeats: 1
                delay_secs: 0.4
                hold_secs: 0
                command: reverse

          percentage_template: "{{ states('input_number.' ~ this.object_id ~'_percentage') if is_state('input_boolean.' ~ this.object_id ~'_state', 'on') else 0 }}"

          set_percentage:
            - service: input_boolean.turn_{{ 'on' if percentage > 0 else 'off' }}
              target:
                entity_id: 'input_boolean.{{this.object_id}}_state'
            - service: input_number.set_value
              target:
                entity_id: 'input_number.{{this.object_id}}_percentage'
              data:
                value: "{{ percentage }}"
            - service: remote.send_command
              target:
                entity_id: remote.linknlink01
              data:
                device: '{{ this.object_id }}'
                num_repeats: 1
                delay_secs: 0.4
                hold_secs: 0
                command: >
                  {% set speed_value = (percentage|float / this.attributes.percentage_step|float)|round(0)|int %}
                  {% if (speed_value|int) > 0 %}
                    speed_{{speed_value}}
                  {% else %}
                    turn_off
                  {% endif %}


      spare_room_fan:
        <<: *hunter-fan-definition
        friendly_name: "Spare Room Fan"
        unique_id: spare_room_fan

      lounge_room_fan:
        <<: *hunter-fan-definition
        friendly_name: "Lounge Room Fan"
        unique_id: lounge_room_fan

#...etc etc...