Need to override this automation if the light turns on manually

YAML attached. It’s a very simple thing, but my brain cannot find the simple solution.

I have a presence sensor in the kitchen. When it detects, lights on. When it stops detecting (it has a 90s clear time from Z2M), lights off.

I want to add an extra condition to the lights going off. With this automation, we NEVER use the light switch anymore to turn them ON.

The extractor hood in the kitchen is wired with the kitchen light. So when cooking, and we leave, the lights go off in 90s and the hood goes off with it.

I don’t want to add extra devices or change wiring. I have been suggested humidity sensors, temp, etc, but they didn’t work well, so I’m going back to basics with this approach.

So I want either of these 2 things, whatever is easier or more elegant.

  1. IF light was switched on MANUALLY (from the switch, and not from this automation), delay going off for 15min. I don’t know how to differentiate the manually from the automation to do it myself.

  2. Create a helper or whatever is needed, so when activated, it starts a timer for 15min. Then use this as a condition in the automation for the lights to go off. I would then either activate this helper with a double click in the switch, or a press and hold (not sure if possible) or if not just a button from Home Assistant itself.

This issue has been chasing me for a long while and wife is getting very annoyed.
Many thanks!

alias: Autolights - Kitchen + Ut
description: ""
trigger:
  - type: present
    platform: device
    device_id: e1ad7b06f6483100fdc1ded7bea6659e
    entity_id: 2875b2fff8b63f52cfc657cefa2ca682
    domain: binary_sensor
    id: Motion detected
  - type: not_present
    platform: device
    device_id: e1ad7b06f6483100fdc1ded7bea6659e
    entity_id: 2875b2fff8b63f52cfc657cefa2ca682
    domain: binary_sensor
    id: Room empty
condition: []
action:
  - choose:
      - conditions:
          - condition: trigger
            id: Motion detected
          - condition: sun
            after: sunset
            enabled: true
            after_offset: "-02:00:00"
          - condition: or
            conditions:
              - condition: time
                before: "00:00:00"
              - condition: time
                before: "00:30:00"
        sequence:
          - type: turn_on
            device_id: 9249067a2b0183a330175957c2bfe383
            entity_id: light.kitchen_lights
            domain: light
          - type: turn_on
            device_id: 751f44bd35db0a1bcd54d35567079ba8
            entity_id: light.utility_room_light
            domain: light
      - conditions:
          - condition: trigger
            id: Room empty
        sequence:
          - type: turn_off
            device_id: 751f44bd35db0a1bcd54d35567079ba8
            entity_id: light.utility_room_light
            domain: light
          - type: turn_off
            device_id: 9249067a2b0183a330175957c2bfe383
            entity_id: light.kitchen_lights
            domain: light
mode: single

1 Like

Is the switch an actual smart switch/relay or just a device that sends a signal?

For a smart switch, you can likely use the context of the state change of the switch. For a device like a smart button that just sends a signal, you will need to trigger off the entity or event that represents that device action.

Does the switch report power usage? You could always wire up a relay of whichever protocol you use (Z-Wave, Zigbee, ESPHome, etc), most that I use have a manual switch component that would allow you to know when you used the local paddle.

I have no contribution toward the solution to your question, unfortunately. I simply came here to say that sounds like a terrible wiring configuration and you should look to rectify that. OMG I would lose my mind if the ventilation turned on every time the lightswitch turned on, and vice/versa. Not to mention that such a thing isn’t even to code here in the US (though I don’t know where you are, so that may not be the case there).

In any event, if you rewired it to a much more user-friendly configuration, the solution to your problem would also become much simpler. :slight_smile:

Best of luck with whatever you decide!

I use helper input Booleans for this. I.e. have the automation turn on a boolean when it turns the device on. When your time trigger goes to turn it off, if the boolean is not set it’s been turned on manually, so don’t turn off, etc.

@exx The hood has a switch itself, but it’s manual buttons on its faceplate.

@Didgeridrew It’s a smart switch (not sure what you mean tbh). How do I see the context? Can’t see it in the logbook.

@CO_4X4 Nope it doesn’t.

@Swallowtail Hmmm that sounds kinda like what I want. I will double read that and try it myself.

I have done this as you suggest @Swallowtail but I’m not certain it will work great. I can see it working, but for it to work I have to manually switch on the light manually (either from HA or the switch without being picked by the presence sensor). It doesn’t feel very natural, as most scenarios will be that I went into the kitchen to cook, so the light turned on already. Now the boolean is On. I would have to manually turn down the boolean (which needs to be done from HA).

Any idea?

Edit:

