Best practices for making an open/close curtains automation

I’m a new Home Assistant user. I’m moving my home automation setup over from Symcon which I’ve used for 10+ years. I’m looking for some guidance on the ‘best’ way to set up my system, as I’ve experienced that it’s usually easy to get ‘something’ to work, but doing it in a clean, maintainable way is hard (just like in programming, hah).

So my first sub-project is getting my curtains to open and close on time. I’m starting with just those in my living room and office. The rules I have in my current/previous system are:

  • open both at 7h30 or sun rise, which ever is latest
  • close both at sunset but no later than 22h

‘sunset’ here is ‘civil twilight’ as per the nomenclature of Twilight - Wikipedia .

So far from what I’ve tried, there are multiple ways I could set this up in HA:

  • The naive way is to make an automation for each curtain that is trigger at both 7h30 and sunrise, and open the curtain
    if it’s not open yet, and the same in the evening. But this would require maintaining two automations that are identical except for the device they work on. It also means I have separate automations for opening and closing, so 4 in total, which is hard to document/keep track of.

  • I could write a script where I do all this in one place, I think? But then I’m programming it all. Which is harder to
    integrate with other functionality. In setting up this system, I’m applying what I’ve learned from other HA systems in the past - don’t try to fight the design, but go along with it as much as possible. I’m feeling like writing scripts is going against the grain of most HA systems.

  • Can this be done with ‘blueprints’? Can I integrate several event responses in one blueprint?

  • Maybe other options?

Can anymore more experienced give me some philosophical guidance on what the current best practice is to get this to work, in a way that is most maintainable going into the future?

Additionally - is there a way to store notes in Home Assistant? Comments that document why each parameter was chosen or why things are set up the way they are? I’m finding my notes from my old system a huge help moving over, and I want to document as much as possible in this Home Assistant setup, but I do want to avoid doing so in a separate Word/text document which I just know is going to get out of sync.

One last question - what does the Home Assistant ‘sun down’ event mean? The docs say ‘the moment the sun goes below/above the horizon’, but what part of the sun and how does that relate to light level? What is the exact, technical concept of ‘sun rise’ and ‘sun down’ in Home Assistant?


Example single automation (untested) below that opens and shuts both curtains in line with your supplied requirements. This works off the sun.sun state, but there are other ways including sun elevation. See the documentation for details: Automation Trigger - Home Assistant

Explanation built into the automation. You didn’t provide details of how your curtains operate, so I’ve had to guess. Please include this sort of detail in future posts.

- alias: Curtain manager
  id: 7869c234-978d-46d9-8dbc-886e81364134

  description: >
    Triggers at 07:30, 22:00, sun up and sun down.
    Conditions ensure that either:
      * sun is up and it's 07:30 or later
      * it's 22:00 or later
      * the sun is down
    Action then operates a pair of curtain switches depending on which trigger
    caused the logic flow to get this far.

    - platform: time
      at: "07:30:00"
      id: open
    - platform: state
      entity_id: sun.sun
      to: 'above_horizon'
      id: open
    - platform: time
      at: "22:00:00"
      id: close
    - platform: state
      entity_id: sun.sun
      to: 'below_horizon'
      id: close

    - or:
      - and:
        - condition: time
          after: "07:29:59"
        - condition: state
          entity_id: sun.sun
          state: 'above_horizon'
      - condition: state
        entity_id: sun.sun
        state: below_horizon
      - condition: time
        after: "21:59:59"

      - service: switch.turn_{{ 'on' if == 'close' else 'off' }}
            - switch.curtains1
            - switch.curtains2

Thanks, this is indeed an elegant way to combine everything into one automation.

I did have to change the ‘condition’ syntax to something like the following:


  • condition: or
    • condition: and
      • condition: time
        after: “07:29:59”
      • condition: state
        entity_id: sun.sun
        state: above_horizon
    • condition: state
      entity_id: sun.sun
      state: below_horizon
    • condition: time
      after: “21:59:59”

Is that normal? Should I edit my yaml file somewhere else than in the “Edit in YAML” mode of the automation editor?

Secondly - the web ui doesn’t accept the switch.turn_{{ ‘on’ if == ‘close’ else ‘off’ }} template syntax, so I can’t save the automation. Where do I put in these raw YAML files?

For completeness, I’m using ZWave curtains so I had to adjust the ‘action’ section a bit but that was easy:


  • type: turn_{{ ‘on’ if == ‘close’ else ‘off’ }}
    device_id: 687006e578f07e51e9b7abf0cdf5538a
    entity_id: switch.curtain_office_front_3
    domain: switch

(except for the string templating problem mentioned above, of course)


Please format code properly: either surround with three backticks or use the </> button. See here: How to help us help you - or How to ask a good question

Personally, I have nearly all of my automations in manually-edited YAML files. Top of my configuration.yaml looks like this:

automation: !include automations.yaml
automation manual: !include_dir_merge_list automations

…and my automations are then in YAML files under the automations folder. For example, automations/lights/hall-on.yaml starts:

- alias: Lights - hall lamp on

  description: >-
    Turns the hall light on if the house is occupied and it gets dark enough,
    or if the house is unoccupied and the sun goes below the horizon.

I can also use the UI for quick and simple automations, which the system stores in automations.yaml.

I’m an experienced Linux user with HA running in a Docker container on my NAS, so I use ssh and vim to create and edit my files.

OK thanks. At least with your approach of sourcing all files from a directory, I can use both hand-written and UI-generated yaml files. I do not want to go back to a state where I have to hand-edit config files over ssh, I’ve been doing that for 25 years. The templating is very powerful, hopefully that can be worked into the visual editors somehow soon.

I have a couple of years more than you then (although telnet before ssh). It has its advantages: if I had to give up one, I’d lose the UI and keep the manual files.

Well I don’t to give one up, what I want is a working UI and text files only to fall back on when SHTF. But I guess we can’t always have in life what we want now can we.

Anyway, after setting this up, it didn’t work last night or this morning. So I’m wondering now - how can I test these automations when they’re set up outside of the UI? Is there a way to force-run the ‘action’ part so that I can check if it’s there or somewhere else? I don’t see anything in the logs either, is there a way to list all scheduled events? Thanks.

Settings / Automations and Scenes. Then:

  • “Run” will run the actions, ignoring conditions — although not sure how the trigger template in the action will behave. It’ll probably default to turn_off.
  • “Traces” will show you what happened on previous triggers provided your automation has a unique ID (either created in the UI or with the id: statement).

There is no list of scheduled events: triggers are evaluated “live”.

How did you “set it up”?

Thanks again, I wasn’t sure if the non-UI automations should show up in that list. The way I set it up was the way you described: split manual automations off into a directory with yaml files that have a list of automations, and include that in configuration.yaml with !include_dir_merge_list . However it turns out that any automations with errors in them that are not yaml syntax errors are silently ignored (at least I couldn’t find a trace of errors in the logs?) and the automation yaml you provided had a typo - the last condition has to be

condition: time

and not

condition: state

I’ll admit I didn’t check that carefully. Either way, through elimination I found that this was the issue, and now it shows up in my automations list and the action part at least seems to work. I’ll know tonight if the trigger and condition parts also work as expected.

Fixed, thanks.

No worries, I appreciate you taking the time to help me out.