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
451 lines
15 KiB
Markdown
451 lines
15 KiB
Markdown
# 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`, and `al_config` fields
|
|
- **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_control` attribute 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**:
|
|
|
|
1. **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
|
|
|
|
2. **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
|
|
|
|
**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):
|
|
1. Import blueprint to Home Assistant
|
|
2. Create test helpers via UI
|
|
3. Create automation from blueprint
|
|
4. Test all input combinations
|
|
5. Verify automation traces for debugging
|
|
6. 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:
|
|
```yaml
|
|
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**:
|
|
```yaml
|
|
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**:
|
|
```yaml
|
|
selector:
|
|
time: # HH:MM:SS time picker
|
|
```
|
|
|
|
**Number selector**:
|
|
```yaml
|
|
selector:
|
|
number:
|
|
min: 1
|
|
max: 100
|
|
step: 1
|
|
unit_of_measurement: "%"
|
|
```
|
|
|
|
**Action selector**:
|
|
```yaml
|
|
selector:
|
|
action: # Full action sequence builder
|
|
```
|
|
|
|
### Mode Settings Schema
|
|
|
|
Each mode uses this nested JSON structure:
|
|
|
|
```json
|
|
{
|
|
"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 entities
|
|
- `action`: Action sequence selector for automation actions
|
|
- `number`: Numeric input with min/max/step validation
|
|
- `boolean`: True/false toggle
|
|
- `text`: String input fields
|
|
- `time`: Time picker (HH:MM:SS format)
|
|
|
|
### Template Usage
|
|
- Use `!input` to 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 running
|
|
- `parallel`: Allows multiple simultaneous executions
|
|
- `queued`: Queues triggers and executes sequentially
|
|
|
|
### Pattern References
|
|
|
|
**Optional input handling** (`presence_mode_reset.yaml:98-116`):
|
|
```yaml
|
|
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`):
|
|
```yaml
|
|
selector:
|
|
entity:
|
|
domain: switch
|
|
integration: adaptive_lighting
|
|
```
|
|
|
|
**Choose action pattern** (for behavior polymorphism):
|
|
```yaml
|
|
- 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:
|
|
1. Create helpers via UI (dropdowns, toggles)
|
|
2. Create automations from blueprints via UI
|
|
3. Test by switching modes via UI
|
|
4. 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_config` is passed to `adaptive_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:
|
|
1. Creating helpers via UI matching their room names
|
|
2. Importing blueprints
|
|
3. Creating automations from blueprints
|
|
4. Deleting old package files
|
|
5. 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**:
|
|
1. LED entity not configured (left empty)
|
|
2. Incorrect entity ID
|
|
3. 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:
|
|
|
|
1. **Blueprint Import**: Verify imports without errors in HA
|
|
2. **Helper Creation**: Create test helpers via UI
|
|
3. **Automation Creation**: Create test automations from blueprints
|
|
4. **Mode Switching**: Test all mode combinations
|
|
5. **Custom Modes**: Create custom mode and verify convention-based lookup
|
|
6. **LED Integration**: Verify LED colors update (if configured)
|
|
7. **Weekend Mode**: Test schedule and AL adjustments
|
|
8. **HA Restart**: Verify persistence across restarts
|
|
9. **Error Handling**: Test missing entities, invalid JSON, etc.
|
|
10. **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
|
|
|
|
## Resources
|
|
|
|
- [Home Assistant Blueprint Documentation](https://www.home-assistant.io/docs/blueprint/)
|
|
- [Adaptive Lighting Integration](https://github.com/basnijholt/adaptive-lighting)
|
|
- [Jinja2 Template Reference](https://jinja.palletsprojects.com/)
|
|
- [YAML Specification](https://yaml.org/)
|