alias: Autolights - Kitchen + Ut
description: ""
trigger:
  - type: present
    platform: device
    device_id: e1ad7b06f6483100fdc1ded7bea6659e
    entity_id: 2875b2fff8b63f52cfc657cefa2ca682
    domain: binary_sensor
    id: Motion detected
  - type: not_present
    platform: device
    device_id: e1ad7b06f6483100fdc1ded7bea6659e
    entity_id: 2875b2fff8b63f52cfc657cefa2ca682
    domain: binary_sensor
    id: Room empty
condition: []
action:
  - choose:
      - conditions:
          - condition: trigger
            id: Motion detected
          - condition: sun
            after: sunset
            enabled: true
            after_offset: "-02:00:00"
          - condition: or
            conditions:
              - condition: time
                before: "00:00:00"
              - condition: time
                before: "00:30:00"
          - condition: device
            type: is_off
            device_id: 9249067a2b0183a330175957c2bfe383
            entity_id: 9c8442f9d2a7c9fa1be5775f2d0da426
            domain: light
        sequence:
          - service: input_boolean.turn_on
            data: {}
            target:
              entity_id: input_boolean.automated_kitchen_lights
          - type: turn_on
            device_id: 9249067a2b0183a330175957c2bfe383
            entity_id: light.kitchen_lights
            domain: light
          - type: turn_on
            device_id: 751f44bd35db0a1bcd54d35567079ba8
            entity_id: light.utility_room_light
            domain: light
      - conditions:
          - condition: trigger
            id: Room empty
          - condition: state
            entity_id: input_boolean.automated_kitchen_lights
            state: "on"
        sequence:
          - type: turn_off
            device_id: 751f44bd35db0a1bcd54d35567079ba8
            entity_id: light.utility_room_light
            domain: light
          - type: turn_off
            device_id: 9249067a2b0183a330175957c2bfe383
            entity_id: light.kitchen_lights
            domain: light
          - service: input_boolean.turn_off
            data: {}
            target:
              entity_id: input_boolean.automated_kitchen_lights
mode: single

Using the context variable, start a timer when the switch is turned on manually. Just FYI, if you are using a helper to change device type of a switch to light, it is best to use the switch entity in the first automation.

alias: Kitchen Lights Manual Timer
description: ""
trigger:
  - platform: state
    entity_id: light.kitchen_lights
    to: "on"
    variables:
      id: "{{trigger.to_state.context.id}}"
      parent: "{{ trigger.to_state.context.parent_id }}"
      user: "{{ trigger.to_state.context.user_id }}"
condition:
  - alias: Test if triggered by physical device
    condition: template
    value_template: "{{ (id!=None, parent, user) == (true, None, None) }}"
action:
  - service: timer.start
    target:
      entity_id: timer.kitchen_lights

Modify your original automation to not turn the lights off when the timer is running and to trigger when the timer finishes.

alias: Autolights - Kitchen + Ut
description: ""
trigger:
  - type: present
    platform: device
    device_id: e1ad7b06f6483100fdc1ded7bea6659e
    entity_id: 2875b2fff8b63f52cfc657cefa2ca682
    domain: binary_sensor
    id: Motion detected
  - type: not_present
    platform: device
    device_id: e1ad7b06f6483100fdc1ded7bea6659e
    entity_id: 2875b2fff8b63f52cfc657cefa2ca682
    domain: binary_sensor
    id: Room empty
  - platform: state
    entity_id: timer.kitchen_lights
    to: idle
    from: active
    id: Timer finished
condition: []
action:
  - choose:
      - conditions:
          - condition: trigger
            id: Motion detected
          - or:
            - condition: sun
              after: sunset
              after_offset: "-02:00:00"
            - condition: time
              before: "00:30:00"
        sequence:
          - service: light.turn_on
            target:
              entity_id: 
                - light.kitchen_lights
                - light.utility_room_light
      - conditions:
          - condition: trigger
            id: 
              - Room empty 
              - Timer finished
          - not:
              - condition: state
                state: active
                entity_id: timer.kitchen_lights
        sequence:
          - service: light.turn_off
            target:
              entity_id: 
                - light.kitchen_lights
                - light.utility_room_light
mode: single
1 Like

Amazing help mate. Thank you very much for the time.

I understand the modified automation fully, but I would like some help to understand the first one as I’m not familiar.
I see you’re setting variables from the trigger turning on, which is the lights. Ok. You define its id, parent and user.

And you check if they are true, None, None.

Can you explain where can I see the possible values of those variables and when do they change? That will help me understand to use it in future occasions.

It would help me seeing them in UI, but it seem variables do not work outside of YAML.

Context documentation

All service calls, fired events and states in Home Assistant have a context object. This object allows HA to attribute changes to events, services, and users.

