Fix false manual override detection and brightness threshold guard in Motion Light
- Add configurable grace period (default 10s) to prevent false manual override detection from delayed device state reports (e.g., Zigbee) - Fix any_device_on guard to respect brightness_threshold so lights below the threshold don't block the automation from triggering Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -17,7 +17,7 @@ This blueprint creates a smart motion-activated light control system. It handles
|
|||||||
- Day/Night mode (different light settings based on time)
|
- Day/Night mode (different light settings based on time)
|
||||||
- Scene support (activate scenes instead of light parameters)
|
- Scene support (activate scenes instead of light parameters)
|
||||||
- Dim before off (visual warning before turning off)
|
- Dim before off (visual warning before turning off)
|
||||||
- Manual override detection (stops automation if user changes light)
|
- Manual override detection (stops automation if user changes light) with configurable grace period
|
||||||
- Brightness threshold (only trigger if light is dim)
|
- Brightness threshold (only trigger if light is dim)
|
||||||
- Custom light parameters (brightness, color, etc.)
|
- Custom light parameters (brightness, color, etc.)
|
||||||
- Callback actions for enable/disable/manual events
|
- Callback actions for enable/disable/manual events
|
||||||
@@ -37,7 +37,8 @@ The automation tracks these states via persistent storage:
|
|||||||
## Behavior Notes
|
## Behavior Notes
|
||||||
|
|
||||||
- Will NOT turn on light if it's already ON (prevents hijacking user control)
|
- Will NOT turn on light if it's already ON (prevents hijacking user control)
|
||||||
- If user changes light while automation is active, enters MANUAL mode
|
- If user changes light while automation is active, enters MANUAL mode (after grace period)
|
||||||
|
- Grace period prevents false manual overrides from delayed device state reports (e.g., Zigbee)
|
||||||
- MANUAL mode exits when light is turned OFF (by any means)
|
- MANUAL mode exits when light is turned OFF (by any means)
|
||||||
- Timeout delay only applies when turning OFF (motion cleared)
|
- Timeout delay only applies when turning OFF (motion cleared)
|
||||||
- Time conditions support overnight windows (e.g., 22:00 to 06:00)
|
- Time conditions support overnight windows (e.g., 22:00 to 06:00)
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ blueprint:
|
|||||||
- switch
|
- switch
|
||||||
- group
|
- group
|
||||||
- light
|
- light
|
||||||
|
- input_boolean
|
||||||
multiple: true
|
multiple: true
|
||||||
|
|
||||||
condition_switches:
|
condition_switches:
|
||||||
@@ -384,6 +385,22 @@ blueprint:
|
|||||||
step: 1
|
step: 1
|
||||||
unit_of_measurement: "seconds"
|
unit_of_measurement: "seconds"
|
||||||
|
|
||||||
|
manual_override_grace_period:
|
||||||
|
name: Manual Override Grace Period (seconds)
|
||||||
|
description: >
|
||||||
|
After the automation turns on a light, ignore state changes for
|
||||||
|
this many seconds to avoid false manual override detection.
|
||||||
|
Some devices (especially Zigbee) report delayed state updates
|
||||||
|
that can be mistaken for manual control. Increase this value
|
||||||
|
if you see false manual overrides in the debug log.
|
||||||
|
default: 10
|
||||||
|
selector:
|
||||||
|
number:
|
||||||
|
min: 0
|
||||||
|
max: 30
|
||||||
|
step: 1
|
||||||
|
unit_of_measurement: "seconds"
|
||||||
|
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
# Debug
|
# Debug
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
@@ -546,6 +563,7 @@ variables:
|
|||||||
min_on_duration: !input min_on_duration
|
min_on_duration: !input min_on_duration
|
||||||
brightness_threshold: !input brightness_threshold
|
brightness_threshold: !input brightness_threshold
|
||||||
transition_duration: !input transition_duration
|
transition_duration: !input transition_duration
|
||||||
|
manual_override_grace_period: !input manual_override_grace_period
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Target Device Resolution
|
# Target Device Resolution
|
||||||
@@ -591,11 +609,22 @@ variables:
|
|||||||
# Reference light for state checks (first available)
|
# Reference light for state checks (first available)
|
||||||
reference_light: "{{ resolved_all_lights[0] if resolved_all_lights | length > 0 else none }}"
|
reference_light: "{{ resolved_all_lights[0] if resolved_all_lights | length > 0 else none }}"
|
||||||
|
|
||||||
# Check if any device is on
|
# Check if any device is on (respects brightness_threshold)
|
||||||
any_device_on: >
|
any_device_on: >
|
||||||
{% set lights_on = resolved_all_lights | select('is_state', 'on') | list | length > 0 %}
|
{% set ns = namespace(lights_on=false) %}
|
||||||
|
{% for light in resolved_all_lights %}
|
||||||
|
{% if is_state(light, 'on') %}
|
||||||
|
{% if brightness_threshold | int(0) > 0 %}
|
||||||
|
{% if state_attr(light, 'brightness') | int(0) >= brightness_threshold | int(0) %}
|
||||||
|
{% set ns.lights_on = true %}
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
{% set ns.lights_on = true %}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
{% set switches_on = resolved_all_switches | select('is_state', 'on') | list | length > 0 %}
|
{% set switches_on = resolved_all_switches | select('is_state', 'on') | list | length > 0 %}
|
||||||
{{ lights_on or switches_on }}
|
{{ ns.lights_on or switches_on }}
|
||||||
|
|
||||||
all_devices_off: "{{ not any_device_on }}"
|
all_devices_off: "{{ not any_device_on }}"
|
||||||
|
|
||||||
@@ -884,9 +913,20 @@ action:
|
|||||||
|
|
||||||
# ----- Sub-case: User manually changed the light -----
|
# ----- Sub-case: User manually changed the light -----
|
||||||
# Transition from ENABLED to MANUAL (user took control)
|
# Transition from ENABLED to MANUAL (user took control)
|
||||||
|
# Grace period: ignore state changes shortly after the automation
|
||||||
|
# turns on the light to avoid false manual override detection.
|
||||||
|
# Some devices (especially Zigbee) report delayed state updates.
|
||||||
- conditions:
|
- conditions:
|
||||||
- condition: template
|
- condition: template
|
||||||
value_template: "{{ state_is_enabled }}"
|
value_template: >
|
||||||
|
{% set last_ts = automation_state.get(state_motion_light_last_action_timestamp, none) %}
|
||||||
|
{% set grace = (transition_duration | float(0)) + (manual_override_grace_period | float(10)) %}
|
||||||
|
{% if state_is_enabled and last_ts is not none %}
|
||||||
|
{% set parsed = last_ts | as_datetime %}
|
||||||
|
{{ parsed is none or (now() - parsed).total_seconds() > grace }}
|
||||||
|
{% else %}
|
||||||
|
{{ state_is_enabled }}
|
||||||
|
{% endif %}
|
||||||
sequence:
|
sequence:
|
||||||
# BUG FIX: Fixed YAML structure - was 'data: >' instead of 'data:' with 'value: >'
|
# BUG FIX: Fixed YAML structure - was 'data: >' instead of 'data:' with 'value: >'
|
||||||
- service: input_text.set_value
|
- service: input_text.set_value
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"version": "2.0.0"
|
"version": "2.2.3"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user