Skip to content

Feature/temperature correction#1

Closed
daniel309 wants to merge 10 commits intomasterfrom
feature/temperature-correction
Closed

Feature/temperature correction#1
daniel309 wants to merge 10 commits intomasterfrom
feature/temperature-correction

Conversation

@daniel309
Copy link
Owner

@daniel309 daniel309 commented Mar 11, 2026

Temperature-Based Household Load Correction with Heater Profile Separation

Base PR: evcc-io#27780 (Weather Tariff)
This PR: Heater Profile Separation for Temperature Correction

Problem

The evopt energy optimizer uses a household load profile (gt) to predict how much energy the home will consume in each future 15-minute slot. This profile is currently computed as a 30-day historical average — the same flat pattern is repeated regardless of weather conditions.

This is a significant blind spot: heating and cooling loads are strongly temperature-dependent. On a cold winter day, a home with a heat pump or electric heating can consume 30–80% more energy than on a mild day. When the optimizer doesn't know this, it:

  • Under-estimates household demand on cold days → schedules EV charging at times when grid power is actually needed for heating
  • Over-estimates household demand on warm days → unnecessarily avoids cheap/green charging windows
  • Misses opportunities to pre-charge the battery before a cold night when heating demand will spike

Solution Overview

This PR builds on evcc-io#27780 (which added the open-meteo weather tariff) and implements temperature-based correction of the household load profile with a critical improvement: the correction is applied only to heating device loads, not the entire household consumption.

Key Innovation: Heater Profile Separation