In this case, the value of the variables in the context object is based on the event of the light changing state. To inspect the context object of specific events you can use the Events tool in the Developer Tools menu. Use the following truth table to determine the general origin of an event:

Action id parent_id user_id
Physical Not Null Null Null
Automation Not Null Not Null Null
UI Not Null Null Not Null

Context is also observable in the Logbook. I haven’t personally tested this extensively, but generally:

  1. Entries that list no user or “by” are Physical.
  2. Those with “by” but no user are Automation.
  3. Those with “by” and a user are UI
2 Likes

Thanks for the explantation.
Whats wired is that even an automation (in node red I should say) still has user_id and parent_id “null”. And over the HA dashboard it is an Automation instead of UI.

Maybe there was a change in HA 2024.02? Or maybe it is the “Supervisor”?
So I can not differentiate between Physically and Supervisor… right?

I’d say it must be node-red or supervisor as you say. Because I’m on 2024.02 too and my light is getting turned on by automation most of the time, and that is not triggering my timer (which does activate when switching manually).

Ok, I have to check if its Node Red. But that’s would be pain in the a** because every light automation is based on Node Red… :frowning:

The primary reason I don’t use Node Red! I played with it but when I considered the ramifications of having all my automation on there I decided against it. I think there is real benefit to using Node Red on some things but not everything.

Got it! Its not Node Red.
If I set an automation in NR it shows as “Automation”.
But the majority of my light automations turns Philips Hue scenes on. That causes it to show as “Manual”.

Dont know (for now) if its just the Hue scenes or if it is a scene (HA) in general.

EDIT: Scenes in general!

For the future googler that lands here, you don’t need a separate automation to check if the device was manually changed. The context is automatically written when the trigger occurs.

If you want to see the context, trigger the automation manually then → traces → click on the choose icon :

Image 055

and click on the “changed variables” on the right. You will see the context info buried in there under the “to_state” info:

Image 056

If you’re using “choose” actions you can just add a “template” condition and enter this code:

{{ (id!=None, parent, user) == (true, null, null) }}

The Template Condition you have suggested will always pass because it always reports boolean true. It’s equivalent to doing this, which also reports boolean true.

{{ 1 + 1 == 2 }}

The id, parent and user variables in your template don’t reference the trigger object that is generated when the automation is triggered. Therefore they’re completely unrelated to any actual triggering activity.

The Solution post of this topic shows how to properly reference a trigger object’s context properties:

Another example is available here:

2 Likes

Actually, my current automation using this is failing often and I’m unsure why.

I want a timer to start only when the Kitchen lights is switched on manually, either button or via HA dashboard. Not when it’s been triggered via an automation (ie. motion sensor).

But I’m finding the timer is getting started sometimes when the motion sensor has switched on the lights, and I guess I made some mistake.

Any idea?

alias: Autolights - Kitchen - Start Timer when Manual
description: ""
trigger:
  - platform: state
    entity_id: light.kitchen_lights
    to: "on"
    variables:
      id: "{{trigger.to_state.context.id}}"
      parent: "{{ trigger.to_state.context.parent_id }}"
      user: "{{ trigger.to_state.context.user_id }}"
  - platform: state
    entity_id: light.kitchen_lights
    to: "off"
    variables:
      id: "{{trigger.to_state.context.id}}"
      parent: "{{ trigger.to_state.context.parent_id }}"
      user: "{{ trigger.to_state.context.user_id }}"
condition:
  - condition: or
    conditions:
      - condition: template
        value_template: "{{ (id!=None, parent, user!=None) == (true, None, true) }}"
      - condition: template
        value_template: "{{ (id!=None, parent, user) == (true, None, None) }}"
action:
  - choose:
      - conditions:
          - condition: state
            entity_id: light.kitchen_lights
            state: "on"
        sequence:
          - service: timer.start
            data:
              duration: "00:45:00"
            target:
              entity_id: timer.kitchen_lights_timer
      - conditions:
          - condition: state
            entity_id: light.kitchen_lights
            state: "off"
        sequence:
          - service: timer.finish
            target:
              entity_id:
                - timer.kitchen_lights_timer
            data: {}

When the automation fails to work the way you expected,
examine its trace to learn why it behaved the way it did.

All details of the automation’s execution (such as its variable’s values and the result of template conditions,
etc) are recorded in the trace.

Why do you put the variables statement inside the trigger and repeat it 2x at that. This might work but I would worry that the context of the variables may only be within the trigger.
Pull those out and add a global variable key with those same variables designated. Then they will work in the actions as intended without a question.
Variables put in global are executed after trigger and before conditions.

1 Like

I think I did so they showed up in UI, as I don’t like looking at automations in YAML.

Having them repeated made no harm really, as only one of the triggers gets executed in each run.

But thanks, I did not know that.