Add custom mode tutorial and update docs for pure blueprint architecture
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
This commit is contained in:
451
CLAUDE.md
451
CLAUDE.md
@@ -4,84 +4,447 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||
|
||||
## Repository Overview
|
||||
|
||||
This is a Home Assistant blueprints repository containing automation blueprints for Home Assistant. The repository follows a simple structure with individual YAML blueprint files in the root directory alongside comprehensive documentation.
|
||||
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
|
||||
- **Blueprint files**: YAML files defining Home Assistant automation blueprints
|
||||
- **Documentation**: README.md provides detailed usage examples and configuration guidance
|
||||
- Each blueprint is self-contained with embedded metadata (name, description, domain, inputs)
|
||||
- **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
|
||||
|
||||
### Current Blueprints
|
||||
### 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
|
||||
|
||||
#### Multi-Press Action Blueprint (`multi_press_action.yaml`)
|
||||
- **Purpose**: Trigger different actions based on rapid entity state changes (single, double, triple, quad press)
|
||||
- **Key features**:
|
||||
- Configurable time window for press detection
|
||||
- Immediate vs delayed single-press modes
|
||||
- Support for complex action sequences with conditions
|
||||
- **Architecture patterns**:
|
||||
- Uses Home Assistant blueprint format with input selectors
|
||||
- Implements state machine logic with press counting
|
||||
- Uses `mode: restart` to handle overlapping triggers
|
||||
- Template-based conditional logic for press count evaluation
|
||||
### 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 Blueprints
|
||||
1. Create new `.yaml` file in repository root
|
||||
2. Follow Home Assistant blueprint format:
|
||||
- `blueprint:` section with metadata
|
||||
- `input:` section with user-configurable parameters
|
||||
- `trigger:` and `action:` sections for automation logic
|
||||
3. Update README.md with new blueprint documentation
|
||||
4. Test blueprint by importing into Home Assistant development environment
|
||||
### 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 selector types for user inputs
|
||||
- Use `mode: restart` or `mode: single` appropriately based on use case
|
||||
- Implement proper variable scoping within actions
|
||||
- Include detailed documentation with usage examples
|
||||
- Include comprehensive documentation in blueprint metadata
|
||||
|
||||
### Testing
|
||||
- No automated testing framework (blueprints are tested in Home Assistant directly)
|
||||
- Manual testing involves:
|
||||
1. Importing blueprint into Home Assistant
|
||||
2. Creating automation from blueprint
|
||||
3. Testing various input combinations and edge cases
|
||||
4. Verifying automation traces for debugging
|
||||
### Home Assistant Blueprint Format
|
||||
|
||||
### Import URLs
|
||||
- Repository uses custom Git hosting at `git.johnogle.info`
|
||||
- Import URL pattern: `https://git.johnogle.info/johno/home-assistant-blueprints/raw/branch/main/{blueprint_name}.yaml`
|
||||
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
|
||||
|
||||
```
|
||||
/
|
||||
├── README.md # Comprehensive documentation
|
||||
├── multi_press_action.yaml # Multi-press detection blueprint
|
||||
└── CLAUDE.md # This file
|
||||
├── 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
|
||||
- `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
|
||||
- `restart`: Stops current execution and restarts on new trigger (used for debouncing)
|
||||
- `single`: Ignores new triggers while running
|
||||
- `parallel`: Allows multiple simultaneous executions
|
||||
- `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/)
|
||||
|
||||
Reference in New Issue
Block a user