Files

12 KiB
Raw Permalink Blame History

HA Energy/Power Analysis Methodology

How to diagnose unexpected power consumption (e.g. nighttime grid draw) using HA history data. Based on a session diagnosing ~200W nighttime grid import caused by a heat pump water heating cycle.

Sensor Inventory (This Homelab)

Grid / Net Power

Entity Name Notes
sensor.evcc_grid_power Leistung Netz EVCC aggregate grid power (W). Positive = import.
sensor.netzfluss_saldo Tibber Pulse Netzfluss Saldo Tibber Pulse grid balance (W). Negative = export. Higher resolution than EVCC.
sensor.stromverbrauch_haus_netto Stromverbrauch Haus netto Net house power consumption (W)

Home / Load

Entity Name Notes
sensor.evcc_home_power Leistung Heim Total home consumption (W)
sensor.stromverbrauch_rest Stromverbrauch "Rest" Unknown/rest consumption

PV

Entity Name Notes
sensor.evcc_pv_power Leistung PV Aggregate PV power (W)
sensor.hm_1500_power HM-1500 Power Hoymiles HM-1500 via OpenDTU/MQTT
sensor.schuppen_string_1_power Schuppen 1 Power Hoymiles Schuppen 1
sensor.schuppen_2_power Schuppen 2 Power Hoymilles Schuppen 2

Batteries

Entity Name Notes
sensor.evcc_battery_power Leistung Batterie EVCC aggregate battery (W). Positive = discharging.
sensor.evcc_battery_soc Batterie Ladezustand EVCC aggregate SOC (%)
sensor.sn_3007105790_battery_power_discharge_total SMA Battery Discharge SMA SunnyBoyStorage discharge (W)
sensor.sn_3007105790_battery_power_charge_total SMA Battery Charge SMA SunnyBoyStorage charge (W)
sensor.sn_3007105790_battery_soc_total SMA Battery SOC SMA SunnyBoyStorage SOC (%)
sensor.marstek_venus_modbus_batterieleistung Marstek Batterieleistung Marstek Venus (W). Negative = discharging.
sensor.marstek_venus_modbus_ac_leistung Marstek AC-Leistung Marstek AC output (W)
sensor.marstek_venus_modbus_batterie_ladezustand Marstek SoC Marstek Venus SOC (%)
sensor.marstek_target_power Marstek Target Power EVCC/setpoint target for Marstek (W)
sensor.sma_target_power SMA Target Power EVCC/setpoint target for SMA (W)

Large Consumers (Individual)

Entity Name Notes
sensor.shellypro3em_08f9e0e98b9c_total_active_power Wärmepumpe Total Heat pump total active power (W). Major consumer — up to 5.4kW.
sensor.strommessung_sauna_total_active_power Sauna Total Sauna total active power (W)
sensor.cu401b_s_verdichterleistung CU401B Verdichterleistung Heat pump compressor power (kW)
sensor.cu401b_s_verdichtermodulation CU401B Verdichtermodulation Heat pump compressor modulation (%)
sensor.cu401b_s_kompressorphase CU401B Kompressorphase Compressor phase: off/preparing/heating/pause
sensor.cu401b_s_ww_speichertemperatur WW-Speichertemperatur Hot water tank temp (°C). Target: 46°C, Hysteresis: 4K
sensor.ev_charger_schon_leistung_ladestation EV Charger Leistung SMA EV Charger station power (W)
sensor.evcc_wallbox_charge_power Wallbox Ladeleistung EVCC wallbox charge power (kW)
sensor.trockner_device_power Trockner Power Dryer power (W)
sensor.samsung_qn90aa_65_tv_power Samsung TV Power TV power (W)

EVCC Config / Tariff

Entity Name Notes
number.evcc_residual_power Restleistung EVCC residual power target (W). Default 100W.
sensor.evcc_tariff_grid Kosten Netz Current grid price (€/kWh)
binary_sensor.evcc_battery_grid_charge_active Hausbatterie Netzladen Whether battery is charging from grid

