User Fighting Automations - how to?

I am somewhat new to home automation and one area I am struggling with, is eliminating the fight between user actions and automations over the controlled entities (i.e. Light)

i.e. User turns light off from switch, but motion based automation turns it back on, right after that.
We are both right, but user action shall prevail.

Which are the suggested ways to address fight over devices?

Thanks for suggestions

You have to think of all possible or required conditions in your automations so that user interactions have precedence.

Only thing I can think of is to use timers to see what happened recently to figure wether your automation should run. E.g. if the light is turned off and motion was off for longer than x time (motion didn’t turn it off) then start a timer “manual off”. If the timer manual off is running, do not turn the light on using motion.

But first think if you can make the motion detection logic smarter so you won’t have to fight it. If you need to fight it a lot, then the automation is not helping but annoying. Also, it may be annoying that if one person uses the manual switch to turn the light off, a few second later someone else is wondering why motion detection isn’t working.

1 Like

Good question. It got me thinking about why I’ve never really liked motion-activated lights inside. Simply put: What if I want the lights off?

I picture myself getting up at night to go to the bathroom, or walking through a hall to reach another room. I don’t want (in the first case) or need (in the second case) the lights on. Or I might be watching TV or otherwise engaged in an activity which shouldn’t be illuminated :wink:

Without automation, I wouldn’t have to touch the switch. I’d just leave it off. If an automation makes it any harder than that (like, having to go turn it off after it came on unwanted) that’s a fail.

I first think hard: do I need it and will it work reasonably well. For instance on the staircase to the top floor it is really dark sometimes. So I did put one there, but I only turn it on at a light glow setting on the dimmer to make it acceptable at night. If I walk past to go to the bathroom, I do not want to trigger it by accident. So I pointed it to have minimal chance on false triggers.

Then I put in extra conditions: not when it is light enough, not when the light is already on, not when the house is set on sleep mode for more than 5 minutes. I never go there when we are supposed to be in bed, but maybe right after I put the house in sleep mode. And then I automated the buttons: if I use those for on, and the light is dim from the motion, I turn it on much brighter and kill the timer that turns it off when motion ends. By the way, I only set the timer on motion, so if the light was already on it won’t go off either.

That way I have full manual control if I want, but light if I’m carrying some stuff to the top floor.

1 Like

As I’ve said in other threads…

I very rarely automate lights since they are very dynamic, examples of which can be found above.

the only way lighting can be functionally automated is if the behavior can be reliably modeled by the behavior being consistent.

a few examples for me are:

  • my deck light is always on from sunset to 1 am. Or if after 1 am it’s still dark out and the door to the deck is open.

  • I turn my computer room light on manually. After 30 minutes if there is no motion I have my Echo device ask if HA should turn off the light. If I say yes or there is no response then the light goes off. Otherwise (me saying no) I reset the 30 minute timer. (I had a hard time remembering to turn the light off if I left “for a minute”… :wink:)

  • my garage lights only need to be on if one of the garage doors are open or if there is motion in the garage. I also control that behavior with an actionable notification, as well, so the lights don’t turn off if I’m under the car.

I have a few more but very few.

1 Like

‘I have my Echo device ask if HA should turn off the light.’

How is this done? I Have Google Home not Alexa, but I assume may be similar.

Thanks!

Unfortunately it’s not built-in to HA. I use a custom integration (Alexa Media Player) that provides that functionality.

I have no idea if GH can do the same.

As far as I know this can’t be done with google.

I have a select entity for every room. Its state is on (automation in control), off (automation disabled until specifically turned back on, primarily at night) and override (automation disabled temporarily, state times out and reverts to on after 30 min of inactivity or 2 hours of continuous activity). The presence lights automation checks this before changing anything in a room.

The select entity itself is also automated. They are all trigger template selects and listen for any changes in lights in their room. When a light changes it checks the context. If user_id is set then the changes was initiated by a user via either HA or Google assistant. Is parent_id is set then the change was initiated by an automation. If neither is set then the change was initiated externally (in my house that means someone pressed the light switch on the wall). If the source was not an automation then the select becomes state override if it was on for a while.

Similar if someone goes to sleep in a room. Then the select entity in that room becomes state off. Until it is detected that everyone in that room is awake then it goes back to on.

Honestly haven’t really had any issues with it. Well at least not with that part. My main problem is simply a lack of a good way to detect occupancy downstairs since we have an open floor plan and can’t use motion sensors due to cats. Still working on that. Upstairs works extremely well though, good occupancy sensors and detecting overrides is very reliable.

2 Likes

Mike, I like your approach.

Do you have some examples I can learn from about how to check for the context?
I’d love to see some of your automations addressing this problem.

Thx
Bogdan

So I actually only have one single automation for my presence lights and its surprisingly simple. The real work around checking context and such is actually in the controllers (the trigger template selects I mentioned earlier), here’s those:

The controllers are the ones watching for sleep changes, light changes, etc. and checking context to automatically set themselves in the correct state (on, off or override). The automation then simply listens for presence events and calls the correct scene/script if the controller lets it:

- id: a6ff604da4c843d98102bbcf0240e890_automation_presence_lights
  alias: Presence lights
  description: Turn on and off rooms based on presence, light level and current overrides
  mode: parallel
  max: 25
  trace:
    stored_traces: 15
  variables: !include_dir_named /config/common/auto/room_presence
  trigger:
    - id: input_change
      platform: state
      entity_id: !include_dir_merge_list /config/common/auto/room_presence/inputs
      to: ['off', 'on', 'override']
      from: ['off', 'on', 'override']
    - platform: state
      entity_id:
        - binary_sensor.away_lights_active
        - switch.emergency_override
      from: 'on'
      to: 'off'
  condition: "{{ not is_state('switch.emergency_override', 'on') }}"
  action:
    alias: Loop through rooms
    repeat:
      for_each: >-
        {{ ([area_name(trigger.entity_id)] if trigger.id == 'input_change' else rooms) | list }}
      sequence:
        - variables:
            entities: "{{ area_entities(repeat.item) }}"
            controller: "{{ controllers | select('in', entities) | first }}"
            detector : "{{ detectors | select('in', entities) | first }}"
            light_sensor: "{{ light_sensors | select('in', entities) | first }}"
            off_scene: "{{ off_scenes | select('in', entities) | first }}"
            on_script: "{{ on_scripts | select('in', entities) | first }}"
        - alias: Is room controller on and sensors in a valid state
          if:
            - "{{ is_state(controller, 'on') }}"
            - "{{ states(detector) in ['on', 'off'] }}"
            - "{{ states(light_sensor) in ['on', 'off'] }}"
          then:
            alias: Room is occupied
            if: "{{ is_state(detector, 'on') }}"
            then:
              service: "{{ on_script }}"
            else:
              alias: Room is unoccupied
              service: scene.turn_on
              data:
                entity_id: "{{ off_scene }}"
                transition: 2.5

Some things to clarify about my setup here:

  1. /config/common/auto/room_presence looks like this
    Screen Shot 2022-06-21 at 12.09.08 PM
    Each of those files has a list of entity IDs for that type of thing (except rooms.yaml which has a list of rooms). So when you see !include references to that folder above, that’s what’s in there. Remember that !include_dir_named uses the file names to make a dictionary (controllers, detectors, etc.) whereas !include_dir_merge_list merges all the files in that folder into one big list
  2. When the trigger for this automation is in one of the rooms with a controller then the automation just changes that room. If its not (either because I manually triggered the automation or it was an area-less event like us arriving home) then it loops through all the rooms and sees if there’s anything to do.
    This is because I wanted the automation to be stateless, to put my whole house in the right state lights-wise every time it is run and not actually depend on the trigger. But I found performance wasn’t great like that, I would walk into a room and if that room happened to be at the end of the list there was a noticeable delay before the lights turned on as it processed the other rooms. So it can still operate statelessly but usually just processes the room the presence event came from.
  3. If my smoke/co detectors say there is an emergency then lights turn on full blast and emergency_override turns on, that’s why that condition is there. And then after that turns off the trigger fires and this reprocesses all the rooms.
  4. Why do I have scripts to turn rooms on and scenes to turn them off? Because off is trivial (everything → off) but on isn’t. The reason is because of light levels and google assistant. When presence lights turns lights on it sets them to 50%. But what if someone has set one light above that manually? Then don’t lower it. Only make lights brighter or adjust automation changed lights. However I also expose the scripts to google assistant and if someone says “Kitchen on” then it should forcibly set the lights to 50% regardless of what they’re currently at. So my scripts handle that. They’re all basically the same, here’s an example:
room_on_bedroom:
  alias: Room on - Bedroom
  icon: mdi:lightbulb-group
  mode: single
  max_exceeded: silent
  variables:
    lights: "{{ state_attr('light.bedroom', 'entity_id') }}"
    outlets: switch.bedroom_tv_outlet
    bright: "{{ is_state('binary_sensor.bright_bedroom', 'on') }}"
  sequence: &room-on-sequence
    parallel:
      - if: "{{ outlets is defined and outlets | count > 0 }}"
        then:
          alias: Turn on outlets
          service: switch.turn_on
          data:
            entity_id: "{{ outlets }}"
      - sequence:
          - variables:
              auto_change: "{{ not (not context.parent_id or context.user_id) }}"
          - choose:
              - alias: Change initiated by automation and room is bright
                conditions: "{{ auto_change and bright }}"
                sequence:
                  alias: Lights off
                  service: light.turn_off
                  data:
                    entity_id: "{{ lights }}"
              - alias: Change initiated by automation and room is dark
                conditions: "{{ auto_change }}"
                sequence:
                  - alias: Filter out lights brighter then 50%
                    variables:
                      low_lights: >-
                        {% set e_lights = expand(lights) %}
                        {{ e_lights
                            | selectattr('state', 'eq', 'off')
                            | map(attribute='entity_id') | list
                          + e_lights
                            | selectattr('state', 'eq', 'on')
                            | selectattr('attributes.brightness', 'lt', 127)
                            | map(attribute='entity_id') | list
                          + e_lights
                            | selectattr('state', 'eq', 'on')
                            | selectattr('attributes.brightness', 'gt', 127)
                            | selectattr('context.user_id', 'none')
                            | rejectattr('context.parent_id', 'none')
                            | map(attribute='entity_id') | list }}
                  - alias: Lights to 50%
                    service: light.turn_on
                    data:
                      entity_id: "{{ low_lights }}"
                      brightness: 127
            default:
              alias: Always set lights to 50% if change is user initiated
              service: light.turn_on
              data:
                entity_id: "{{ lights }}"
                brightness: 127
