A power manager component for home assistant (SMA-only currently)
This repository has been archived on 2026-09-12. You can view files and clone it, but you cannot make any changes to its state, such as pushing and creating new issues, pull requests or comments.
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Philipp A. Baer 3b1f6a4079
Some checks failed
HACS integration / validate-and-release (push) Failing after 9s
Tests / test (push) Successful in 25s
fix(control): allow confirmed devices without firmware identity
2026-09-06 07:07:14 +02:00
.forgejo/workflows ci: validate Home Assistant integration metadata 2026-08-31 07:27:35 +02:00
.github/workflows ci(release): gate HACS package on runtime validation 2026-09-05 06:22:18 +02:00
custom_components/powermanager fix(control): allow confirmed devices without firmware identity 2026-09-06 07:07:14 +02:00
docs/knowledge fix(control): allow confirmed devices without firmware identity 2026-09-06 07:07:14 +02:00
scripts fix(speedwire): accept live telegram header 2026-08-30 09:27:11 +02:00
tests fix(control): allow confirmed devices without firmware identity 2026-09-06 07:07:14 +02:00
.gitignore build: adopt uv for project management 2026-08-30 08:54:21 +02:00
.python-version build: adopt uv for project management 2026-08-30 08:54:21 +02:00
AGENTS.md chore: document project agent rules 2026-09-04 06:25:48 +02:00
hacs.json chore: initialize project documentation and CI 2026-08-30 08:41:05 +02:00
Handover_ Local Predictive Battery Control for Viessmann Vitocharge - SMA Sunny Island.md fix(monitor): harden passive ownership detection and document production gates 2026-09-05 06:17:55 +02:00
LICENSE chore: initialize project documentation and CI 2026-08-30 08:41:05 +02:00
pyproject.toml fix(ha): align Modbus requirement with Core 2026-09-04 07:48:34 +02:00
README.md fix(control): allow confirmed devices without firmware identity 2026-09-06 07:07:14 +02:00
rules.example.yaml fix(safety): bound charging by PV surplus 2026-09-06 06:17:55 +02:00
uv.lock fix(ha): align Modbus requirement with Core 2026-09-04 07:48:34 +02:00

PowerManager

PowerManager is an unofficial, fully local Home Assistant integration and reusable Python core for monitoring home batteries. Its first backend targets an SMA Sunny Island used in older Viessmann Vitocharge systems.

Safety status

0.1.0 remains monitor only by default. A guarded write adapter, heartbeat, restore-normal path, and read-only commissioning preflight are present. Active control requires explicit commissioning confirmations and remains fail-closed on ownership, telemetry, operating state, power bounds, watchdog, and session lifecycle. See the production handover for the ordered implementation checklist and acceptance gates.

Passive Home Manager detection warns about unclassified other SMA senders; it does not prove their identity or exclusive control ownership. Verified reporting-only addresses remain visible but do not block ownership. Warnings persist across polls and listener retries. The warning's observation_state attribute distinguishes unknown, offline, stale, and online observation. Its observed_sources and external_sources attributes show the IPv4 senders seen on Speedwire; diagnostics include the complete list for identifying a broadcaster on the local LAN. The device also exposes separate source-count and source-address sensors. Failed listeners retry after 30 seconds; traffic expires after 300 seconds in the HA coordinator. Silence never grants ownership eligibility. Reload starts a new observation history. No indicator enables writes.

An observed sender address is not treated as a device-role determination. Verified telemetry-only devices can be added to normalized HA sensors in future protocol adapters, while unknown or control-capable sources remain a control blocker. Any verified control datagram must inhibit control immediately; silence or missing packets can never authorize it.

Development

The project uses uv for fast, reproducible local environment management. Install uv, then run:

uv sync --extra sma --extra dev
uv run pytest
uv run ruff check .
uv run powermanager status --host 192.168.1.50
uv run powermanager commission --host 192.168.1.50
uv run powermanager speedwire-capture --duration 60 --show-hex

When selecting a specific LAN interface, pass its local address with --interface (for example 10.0.1.254). The listener binds the UDP socket to the wildcard address and uses that value only to select the multicast interface.

The committed uv.lock keeps the development and SMA protocol dependencies reproducible. Use uv lock --upgrade deliberately when updating dependencies.

The Home Assistant integration is located at custom_components/powermanager and is packaged directly by the release workflows for HACS.

The planned control architecture and declarative rule format are documented in docs/knowledge/control-plan.md. Control remains disabled unless the operator explicitly enables the commissioned scheduled or manual path. The predictive scheduler is an opt-in constrained to measured PV surplus.

The polling interval can be adjusted from the integration's Home Assistant options flow (5300 seconds). Connection details remain in the config entry; device communication is read-only unless the explicit active-control gates are enabled.

