Restructure repository: organize blueprints into folders
Each blueprint now has its own folder containing: - blueprint.yaml: The automation code with a short header - README.md: Detailed documentation extracted from headers Updated CLAUDE.md with repository structure guidelines. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
169
Common/Time Of Day Controller/blueprint.yaml
Normal file
169
Common/Time Of Day Controller/blueprint.yaml
Normal file
@@ -0,0 +1,169 @@
|
||||
# Time of Day State Machine Blueprint
|
||||
# Updates an input_select based on time-of-day thresholds.
|
||||
# See README.md for detailed documentation.
|
||||
|
||||
blueprint:
|
||||
name: "Custom: Time of Day State Machine"
|
||||
description: >
|
||||
Automatically sets an input_select based on time-of-day thresholds.
|
||||
Maps states to times by index (state[0] ↔ time[0], state[1] ↔ time[1], etc.).
|
||||
Supports input_datetime entities and sensors reporting HH:MM[:SS] values.
|
||||
domain: automation
|
||||
|
||||
input:
|
||||
# -------------------------------------------------------------------------
|
||||
# Output Configuration
|
||||
# -------------------------------------------------------------------------
|
||||
tod_select:
|
||||
name: Time of Day Selector
|
||||
description: >
|
||||
The input_select entity that holds the current time-of-day state.
|
||||
Its options should match the states defined below.
|
||||
selector:
|
||||
entity:
|
||||
domain: input_select
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# State/Time Mapping Configuration
|
||||
# -------------------------------------------------------------------------
|
||||
tod_states:
|
||||
name: Time of Day States
|
||||
description: >
|
||||
Ordered list of state names (must match input_select options exactly).
|
||||
Example: ["Night", "Morning", "Afternoon", "Evening"]
|
||||
selector:
|
||||
text:
|
||||
multiple: true
|
||||
|
||||
tod_times:
|
||||
name: Time of Day Thresholds
|
||||
description: >
|
||||
Ordered list of time entities (same length as states list).
|
||||
Each time defines when the corresponding state becomes active.
|
||||
Supports input_datetime (time-only) or sensor entities.
|
||||
selector:
|
||||
entity:
|
||||
domain:
|
||||
- input_datetime
|
||||
- sensor
|
||||
multiple: true
|
||||
|
||||
# Restart mode ensures time changes are processed with fresh calculations
|
||||
mode: restart
|
||||
|
||||
# =============================================================================
|
||||
# Triggers
|
||||
# =============================================================================
|
||||
trigger:
|
||||
# Re-evaluate when any time threshold entity changes (e.g., sunset time updates)
|
||||
- platform: state
|
||||
entity_id: !input tod_times
|
||||
id: "time_entity_changed"
|
||||
|
||||
# Re-evaluate every minute to catch time threshold crossings
|
||||
- platform: time_pattern
|
||||
minutes: "/1"
|
||||
id: "minute_tick"
|
||||
|
||||
# =============================================================================
|
||||
# Variables
|
||||
# =============================================================================
|
||||
variables:
|
||||
# Input references
|
||||
states: !input tod_states
|
||||
times: !input tod_times
|
||||
tod_select: !input tod_select
|
||||
|
||||
# Convert each time entity state into seconds since midnight
|
||||
# Handles both input_datetime (HH:MM:SS) and sensor entities
|
||||
thresholds: >
|
||||
{% set ns = namespace(out=[]) %}
|
||||
{% for t in times %}
|
||||
{% set raw = states(t) %}
|
||||
{% set val = raw | as_datetime %}
|
||||
{% if val is not none %}
|
||||
{# as_datetime succeeded - extract time components #}
|
||||
{% set sec = val.hour * 3600 + val.minute * 60 + val.second %}
|
||||
{% set ns.out = ns.out + [sec] %}
|
||||
{% else %}
|
||||
{# Try parsing as HH:MM:SS or HH:MM string #}
|
||||
{% set parts = raw.split(':') %}
|
||||
{% if parts | length >= 2 %}
|
||||
{% set h = parts[0] | int(0) %}
|
||||
{% set m = parts[1] | int(0) %}
|
||||
{% set s = parts[2] | int(0) if parts | length > 2 else 0 %}
|
||||
{% set sec = h * 3600 + m * 60 + s %}
|
||||
{% set ns.out = ns.out + [sec] %}
|
||||
{% else %}
|
||||
{# Fallback: use 0 (midnight) if parsing fails #}
|
||||
{% set ns.out = ns.out + [0] %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{{ ns.out }}
|
||||
|
||||
# Current time in seconds since midnight
|
||||
now_sec: >
|
||||
{% set n = now() %}
|
||||
{{ n.hour * 3600 + n.minute * 60 + n.second }}
|
||||
|
||||
# Find the index of the current state based on time
|
||||
# Logic: Find the last threshold that current time has passed
|
||||
current_index: >
|
||||
{% set ns = namespace(idx=0) %}
|
||||
{% for i in range(thresholds | length) %}
|
||||
{% if now_sec >= thresholds[i] %}
|
||||
{% set ns.idx = i %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{{ ns.idx }}
|
||||
|
||||
# The state name corresponding to current time
|
||||
current_state: "{{ states[current_index] if current_index < states | length else states[0] }}"
|
||||
|
||||
# Current state of the input_select (for comparison)
|
||||
existing_state: "{{ states(tod_select) }}"
|
||||
|
||||
# Debug flag - set to true to enable persistent notifications for troubleshooting
|
||||
is_debug: false
|
||||
|
||||
# =============================================================================
|
||||
# Condition - Only proceed if state actually needs to change
|
||||
# =============================================================================
|
||||
condition:
|
||||
- condition: template
|
||||
value_template: "{{ current_state != existing_state }}"
|
||||
|
||||
# =============================================================================
|
||||
# Actions
|
||||
# =============================================================================
|
||||
action:
|
||||
# ---------------------------------------------------------------------------
|
||||
# Debug Logging (optional)
|
||||
# ---------------------------------------------------------------------------
|
||||
- choose:
|
||||
- conditions:
|
||||
- condition: template
|
||||
value_template: "{{ is_debug }}"
|
||||
sequence:
|
||||
- service: persistent_notification.create
|
||||
data:
|
||||
title: "Time of Day Debug"
|
||||
message: >
|
||||
Current time: {{ now().strftime('%H:%M:%S') }} ({{ now_sec }}s)
|
||||
|
||||
Thresholds: {{ thresholds }}
|
||||
States: {{ states }}
|
||||
|
||||
Current index: {{ current_index }}
|
||||
Current state: {{ current_state }}
|
||||
Existing state: {{ existing_state }}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Update Time of Day State
|
||||
# ---------------------------------------------------------------------------
|
||||
- service: input_select.select_option
|
||||
target:
|
||||
entity_id: "{{ tod_select }}"
|
||||
data:
|
||||
option: "{{ current_state }}"
|
||||
Reference in New Issue
Block a user