Best Practices for Setting Up Automations and Scripts in Home Assistant

Unless you have very inefficient automations (meaning the automations run more than they need to), you probably won’t notice performance issues, directly related to the number of automations you have.

The time you might notice is when a major event happens (for example first person to arrive home), since HA has to do a bunch of stuff at once **.

In my case I notice a slight “wave” of actions as the actions fire in sequence - TBF its still under a second and if you are not explicitly looking for it you wouldn’t notice - kinda like a flickering light doesn’t bother you until you notice it.

** - I don’t think this is actually a HA issue, I think its “backing up” sending all the commands over Zigbee.

I generally find that most automations follow common patterns:

  • Motion detected → turn on light.
  • Button pressed → toggle something on/off

I typically use 1 automation per pattern, regardless of the number of devices that it controls, so for example I have a single automation that handles all of my presence/motion detectors.

I find that having a lot of branching in automations or scripts is what makes them difficult to read, therefore I used “tricks” to try to eliminate most (and occasionally all) branching.

For example here is my motion detected automation:

mode: single
alias: Motion Detected
description: ""
triggers:
  - trigger: state
    entity_id:
      - input_select.sensor_mode
      - binary_sensor.sensor_group_bedroom
      - binary_sensor.sensor_group_hall_delayed
      - binary_sensor.sensor_group_living
      - binary_sensor.sensor_group_closet
      - binary_sensor.sensor_group_kitchen_combo
conditions: []
variables:
  present_bedroom: "{{ is_state('binary_sensor.sensor_group_bedroom',       'on') }}"
  present_hall: "{{    is_state('binary_sensor.sensor_group_hall_delayed',  'on') }}"
  present_living: "{{  is_state('binary_sensor.sensor_group_living',        'on') }}"
  present_closet: "{{  is_state('binary_sensor.sensor_group_closet',        'on') }}"
  present_kitchen: "{{ is_state('binary_sensor.sensor_group_kitchen_combo', 'on') }}"
  active_mode: "{{ states('input_select.sensor_mode') }}"
  scene_map:
    "Off": []
    Day:
      - selector: input_select.hall_lighting
        value: Bright
        present: "{{ present_hall }}"
      - selector: input_select.kitchen_lighting
        value: "{{ states('input_text.kitchen_lighting_last') }}"
        present: "{{ present_kitchen }}"
      - selector: input_select.bedroom_lighting
        value: Day
        present: "{{ present_bedroom }}"
      - selector: input_select.closet_lighting
        value: Bright
        present: "{{ present_closet }}"
    Night:
      - selector: input_select.hall_lighting
        value: Red
        present: "{{ present_hall }}"
    Away:
      - selector: input_select.living_lighting
        value: Arm
        present: "{{ present_living }}"
  active_setting: "{{ scene_map[active_mode] }}"
actions:
  - repeat:
      for_each: "{{ active_setting }}"
      sequence:
        - action: input_select.select_option
          metadata: {}
          data:
            option: "{{ iif(repeat.item.present, repeat.item.value, 'Off') }}"
          target:
            entity_id: "{{ repeat.item.selector }}"

Tricks:

  • All presence sensors are in groups (some groups only have one sensor).
  • This is an “input” automation, so I take inputs and update “helper” input selects - it may do a little more than it needs to, but at the end of the day its only updating UI (helper) elements.
  • I use a map (scene_map) instead of doing a condition in the actions section, hence my house modes (Off, Day, Night & Away) are all defined in the scene_map.
  • The scenes to activate are defined as lists, therefore I can have any number of them without needing an if condition. Additionally if I don’t want any actions I simply use an empty list (as in the case of the Off sensor mode).
  • There is also an Off scene for every room, so I don’t need a special case I just activate the Off scene.

Note: There is an accompanying “output” automation that reads the helpers and applies scenes (to change the lights). The output automation only fires if the select actually changes, so it doesn’t matter if input automations fire a little more than needed, as nothing actually happens.

I don’t always split “input” and “output” automations, but I often find there are multiple input automations and only a single output, so it saves duplicating the output logic multiple times (my scene switches update the same UI helper selects, hence re-use the same output automation as the motion detectors).

In answer to your question (about script usage) I have refactored my scripts/automations so that I don’t have to have any scripts, however I have 3 scripts which are invoked by my “Button Pressed” automation, so that I can have 3 clear sections/functions (Scenes, AC, House Modes).