mirror of
https://github.com/Akkudoktor-EOS/EOS.git
synced 2026-07-12 21:08:13 +00:00
Add PVForecastForecastSolar, a PV forecast provider for the free Forecast.Solar API (https://forecast.solar), giving operators a no-account forecast source in addition to Akkudoktor, VRM, Import and pvnode. An optional API key raises the rate limit. result.watts is the instantaneous AC power per timestamp, fed directly as pvforecast_ac_power. Plants with several roof planes issue one request per plane (Forecast.Solar is single-plane) and the powers are summed per timestamp. Forecast.Solar azimuth (-180=N..0=S..90=W) is converted from EOS surface_azimuth (north=0..south=180); local wall-clock timestamps are resolved via the response timezone before resampling. Registered in pvforecast.py and prediction.py. Adds tests for timezone resolution, azimuth conversion, multi-plane summation and HTTP-error handling.
199 lines
6.6 KiB
Python
199 lines
6.6 KiB
Python
"""Prediction module for weather and photovoltaic forecasts.
|
|
|
|
This module provides a `Prediction` class to manage and update a sequence of
|
|
prediction providers. The `Prediction` class is a subclass of `PredictionContainer`
|
|
and is initialized with a set of forecast providers, such as `WeatherBrightSky`,
|
|
`WeatherClearOutside`, and `PVForecastAkkudoktor`.
|
|
|
|
Usage:
|
|
Instantiate the `Prediction` class with the required providers, maintaining
|
|
the necessary order. Then call the `update` method to refresh forecasts from
|
|
all providers in sequence.
|
|
|
|
Example:
|
|
# Create singleton prediction instance with prediction providers
|
|
from akkudoktoreos.prediction.prediction import prediction
|
|
|
|
prediction.update_data()
|
|
print("Prediction:", prediction)
|
|
|
|
Classes:
|
|
Prediction: Manages a list of forecast providers to fetch and update predictions.
|
|
|
|
Attributes:
|
|
pvforecast_akkudoktor (PVForecastAkkudoktor): Forecast provider for photovoltaic data.
|
|
weather_brightsky (WeatherBrightSky): Weather forecast provider using BrightSky.
|
|
weather_clearoutside (WeatherClearOutside): Weather forecast provider using ClearOutside.
|
|
"""
|
|
|
|
from typing import Optional, Union
|
|
|
|
from pydantic import Field
|
|
|
|
from akkudoktoreos.config.configabc import SettingsBaseModel
|
|
from akkudoktoreos.prediction.elecpriceakkudoktor import ElecPriceAkkudoktor
|
|
from akkudoktoreos.prediction.elecpriceenergycharts import ElecPriceEnergyCharts
|
|
from akkudoktoreos.prediction.elecpricefixed import ElecPriceFixed
|
|
from akkudoktoreos.prediction.elecpriceimport import ElecPriceImport
|
|
from akkudoktoreos.prediction.feedintarifffixed import FeedInTariffFixed
|
|
from akkudoktoreos.prediction.feedintariffimport import FeedInTariffImport
|
|
from akkudoktoreos.prediction.loadakkudoktor import (
|
|
LoadAkkudoktor,
|
|
LoadAkkudoktorAdjusted,
|
|
)
|
|
from akkudoktoreos.prediction.loadimport import LoadImport
|
|
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.pvforecastimport import PVForecastImport
|
|
from akkudoktoreos.prediction.pvforecastpvnode import PVForecastPVNode
|
|
from akkudoktoreos.prediction.pvforecastvrm import PVForecastVrm
|
|
from akkudoktoreos.prediction.weatherbrightsky import WeatherBrightSky
|
|
from akkudoktoreos.prediction.weatherclearoutside import WeatherClearOutside
|
|
from akkudoktoreos.prediction.weatherimport import WeatherImport
|
|
from akkudoktoreos.prediction.weatheropenmeteo import WeatherOpenMeteo
|
|
|
|
|
|
class PredictionCommonSettings(SettingsBaseModel):
|
|
"""General Prediction Configuration."""
|
|
|
|
hours: Optional[int] = Field(
|
|
default=48,
|
|
ge=0,
|
|
json_schema_extra={"description": "Number of hours into the future for predictions"},
|
|
)
|
|
|
|
historic_hours: Optional[int] = Field(
|
|
default=48,
|
|
ge=0,
|
|
json_schema_extra={
|
|
"description": "Number of hours into the past for historical predictions data"
|
|
},
|
|
)
|
|
|
|
|
|
# Initialize forecast providers, all are singletons.
|
|
elecprice_akkudoktor = ElecPriceAkkudoktor()
|
|
elecprice_energy_charts = ElecPriceEnergyCharts()
|
|
elecprice_fixed = ElecPriceFixed()
|
|
elecprice_import = ElecPriceImport()
|
|
feedintariff_fixed = FeedInTariffFixed()
|
|
feedintariff_import = FeedInTariffImport()
|
|
loadforecast_akkudoktor = LoadAkkudoktor()
|
|
loadforecast_akkudoktor_adjusted = LoadAkkudoktorAdjusted()
|
|
loadforecast_vrm = LoadVrm()
|
|
loadforecast_import = LoadImport()
|
|
pvforecast_akkudoktor = PVForecastAkkudoktor()
|
|
pvforecast_vrm = PVForecastVrm()
|
|
pvforecast_pvnode = PVForecastPVNode()
|
|
pvforecast_forecastsolar = PVForecastForecastSolar()
|
|
pvforecast_import = PVForecastImport()
|
|
weather_brightsky = WeatherBrightSky()
|
|
weather_clearoutside = WeatherClearOutside()
|
|
weather_openmeteo = WeatherOpenMeteo()
|
|
weather_import = WeatherImport()
|
|
|
|
|
|
def prediction_providers() -> list[
|
|
Union[
|
|
ElecPriceAkkudoktor,
|
|
ElecPriceEnergyCharts,
|
|
ElecPriceFixed,
|
|
ElecPriceImport,
|
|
FeedInTariffFixed,
|
|
FeedInTariffImport,
|
|
LoadAkkudoktor,
|
|
LoadAkkudoktorAdjusted,
|
|
LoadVrm,
|
|
LoadImport,
|
|
PVForecastAkkudoktor,
|
|
PVForecastVrm,
|
|
PVForecastPVNode,
|
|
PVForecastForecastSolar,
|
|
PVForecastImport,
|
|
WeatherBrightSky,
|
|
WeatherClearOutside,
|
|
WeatherOpenMeteo,
|
|
WeatherImport,
|
|
]
|
|
]:
|
|
"""Return list of prediction providers.
|
|
|
|
Factory for prediction container.
|
|
"""
|
|
global \
|
|
elecprice_akkudoktor, \
|
|
elecprice_energy_charts, \
|
|
elecprice_fixed, \
|
|
elecprice_import, \
|
|
feedintariff_fixed, \
|
|
feedintariff_import, \
|
|
loadforecast_akkudoktor, \
|
|
loadforecast_akkudoktor_adjusted, \
|
|
loadforecast_vrm, \
|
|
loadforecast_import, \
|
|
pvforecast_akkudoktor, \
|
|
pvforecast_vrm, \
|
|
pvforecast_pvnode, \
|
|
pvforecast_forecastsolar, \
|
|
pvforecast_import, \
|
|
weather_brightsky, \
|
|
weather_clearoutside, \
|
|
weather_openmeteo, \
|
|
weather_import
|
|
|
|
# Care for provider sequence as providers may rely on others to be updated before.
|
|
return [
|
|
elecprice_akkudoktor,
|
|
elecprice_energy_charts,
|
|
elecprice_fixed,
|
|
elecprice_import,
|
|
feedintariff_fixed,
|
|
feedintariff_import,
|
|
loadforecast_akkudoktor,
|
|
loadforecast_akkudoktor_adjusted,
|
|
loadforecast_vrm,
|
|
loadforecast_import,
|
|
pvforecast_akkudoktor,
|
|
pvforecast_vrm,
|
|
pvforecast_pvnode,
|
|
pvforecast_forecastsolar,
|
|
pvforecast_import,
|
|
weather_brightsky,
|
|
weather_clearoutside,
|
|
weather_openmeteo,
|
|
weather_import,
|
|
]
|
|
|
|
|
|
class Prediction(PredictionContainer):
|
|
"""Prediction container to manage multiple prediction providers."""
|
|
|
|
providers: list[
|
|
Union[
|
|
ElecPriceAkkudoktor,
|
|
ElecPriceEnergyCharts,
|
|
ElecPriceFixed,
|
|
ElecPriceImport,
|
|
FeedInTariffFixed,
|
|
FeedInTariffImport,
|
|
LoadAkkudoktor,
|
|
LoadAkkudoktorAdjusted,
|
|
LoadVrm,
|
|
LoadImport,
|
|
PVForecastAkkudoktor,
|
|
PVForecastVrm,
|
|
PVForecastPVNode,
|
|
PVForecastForecastSolar,
|
|
PVForecastImport,
|
|
WeatherBrightSky,
|
|
WeatherClearOutside,
|
|
WeatherOpenMeteo,
|
|
WeatherImport,
|
|
]
|
|
] = Field(
|
|
default_factory=prediction_providers,
|
|
json_schema_extra={"description": "List of prediction providers"},
|
|
)
|