mirror of
https://github.com/Akkudoktor-EOS/EOS.git
synced 2026-09-03 14:36:37 +00:00
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:
co-authored by
Claude Sonnet 5
Mathias
Mathias
parent
ba76087db9
commit
7bafc8d02d
@@ -29,6 +29,7 @@ from akkudoktoreos.prediction.prediction import (
|
||||
)
|
||||
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
|
||||
@@ -75,6 +76,7 @@ def forecast_providers():
|
||||
LoadVrm(),
|
||||
PVForecastAkkudoktor(),
|
||||
PVForecastForecastSolar(),
|
||||
PVForecastHomeAssistant(),
|
||||
PVForecastImport(),
|
||||
PVForecastPVLib(),
|
||||
PVForecastPVNode(),
|
||||
@@ -137,11 +139,12 @@ def test_provider_sequence(prediction):
|
||||
assert isinstance(prediction.providers[22], LoadVrm)
|
||||
assert isinstance(prediction.providers[23], PVForecastAkkudoktor)
|
||||
assert isinstance(prediction.providers[24], PVForecastForecastSolar)
|
||||
assert isinstance(prediction.providers[25], PVForecastImport)
|
||||
assert isinstance(prediction.providers[26], PVForecastPVLib)
|
||||
assert isinstance(prediction.providers[27], PVForecastPVNode)
|
||||
assert isinstance(prediction.providers[28], PVForecastSolcast)
|
||||
assert isinstance(prediction.providers[29], PVForecastVrm)
|
||||
assert isinstance(prediction.providers[25], PVForecastHomeAssistant)
|
||||
assert isinstance(prediction.providers[26], PVForecastImport)
|
||||
assert isinstance(prediction.providers[27], PVForecastPVLib)
|
||||
assert isinstance(prediction.providers[28], PVForecastPVNode)
|
||||
assert isinstance(prediction.providers[29], PVForecastSolcast)
|
||||
assert isinstance(prediction.providers[30], PVForecastVrm)
|
||||
|
||||
|
||||
def test_provider_by_id(prediction, forecast_providers):
|
||||
@@ -175,6 +178,7 @@ def test_prediction_repr(prediction):
|
||||
assert "LoadVrm" in result
|
||||
assert "PVForecastAkkudoktor" in result
|
||||
assert "PVForecastForecastSolar" in result
|
||||
assert "PVForecastHomeAssistant" in result
|
||||
assert "PVForecastImport" in result
|
||||
assert "PVForecastPVLib" in result
|
||||
assert "PVForecastPVNode" in result
|
||||
|
||||
Reference in New Issue
Block a user