Add ADDING_MODES.md tutorial covering: - UI-created modes (recommended) and package-defined modes - Complete schema reference with nested al_config - Behavior types (adaptive_lighting, scene, script) - Manual control support and advanced examples Update all documentation to reflect: - Zero YAML editing for room setup (UI-driven workflow) - Convention-based mode lookup pattern - Pure blueprint architecture (3 core + 3 optional blueprints) - Extensibility via helpers instead of template copying
15 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Repository Overview
This is a Home Assistant blueprints repository containing automation blueprints and a global package for Adaptive Lighting mode management. The repository uses a pure blueprint architecture with convention-based entity lookup for extensibility.
Architecture
Blueprint Structure
- 3 core blueprints for Adaptive Lighting mode system (mode application + 2 weekend mode blueprints)
- 3 optional blueprints for Inovelli switch integration and presence-based automation
- Convention-based entity lookup: Blueprints dynamically discover mode settings using naming convention (
adaptive_lighting_settings_{{mode}}) - Optional input handling: Blueprints use
default: {}pattern for optional inputs
Package Structure
- 1 global package with 8 mode definitions (
adaptive_lighting_global.yaml) - Nested JSON schema: Each mode contains
behavior,manual_control,led_color, andal_configfields - No room templates: Room configuration done entirely via Home Assistant UI
User Workflow
- Zero YAML editing for room setup
- Create helpers via Settings → Helpers (dropdowns, toggles, text inputs)
- Import blueprints via Settings → Blueprints
- Create automations from blueprints via UI
- Add custom modes by creating helpers following naming convention
Core Blueprints
Apply Lighting Mode Blueprint (apply_lighting_mode.yaml)
Purpose: Data-driven mode application using convention-based entity lookup
Key features:
- Convention-based entity lookup:
adaptive_lighting_settings_{{mode | lower | replace(' ', '_')}} - Behavior polymorphism: Supports "adaptive_lighting", "scene", and "script" behaviors
- Manual control support: Top-level
manual_controlattribute controls AL manual control state - Optional LED color integration for Inovelli switches
- Mode: restart for debouncing rapid state changes
Architecture patterns:
- Dynamic entity ID construction from mode name
- Nested al_config extraction to avoid service validation errors
- Conditional execution based on behavior type
- Optional input handling with
default: {}
Weekend Mode Schedule Blueprint (weekend_mode_schedule.yaml)
Purpose: Auto-enable/disable weekend mode based on day of week
Key features:
- Single automation combines enable + disable logic using choose action
- Time trigger checks day of week
- Toggles input_boolean based on weekday condition
- Mode: single to prevent overlapping executions
Weekend Mode Apply Settings Blueprint (weekend_mode_apply_settings.yaml)
Purpose: Apply AL adjustments when weekend mode toggles
Key features:
- Delayed sunrise time for sleeping in on weekends
- Extended sunset time for staying up later
- Reduced max brightness
- Reset to defaults when weekend mode turns off
- Triggers on boolean state change + HA restart
- Mode: restart for debouncing
Development Workflow
Adding New Modes
Two methods:
-
UI-created modes (recommended):
- Create input_text helper via Settings → Helpers
- Follow naming convention:
input_text.adaptive_lighting_settings_{{mode}} - Use nested schema:
{"behavior":"adaptive_lighting","manual_control":false,"led_color":170,"al_config":{...}} - No restart required
- Reference: ADDING_MODES.md tutorial
-
Package-defined modes (version controlled):
- Edit
adaptive_lighting_global.yaml - Add new input_text entity following existing patterns
- Use nested schema with behavior, manual_control, led_color, al_config
- Reload YAML configuration
- Edit
Key principle: Modes are discovered by convention, not hardcoded. Adding a mode doesn't require blueprint changes.
Blueprint Testing
Manual testing workflow (no automated testing framework for HA blueprints):
- Import blueprint to Home Assistant
- Create test helpers via UI
- Create automation from blueprint
- Test all input combinations
- Verify automation traces for debugging
- Check Home Assistant logs for errors
Blueprint Best Practices
- Convention-based entity naming for extensibility (modes, devices)
- Optional input handling with
default: {}for flexible configuration - Mode: restart for debouncing state changes
- Mode: single for preventing overlapping executions
- Nested JSON schema to satisfy service validation constraints
- Integration filters (
domain: switch, integration: adaptive_lighting) for user-friendly entity selection - Use descriptive names and clear descriptions for inputs
- Provide sensible defaults for optional parameters
- Include comprehensive documentation in blueprint metadata
Home Assistant Blueprint Format
Blueprints follow this structure:
blueprint:
name: Blueprint Name
description: Clear description of what this blueprint does
domain: automation
input:
input_name:
name: User-Facing Name
description: Clear description of this input
default: {} # For optional inputs
selector:
entity:
domain: switch
integration: adaptive_lighting # Optional filter
mode: restart # or single, queued, parallel
max_exceeded: silent
trigger:
- platform: state
entity_id: !input input_name
variables:
var_name: !input input_name
derived_var: "{{ template_expression }}"
action:
- service: some.service
target:
entity_id: "{{ var_name }}"
data:
setting: "{{ derived_var }}"
Input Selectors
Common selector types used in this repository:
Entity selectors:
selector:
entity:
domain: input_select # Dropdown helpers
# or
domain: input_boolean # Toggle helpers
# or
domain: switch
integration: adaptive_lighting # Filter by integration
# or
domain: number # Number entities (LED color)
Time selector:
selector:
time: # HH:MM:SS time picker
Number selector:
selector:
number:
min: 1
max: 100
step: 1
unit_of_measurement: "%"
Action selector:
selector:
action: # Full action sequence builder
Mode Settings Schema
Each mode uses this nested JSON structure:
{
"behavior": "adaptive_lighting", // or "scene", "script"
"manual_control": false, // Controls AL manual control state
"led_color": 170, // 0-255 hue value for Inovelli LED
"al_config": { // Nested object for AL settings
"min_brightness": 20,
"max_brightness": 80,
"min_color_temp": 2000,
"max_color_temp": 4000,
"transition": 5
}
}
Why nested?: The adaptive_lighting.change_switch_settings service performs strict key validation, rejecting unknown keys. The nested structure isolates AL-specific settings in al_config, while metadata like behavior and led_color remain at the top level.
Manual control: The manual_control attribute (defaults to false) controls whether AL manual control is enabled for the mode. When true, AL is paused and won't adjust lights. The blueprint always calls adaptive_lighting.set_manual_control with this value.
File Organization
/
├── blueprints/
│ └── automation/
│ ├── apply_lighting_mode.yaml # Core: Data-driven mode application
│ ├── weekend_mode_schedule.yaml # Core: Auto-enable/disable weekend mode
│ ├── weekend_mode_apply_settings.yaml # Core: Apply weekend AL adjustments
│ ├── inovelli_mode_cycling.yaml # Optional: Config button mode cycling
│ ├── inovelli_button_actions.yaml # Optional: Multi-tap button actions
│ ├── presence_mode_reset.yaml # Optional: Auto-reset on room exit
│ └── occupancy_controlled_lights.yaml # Standalone: Occupancy-based lighting
├── packages/
│ └── adaptive_lighting_global.yaml # Global mode definitions (8 modes)
├── hardware/
│ └── inovelli/
│ └── blue-dimmer-2-in-1-vzt31.md # Inovelli Blue Dimmer documentation
├── README.md # Main documentation
├── PACKAGE_SETUP_GUIDE.md # Global package installation
├── ROOM_CONFIGURATION_GUIDE.md # UI-driven room setup
├── ADDING_MODES.md # Custom mode creation tutorial
└── CLAUDE.md # This file
Home Assistant Blueprint Conventions
Input Types
entity: Entity selector for picking Home Assistant entitiesaction: Action sequence selector for automation actionsnumber: Numeric input with min/max/step validationboolean: True/false toggletext: String input fieldstime: Time picker (HH:MM:SS format)
Template Usage
- Use
!inputto reference blueprint inputs - Template conditions with
{{ }}syntax for dynamic logic - Variable assignment and reference within action sequences
- Jinja2 filters for string manipulation (
lower,replace,from_json)
Automation Modes
restart: Stops current execution and restarts on new trigger (used for debouncing)single: Ignores new triggers while runningparallel: Allows multiple simultaneous executionsqueued: Queues triggers and executes sequentially
Pattern References
Optional input handling (presence_mode_reset.yaml:98-116):
input:
optional_entity:
default: {}
selector:
entity:
domain: input_select
# Later in action:
- if:
- condition: template
value_template: "{{ optional_entity not in [none, {}, ''] }}"
then:
- service: some.service
target:
entity_id: "{{ optional_entity }}"
Integration filter (inovelli_button_actions.yaml:36-42):
selector:
entity:
domain: switch
integration: adaptive_lighting
Choose action pattern (for behavior polymorphism):
- choose:
- conditions: "{{ behavior == 'adaptive_lighting' }}"
sequence:
- service: adaptive_lighting.change_switch_settings
data: "{{ al_config }}"
- conditions: "{{ behavior == 'scene' }}"
sequence:
- service: scene.turn_on
target:
entity_id: "{{ settings.scene_entity }}"
- conditions: "{{ behavior == 'script' }}"
sequence:
- service: script.turn_on
target:
entity_id: "{{ settings.script_entity }}"
Import URLs
Blueprints are hosted at:
- Base URL:
https://git.johnogle.info/johno/home-assistant-blueprints/raw/branch/main/ - Pattern:
{base_url}/blueprints/automation/{blueprint_name}.yaml
Example: https://git.johnogle.info/johno/home-assistant-blueprints/raw/branch/main/blueprints/automation/apply_lighting_mode.yaml
Design Principles
Convention Over Configuration
Key insight: Extend the blueprint once to add a capability, then use that capability unlimited times via helpers.
Examples:
- Want 100 adaptive_lighting modes? Create 100 helpers following naming convention (no blueprint changes)
- Want scene-based modes? Blueprint already supports it (no changes needed)
- Want custom "Bowling" mode? Create one helper with correct entity ID (no changes needed)
This is the power of convention-based design.
Zero YAML Editing for Users
Room configuration workflow:
- Create helpers via UI (dropdowns, toggles)
- Create automations from blueprints via UI
- Test by switching modes via UI
- Add custom modes by creating text helpers via UI
No template copying, no YAML editing, no search/replace, no package files per room.
Nested Schema for Service Validation
Why nested al_config?
- Home Assistant services perform strict validation
- Unknown keys cause errors
- Nested structure separates metadata from service parameters
- Only
al_configis passed toadaptive_lighting.change_switch_settings - Top-level fields (
behavior,manual_control,led_color) used by blueprint logic
Behavior Polymorphism
Modes can have different behaviors:
- adaptive_lighting: Apply AL settings (default)
- scene: Activate Home Assistant scene
- script: Run Home Assistant script
This enables complex use cases (movie scenes, light shows) without modifying blueprint core logic.
Migration Notes
No migration needed - repository contains only blueprints and one global package, no deployed room configurations.
For future users: If this becomes public, users would migrate from template packages to blueprint + UI workflow by:
- Creating helpers via UI matching their room names
- Importing blueprints
- Creating automations from blueprints
- Deleting old package files
- Reloading YAML configuration
Performance Considerations
No performance concerns:
- Automations trigger only on mode changes (user-initiated, infrequent)
- JSON parsing is fast and cached by Home Assistant
- Convention-based lookup is simple string templating
- No polling, no external services, no heavy computation
- Mode: restart prevents rapid-fire executions
Common Issues and Solutions
Service Validation Errors
Symptom: "extra keys not allowed" in logs
Cause: Passing top-level fields to adaptive_lighting.change_switch_settings
Solution: Only pass al_config nested object to service
Missing Mode Entities
Symptom: Blueprint fails to find mode settings
Cause: Entity ID doesn't match naming convention
Solution: Verify entity ID follows pattern input_text.adaptive_lighting_settings_{{mode | lower | replace(' ', '_')}}
LED Color Not Updating
Symptom: Mode changes but LED stays same color
Causes:
- LED entity not configured (left empty)
- Incorrect entity ID
- Inovelli switch firmware issue
Solution: Check automation configuration, verify entity ID, test LED manually
Testing Guidelines
Since Home Assistant blueprints have no automated testing framework, all testing is manual:
- Blueprint Import: Verify imports without errors in HA
- Helper Creation: Create test helpers via UI
- Automation Creation: Create test automations from blueprints
- Mode Switching: Test all mode combinations
- Custom Modes: Create custom mode and verify convention-based lookup
- LED Integration: Verify LED colors update (if configured)
- Weekend Mode: Test schedule and AL adjustments
- HA Restart: Verify persistence across restarts
- Error Handling: Test missing entities, invalid JSON, etc.
- Logs: Check for errors in Settings → System → Logs
Always check automation traces (Settings → Automations → [automation] → Traces) for debugging.
Key Differences from Traditional Approach
Old approach (template packages):
- Copy package file per room
- Search/replace entity IDs
- Edit YAML to add modes
- Hardcoded choose blocks for each mode
- Adding mode requires editing every room
New approach (pure blueprints):
- Create helpers via UI
- Create automations via UI
- Zero YAML editing for rooms
- Convention-based mode lookup
- Adding mode = create ONE helper
Benefits:
- Lower friction for users
- No YAML syntax errors from manual editing
- Extensible without code changes
- Easier to maintain
- Better user experience