mirror of
https://github.com/Akkudoktor-EOS/EOS.git
synced 2026-10-13 09:31:56 +00:00
feat(pvforecast): add calibrated local Akkudoktor backend
Port local PV modeling and outage calibration from feature commitsf976335,6dc58c3andfaed0fdby Andreas. Keep PVForecastAkkudoktor identity and remote default, adapt to async storage, and migrate legacy provider settings.
This commit is contained in:
@@ -197,8 +197,26 @@ def migrate_config_data(config_data: Dict[str, Any]) -> "SettingsEOSDefaults":
|
||||
skipped_paths = []
|
||||
|
||||
from akkudoktoreos.config.config import SettingsEOSDefaults
|
||||
from akkudoktoreos.prediction.pvforecastakkudoktorlocal import (
|
||||
PVForecastAkkudoktorLocalCommonSettings,
|
||||
normalize_akkudoktor_settings,
|
||||
)
|
||||
|
||||
# Normalize this provider before the generic field-by-field transfer. Validate
|
||||
# coupled bounds together so a transient intermediate default cannot lose them.
|
||||
config_data = dict(config_data)
|
||||
pv_settings = normalize_akkudoktor_settings(config_data.get("pvforecast"))
|
||||
if isinstance(pv_settings, dict):
|
||||
config_data["pvforecast"] = pv_settings
|
||||
|
||||
new_config = SettingsEOSDefaults()
|
||||
if isinstance(pv_settings, dict) and "akkudoktor" in pv_settings:
|
||||
local_settings = PVForecastAkkudoktorLocalCommonSettings.model_validate(
|
||||
pv_settings["akkudoktor"]
|
||||
)
|
||||
new_config.set_nested_value("pvforecast/akkudoktor", local_settings)
|
||||
migrated_source_paths.add("pvforecast/akkudoktor")
|
||||
mapped_count += 1
|
||||
|
||||
# 1) Apply explicit migration map
|
||||
for old_path, mapping in MIGRATION_MAP.items():
|
||||
|
||||
@@ -7,6 +7,10 @@ from pydantic import Field, computed_field, field_validator, model_validator
|
||||
from akkudoktoreos.config.configabc import SettingsBaseModel
|
||||
from akkudoktoreos.core.coreabc import get_prediction
|
||||
from akkudoktoreos.prediction.pvforecastabc import PVForecastProvider
|
||||
from akkudoktoreos.prediction.pvforecastakkudoktorlocal import (
|
||||
PVForecastAkkudoktorLocalCommonSettings,
|
||||
normalize_akkudoktor_settings,
|
||||
)
|
||||
from akkudoktoreos.prediction.pvforecastforecastsolar import (
|
||||
PVForecastForecastSolarCommonSettings,
|
||||
)
|
||||
@@ -202,6 +206,13 @@ class PVForecastCommonSettings(SettingsBaseModel):
|
||||
},
|
||||
)
|
||||
|
||||
akkudoktor: PVForecastAkkudoktorLocalCommonSettings = Field(
|
||||
default_factory=PVForecastAkkudoktorLocalCommonSettings,
|
||||
json_schema_extra={
|
||||
"description": "Akkudoktor forecast backend and local calibration settings",
|
||||
},
|
||||
)
|
||||
|
||||
pvforecastimport: PVForecastImportCommonSettings = Field(
|
||||
default_factory=PVForecastImportCommonSettings,
|
||||
json_schema_extra={"description": "PV forecast import provider settings"},
|
||||
@@ -300,6 +311,12 @@ class PVForecastCommonSettings(SettingsBaseModel):
|
||||
return pvforecast_provider_ids()
|
||||
|
||||
# Validators
|
||||
@model_validator(mode="before")
|
||||
@classmethod
|
||||
def migrate_local_akkudoktor_settings(cls, data: Any) -> Any:
|
||||
"""Accept the feature branch's local backend configuration."""
|
||||
return normalize_akkudoktor_settings(data)
|
||||
|
||||
@field_validator("provider", mode="after")
|
||||
@classmethod
|
||||
def validate_provider(cls, value: Optional[str]) -> Optional[str]:
|
||||
|
||||
@@ -87,10 +87,8 @@ from pydantic import Field, ValidationError, computed_field, field_validator
|
||||
from akkudoktoreos.core.cache import cache_in_file
|
||||
from akkudoktoreos.core.pydantic import PydanticBaseModel
|
||||
from akkudoktoreos.prediction.pvforecast import PVForecastPlaneSetting
|
||||
from akkudoktoreos.prediction.pvforecastabc import (
|
||||
PVForecastDataRecord,
|
||||
PVForecastProvider,
|
||||
)
|
||||
from akkudoktoreos.prediction.pvforecastabc import PVForecastDataRecord
|
||||
from akkudoktoreos.prediction.pvforecastakkudoktorlocal import PVForecastAkkudoktorLocal
|
||||
from akkudoktoreos.utils.datetimeutil import compare_datetimes, to_datetime
|
||||
|
||||
|
||||
@@ -188,7 +186,7 @@ class PVForecastAkkudoktorDataRecord(PVForecastDataRecord):
|
||||
return self.pvforecast_ac_power
|
||||
|
||||
|
||||
class PVForecastAkkudoktor(PVForecastProvider[PVForecastAkkudoktorDataRecord]):
|
||||
class PVForecastAkkudoktor(PVForecastAkkudoktorLocal[PVForecastAkkudoktorDataRecord]):
|
||||
"""Fetch and process PV forecast data from akkudoktor.net.
|
||||
|
||||
PVForecastAkkudoktor is a singleton-based class that retrieves weather forecast data
|
||||
@@ -385,6 +383,10 @@ class PVForecastAkkudoktor(PVForecastProvider[PVForecastAkkudoktorDataRecord]):
|
||||
# Get Akkudoktor PV Forecast data for the given configuration.
|
||||
if force_update:
|
||||
logger.info("[PVForecastAkkudoktor] force update.")
|
||||
if self.config.pvforecast.akkudoktor.backend == "local":
|
||||
await self._update_local_data(force_update=force_update)
|
||||
return
|
||||
|
||||
akkudoktor_data = self._request_forecast(force_update=force_update) # type: ignore
|
||||
|
||||
# Timezone of the PV system
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user