Help with reusing similar code

TLDR: How do I reuse my conditions without copying and pasting a load of code?


I’m setting up holiday specific automations for my lights etc (eg specific colours for halloween, different ones for Christmas, new year, Paddy’s day etc).

My approach was to set up a Local Calendar with events for each holiday (eg my Halloween event is from 25th to 31st October) and I also have an input select to override that, with each of the holidays included so I can set them manually at other times if I want. The calendar is only checked if the input select is set to “automatic”, and I have an “off” option too which stops the calendar being checked at all.

So my automations will have multiple choices with OR conditions checking whether a) the holiday is selected manually on the input select, or b) the input select set to “auto” and the calendar event is active.

All that is working fine, but there is a LOT of repetition for each script/automation (multiple conditions to define a choice for each holiday in each automation…) and I’m sure there are ways to streamline this.

I tried with anchors/aliases and I can get it working to repeat a block of YAML, but I can’t figure out how to override the individual lines in that block the way I need to (multiple conditions have the same keys for example). I could maybe use multiple anchors, one for each of the conditions, but when I add in all the lines to override with the correct holiday info, that doesn’t actually reduce the total lines of code much.

Or do I maybe need to use jinja macros? I haven’t really got my head round those yet…

How would you do this?

Here’s an quick example of what I’m working with, with just two holidays and only one action per holiday:

script:
  test_holiday_script:

    alias: Test Holiday Script
    sequence:

      # CHECK FOR HOLIDAY
      - choose:

          # HALLOWEEN
          - conditions:
              # IF EITHER
              - condition: or
                conditions:
                  # INPUT SELECT IS SET TO HALLOWEEN
                  - condition: state
                    entity_id: input_select.holidays
                    state: Halloween
                  # OR THE INPUT SELECT IS SET TO AUTO AND CALENDAR SAYS HALLOWEEN
                  - condition: and
                    conditions:
                    - condition: state
                      entity_id: input_select.holidays
                      state: Automatic
                    - condition: state
                      entity_id: calendar.holidays
                      attribute: message
                      state: Halloween
            # DO THESE ACTIONS
            sequence:
              - action: light.turn_on
                metadata: {}
                data:
                  rgb_color:
                    - 255
                    - 38
                    - 0
                target:
                  entity_id: light.left_spot

          # CHRISTMAS
          - conditions: 
              # IF EITHER
              - condition: or
                conditions:
                  # INPUT SELECT IS SET TO CHRISTMAS
                  - condition: state
                    entity_id: input_select.holidays
                    state: Christmas
                  # OR THE INPUT SELECT IS SET TO AUTO AND CALENDAR SAYS CHRISTMAS
                  - condition: and
                    conditions:
                    - condition: state
                      entity_id: input_select.holidays
                      state: Automatic
                    - condition: state
                      entity_id: calendar.holidays
                      attribute: message
                      state: Christmas
            # DO THESE ACTIONS
            sequence:
              - action: light.turn_on
                metadata: {}
                data:
                  rgb_color:
                    - 4
                    - 51
                    - 255
                target:
                  entity_id: light.left_spot

        # IF NONE OF THE ABOVE MATCH, DO THESE ACTIONS
        default:
          sequence:
            - action: light.turn_on
              metadata: {}
              data:
                rgb_color:
                  - 255
                  - 255
                  - 255
              target:
                entity_id: light.left_spot

I’m not familiar with Jinja Macros but one option might be to use !include to include a file that has the redundant YAML in it. See Splitting up the configuration for how to use it.

I have my config split and I use packages for some stuff, not sure how that helps me here? What are you suggesting I do with an include?

One option would be to move the states you want to check and all the rgb color lists into variables:

script:
  test_holiday_script:

    alias: Test Holiday Script
    sequence:
      - variables:
          selected_holiday: "{{ states('input_select.holidays') }}"
          calendar_holiday: "{{ state_attr('calendar.holidays', 'message') }}"
          colors:
            default:
              - 255
              - 255
              - 255
            Halloween:
              - 255
              - 38
              - 0
            Christmas:
              - 4
              - 51
              - 255
          active_color: |
            {% set x =  calendar_holiday if selected_holiday == 'Automatic' else selected_holiday %}
            {{ colors.get(x, 'default') }}
      - action: light.turn_on
        metadata: {}
        data:
          rgb_color: "{{ active_color }}"
        target:
          entity_id: light.left_spot

1 Like

Ok so I’ve moved all the relevant automations/scripts into the same package and I created anchors for the first set of conditions for each holiday, so the next time I need them I just use the alias rather than paste the entire “conditions” section.

Still feel like jinja templates would be better.

This looks great, I’ll take a proper look tomorrow! The colours were just a placeholder, there’s a lot more going on, but that will get me started for sure.

Hi Scoobydoofus,

YAML Anchors