Detect How a Device was Turned On

I’ve run into a bit of a wall. I have a motion sensor (Zigbee) in a closet that triggers the lights to turn on. The issue I am running in to is keeping those lights on if there is someone in the closet. The problem is that the presence detection (in the motion sensor) is too slow to use it to turn off the lights if someone leaves, but unless there is constant, recognizable motion, the motion sensor won’t keep the lights on. The idea is that if the light is turned on via the light switch (also Zigbee), it stays on i.e.

Turned on via light switch Turned off via light switch
Person in closet (Motion/Occupancy) Stay on Stay off for time interval
Person not in closet (Motion/Occupancy) Stay on Stay off until motion/light switch activation
I imagine the real question here is if I can detect that the light was turned on via the switch vs the automation in the first place, which I haven't been able to do.

Probably with a helper entity.
I had the same question with a PIR sensor in my basement and spent a day trying to write an automation in Home Assistant, then gave up and did it in the Node Red add-on with four nodes.

If you want to go with Node Red, here is the flow.

[{"id":"7e9a7e566f624b77","type":"server-state-changed","z":"b4d57b7976516af6","name":"Workshop PIR","server":"cc0d1734.6963a8","version":4,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"binary_sensor.workshop_pir_pir","entityidfiltertype":"exact","outputinitially":true,"state_type":"str","haltifstate":"on","halt_if_type":"str","halt_if_compare":"is","outputs":2,"output_only_on_state_change":true,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":true,"ignorePrevStateUnknown":true,"ignorePrevStateUnavailable":true,"ignoreCurrentStateUnknown":true,"ignoreCurrentStateUnavailable":true,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"eventData"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"x":150,"y":980,"wires":[["79fce5c5419a5433","298920f7359f7829"],[]]},{"id":"79fce5c5419a5433","type":"stoptimer-varidelay","z":"b4d57b7976516af6","duration":"10","durationType":"num","units":"Minute","payloadtype":"num","payloadval":"0","name":"","reporting":"every_second","persist":false,"ignoretimerpass":false,"x":400,"y":1040,"wires":[["bf8dbceae8f8e91b"],[],[]]},{"id":"298920f7359f7829","type":"api-call-service","z":"b4d57b7976516af6","name":"","server":"cc0d1734.6963a8","version":5,"debugenabled":false,"domain":"switch","service":"turn_on","areaId":[],"deviceId":[],"entityId":["switch.utilityroom_light_2"],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":620,"y":980,"wires":[[]]},{"id":"bf8dbceae8f8e91b","type":"api-call-service","z":"b4d57b7976516af6","name":"","server":"cc0d1734.6963a8","version":5,"debugenabled":false,"domain":"switch","service":"turn_off","areaId":[],"deviceId":[],"entityId":["switch.utilityroom_light_2"],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":620,"y":1040,"wires":[[]]},{"id":"cc0d1734.6963a8","type":"server","name":"Home Assistant- Raspberry","version":5,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":30,"areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m","enableGlobalContextStore":true}]

The magic is in the Timer Node. Every time the PIR detects movement, it turns on the light and resets the timer to 10 minutes. If there is no movement for ten minutes the light turns off.

If someone has a Home Assistant automation solution, I would like to see it too.

I had a similar issue where I needed to know if someone had turned a light off MANUALLY so in the use case where they leave the room after turning off a light switch, the motion sensor would not turn the light back on again (for 5 minutes after it was turned off, but only if turned off MANUALLY).

I think you might be able to use similar logic. The only place where you can capture if a device had a state change that was NOT done by a HA automation, is to chewck and keep track when the state changes in that one case (done manually), right in the trigger when it happens:

  • “{{ trigger.to_state.context.id != none }}”
  • “{{ trigger.to_state.context.parent_id == none }}”
  • “{{ trigger.to_state.context.user_id == none }}”

I used that to keep track of the exact time it would happen MANUALLY so I could add logic to the code where the light would have gone on if there was motion to check if it was within the 5 minutes of the manually turn off taking place.

Below is my whole explanation of how I solved the issue I had, hope this helps -

The above might not be the most elegant way, because I was thinking there should be somehing in the history that recorded the trigger information as well so it could be checked at a later date, which is much more elegant - but I wasn’t able to figure out how to do that (that level of detail might not be kept in history)… If you can find where that is, let me know - otherwise this works well for me!

Wouldn’t this do the same:

mode: single
trigger:
  - platform: state
    entity_id:
      - binary_sensor.motion_master_closet_occupancy
    to: "on"
    id: Motion Detected
  - platform: state
    entity_id:
      - binary_sensor.motion_master_closet_occupancy
    id: No Motion for 10 Minutes
    to: "off"
    for:
      hours: 0
      minutes: 10
      seconds: 0
condition: []
action:
  - choose:
      - conditions:
          - condition: trigger
            id: Motion Detected
        sequence:
          - service: light.turn_on
            data: {}
            target:
              entity_id: light.master_closet_lights
      - conditions:
          - condition: trigger
            id: No Motion for 10 Minutes
        sequence:
          - service: light.turn_off
            data: {}
            target:
              entity_id: light.master_closet_lights