feat: add PVForecastHomeAssistant provider (#1258)

* feat: add PVForecastHomeAssistant provider

Reads a PV forecast time series directly from a Home Assistant entity
attribute (matching the {"forecast": [{"datetime", "watts"}]} shape
already exposed by common HA PV forecast integrations, e.g. Helios
Forecast and Solcast) and feeds it into pvforecast_ac_power, following
the same self-polling provider pattern as PVForecastVrm.

Closes #1232.

* fix: use MagicMock instead of monkeypatched Response for mypy

requests.Response().json is a typed bound method; reassigning it to a
lambda fails mypy's method-assign check. Use MagicMock(spec=...) instead,
which mocks the response without fighting its static type.

* fix: address PR review on PVForecastHomeAssistant provider

Fixes two issues raised in review on PR #1258:
- _update_data() left stale pvforecast_ac_power values in place when a
  refreshed forecast was empty or shorter than a previous one; it now
  clears the active forecast window before writing and raises instead
  of silently no-op'ing when the response has no usable data.
- pvforecast.homeassistant.entity_id used a "select" widget with no
  manual-entry fallback in EOSdash, leaving it unusable in standalone
  mode where the entity list can't be resolved without SUPERVISOR_TOKEN;
  switched to a plain text field.

Also fills in the config docs and openapi.json for the new
pvforecast.homeassistant.* fields, which were missing from the
original commit.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix: preserve retained forecast history when clearing stale entries

The previous fix cleared pvforecast_ac_power from start-of-day, but
PredictionProvider deliberately retains historical records back to
keep_datetime (prediction.historic_hours). Since Home Assistant
forecasts are future-only, that clear wiped out retained history
between midnight and the EMS start on every refresh.

Narrow the clear to [ems_start_datetime, end_datetime) - the actual
active forecast window, DST-adjusted - instead of the day boundary.

Addresses review feedback from @NormannK on PR #1258.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

---------

Co-authored-by: Mathias <mathias@Mathiass-MacBook-Air.local>
Co-authored-by: Mathias <mathias@Mathiass-Air.localdomain>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
matjhgc534z67umb
2026-09-03 00:15:40 +02:00
committed by GitHub
co-authored by Claude Sonnet 5 Mathias Mathias
parent ba76087db9
commit 7bafc8d02d
10 changed files with 600 additions and 7 deletions
@@ -55,6 +55,7 @@ from akkudoktoreos.prediction.loadvrm import LoadVrm
from akkudoktoreos.prediction.predictionabc import PredictionContainer
from akkudoktoreos.prediction.pvforecastakkudoktor import PVForecastAkkudoktor
from akkudoktoreos.prediction.pvforecastforecastsolar import PVForecastForecastSolar
from akkudoktoreos.prediction.pvforecasthomeassistant import PVForecastHomeAssistant
from akkudoktoreos.prediction.pvforecastimport import PVForecastImport
from akkudoktoreos.prediction.pvforecastpvlib import PVForecastPVLib
from akkudoktoreos.prediction.pvforecastpvnode import PVForecastPVNode
@@ -106,6 +107,7 @@ loadforecast_vrm = LoadVrm()
loadforecast_import = LoadImport()
pvforecast_akkudoktor = PVForecastAkkudoktor()
pvforecast_vrm = PVForecastVrm()
pvforecast_homeassistant = PVForecastHomeAssistant()
pvforecast_pvlib = PVForecastPVLib()
pvforecast_pvnode = PVForecastPVNode()
pvforecast_forecastsolar = PVForecastForecastSolar()
@@ -177,6 +179,7 @@ def prediction_providers() -> list[
loadforecast_import, \
pvforecast_akkudoktor, \
pvforecast_vrm, \
pvforecast_homeassistant, \
pvforecast_pvlib, \
pvforecast_pvnode, \
pvforecast_forecastsolar, \
@@ -217,6 +220,7 @@ def prediction_providers() -> list[
loadforecast_vrm,
pvforecast_akkudoktor,
pvforecast_forecastsolar,
pvforecast_homeassistant,
pvforecast_import,
pvforecast_pvlib,
pvforecast_pvnode,
@@ -251,6 +255,7 @@ class Prediction(PredictionContainer):
LoadVrm,
PVForecastAkkudoktor,
PVForecastForecastSolar,
PVForecastHomeAssistant,
PVForecastImport,
PVForecastPVLib,
PVForecastPVNode,