Heat Pump Config (ViCare / CU401B S)

Entity Name Notes
climate.vicare_heating CU401B S Heizung Climate entity. Presets: comfort/eco/home/sleep
number.cu401b_s_ww_temperatur WW-Temperatur WW target temp (°C). Currently 46.
number.cu401b_s_ww_hystereseschalter_ein WW-Hysterese ein WW hysteresis ON (K). Currently 4.
number.cu401b_s_ww_hystereseschalter_aus WW-Hysterese aus WW hysteresis OFF (K). Currently 4.
automation.komfort_heizung Komfort Heizung Automation controlling heating comfort mode

Analysis Workflow

  1. Confirm the anomaly: Query sensor.evcc_grid_power history for the suspected time window. Summarize in 30-min buckets to see the pattern. Important: Ask the user for approximate time — they may point to a different window than the first obvious spike. In one session, the first analysis found a 02:47 heat pump spike, but the user clarified the issue was at 04:30+, revealing a second smaller spike that was initially overlooked.

  2. Decompose the power equation: At any moment: grid = home - pv - battery_discharge + battery_charge. Query all four simultaneously to see which component is causing the imbalance.

  3. Check battery SOC trajectory: If batteries drain to low SOC during the night, they can't cover the remaining demand → grid import kicks in. Plot SOC over time for both batteries.

  4. Identify the triggering consumer: Query individual large-consumer sensors (heat pump, sauna, EV charger, dryer) for the same time window. Look for spikes or sustained elevated consumption.

  5. Correlate with heat pump phases: The cu401b_s_kompressorphase and cu401b_s_verdichtermodulation entities show exactly when the compressor starts, what phase it's in, and how hard it's working. The ww_speichertemperatur shows whether it's a hot-water heating cycle (temp rising toward target).

  6. Check EVCC control targets: marstek_target_power and sma_target_power show what EVCC is commanding the batteries to do. If these are 0, EVCC isn't actively discharging the batteries — they may be in passive mode.

  7. Summarize findings: Present a timeline table showing the key events and a root-cause explanation, followed by prevention options.

Multiple Spikes Per Night (2026-07-09 Session)

In one session, two distinct grid import spikes were found in a single night:

Time Grid Peak Home Peak Heat Pump Cause
02:47 4,808 W 6,151 W 5,440 W Heat pump WW heating (compressor 47-50% modulation, WW temp 38→47°C)
04:30 3,570 W 4,920 W 91 W (standby) Unknown — heat pump was idle. Possibly a second WW cycle or another consumer not covered by monitored sensors.

Lesson: Don't assume the first spike is the only one. Query the full 02:0007:00 window and look for ALL grid import periods >100W. The 04:30 spike showed home power at 4,920W but the heat pump was only drawing 91W — the 4,800W delta came from an unmonitored consumer. Future analysis should query ALL available power sensors (including sensor.stromverbrauch_haus_netto which aggregates differently from evcc_home_power) and consider unmonitored circuits.

Prevention Strategies for Nighttime Grid Import

Heat Pump WW Timing

The most impactful fix: shift hot water preparation to daytime PV hours.

  • ViCare schedule: Set WW heating to only occur between 10:0015:00 (main PV production window).
  • Increase hysteresis: Change ww_hystereseschalter_ein from 4K to 6K → starts later, fewer cycles.
  • Lower WW target: Reduce ww_temperatur from 46°C to 43°C → less energy per cycle.

Battery SOC Management

Ensure batteries start the night at 100%:

  • EVCC priority SOC: Ensure evcc_priority_soc is set appropriately so batteries reserve enough for overnight.
  • Force charge before sunset: If PV forecast predicts low production, trigger battery charging from PV surplus in late afternoon.
  • Marstek discharge limit: number.marstek_venus_modbus_entladeleistung_einstellen controls max discharge rate. Lowering it extends battery runtime but may not fully cover peaks.

Both WW timing AND battery management together provide the most robust solution.

EVCC-Side Battery Discharge Diagnosis