The integration exposes the current control mode and includes the block reason in diagnostics. It also reads the Sunny Island serial number and packed firmware identity for stable device metadata. These indicators do not authorize control; supervised hardware commissioning is still required before any command adapter can be used.

The firmware identity is a commissioning input, not a prerequisite for ordinary read-only telemetry. If Modbus registers 30061/30063 return SMA's unavailable value (0xFFFFFFFF) or an unknown packed format, the firmware sensor reports unknown. Active control still requires the explicit firmware/Modbus behavior confirmation; a missing identity alone does not block a confirmed installation.

The integration includes explicit powermanager.start_control and powermanager.stop_control services for a bounded manual session. They remain locked unless the operator enables active control and confirms the single-phase topology, firmware/fallback behavior, sole ownership, and the LS/RCD isolation procedure. Every heartbeat rechecks fresh telemetry, SoC reserve, operating state, ownership, and configured power bounds. Existing Sunny Island external setpoint, fallback, timeout, and power-bound settings are read during preflight and never rewritten by PowerManager. A restart or unload cannot resume a prior session. Scheduled control is a separate opt-in and must follow supervised manual testing. The supervised HA instance has the predictive option enabled; loading and health checks passed, but a successful live write has not been independently verified in this handover.

Sunny Island event 7613 (“communication with meter faulty”) is treated as a charge-only warning: a bounded charge request may proceed when all other safety inputs are fresh, while discharge remains blocked and grid-dependent rules still require valid grid telemetry. Other warning or error events remain blocked.

The disconnected command-session adapter keeps a bounded, sanitized event buffer for future diagnostics and verifies baseline restoration after each bounded test session. Home Assistant setup removes that passive monitor state if platform forwarding fails or the entry unloads, so retries cannot inherit a leaked listener.

Optional grid/PV/load and price telemetry is accepted only while fresh. Grid power is normalized from kW to W. Configure either a market-price entity or a fixed contract import price in EUR/kWh; a fixed price does not require a Home Assistant helper. A market-price entity must expose an explicit currency-per-energy unit: prices in /MWh are normalized to /kWh, while unitless or ambiguous prices are not used.

For grid exchange, configure either one signed instantaneous-power entity (positive import, negative export), or both separate import and export power entities. The latter normally map to OBIS 1.7.0 and 2.7.0. OBIS 1.8.0 and 2.8.0 are cumulative energy counters, so they are deliberately not accepted as grid-power sources.

The options flow accepts one or more local remaining-PV forecast entities and an expected-remaining-load forecast entity. They must expose Wh, kWh, or MWh. Separate PV forecasts are summed only when every selected value is fresh. They are used only for simulation/policy eligibility; neither forecast data nor a policy can enable a device write.

Charging is additionally bounded by the current measured PV surplus. A positive charge target is rejected when fresh site telemetry cannot prove enough PV power is available, or when the target would exceed the conservative minimum of PV minus load and measured grid export. PV generation and household load telemetry are required; grid export alone is not treated as proof that solar energy is available. The example rules keep their targets at or below their export thresholds as an additional policy guard.

Energy Dashboard interval forecasts also expose the predicted PV power for the currently active interval. Rules can use forecast_pv_power_above_w to choose charge tiers from the forecast itself, so a policy does not assume that noon is the daily production peak. If the forecast platform does not provide an active interval, that condition remains ineligible and the policy can fall back to measured-export rules.

Multiple inverter telemetry sources can be configured with the optional inverters_yaml option. The options flow also offers native Home Assistant entity pickers: set the number of profiles and complete one role-aware form per inverter. The YAML field remains available for advanced import/export. Each source is read from existing Home Assistant entities:

When the Home Assistant Energy Dashboard is configured, PowerManager imports its grid, solar, battery, tariff, and solar-forecast topology automatically. The options form prints every imported PV source and any missing instantaneous sensor. It refuses to save an incomplete dashboard topology until the missing source is supplied manually. A whole-home remaining-load forecast (or the automatically derived PowerManager whole-home load sensor plus historical estimation) is also required because the Energy Dashboard has no household load forecast. The derived sensor is only populated when signed grid, PV, and battery telemetry is fresh.

inverters:
  - id: sunnyboy_main
    role: pv
    generation_power_entity: sensor.sunnyboy_power
    remaining_pv_forecast_entity: sensor.sunnyboy_remaining_forecast
  - id: garage_hybrid
    role: hybrid
    generation_power_entity: sensor.garage_pv_power
    battery_power_entity: sensor.garage_battery_power
    remaining_pv_forecast_entity: sensor.garage_remaining_forecast

