Files
haos-blueprints/Common/Time Of Day Controller/blueprint.yaml
alexei.dolgolyov 7b00899903 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>
2026-02-01 02:38:52 +03:00

170 lines
6.0 KiB
YAML

# 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 }}"