When the question shifts from "what consumed the power?" to "why didn't the battery cover the gap?", the EVCC api/state endpoint provides the answer. This is a different diagnostic axis from the consumption-side analysis above.

Key Fields in curl -s http://10.0.30.10:7070/api/state

Field Path Meaning
Controllable battery.devices[].controllable false = EVCC reads SoC/power but cannot command discharge
Discharge control batteryDischargeControl false = passive monitoring, no active discharge management
Residual power residualPower Watts EVCC tolerates from grid before reacting (default 100)
Battery mode batteryMode unknown = no active mode set
Per-battery power battery.devices[].power Current output (W) — compare to home power
Per-battery SOC battery.devices[].soc High SOC + low output = battery is limited, not empty

Diagnosis Flow

  1. Check controllable — if false, EVCC cannot increase discharge. The battery's own internal limit is the bottleneck.
  2. Check residualPower — if >0, EVCC deliberately allows that much grid import as baseline.
  3. Compare battery output to home power — if battery output << home power and SOC is high, the battery's internal discharge limit (not EVCC) is the constraint.
  4. Verify by checking spike behavior — if the battery briefly delivered much more during a spike (e.g. Marstek hit 1,437W during heat pump cycle but settled to ~650W steady-state), that confirms an internal limiter, not a capacity issue.

Case Study: Marstek Venus Not Covering 200W Gap (2026-07-10)

Symptom: ~200W continuous grid import 03:0004:00 despite Marstek SoC at 73%.

Initial hypothesis (INCOMPLETE): EVCC controllable: false + residualPower: 100 + Marstek internal discharge limit ≈ 650W.

Actual root cause: The HA automation "Marstek Kaskaden-Steuerung (Modbus)" (automation.marstek_modbus_steuerung) controls the Marstek, NOT EVCC. EVCC sees controllable: false because it's only a passive observer. The automation has a feedback-loop bug in its echter_bedarf formula:

# BUG: uses setpoint (number.*_einstellen) instead of measured (sensor.*)
echter_bedarf: "{{ power_home - production + marstek_current_discharge - marstek_current_power }}"
# marstek_current_discharge = states('number.marstek_venus_modbus_entladeleistung_einstellen')  ← SETPOINT

This causes the discharge setpoint to spiral: 0 → 870 → 1740 → 2500 (capped) within 3 cycles (6 min). The Marstek's anti_feed mode then throttles actual output to ~650W (preventing grid export from the oversized command). The ~200W gap is the difference between what the automation commands (2500W) and what the Marstek actually delivers after anti_feed throttling (~650W), versus what the house needs (~870W).

Evidence: During the 02:4302:57 heat pump spike, Marstek delivered up to 1,437W (proving capacity exists), but settled back to ~650W afterward — consistent with the automation ramping the setpoint up and anti_feed throttling back.

Fix: Replace setpoint variables with measured AC power in the automation:

# FIXED:
marstek_actual_ac: "{{ states('sensor.marstek_venus_modbus_ac_leistung') | float(0) }}"
echter_bedarf: "{{ power_home - production - marstek_actual_ac }}"

Result: echter_bedarf = 870 - 0 - 650 = 220W → new setpoint = 650 + 220 = 870W. Stable convergence.

See references/marstek-cascade-automation.md for the full automation YAML and analysis.

Query Templates

See references/ha-browser-console-access.md for the browser-console technique used to execute these queries when no local API token is available.

Summary query (all sensors, 30-min buckets)

// Adapt entity list and time range as needed
const entities = 'sensor.evcc_grid_power,sensor.evcc_home_power,sensor.evcc_battery_power,sensor.evcc_pv_power';
const url = '/api/history/period/2026-07-09T03:00:00?filter_entity_id=' + entities +
            '&end_time=2026-07-09T06:00:00&minimal_response';

Individual consumer spike detection

// Filter history records where power > threshold
const spikes = hist.filter(h => parseFloat(h.state) > 100).map(h => ({
  t: h.last_changed.substring(11, 16),
  v: parseFloat(h.state)
}));