PV generation values are normalized to watts and PV forecasts to kWh. Battery power is an optional signed value for battery-capable or hybrid sources. Grid import/export and household load forecasts remain site-level inputs; they are never inferred from PV inverter output and are not duplicated per inverter. When no site PV forecast is configured, all configured PV forecasts must be fresh before they are combined for simulation and the predictive planner. The sources remain read-only and do not create an inverter write path.

Simulation-only rules can be edited as versioned YAML in the integration options. PowerManager exposes the currently matching simulated rule and its requested target power, but never sends that target to the Sunny Island.

The core also includes a predictive planner that accounts for usable capacity, reserve and end-of-day targets, forecast uncertainty, export capacity, current PV surplus, and charge limits. It produces explainable recommendations and deterministic replay and SoC/reserve outcome results for backtesting. Home Assistant exposes the recommendation and its reason as sensors. The predictive_control_enabled option can promote that recommendation into the existing bounded scheduled-control path after all active-control commissioning gates pass; it remains disabled by default and never authorizes grid charging or a target above measured PV surplus. The Sunny Island remains the authority for battery SoC estimation, charging phases, and battery protection. PowerManager must send bounded power targets and must never write or invent a battery SoC.

PowerManager adds recorder-friendly forecast sensors for PV power now, estimated household load power now, planned charge power, planned discharge power, and the PV/load forecast errors. The PV and estimated-load sensors include a timestamped forecast_profile attribute for the next 24 hours. Add the sensors to a native Home Assistant history graph to compare predictions with measured PV and load:

type: history-graph
title: PowerManager forecast validation
hours_to_show: 24
entities:
  - sensor.<device>_forecast_pv_power_now
  - sensor.<device>_pv_power
  - sensor.<device>_forecast_load_power_now
  - sensor.<device>_load_power
  - sensor.<device>_planned_charge_power
  - sensor.<device>_planned_discharge_power
  - sensor.<device>_forecast_pv_error
  - sensor.<device>_forecast_load_error

The exact entity IDs are shown in the integration device. This graph records what PowerManager predicted at each poll and what actually happened afterward; the forecast profile attribute exposes the next 24 hours of future PV/load points used by the planner. The profile is deliberately bounded so Home Assistant Recorder can retain the attributes. Load estimation prefers recent complete days with the same weekday and falls back to recent complete days when Recorder lacks enough matching history. The displayed load forecast follows the averaged hourly shape of those days; the planner still uses the independently integrated remaining kWh total.

Instead of supplying an expected-load forecast entity, PowerManager can estimate the remaining load until local midnight from the selected whole-home load-power entity. It averages the same remainder of each of the configured number of complete prior days (seven by default) using local Recorder history. The estimate is withheld if any required day is incomplete, stale, or invalid.

powermanager commission performs a read-only preflight of the Sunny Island's external-setpoint and fallback configuration. It never sends a setpoint or changes an inverter parameter.

speedwire-capture passively prints validated SMA multicast frames for protocol analysis; it does not transmit packets or decode unverified measurement offsets.

Speedwire capture troubleshooting

If the Home Manager is transmitting but capture is empty, check the host firewall. UFW commonly blocks SMA multicast UDP even when the switch has IGMP snooping disabled. For a host whose LAN interface is enp0s13f0u1u4, allow only the Home Manager sender and Speedwire port:

sudo ufw allow in on enp0s13f0u1u4 from 10.0.1.192 to any port 9522 proto udp

Adjust the interface and Home Manager address for your network. The rule is optional when the host firewall is disabled; do not broadly expose UDP/9522 to untrusted networks.

For a remote Home Assistant host, scripts/speedwire-relay.py can run on a LAN-side machine and forward validated frames over unicast UDP:

python3 scripts/speedwire-relay.py --destination-host 10.0.12.2

The receiving listener must be configured for the chosen unicast port (default 19522). The relay is intentionally raw and read-only: it never sends anything to the SMA multicast group.

Speedwire protocol status

A live capture from a Sunny Home Manager on the local LAN produced 608-byte telegrams from 10.0.1.192 to 239.12.255.254:9522. The payload contains SMA's documented 0x6069 energy-meter protocol. The captured fixture now validates telegram framing and individual raw records. Semantic mapping of those records to grid or PV values remains pending independent verification.

Supported backend status

Backend Status
SMA Sunny Island Modbus TCP Read-only identity and battery measurements verified against an SI4.4M-12
SMA Sunny Home Manager / Speedwire Planned passive telemetry provider
Active battery control Not implemented

Continuous integration runs unit tests, Ruff, HACS validation, and Home Assistant hassfest. Hardware commissioning is deliberately not a CI task and remains a supervised, read-only-first field procedure.