# CLAUDE.md - Development Context for Excess PV Boiler Control ## Project Purpose This Home Assistant package controls an auxiliary electric heater installed in a DHW (Domestic Hot Water) boiler. It works alongside a heat pump to provide: - **Preset-based temperature control** with user-adjustable temperatures per preset - **PV excess utilization** to use surplus solar power instead of exporting - **Bath boost** with configurable timer for rapid hot water - **Manual override** for emergency/testing scenarios ## Architecture ``` [Solar Inverter] --> sensor.deye_12_external_ct*_power (3-phase grid power) | [binary_sensor.dhw_pv_power_enough_for_aux_heater] | [automation: DHW Manage PV Thermostat] | [climate.dhw_pv_excess_heating] (shadow thermostat) | [binary_sensor.dhw_use_boiler_aux_heater] <-- [manual override] | <-- [boost modes] [automation: DHW Boiler Heater Relay] | [switch.boiler_heater_relay_switch_0] (physical relay) [input_select.dhw_boiler_preset] --> [automation: DHW Boiler Preset Manager] [input_number.dhw_boiler_temp_*] | v [climate.boiler_temperature] (main thermostat) [script.dhw_start_bath_boost] --> [timer.bath_time] --> [automation: DHW Bath Time] [input_number.dhw_bath_boost_duration] | v [input_boolean.dhw_bath_boost] + [switch.acm_pump_switch] ``` ## Key Entities ### Input Booleans (Modes/Toggles) | Entity | Purpose | |--------|---------| | `input_boolean.dhw_aux_heater_manual_override` | Force heater ON regardless of conditions | | `input_boolean.dhw_allow_aux_heater_usage` | Master enable for aux heater | | `input_boolean.dhw_use_excess_pv_for_aux_heater` | Enable PV excess mode | | `input_boolean.dhw_allow_aux_heater_in_all_modes` | Allow boost in normal thermostat mode | | `input_boolean.boiler_pv_dummy_heater` | Virtual switch for shadow thermostat | | `input_boolean.dhw_bath_boost` | Bath boost active flag (managed by automations) | ### Input Select (Presets) | Entity | Purpose | |--------|---------| | `input_select.dhw_boiler_preset` | Active boiler preset: Normal, Eco, Boost, Sleep, Away, Off | ### Timer | Entity | Purpose | |--------|---------| | `timer.bath_time` | Countdown timer for bath boost duration | ### Input Numbers (Thresholds) | Entity | Purpose | Range | |--------|---------|-------| | `input_number.dhw_aux_heater_cut_off_temperature_threshold` | Max temp before heater stops | 50-85°C | | `input_number.dhw_aux_heater_temperature_threshold` | Hysteresis threshold | 1-15°C | | `input_number.dhw_pv_target_temperature` | Target temp for PV heating | 40-70°C | | `input_number.dhw_pv_excess_usage_buffer` | Buffer power before triggering | 0-1000W | | `input_number.dhw_aux_heater_power` | Heater power rating | 500-9000W | | `input_number.dhw_pv_excess_usage_start_delay` | Delay before starting PV mode | 1-300s | | `input_number.dhw_pv_excess_usage_stop_delay` | Delay before stopping PV mode | 1-300s | ### Input Numbers (Preset Temperatures) | Entity | Purpose | Range | |--------|---------|-------| | `input_number.dhw_boiler_temp_normal` | Normal preset target temperature | 30-65°C | | `input_number.dhw_boiler_temp_eco` | Eco preset target temperature | 30-60°C | | `input_number.dhw_boiler_temp_boost` | Boost preset target temperature | 40-70°C | | `input_number.dhw_boiler_temp_sleep` | Sleep preset target temperature | 25-55°C | | `input_number.dhw_boiler_temp_away` | Away preset target temperature | 20-50°C | | `input_number.dhw_bath_boost_duration` | Duration for bath boost timer | 5-120 min | ### Scripts | Entity | Purpose | |--------|---------| | `script.dhw_start_bath_boost` | Starts `timer.bath_time` with duration from `dhw_bath_boost_duration` | ### Climate (Generic Thermostats) | Entity | Purpose | |--------|---------| | `climate.dhw_pv_excess_heating` | Shadow thermostat for PV excess mode | | `climate.boiler_temperature` | Main boiler thermostat (target set by preset manager) | ### Automations | Entity | Purpose | |--------|---------| | `DHW Boiler Heater Relay Automation` | Switches physical relay based on decision sensor | | `DHW Manage PV Thermostat` | Controls shadow thermostat based on PV availability | | `DHW Boiler Preset Manager` | Syncs preset selection + temperatures to thermostat, toggles bath boost | | `DHW Bath Time` | Manages bath boost lifecycle: pump + boost on/off with timer | ### External Entities (Not Defined in Package) These must exist in your HA instance from other integrations or manual UI setup: | Entity | Source | Purpose | Fallback if Unavailable | |--------|--------|---------|------------------------| | `sensor.boiler_temp` | Heat pump / temperature probe | Boiler water temperature | 100 (prevents running) | | `sensor.deye_12_external_ct1_power` | Deye inverter integration | Phase 1 grid power (negative = export) | 0 | | `sensor.deye_12_external_ct2_power` | Deye inverter integration | Phase 2 grid power | 0 | | `sensor.deye_12_external_ct3_power` | Deye inverter integration | Phase 3 grid power | 0 | | `sensor.heat_pump_auxiliary_heater` | Heat pump integration | HP aux heater state | treated as 'off' | | `switch.boiler_heater_relay_switch_0` | Relay device (Shelly, etc.) | Physical heater control | N/A | | `switch.acm_pump_switch` | Pump relay/smart plug | DHW circulation pump | N/A | | `switch.schedule_f403a3` | Scheduler integration | Pump schedule to restore after boost | N/A | ## Decision Logic ### binary_sensor.dhw_use_boiler_aux_heater This is the main decision sensor. It turns ON when: 1. **Manual override** is ON, OR 2. **All conditions met**: - Heat pump aux heater is OFF - Boiler aux usage is allowed - Boiler temp is below cut-off threshold - AND one of: - PV excess mode active AND shadow thermostat is heating - Bath boost active AND main thermostat is heating - All-modes boost enabled AND main thermostat is heating ### binary_sensor.dhw_pv_power_enough_for_aux_heater Determines if there's enough solar export to run the heater: - **When heater is OFF**: All 3 phases must export > (buffer + heater_power) / 3 - **When heater is ON**: All 3 phases must still be exporting (<=0W import) ### Preset Manager Flow 1. User selects preset from `input_select.dhw_boiler_preset` 2. Automation reads corresponding `input_number.dhw_boiler_temp_` value 3. Sets `climate.boiler_temperature` to that target + heat mode (or off for "Off" preset) 4. Toggles `input_boolean.dhw_bath_boost` on/off based on whether Boost is selected 5. If user changes a preset temperature input_number, automation re-applies current preset ### Bath Boost Flow 1. User calls `script.dhw_start_bath_boost` (e.g., from a dashboard button) 2. Script starts `timer.bath_time` with duration from `input_number.dhw_bath_boost_duration` 3. `DHW Bath Time` automation detects timer active: turns on pump + bath boost 4. Timer finishes: automation restores pump schedule + turns off boost ## Common Modifications ### Changing Preset Temperatures Adjust via dashboard sliders at runtime (no YAML edit needed). The `input_number.dhw_boiler_temp_*` entities store each preset's temperature. ### Adding New Presets 1. Add option to `input_select.dhw_boiler_preset` 2. Add corresponding `input_number.dhw_boiler_temp_` (name must be lowercase match) 3. The preset manager automation uses dynamic entity resolution, so no automation changes needed ### Changing Power Thresholds Adjust via dashboard at runtime: - `dhw_pv_excess_usage_buffer`: Increase for more conservative PV triggering - `dhw_aux_heater_power`: Match to actual heater rating ### Adjusting Timing Adjust via dashboard at runtime: - `dhw_pv_excess_usage_start_delay`: Increase to avoid rapid cycling - `dhw_pv_excess_usage_stop_delay`: Increase to ride through clouds - `dhw_bath_boost_duration`: Duration of bath boost timer ### Adding New Heating Modes Edit template section, add new condition in `binary_sensor.dhw_use_boiler_aux_heater` alongside `pv_excess`, `thermostat_activity_boost`, etc. ## Testing/Validation 1. **YAML Syntax**: Run `yamllint *.yaml` or use HA's configuration check 2. **Entity References**: Ensure all `states()` calls reference defined entities 3. **Default Fallbacks**: Verify all `float()` filters have appropriate defaults: - Temperature sensors: `float(100)` (fail-safe: heater OFF) - Power sensors: `float(0)` (fail-safe: no export detected) - Input numbers: `float()` ## File Structure | File | Purpose | |------|---------| | `use_excess_pv_in_boiler.yaml` | **Main package file** - install this in HA packages directory | | `CLAUDE.md` | Development context for AI assistants | | `README.md` | User-facing documentation | ## Safety Considerations 1. **Never run both heaters**: Template checks `sensor.heat_pump_auxiliary_heater != 'on'` 2. **Temperature cut-off**: Hard limit prevents overheating 3. **Unavailable sensors**: Default to safe values (temp=100, power=0) 4. **Manual override**: Bypasses all checks - use with caution 5. **Bath boost timer**: Auto-disables boost when timer expires