room_on_guest_room:
  alias: Room on - Guest Room
  icon: mdi:lightbulb-group
  mode: single
  max_exceeded: silent
  sequence: *room-on-sequence
  variables:
    lights: ["light.guest_room"]
    outlets:
      - switch.guest_room_left_monitor_outlet
      - switch.guest_room_right_monitor_outlet
    bright: "{{ is_state('binary_sensor.bright_guest_room', 'on') }}"

The sequence is literally an anchor like I’m showing for guest room in all the others, the only difference is what lights and outlets are in that room and what decides if its already bright in there.

Also note that in here I also check context. That’s how I determine if this script was started by automation or by a human (either clicking a button or telling google assistant to run it). Or if the lights were last changed by a human or by automation.

This is a lot I know. Feel free to ask if you have other questions. I thought about putting together a package but I feel like a lot of this is tied to my particular rooms and things so I’m not sure how useful that would be. I’ll think about it though.

I generally use occupancy to handle these types of things. I’ll turn it on when occupancy is detected, turn it off when it has expired after some time (timer). If its actioned while the occupancy is already set (before the timer expires at the exit), then leave it.

Occupancy: I use box/wasp appdaemon in conjuntion with things like ‘tv on’ and other activity in the room to formulate if a room is occupied.

I’ve also used wait for logic to detect if the switch was toggled during the timer and if that is the case, I extend the timer significantly because I assume the user wanted it to stay that way. I still use the timer though with an extended amount of time to put it back on automation after some hours just incase it was forgotten.

Lastly, i’ve used triple double tabs during a short frequency to toggle a ‘manual only’ operation until its manually turned back on. My light switches have an LED on them, and I keep that off while its on automatic and ON when it is manual so I can ‘see’ it. The LED becomes the manual switch override.

hi Mike,
I have to say my head is spinning by trying to understand what you’re doing. This is an absolute compliment :slight_smile:

I am trying to put together the triggers like you did in Presence lights, but I stumble across this declaration for entity_id:

trigger:
    - id: input_change
      platform: state
      entity_id: !include_dir_merge_list /config/common/auto/room_presence/inputs
      to: ['off', 'on', 'override']
      from: ['off', 'on', 'override']

I am getting errors trying to get the !include to work, and I am wondering if is because I shall also have the package “hack” in place. Talking about the the wildcard state triggers solution you are mentioning in the forum.

TIA

this is also a neat idea.
What kind / model of switches are those that you can programmatically access their LED?

Thx

To use that !include directive the folder /config/common/auto/room_presence/inputs would need to exist on your system. And every file in it would need to be a yaml file containing a list of entity IDs. They each would look like this:

- sensor.a
- binary_sensor.b
- input_boolean.c
- ...

Is that what you have on your system? I would guess not unless you happen to be using my wildcard state triggers project as well.

Just replace that with a list of entity IDs that you use. You don’t have to use the !include, you can just list what you use like normal.

Mike, Yes,
I created the folder structure and also have the files with lists of entity_id’s as you described.

Is that sufficient in order to allow the !include directive to the folder work?
Or do I neeed the wildcard state triggers as well?

I am very new at using the include! directives BTW and any help is appreciated.

automation error:

list1.yaml content and folder structure:

TIA

Oh I see the problem. !include does not work in the GUI editor for automations and scripts, even in YAML mode.

You can enter that in your automations.yaml file but tbh that won’t really work either. It will save and load if you do that but as soon as you change any automation in the GUI it will rewrite that file completely. And when it does it will suck in the contents of the yaml files in config/auto/inputs and replace the !include with a hard-coded list.

If you want to use !include in an automation you can only do so in a YAML-only automation. You can follow the directions here to see how to make a separate set of automations that is only editable in YAML and can’t be modified in the GUI. That’s the only way to use any of the !include directives in there, otherwise you will have to insert the list of entity IDs directly in the GUI/YAML.

EDIT: Other then that your file and folder structure is fine. You don’t have to use my wildcard state triggers project. Everything you have is good other then it doesn’t work in the GUI.

Mike,

THANK YOU, THANK YOU! I can bet this will solve my issue. Will try it tonight.

I am almost ashamed to recognize I spent 3-4 hours running in circles on this one, but I learned some new things along the way for sure.

cheers!

1 Like