The original approach (discussed in evcc-io#27780) applied temperature correction to the entire household profile. However, only heating/cooling loads are temperature-dependent. Base household loads (lighting, appliances, cooking, etc.) remain constant regardless of outdoor temperature.

This PR implements a three-step process:

  1. Separate: Extract heater consumption into its own profile (gt_heater)
  2. Correct: Apply temperature adjustment only to gt_heater
  3. Merge: Combine corrected heater profile with unchanged base load
Total Household (gt_total) = Base Load (gt_base) + Heater Load (gt_heater)
                                    ↓                        ↓
                              [unchanged]        [temperature corrected]
                                    ↓                        ↓
                          Final Profile = gt_base + gt_heater_corrected

Temperature Correction Algorithm

The correction algorithm (from base PR evcc-io#27780) remains unchanged:

load[i] = load_avg[i] × (1 + heatingCoefficient × (T_past_avg[h] − T_forecast[i]))

where:

  • T_past_avg[h] = average temperature at hour-of-day h over the past 7 days
  • T_forecast[i] = forecast temperature at the wall-clock time of slot i
  • heatingCoefficient = fractional load sensitivity per °C (default 0.05 = 5%/°C)

The correction is gated on the 24h average actual temperature of the past 24 hours. If that average is at or above heatingThreshold (default 12°C), heating is considered off and no correction is applied to any slot.

Example: With default settings and a 7-day historical average of 8°C:

  • Forecast 8°C → no correction (delta = 0, factor = 1.0)
  • Forecast 3°C → +25% heater load (delta = +5°C, factor = 1.25)
  • Forecast −2°C → +50% heater load (delta = +10°C, factor = 1.50)
  • Forecast 13°C → −25% heater load (delta = −5°C, factor = 0.75)

Files Changed

File Change
core/metrics/db.go Extended schema for per-loadpoint tracking (from previous work)
core/site.go Added loadpoint energy tracking infrastructure (~50 lines)
core/site_optimizer.go Added profile extraction and modified correction flow (~130 lines)

Configuration

The feature is fully opt-in — no changes needed for existing setups. Temperature correction is only active when explicitly configured.

To enable (requires base PR evcc-io#27780):

tariffs:
  temperature:
    type: template
    template: open-meteo-temperature
    latitude: 48.1
    longitude: 11.6

site:
  title: My Home
  meters:
    grid: grid0
    pv: pv0
  heatingThreshold: 12.0    # °C — 24h avg above which corrections are disabled
  heatingCoefficient: 0.05  # fraction — load changes by this fraction per °C delta

Important: Both heatingThreshold and heatingCoefficient must be explicitly configured. There are no default values. If either is missing (or 0), temperature correction is completely disabled.

Tuning Guidance

  • heatingThreshold: Set to the 24h average outdoor temperature above which your heating system is fully off. Typical values: 10–15°C depending on building insulation. Start with 12°C for an average insulated house and adjust based on your system.
  • heatingCoefficient: Represents how sensitive your heating load is to temperature changes. A well-insulated passive house might use 0.02–0.03; a poorly insulated older building might use 0.08 or higher. Start with 0.05 (5% per °C) and tune based on observed behavior.

Backward Compatibility

The feature is completely opt-in and requires explicit configuration. Existing setups are unaffected.

Heating Consumption Always Included

Important: Heating device consumption is always added to the household profile, regardless of whether temperature correction can be applied. This ensures accurate total household load forecasts in all scenarios.

The algorithm works as follows:

Total Household = Base Load + Heating Load
                  (meter=1)   (meter=2, corrected if possible)

Temperature Correction Conditions

Temperature correction is only applied to heating loads when ALL of the following conditions are met:

  1. ✅ Weather tariff configured (tariffs.temperature)
  2. ✅ Heating devices present (detected via api.Heating feature flag)
  3. heatingThreshold explicitly configured (no default)
  4. heatingCoefficient explicitly configured (no default)
  5. ✅ Historical heater consumption data available
  6. ✅ Weather data available from Open-Meteo

If any condition is not met, the uncorrected heating profile is used, but heating consumption is still added to the base load.

Key Points:

  • Temperature correction is never applied to base household loads (lighting, appliances, etc.)
  • Temperature correction is only applied to heating device loads when all conditions are met
  • Heating consumption is always included in total household forecast (corrected or uncorrected)
  • If correction fails, the system gracefully falls back to using historical heating averages

Multiple Heater Support

The implementation fully supports multiple heating devices:

  1. Automatic Detection: All loadpoints with api.Heating feature are automatically identified
  2. Individual Tracking: Each heater's consumption is tracked separately in the database using its loadpoint title
  3. Slot-by-Slot Aggregation: Multiple heater profiles are summed together for each 15-minute slot
  4. Combined Correction: Temperature correction is applied to the aggregated heating profile

Example with 2 heaters:

Heat Pump:     [2.0, 2.5, 3.0, ...] kWh per 15min
Aux Heater:    [0.5, 0.3, 0.8, ...] kWh per 15min
              ─────────────────────────────────
Combined:      [2.5, 2.8, 3.8, ...] kWh per 15min
                        ↓
              Temperature Correction
                        ↓
Final = Base Load + Corrected Combined Heating

This approach ensures that:

  • Each heater's historical pattern is preserved
  • Total heating load is accurately represented
  • Temperature correction scales the entire heating system appropriately
  • Works with any number of heating devices (heat pumps, electric heaters, etc.)

Database Schema

Adds loadpoint column to meters table with default value '_household' to distinguish between:

  • Household base load (meter=1, loadpoint='_household') - total home consumption excluding loadpoints
  • Individual loadpoints (meter=2, loadpoint=) - specific device consumption (e.g., heaters)

The default value ensures existing household records are automatically backfilled when the column is added.
Migration is automatic via GORM AutoMigrate - no manual intervention required.

Benefits

Accuracy Improvements

  • More precise optimizer predictions on temperature extremes
  • Better EV charging schedules that don't conflict with heating needs
  • Improved battery utilization during cold/warm periods
  • Preserved daily patterns (evening peaks, etc.) while adjusting magnitude

Notes

  • Heating devices are automatically identified via existing api.Heating feature flag (heat pumps, electric heaters, etc.)
  • Historical heater data starts accumulating from deployment — no migration needed
  • The correction only applies to future slots in the optimizer horizon
  • Safe degradation if heater data unavailable (returns uncorrected profile, no temperature adjustment)
  • Open-Meteo is fetched once per hour with exponential backoff on failure
  • Past temperatures (7 days) and future forecast (3 days) fetched in single API call

Dependencies

Adds optional temperature correction to household load forecasts for the
optimizer, allowing more accurate predictions when heating/cooling loads
vary with outdoor temperature.

Configuration (optional, in site config):
- heatingThreshold: °C 24h avg above which corrections are disabled (default 12°C)
- heatingCoefficient: fractional load change per °C delta (default 0.05 = 5%)

Algorithm:
1. Gates on past 24h avg temperature vs threshold (heating active if below)
2. For each future slot, compares forecast temp to historical avg at same hour
3. Adjusts load: load *= (1 + coeff * (T_historical_avg - T_forecast))
   - Colder forecast → higher load estimate
   - Warmer forecast → lower load estimate

Requires the Temperature tariff (TariffUsageTemperature) to be configured.

Changes household profile lookback from 30 days to 7 days because:
- 7 days follows household rhythms more closely (weekly patterns)
- Temperature changes too much over 30 days, making older data less relevant
- Separate heater load from base household consumption
- Apply temperature correction only to heating devices (heat pumps, electric heaters)
- Base loads (lighting, appliances) remain unchanged
- Backward compatible: falls back to old behavior if no heating devices

Changes:
- Extended metrics DB to track per-loadpoint consumption
- Added loadpoint energy tracking infrastructure in Site
- Implemented profile extraction and aggregation functions
- Modified homeProfile() to separate, correct, and merge profiles

Addresses feedback on PR evcc-io#27780 that temperature adjustment should only
apply to heating devices, not entire household consumption.
The fallback behavior was incorrectly applying temperature correction
to the entire household profile when no heating devices or heater data
were available. This defeated the purpose of heater profile separation.

Temperature correction should ONLY be applied to heating device loads,
never to the entire household consumption. When heating devices or data
are not available, the profile should be returned uncorrected.

This ensures:
- Systems without heating devices: no temperature correction
- Systems with heating devices but no data: no temperature correction
- Systems with heating devices and data: correction only to heater load

Fixes the logic to align with the design intent of separating base
household loads (lighting, appliances, cooking) from temperature-
dependent heating loads.
Added cautious logging to track heater profile extraction and separation:
- DEBUG: Log when heater profile is extracted with slot count
- DEBUG: Log when no heating devices/data, returning uncorrected profile
- DEBUG: Log when applying temperature correction to heater profile only
- WARN: Log when negative base load detected (heater > total consumption)
- DEBUG: Detailed logging in extractHeaterProfile for each loadpoint

This helps diagnose issues with:
- Heating device detection
- Historical data availability
- Profile separation calculations
- Temperature correction application

Follows existing evcc logging patterns using site.log.DEBUG/WARN.
Changed temperature correction to be fully opt-in by removing default
values for heatingThreshold and heatingCoefficient. The correction
algorithm is now only active when BOTH values are explicitly configured.

Before: Used defaults (12.0°C threshold, 0.05 coefficient)
After: Skips correction if either value is 0 (not configured)

This ensures users must consciously enable and tune the feature for
their specific setup, preventing unexpected behavior with default values
that may not suit all installations.

Configuration required:
  heatingThreshold: 12.0    # Must be set explicitly
  heatingCoefficient: 0.05  # Must be set explicitly
Removed PR_DESCRIPTION.md and TEMPERATURE_CORRECTION_LOGIC_FIX.md.
These are temporary development files not needed in the repository.
Both weather data and profiles are on 15-minute slots, so direct
timestamp matching is simpler and more accurate than searching for
the nearest rate.
Replace magic numbers with named constants:
- MeterTypeHousehold = 1
- MeterTypeLoadpoint = 2

Makes the code more self-documenting and maintainable.
- Changed LoadpointNameHousehold from empty string to '_household'
- Added default:'_household' to loadpoint column in GORM schema
- Ensures automatic backfilling when column is added to existing databases
- More explicit and maintainable than empty string identifier
@daniel309 daniel309 closed this Mar 15, 2026
@daniel309
Copy link
Owner Author

closed in favor of: evcc-io#28232

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant