777 lines
31 KiB
YAML
777 lines
31 KiB
YAML
# =============================================================================
|
|
# Motion Light Automation Blueprint for Home Assistant
|
|
# =============================================================================
|
|
# This blueprint creates a smart motion-activated light control system.
|
|
# It handles motion detection, luminance-based triggering, and manual override
|
|
# detection to provide intelligent lighting automation.
|
|
#
|
|
# Features:
|
|
# - Multiple motion sensor support (triggers on ANY sensor)
|
|
# - Condition switches (ALL must be ON for automation to work)
|
|
# - Light and/or switch control
|
|
# - Configurable timeout delay before turning off
|
|
# - Luminance sensor support (only trigger in dark conditions)
|
|
# - Manual override detection (stops automation if user changes light)
|
|
# - Brightness threshold (only trigger if light is dim)
|
|
# - Custom light parameters (brightness, color, etc.)
|
|
# - Callback actions for enable/disable/manual events
|
|
#
|
|
# State Machine:
|
|
# The automation tracks these states via persistent storage:
|
|
# - NONE (0): Idle, waiting for motion
|
|
# - ENABLING (2): Light turn-on command sent, waiting for state change
|
|
# - ENABLED (1): Light is ON and controlled by automation
|
|
# - MANUAL (3): User took control, automation paused until light turns off
|
|
#
|
|
# Behavior Notes:
|
|
# - 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
|
|
# - MANUAL mode exits when light is turned OFF (by any means)
|
|
# - Timeout delay only applies when turning OFF (motion cleared)
|
|
#
|
|
# Requirements:
|
|
# - At least one motion sensor
|
|
# - input_text entity for persistent state storage
|
|
# - Target light and/or switch to control
|
|
#
|
|
# Author: Custom Blueprint
|
|
# =============================================================================
|
|
|
|
blueprint:
|
|
name: "Custom: Motion Light"
|
|
description: >
|
|
Smart motion sensor automation blueprint.
|
|
Note: By default will not run if light was already ON. If light was turned
|
|
ON during automation running, the automation will enter manual state and
|
|
will not trigger until the light is turned off.
|
|
Note: Not tested when motion sensors and state sensors are used at the same time.
|
|
domain: automation
|
|
|
|
# ===========================================================================
|
|
# INPUT CONFIGURATION
|
|
# ===========================================================================
|
|
input:
|
|
|
|
# -------------------------------------------------------------------------
|
|
# Motion & Condition Sensors
|
|
# -------------------------------------------------------------------------
|
|
controls:
|
|
name: "Controls"
|
|
collapsed: false
|
|
input:
|
|
motion_sensors:
|
|
name: Motion sensors
|
|
description: >
|
|
Select one or more motion sensors. Light turns ON if ANY sensor
|
|
detects motion (OR logic).
|
|
default: []
|
|
selector:
|
|
entity:
|
|
domain:
|
|
- binary_sensor
|
|
- switch
|
|
- group
|
|
- light
|
|
multiple: true
|
|
|
|
condition_switches:
|
|
name: Condition switches
|
|
description: >
|
|
Automation will not trigger if ANY of these switches is OFF.
|
|
All must be ON for the automation to work (AND logic).
|
|
default: []
|
|
selector:
|
|
entity:
|
|
domain:
|
|
- input_boolean
|
|
- switch
|
|
- group
|
|
- light
|
|
- binary_sensor
|
|
multiple: true
|
|
|
|
# -------------------------------------------------------------------------
|
|
# Target Devices
|
|
# -------------------------------------------------------------------------
|
|
devices_group:
|
|
name: "Devices"
|
|
collapsed: false
|
|
input:
|
|
target_light:
|
|
name: Target Light (optional)
|
|
description: "Light to control. Supports single light only."
|
|
default: []
|
|
selector:
|
|
entity:
|
|
domain: light
|
|
multiple: true
|
|
|
|
target_light_data:
|
|
name: Light Data Dictionary (optional)
|
|
default: ""
|
|
description: >
|
|
Provide a YAML dictionary of light.turn_on parameters.
|
|
If not specified, the light's last settings are preserved.
|
|
Example:
|
|
brightness: 200
|
|
color_temp: 350
|
|
rgb_color: [255, 0, 0]
|
|
effect: rainbow
|
|
selector:
|
|
object: {}
|
|
|
|
brightness_threshold:
|
|
name: Brightness Threshold
|
|
description: >
|
|
Automation only triggers if the light's current brightness is
|
|
below this value. Set to 0 to disable this check.
|
|
default: 0
|
|
selector:
|
|
number:
|
|
min: 0
|
|
max: 255
|
|
step: 1
|
|
|
|
target_switch:
|
|
name: Target Switch (optional)
|
|
description: "Switch to control. Supports single switch only."
|
|
default: []
|
|
selector:
|
|
entity:
|
|
domain: switch
|
|
multiple: true
|
|
|
|
timeout_delay:
|
|
name: Timeout delay (seconds)
|
|
description: >
|
|
Delay before turning off the light after all motion sensors
|
|
clear. Set to 0 for immediate turn off.
|
|
default: 0
|
|
selector:
|
|
number:
|
|
min: 0
|
|
max: 3600
|
|
step: 1
|
|
unit_of_measurement: seconds
|
|
|
|
# -------------------------------------------------------------------------
|
|
# Persistent State Configuration
|
|
# -------------------------------------------------------------------------
|
|
persistent_state:
|
|
name: "Persistent State"
|
|
collapsed: true
|
|
input:
|
|
automation_state_entity:
|
|
name: Automation state entity
|
|
description: >
|
|
`input_text` entity that stores the automation state in JSON format.
|
|
Required for manual override detection and state tracking.
|
|
Doesn't require specific initial state - values can be empty.
|
|
Each automation instance must have its own entity.
|
|
selector:
|
|
entity:
|
|
domain: input_text
|
|
|
|
automation_state_placeholder_key:
|
|
name: Automation state placeholder key
|
|
description: >
|
|
Overrides key for persistent storage if not empty.
|
|
By default uses the target light/switch entity ID.
|
|
Don't override if you don't understand the meaning.
|
|
default: ''
|
|
selector:
|
|
text:
|
|
|
|
# -------------------------------------------------------------------------
|
|
# Luminance Control
|
|
# -------------------------------------------------------------------------
|
|
luminance:
|
|
name: "Luminance"
|
|
collapsed: true
|
|
input:
|
|
luminance_sensor:
|
|
name: Luminance sensor (optional)
|
|
description: Sensor reporting ambient light level (lux)
|
|
default: null
|
|
selector:
|
|
entity:
|
|
domain: sensor
|
|
|
|
luminance_threshold:
|
|
name: Luminance threshold (optional)
|
|
description: >
|
|
Light will only turn on if luminance sensor value is below
|
|
this threshold (darker than this level).
|
|
default: 100
|
|
selector:
|
|
number:
|
|
min: 0
|
|
max: 10000
|
|
step: 1
|
|
unit_of_measurement: "lux"
|
|
|
|
luminance_enable_switch:
|
|
name: Luminance control enable switch (optional)
|
|
description: >
|
|
Switch or input_boolean to enable/disable luminance-based control.
|
|
When OFF, luminance check is skipped.
|
|
default: null
|
|
selector:
|
|
entity:
|
|
domain:
|
|
- switch
|
|
- input_boolean
|
|
|
|
# -------------------------------------------------------------------------
|
|
# Callback Actions
|
|
# -------------------------------------------------------------------------
|
|
actions:
|
|
name: "Actions"
|
|
collapsed: true
|
|
input:
|
|
user_condition:
|
|
name: Condition block
|
|
description: Optional condition(s) that must pass for actions to run
|
|
default: []
|
|
selector:
|
|
condition: {}
|
|
|
|
enable_action:
|
|
name: Enable callback action (optional)
|
|
description: Runs when light is turned ON by this automation
|
|
default: []
|
|
selector:
|
|
action: {}
|
|
|
|
disable_action:
|
|
name: Disable callback action (optional)
|
|
description: Runs when light is turned OFF by this automation
|
|
default: []
|
|
selector:
|
|
action: {}
|
|
|
|
manual_action_runs_disable_action:
|
|
name: Manual also runs disable action
|
|
description: >
|
|
If checked, entering manual mode will also execute the
|
|
disable callback action.
|
|
default: false
|
|
selector:
|
|
boolean: {}
|
|
|
|
manual_action:
|
|
name: Manual callback action (optional)
|
|
description: >
|
|
Runs when user manually changes the light while automation is active.
|
|
Requires 'Automation state entity' to be configured.
|
|
default: []
|
|
selector:
|
|
action: {}
|
|
|
|
# =============================================================================
|
|
# AUTOMATION MODE
|
|
# =============================================================================
|
|
# Restart mode ensures rapid motion events don't queue up
|
|
mode: restart
|
|
|
|
# =============================================================================
|
|
# TRIGGERS
|
|
# =============================================================================
|
|
trigger:
|
|
# Motion sensors ON/OFF
|
|
- platform: state
|
|
entity_id: !input motion_sensors
|
|
id: "motion_sensor"
|
|
|
|
# Condition switches ON/OFF
|
|
- platform: state
|
|
entity_id: !input condition_switches
|
|
|
|
# Light state changed (for manual override detection)
|
|
- platform: state
|
|
entity_id: !input target_light
|
|
id: "light_state_changed"
|
|
|
|
# Switch state changed (for manual override detection)
|
|
- platform: state
|
|
entity_id: !input target_switch
|
|
id: "switch_state_changed"
|
|
|
|
# Luminance sensor value changed
|
|
- platform: template
|
|
value_template: >
|
|
{% if luminance_sensor %}
|
|
{{ states(luminance_sensor) not in ['unknown','unavailable'] }}
|
|
{% else %}
|
|
false
|
|
{% endif %}
|
|
|
|
# Luminance enable switch changed
|
|
- platform: template
|
|
value_template: >
|
|
{% if luminance_enable_switch %}
|
|
{{ states(luminance_enable_switch) not in ['unknown','unavailable'] }}
|
|
{% else %}
|
|
false
|
|
{% endif %}
|
|
|
|
# =============================================================================
|
|
# CONDITIONS
|
|
# =============================================================================
|
|
condition: !input user_condition
|
|
|
|
# =============================================================================
|
|
# VARIABLES
|
|
# =============================================================================
|
|
variables:
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Debug Flags
|
|
# ---------------------------------------------------------------------------
|
|
is_debug: false # Detailed debug for specific actions
|
|
is_base_debug: false # Basic debug info at start
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# State Machine Constants
|
|
# ---------------------------------------------------------------------------
|
|
# These define the possible automation states stored in persistent storage
|
|
automation_state_invalid: '-1' # Error state
|
|
automation_state_none: '0' # Idle, waiting for motion
|
|
automation_state_enabled: '1' # Light is ON and controlled by automation
|
|
automation_state_enabling: '2' # Turn-on command sent, awaiting confirmation
|
|
automation_state_manual: '3' # User took control, automation paused
|
|
|
|
# Persistent state JSON keys
|
|
state_motion_light_state: 'mls' # Current state machine state
|
|
state_motion_light_last_action_timestamp: 'mllat' # Last action timestamp
|
|
state_motion_light_last_brightness: 'mllb' # Brightness before automation
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Trigger Context
|
|
# ---------------------------------------------------------------------------
|
|
date_time_now: "{{ now() }}"
|
|
trigger_id: "{{ trigger.id }}"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Input Variables
|
|
# ---------------------------------------------------------------------------
|
|
sensors: !input motion_sensors
|
|
condition_switches: !input condition_switches
|
|
timeout: !input timeout_delay
|
|
brightness_threshold: !input brightness_threshold
|
|
|
|
# Light configuration
|
|
light_entities: !input target_light
|
|
light_entity: "{{ light_entities[0] if light_entities | length != 0 else none }}"
|
|
|
|
# Switch configuration
|
|
switch_entities: !input target_switch
|
|
switch_entity: "{{ switch_entities[0] if switch_entities | length != 0 else none }}"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Persistent State Management
|
|
# ---------------------------------------------------------------------------
|
|
automation_state_entity: !input automation_state_entity
|
|
|
|
# Parse global state JSON from input_text entity
|
|
automation_state_global: >
|
|
{% set text = states(automation_state_entity) | string %}
|
|
{% if text in ['unknown','unavailable','none',''] %}
|
|
{{ dict() }}
|
|
{% else %}
|
|
{{ text | from_json }}
|
|
{% endif %}
|
|
|
|
automation_state_placeholder_key: !input automation_state_placeholder_key
|
|
|
|
# Determine the key for this automation's state
|
|
automation_state_key: >
|
|
{% if automation_state_placeholder_key != '' %}
|
|
{{ automation_state_placeholder_key }}
|
|
{% elif switch_entity is not none %}
|
|
{{ switch_entity }}
|
|
{% elif light_entity is not none %}
|
|
{{ light_entity }}
|
|
{% else %}
|
|
{{ 'default_motion_light_placeholder' }}
|
|
{% endif %}
|
|
|
|
# Get this automation's state from global state
|
|
# BUG FIX: Changed from 'light_entity != ""' to proper none check
|
|
automation_state: "{{ automation_state_global.get(automation_state_key, dict()) if (light_entity is not none or switch_entity is not none) else dict() }}"
|
|
|
|
# Current state machine state
|
|
motion_light_state: "{{ automation_state.get(state_motion_light_state, automation_state_none) }}"
|
|
|
|
# Track last action timestamp
|
|
motion_light_last_action_timestamp: >
|
|
{% if trigger_id == 'state_motion' %}
|
|
{{ date_time_now }}
|
|
{% else %}
|
|
{{ automation_state.get(state_motion_light_last_action_timestamp, none) }}
|
|
{% endif %}
|
|
|
|
# State machine state checks (for readability)
|
|
state_is_none: "{{ (motion_light_state | string) == automation_state_none }}"
|
|
state_is_enabled: "{{ (motion_light_state | string) == automation_state_enabled }}"
|
|
state_is_enabling: "{{ (motion_light_state | string) == automation_state_enabling }}"
|
|
state_is_manual: "{{ (motion_light_state | string) == automation_state_manual }}"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Callback Actions
|
|
# ---------------------------------------------------------------------------
|
|
manual_action: !input manual_action
|
|
disable_action: !input disable_action
|
|
enable_action: !input enable_action
|
|
manual_action_runs_disable_action: !input manual_action_runs_disable_action
|
|
light_data: !input target_light_data
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Luminance Configuration
|
|
# ---------------------------------------------------------------------------
|
|
luminance_sensor: !input luminance_sensor
|
|
luminance_threshold: !input luminance_threshold
|
|
luminance_enable_switch: !input luminance_enable_switch
|
|
|
|
# Check if luminance conditions allow triggering
|
|
luminance_ok: >
|
|
{% if luminance_sensor is not none and luminance_threshold is not none %}
|
|
{% set val = states(luminance_sensor) | float(0) %}
|
|
{% set enabled = true %}
|
|
{% if luminance_enable_switch %}
|
|
{% set enabled = is_state(luminance_enable_switch, 'on') %}
|
|
{% endif %}
|
|
{{ enabled and val < luminance_threshold }}
|
|
{% else %}
|
|
{{ true }}
|
|
{% endif %}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Trigger Evaluation
|
|
# ---------------------------------------------------------------------------
|
|
# Check if ALL condition switches are ON (AND logic)
|
|
all_of_condition_switches_on: >
|
|
{% set e = condition_switches if condition_switches is iterable else [condition_switches] %}
|
|
{% if e | length == 0 %}
|
|
{{ true }}
|
|
{% else %}
|
|
{{ (e | select('is_state', 'on') | list | length) == (e | length) }}
|
|
{% endif %}
|
|
|
|
# Count how many motion sensors are currently detecting motion
|
|
count_of_enabled_sensor: >
|
|
{% set e = sensors if sensors is iterable else [sensors] %}
|
|
{{ e | select('is_state', 'on') | list | length }}
|
|
|
|
# Motion state checks
|
|
motion_on: "{{ count_of_enabled_sensor > 0 }}"
|
|
motion_all_off: "{{ count_of_enabled_sensor == 0 }}"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Enable/Disable Decision Logic
|
|
# ---------------------------------------------------------------------------
|
|
# Should we enable the light? (All conditions must be met)
|
|
must_be_enabled_preview: >
|
|
{{ (all_of_condition_switches_on and luminance_ok and motion_on) | bool }}
|
|
must_be_enabled_guard: "{{ state_is_none }}"
|
|
must_be_enabled: >
|
|
{{ must_be_enabled_preview and must_be_enabled_guard }}
|
|
|
|
# Should we disable the light? (Motion cleared OR condition switch turned off)
|
|
must_be_disabled_preview: >
|
|
{{ ((not all_of_condition_switches_on) or motion_all_off) | bool }}
|
|
must_be_disabled_guard: "{{ state_is_enabled }}"
|
|
must_be_disabled: >
|
|
{{ must_be_disabled_preview and must_be_disabled_guard }}
|
|
|
|
# =============================================================================
|
|
# ACTIONS
|
|
# =============================================================================
|
|
action:
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# DEBUG: Log basic info (enable by setting is_base_debug: true)
|
|
# ---------------------------------------------------------------------------
|
|
- choose:
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ is_base_debug }}"
|
|
sequence:
|
|
- service: persistent_notification.create
|
|
data:
|
|
title: "Debug Info - Motion Light"
|
|
message: >
|
|
must_be_enabled_preview: {{ must_be_enabled_preview }},
|
|
must_be_disabled_preview: {{ must_be_disabled_preview }},
|
|
must_be_disabled: {{ must_be_disabled }},
|
|
must_be_disabled_guard: {{ must_be_disabled_guard }},
|
|
trigger_id: {{ trigger.id }}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# GUARDS: Validate prerequisites
|
|
# ---------------------------------------------------------------------------
|
|
# Guard: Only one light supported
|
|
- choose:
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ light_entities | length > 1 }}"
|
|
sequence:
|
|
- stop: "Only one light is supported currently"
|
|
|
|
# Guard: Only one switch supported
|
|
- choose:
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ switch_entities | length > 1 }}"
|
|
sequence:
|
|
- stop: "Only one switch is supported currently"
|
|
|
|
# ===========================================================================
|
|
# MAIN STATE MACHINE
|
|
# ===========================================================================
|
|
- choose:
|
|
|
|
# -----------------------------------------------------------------------
|
|
# CASE 1: Light/Switch State Changed (Manual Override Detection)
|
|
# -----------------------------------------------------------------------
|
|
# Handles state changes from the light/switch itself to detect
|
|
# when automation turned it on vs when user manually changed it
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ trigger_id == 'light_state_changed' or trigger_id == 'switch_state_changed' }}"
|
|
sequence:
|
|
- choose:
|
|
|
|
# ----- Sub-case: Light/Switch turned OFF -----
|
|
# Reset to NONE state so automation can work again
|
|
- conditions:
|
|
- condition: template
|
|
value_template: >
|
|
{# BUG FIX: Changed from 'res = false' to 'res = true' for AND logic #}
|
|
{% set res = true %}
|
|
{% if light_entity is not none %}
|
|
{% set brightness = state_attr(light_entity, 'brightness') | int(0) %}
|
|
{% set light_off = is_state(light_entity, 'off') or brightness < brightness_threshold %}
|
|
{% set res = res and light_off %}
|
|
{% endif %}
|
|
{% if switch_entity is not none %}
|
|
{% set res = res and is_state(switch_entity, 'off') %}
|
|
{% endif %}
|
|
{# Only true if we have at least one device and all are off #}
|
|
{{ res and (light_entity is not none or switch_entity is not none) }}
|
|
|
|
sequence:
|
|
# Reset state to NONE
|
|
- service: input_text.set_value
|
|
target:
|
|
entity_id: "{{ automation_state_entity }}"
|
|
data:
|
|
value: >
|
|
{% set new_automation_state = (automation_state | combine({ state_motion_light_state: automation_state_none })) %}
|
|
{{ automation_state_global | combine({ automation_state_key: new_automation_state }) | tojson }}
|
|
|
|
# ----- Sub-case: Automation just turned on the light -----
|
|
# Transition from ENABLING to ENABLED
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ state_is_enabling }}"
|
|
sequence:
|
|
- service: input_text.set_value
|
|
target:
|
|
entity_id: "{{ automation_state_entity }}"
|
|
data:
|
|
value: >
|
|
{% set new_automation_state = (automation_state | combine({ state_motion_light_state: automation_state_enabled })) %}
|
|
{{ automation_state_global | combine({ automation_state_key: new_automation_state }) | tojson }}
|
|
|
|
# ----- Sub-case: User manually changed the light -----
|
|
# Transition from ENABLED to MANUAL (user took control)
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ state_is_enabled }}"
|
|
sequence:
|
|
# BUG FIX: Fixed YAML structure - was 'data: >' instead of 'data:' with 'value: >'
|
|
- service: input_text.set_value
|
|
target:
|
|
entity_id: "{{ automation_state_entity }}"
|
|
data:
|
|
value: >
|
|
{% set new_automation_state = (automation_state | combine({ state_motion_light_state: automation_state_manual })) %}
|
|
{{ automation_state_global | combine({ automation_state_key: new_automation_state }) | tojson }}
|
|
|
|
# Call disable action if configured
|
|
- choose:
|
|
- conditions: "{{ manual_action_runs_disable_action and disable_action != [] }}"
|
|
sequence: !input disable_action
|
|
|
|
# Call manual action callback
|
|
- choose:
|
|
- conditions: "{{ manual_action != [] }}"
|
|
sequence: !input manual_action
|
|
|
|
# -----------------------------------------------------------------------
|
|
# CASE 2: Enable Path (Motion Detected, Should Turn On)
|
|
# -----------------------------------------------------------------------
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ must_be_enabled }}"
|
|
sequence:
|
|
- choose:
|
|
# Guard: Stop if light is already ON
|
|
# (Don't hijack user-controlled light)
|
|
- conditions:
|
|
- condition: template
|
|
value_template: >
|
|
{% set res = false %}
|
|
{% if light_entity is not none %}
|
|
{# BUG FIX: Added proper null check for brightness #}
|
|
{% set brightness = state_attr(light_entity, 'brightness') | int(0) %}
|
|
{% set res = res or (is_state(light_entity, 'on') and brightness > brightness_threshold) %}
|
|
{% endif %}
|
|
{% if switch_entity is not none %}
|
|
{% set res = res or is_state(switch_entity, 'on') %}
|
|
{% endif %}
|
|
{{ res }}
|
|
sequence:
|
|
- stop: "Light is already ON when sensors were triggered"
|
|
|
|
# Enable the light/switch
|
|
default:
|
|
# Debug info
|
|
- choose:
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ is_debug }}"
|
|
sequence:
|
|
- service: persistent_notification.create
|
|
data:
|
|
title: "Debug Info (Enable Path)"
|
|
message: >
|
|
Enabling light. light_entity: {{ light_entity }}
|
|
|
|
# Store current brightness (to restore later if configured)
|
|
- variables:
|
|
last_brightness: >
|
|
{% if light_entity is none or is_state(light_entity, 'off') %}
|
|
{{ 0 }}
|
|
{% else %}
|
|
{{ state_attr(light_entity, 'brightness') | int(0) }}
|
|
{% endif %}
|
|
|
|
# Turn ON the light
|
|
- choose:
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ light_entity is not none }}"
|
|
sequence:
|
|
- service: light.turn_on
|
|
target:
|
|
entity_id: "{{ light_entity }}"
|
|
data: "{{ light_data if light_data else {} }}"
|
|
|
|
# Turn ON the switch
|
|
- choose:
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ switch_entity is not none }}"
|
|
sequence:
|
|
- service: switch.turn_on
|
|
target:
|
|
entity_id: "{{ switch_entity }}"
|
|
|
|
# Update state to ENABLING (waiting for light state change confirmation)
|
|
- service: input_text.set_value
|
|
target:
|
|
entity_id: "{{ automation_state_entity }}"
|
|
data:
|
|
value: >
|
|
{% set new_automation_state = (automation_state | combine({
|
|
state_motion_light_state: automation_state_enabling,
|
|
state_motion_light_last_action_timestamp: date_time_now,
|
|
state_motion_light_last_brightness: last_brightness
|
|
})) %}
|
|
{{ automation_state_global | combine({ automation_state_key: new_automation_state }) | tojson }}
|
|
|
|
# Execute enable callback action
|
|
- choose:
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ enable_action != [] }}"
|
|
sequence: !input enable_action
|
|
|
|
# -----------------------------------------------------------------------
|
|
# CASE 3: Disable Path (Motion Cleared, Should Turn Off)
|
|
# -----------------------------------------------------------------------
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ must_be_disabled }}"
|
|
sequence:
|
|
# Debug info
|
|
- choose:
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ is_debug }}"
|
|
sequence:
|
|
- service: persistent_notification.create
|
|
data:
|
|
title: "Debug Info (Disable Path)"
|
|
message: >
|
|
Disabling light. light_entity: {{ light_entity }}
|
|
|
|
# Wait for timeout before turning off
|
|
- delay:
|
|
seconds: "{{ timeout }}"
|
|
|
|
# Turn OFF or restore the light
|
|
- choose:
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ light_entity is not none }}"
|
|
sequence:
|
|
- variables:
|
|
last_brightness: "{{ automation_state.get(state_motion_light_last_brightness, 0) | int }}"
|
|
|
|
- choose:
|
|
# Restore previous brightness if it was set
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ last_brightness > 0 }}"
|
|
sequence:
|
|
- service: light.turn_on
|
|
target:
|
|
entity_id: "{{ light_entity }}"
|
|
data:
|
|
brightness: "{{ last_brightness }}"
|
|
|
|
# Otherwise turn off completely
|
|
default:
|
|
- service: light.turn_off
|
|
target:
|
|
entity_id: "{{ light_entity }}"
|
|
|
|
# Turn OFF the switch
|
|
- choose:
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ switch_entity is not none }}"
|
|
sequence:
|
|
- service: switch.turn_off
|
|
target:
|
|
entity_id: "{{ switch_entity }}"
|
|
|
|
# Update state to NONE (ready for next motion event)
|
|
- service: input_text.set_value
|
|
target:
|
|
entity_id: "{{ automation_state_entity }}"
|
|
data:
|
|
value: >
|
|
{% set new_automation_state = (automation_state | combine({ state_motion_light_state: automation_state_none })) %}
|
|
{{ automation_state_global | combine({ automation_state_key: new_automation_state }) | tojson }}
|
|
|
|
# Execute disable callback action
|
|
- choose:
|
|
- conditions:
|
|
- condition: template
|
|
value_template: "{{ disable_action != [] }}"
|
|
sequence: !input disable_action
|