mirror of
https://github.com/Akkudoktor-EOS/EOS.git
synced 2026-08-25 17:56:37 +00:00
feat: add pvlib pv forecast provider (#1214)
Add a PV forecast provider that calculates the forecast using a PVLib system model and weather forecast from the EOS weather forecast provider. Additional module and inverter models can be easily added as the database is build from PVLib and SAM databases and a bundled csv file. The module model and inververt model names are provided by new endpoints to be used in configuration. The provider is based on the fantastic work of EMHASS. See https://github.com/davidusb-geek/emhass/blob/master/src/emhass/forecast.py A short description of the provider is added to the documentation. Besides the new features there are the fixes and improvements: * feat: improve EOSdash config page * fix: kex_to_series for start_datetime Make key_to_series always start the series at start_datetime. * fix: default provider for GENETIC and GENETIC0 optimization To make the default less dependent on internet servers (with API changes and availability issues) the default for PVForecast is set to PVForecastPVLib and for ElecPrice to ElecPriceFixed. The default weather provider is changed to OpenMeteo. * fix: EOSdash display resampled prediction values Make EOSdash display resampled prediction values where resampling fits to the prediction value type. Use bar width that fits to 15 minutes value samples. * chore: add a UI hints system to EOSdash The UI hints system eases the definition of forms for configuration items. There are also forms for items in maps and lists. These forms allow to add and delete items to/ from maps and lists. The forms ensure that all required fields of newly added items are filled. * chore: Create an enum for valid optimization algorithms * chore. Make config also provide the available energy management modes. Used for configuration hints. * chore: Randomize default device id in configuration Signed-off-by: Bobby Noelte <b0661n0e17e@gmail.com>
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
|
||||
import bz2
|
||||
import hashlib
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import pickle
|
||||
import signal
|
||||
import subprocess
|
||||
import sys
|
||||
@@ -14,6 +17,7 @@ from pathlib import Path
|
||||
from typing import Generator, Optional, Union
|
||||
from unittest.mock import PropertyMock, patch
|
||||
|
||||
import pandas as pd
|
||||
import pendulum
|
||||
import psutil
|
||||
import pytest
|
||||
@@ -176,6 +180,74 @@ def cfg_non_existent(request):
|
||||
# ------------------------------------
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def cec_databases_data() -> tuple[pd.DataFrame, pd.DataFrame]:
|
||||
"""Load CEC test databases once per test session."""
|
||||
DIR_TESTDATA = Path(__file__).parent / "testdata" / "pvforecastpvlib"
|
||||
FILE_TESTDATA_CEC_INVERTERS_PBZ2 = DIR_TESTDATA / "cec_inverters.pbz2"
|
||||
FILE_TESTDATA_CEC_MODULES_PBZ2 = DIR_TESTDATA / "cec_modules.pbz2"
|
||||
|
||||
with bz2.BZ2File(FILE_TESTDATA_CEC_MODULES_PBZ2, "rb") as f:
|
||||
modules: pd.DataFrame = pickle.load(f)
|
||||
with bz2.BZ2File(FILE_TESTDATA_CEC_INVERTERS_PBZ2, "rb") as f:
|
||||
inverters: pd.DataFrame = pickle.load(f)
|
||||
|
||||
return modules, inverters
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def cec_databases(monkeypatch, cec_databases_data) -> tuple[pd.DataFrame, pd.DataFrame]:
|
||||
"""Short-circuit CEC database access for every test (per-test patch, session-cached data).
|
||||
|
||||
Config requests the database in PVForecastPVLibCommonSettings by a computed_field.
|
||||
|
||||
To undo this fixture in a specific class do:
|
||||
@pytest.fixture(autouse=True)
|
||||
def cec_databases(self):
|
||||
yield None
|
||||
"""
|
||||
modules, inverters = cec_databases_data
|
||||
|
||||
def fake_update_cec_database() -> None:
|
||||
#print(f"_update_cec_database faked")
|
||||
pass
|
||||
|
||||
def fake_load_cec_database(path: Path) -> pd.DataFrame:
|
||||
#print(f"_loadcec_database faked")
|
||||
if "inverter" in path.name:
|
||||
return inverters
|
||||
if "module" in path.name:
|
||||
return modules
|
||||
raise ValueError(f"Unexpected CEC database path in test: {path}")
|
||||
|
||||
def fake_cec_inverters() -> pd.DataFrame:
|
||||
#print(f"_cec_inverters faked")
|
||||
return inverters
|
||||
|
||||
def fake_cec_modules() -> pd.DataFrame:
|
||||
#print(f"_cec_modules faked")
|
||||
return modules
|
||||
|
||||
monkeypatch.setattr(
|
||||
"akkudoktoreos.prediction.pvforecastpvlib._update_cec_database",
|
||||
fake_update_cec_database,
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
"akkudoktoreos.prediction.pvforecastpvlib._load_cec_database",
|
||||
fake_load_cec_database,
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
"akkudoktoreos.prediction.pvforecastpvlib._cec_inverters",
|
||||
fake_cec_inverters,
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
"akkudoktoreos.prediction.pvforecastpvlib._cec_modules",
|
||||
fake_cec_modules,
|
||||
)
|
||||
|
||||
return modules, inverters
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def config_default_dirs(tmpdir):
|
||||
"""Fixture that provides a list of directories to be used as config dir."""
|
||||
@@ -234,6 +306,7 @@ def user_data_dir(config_default_dirs):
|
||||
|
||||
@pytest.fixture
|
||||
def config_eos_factory(
|
||||
cec_databases,
|
||||
disable_debug_logging,
|
||||
user_config_dir,
|
||||
user_data_dir,
|
||||
|
||||
@@ -17,6 +17,7 @@ from akkudoktoreos.core.emsettings import EnergyManagementMode
|
||||
from akkudoktoreos.optimization.genetic0.genetic0params import (
|
||||
Genetic0OptimizationParameters,
|
||||
)
|
||||
from akkudoktoreos.optimization.optimization import OptimizationAlgorithm
|
||||
from akkudoktoreos.utils.datetimeutil import to_datetime
|
||||
|
||||
config_eos = get_config()
|
||||
@@ -431,7 +432,7 @@ def run_optimization(
|
||||
ems_eos.run(
|
||||
start_datetime=start_datetime,
|
||||
mode=EnergyManagementMode.OPTIMIZATION,
|
||||
algorithm="GENETIC0",
|
||||
algorithm=OptimizationAlgorithm.GENETIC0,
|
||||
genetic0_parameters=parameters,
|
||||
genetic0_generations=ngen,
|
||||
genetic0_seed=seed,
|
||||
|
||||
@@ -17,6 +17,7 @@ from akkudoktoreos.core.emsettings import EnergyManagementMode
|
||||
from akkudoktoreos.optimization.genetic.geneticparams import (
|
||||
GeneticOptimizationParameters,
|
||||
)
|
||||
from akkudoktoreos.optimization.optimization import OptimizationAlgorithm
|
||||
from akkudoktoreos.utils.datetimeutil import to_datetime
|
||||
|
||||
config_eos = get_config()
|
||||
@@ -432,6 +433,7 @@ def run_optimization(
|
||||
ems_eos.run(
|
||||
start_datetime=start_datetime,
|
||||
mode=EnergyManagementMode.OPTIMIZATION,
|
||||
algorithm=OptimizationAlgorithm.GENETIC,
|
||||
genetic_parameters=parameters,
|
||||
genetic_generations=ngen,
|
||||
genetic_seed=seed,
|
||||
|
||||
@@ -46,6 +46,16 @@ IGNORE_LOCATIONS = [
|
||||
# pathlib
|
||||
r"\.Path.*",
|
||||
|
||||
# PVLib
|
||||
r"\.pvlib.*",
|
||||
r"\.PVSystem.*",
|
||||
r"\.disc.*",
|
||||
r"\.Location.*",
|
||||
r"\.ModelChain.*",
|
||||
r"\.retrieve_sam.*",
|
||||
r"\.get_solarposition.*",
|
||||
r"\.TEMPERATURE_MODEL_PARAMETERS.*",
|
||||
|
||||
# MarkdownIt
|
||||
r"\.MarkdownIt.*",
|
||||
|
||||
|
||||
+45
-36
@@ -26,6 +26,7 @@ from akkudoktoreos.prediction.prediction import (
|
||||
from akkudoktoreos.prediction.pvforecastakkudoktor import PVForecastAkkudoktor
|
||||
from akkudoktoreos.prediction.pvforecastforecastsolar import PVForecastForecastSolar
|
||||
from akkudoktoreos.prediction.pvforecastimport import PVForecastImport
|
||||
from akkudoktoreos.prediction.pvforecastpvlib import PVForecastPVLib
|
||||
from akkudoktoreos.prediction.pvforecastpvnode import PVForecastPVNode
|
||||
from akkudoktoreos.prediction.pvforecastsolcast import PVForecastSolcast
|
||||
from akkudoktoreos.prediction.pvforecastvrm import PVForecastVrm
|
||||
@@ -45,6 +46,10 @@ def prediction():
|
||||
def forecast_providers():
|
||||
"""Fixture for singleton forecast provider instances."""
|
||||
return [
|
||||
WeatherBrightSky(),
|
||||
WeatherClearOutside(),
|
||||
WeatherImport(),
|
||||
WeatherOpenMeteo(),
|
||||
ElecPriceAkkudoktor(),
|
||||
ElecPriceEnergyCharts(),
|
||||
ElecPriceFixed(),
|
||||
@@ -58,18 +63,15 @@ def forecast_providers():
|
||||
FeedInTariffTibber(),
|
||||
LoadAkkudoktor(),
|
||||
LoadAkkudoktorAdjusted(),
|
||||
LoadVrm(),
|
||||
LoadImport(),
|
||||
LoadVrm(),
|
||||
PVForecastAkkudoktor(),
|
||||
PVForecastVrm(),
|
||||
PVForecastPVNode(),
|
||||
PVForecastForecastSolar(),
|
||||
PVForecastSolcast(),
|
||||
PVForecastImport(),
|
||||
WeatherBrightSky(),
|
||||
WeatherClearOutside(),
|
||||
WeatherOpenMeteo(),
|
||||
WeatherImport(),
|
||||
PVForecastPVLib(),
|
||||
PVForecastPVNode(),
|
||||
PVForecastSolcast(),
|
||||
PVForecastVrm(),
|
||||
]
|
||||
|
||||
|
||||
@@ -102,31 +104,32 @@ def test_initialization(prediction, forecast_providers):
|
||||
|
||||
def test_provider_sequence(prediction):
|
||||
"""Test the provider sequence is maintained in the Prediction instance."""
|
||||
assert isinstance(prediction.providers[0], ElecPriceAkkudoktor)
|
||||
assert isinstance(prediction.providers[1], ElecPriceEnergyCharts)
|
||||
assert isinstance(prediction.providers[2], ElecPriceFixed)
|
||||
assert isinstance(prediction.providers[3], ElecPriceImport)
|
||||
assert isinstance(prediction.providers[4], ElecPriceTibber)
|
||||
assert isinstance(prediction.providers[5], FeedInTariffAkkudoktor)
|
||||
assert isinstance(prediction.providers[6], FeedInTariffDvhubOnline)
|
||||
assert isinstance(prediction.providers[7], FeedInTariffEnergyCharts)
|
||||
assert isinstance(prediction.providers[8], FeedInTariffFixed)
|
||||
assert isinstance(prediction.providers[9], FeedInTariffImport)
|
||||
assert isinstance(prediction.providers[10], FeedInTariffTibber)
|
||||
assert isinstance(prediction.providers[11], LoadAkkudoktor)
|
||||
assert isinstance(prediction.providers[12], LoadAkkudoktorAdjusted)
|
||||
assert isinstance(prediction.providers[13], LoadVrm)
|
||||
assert isinstance(prediction.providers[14], LoadImport)
|
||||
assert isinstance(prediction.providers[15], PVForecastAkkudoktor)
|
||||
assert isinstance(prediction.providers[16], PVForecastVrm)
|
||||
assert isinstance(prediction.providers[17], PVForecastPVNode)
|
||||
assert isinstance(prediction.providers[18], PVForecastForecastSolar)
|
||||
assert isinstance(prediction.providers[19], PVForecastSolcast)
|
||||
assert isinstance(prediction.providers[20], PVForecastImport)
|
||||
assert isinstance(prediction.providers[21], WeatherBrightSky)
|
||||
assert isinstance(prediction.providers[22], WeatherClearOutside)
|
||||
assert isinstance(prediction.providers[23], WeatherOpenMeteo)
|
||||
assert isinstance(prediction.providers[24], WeatherImport)
|
||||
assert isinstance(prediction.providers[0], WeatherBrightSky)
|
||||
assert isinstance(prediction.providers[1], WeatherClearOutside)
|
||||
assert isinstance(prediction.providers[2], WeatherImport)
|
||||
assert isinstance(prediction.providers[3], WeatherOpenMeteo)
|
||||
assert isinstance(prediction.providers[4], ElecPriceAkkudoktor)
|
||||
assert isinstance(prediction.providers[5], ElecPriceEnergyCharts)
|
||||
assert isinstance(prediction.providers[6], ElecPriceFixed)
|
||||
assert isinstance(prediction.providers[7], ElecPriceImport)
|
||||
assert isinstance(prediction.providers[8], ElecPriceTibber)
|
||||
assert isinstance(prediction.providers[9], FeedInTariffAkkudoktor)
|
||||
assert isinstance(prediction.providers[10], FeedInTariffDvhubOnline)
|
||||
assert isinstance(prediction.providers[11], FeedInTariffEnergyCharts)
|
||||
assert isinstance(prediction.providers[12], FeedInTariffFixed)
|
||||
assert isinstance(prediction.providers[13], FeedInTariffImport)
|
||||
assert isinstance(prediction.providers[14], FeedInTariffTibber)
|
||||
assert isinstance(prediction.providers[15], LoadAkkudoktor)
|
||||
assert isinstance(prediction.providers[16], LoadAkkudoktorAdjusted)
|
||||
assert isinstance(prediction.providers[17], LoadImport)
|
||||
assert isinstance(prediction.providers[18], LoadVrm)
|
||||
assert isinstance(prediction.providers[19], PVForecastAkkudoktor)
|
||||
assert isinstance(prediction.providers[20], PVForecastForecastSolar)
|
||||
assert isinstance(prediction.providers[21], PVForecastImport)
|
||||
assert isinstance(prediction.providers[22], PVForecastPVLib)
|
||||
assert isinstance(prediction.providers[23], PVForecastPVNode)
|
||||
assert isinstance(prediction.providers[24], PVForecastSolcast)
|
||||
assert isinstance(prediction.providers[25], PVForecastVrm)
|
||||
|
||||
|
||||
def test_provider_by_id(prediction, forecast_providers):
|
||||
@@ -145,20 +148,26 @@ def test_prediction_repr(prediction):
|
||||
assert "ElecPriceImport" in result
|
||||
assert "ElecPriceTibber" in result
|
||||
assert "FeedInTariffAkkudoktor" in result
|
||||
assert "FeedInTariffDvhubOnline" in result
|
||||
assert "FeedInTariffEnergyCharts" in result
|
||||
assert "FeedInTariffFixed" in result
|
||||
assert "FeedInTariffImport" in result
|
||||
assert "FeedInTariffTibber" in result
|
||||
assert "LoadAkkudoktor" in result
|
||||
assert "LoadVrm" in result
|
||||
assert "LoadAkkudoktorAdjusted" in result
|
||||
assert "LoadImport" in result
|
||||
assert "LoadVrm" in result
|
||||
assert "PVForecastAkkudoktor" in result
|
||||
assert "PVForecastVrm" in result
|
||||
assert "PVForecastForecastSolar" in result
|
||||
assert "PVForecastImport" in result
|
||||
assert "PVForecastPVLib" in result
|
||||
assert "PVForecastPVNode" in result
|
||||
assert "PVForecastSolcast" in result
|
||||
assert "PVForecastVrm" in result
|
||||
assert "WeatherBrightSky" in result
|
||||
assert "WeatherClearOutside" in result
|
||||
assert "WeatherOpenMeteo" in result
|
||||
assert "WeatherImport" in result
|
||||
assert "WeatherOpenMeteo" in result
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+3
-3
@@ -209,7 +209,7 @@
|
||||
| ac_to_dc_efficiency | `float` | `rw` | `1.0` | Efficiency of AC to DC conversion for grid-to-battery AC charging (0-1). Set to 0 to disable AC charging. Default 1.0 (no additional inverter loss). |
|
||||
| battery_id | `str | None` | `rw` | `None` | ID of battery controlled by this inverter. |
|
||||
| dc_to_ac_efficiency | `float` | `rw` | `1.0` | Efficiency of DC to AC conversion for battery discharging to AC load/grid (0-1). Default 1.0 (no additional inverter loss). |
|
||||
| device_id | `str` | `rw` | `<unknown>` | ID of device |
|
||||
| device_id | `str` | `rw` | `required` | ID of device |
|
||||
| max_ac_charge_power_w | `float | None` | `rw` | `None` | Maximum AC charging power in watts. null means no additional limit. Set to 0 to disable AC charging. |
|
||||
| max_power_w | `float | None` | `rw` | `None` | Maximum power [W]. |
|
||||
| measurement_keys | `list[str] | None` | `ro` | `N/A` | Measurement keys for the inverter stati that are measurements. |
|
||||
@@ -372,7 +372,7 @@ as a cohesive unit for scheduling and availability checking.
|
||||
| Name | Type | Read-Only | Default | Description |
|
||||
| ---- | ---- | --------- | ------- | ----------- |
|
||||
| consumption_wh | `int` | `rw` | `required` | Energy consumption [Wh]. |
|
||||
| device_id | `str` | `rw` | `<unknown>` | ID of device |
|
||||
| device_id | `str` | `rw` | `required` | ID of device |
|
||||
| duration_h | `int` | `rw` | `required` | Usage duration in hours [0 ... 24]. |
|
||||
| measurement_keys | `list[str] | None` | `ro` | `N/A` | Measurement keys for the home appliance stati that are measurements. |
|
||||
| time_windows | `akkudoktoreos.config.configabc.TimeWindowSequence | None` | `rw` | `None` | Sequence of allowed time windows. Defaults to optimization general time window. |
|
||||
@@ -454,7 +454,7 @@ as a cohesive unit for scheduling and availability checking.
|
||||
| capacity_wh | `int` | `rw` | `8000` | Capacity [Wh]. |
|
||||
| charge_rates | `list[float] | None` | `rw` | `[0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]` | Charge rates as factor of maximum charging power [0.00 ... 1.00]. None triggers fallback to default charge-rates. |
|
||||
| charging_efficiency | `float` | `rw` | `0.88` | Charging efficiency [0.01 ... 1.00]. |
|
||||
| device_id | `str` | `rw` | `<unknown>` | ID of device |
|
||||
| device_id | `str` | `rw` | `required` | ID of device |
|
||||
| discharging_efficiency | `float` | `rw` | `0.88` | Discharge efficiency [0.01 ... 1.00]. |
|
||||
| levelized_cost_of_storage_kwh | `float` | `rw` | `0.0` | Levelized cost of storage (LCOS), the average lifetime cost of delivering one kWh [amount/kWh]. |
|
||||
| max_charge_power_w | `float | None` | `rw` | `5000` | Maximum charging power [W]. |
|
||||
|
||||
+24
-2
@@ -8,13 +8,14 @@
|
||||
| Name | Environment Variable | Type | Read-Only | Default | Description |
|
||||
| ---- | -------------------- | ---- | --------- | ------- | ----------- |
|
||||
| interval | `EOS_EMS__INTERVAL` | `float` | `rw` | `300.0` | Intervall between EOS energy management runs [seconds]. |
|
||||
| mode | `EOS_EMS__MODE` | `<enum 'EnergyManagementMode'>` | `rw` | `required` | Energy management mode [DISABLED | OPTIMIZATION | PREDICTION]. |
|
||||
| mode | `EOS_EMS__MODE` | `<enum 'EnergyManagementMode'>` | `rw` | `required` | Energy management mode [DISABLED | PREDICTION | OPTIMIZATION]. Defaults to DISABLED. |
|
||||
| modes | | `list[str]` | `ro` | `N/A` | Available energy management modes. |
|
||||
| startup_delay | `EOS_EMS__STARTUP_DELAY` | `float` | `rw` | `5` | Startup delay in seconds for EOS energy management runs. |
|
||||
:::
|
||||
<!-- pyml enable line-length -->
|
||||
|
||||
<!-- pyml disable no-emphasis-as-heading -->
|
||||
**Example Input/Output**
|
||||
**Example Input**
|
||||
<!-- pyml enable no-emphasis-as-heading -->
|
||||
|
||||
<!-- pyml disable line-length -->
|
||||
@@ -28,3 +29,24 @@
|
||||
}
|
||||
```
|
||||
<!-- pyml enable line-length -->
|
||||
|
||||
<!-- pyml disable no-emphasis-as-heading -->
|
||||
**Example Output**
|
||||
<!-- pyml enable no-emphasis-as-heading -->
|
||||
|
||||
<!-- pyml disable line-length -->
|
||||
```json
|
||||
{
|
||||
"ems": {
|
||||
"startup_delay": 5.0,
|
||||
"interval": 300.0,
|
||||
"mode": "OPTIMIZATION",
|
||||
"modes": [
|
||||
"DISABLED",
|
||||
"PREDICTION",
|
||||
"OPTIMIZATION"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
<!-- pyml enable line-length -->
|
||||
|
||||
@@ -217,6 +217,7 @@
|
||||
"token": "your-token",
|
||||
"site_id": 12345
|
||||
},
|
||||
"pvlib": {},
|
||||
"pvnode": {
|
||||
"api_key": "",
|
||||
"site_id": null,
|
||||
|
||||
+2
-2
@@ -63,8 +63,8 @@
|
||||
"providers": [
|
||||
"LoadAkkudoktor",
|
||||
"LoadAkkudoktorAdjusted",
|
||||
"LoadVrm",
|
||||
"LoadImport"
|
||||
"LoadImport",
|
||||
"LoadVrm"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
|
||||
| Name | Environment Variable | Type | Read-Only | Default | Description |
|
||||
| ---- | -------------------- | ---- | --------- | ------- | ----------- |
|
||||
| algorithm | `EOS_OPTIMIZATION__ALGORITHM` | `str` | `rw` | `GENETIC` | The optimization algorithm. Defaults to GENETIC |
|
||||
| algorithm | `EOS_OPTIMIZATION__ALGORITHM` | `<enum 'OptimizationAlgorithm'>` | `rw` | `required` | Optimization algorithm [GENETIC | GENETIC0]. Defaults to GENETIC. |
|
||||
| algorithms | | `list[str]` | `ro` | `N/A` | Available optimization algorithms. |
|
||||
| genetic | `EOS_OPTIMIZATION__GENETIC` | `GeneticCommonSettings` | `rw` | `required` | GENETIC optimization algorithm configuration. |
|
||||
| genetic0 | `EOS_OPTIMIZATION__GENETIC0` | `Genetic0CommonSettings` | `rw` | `required` | GENETIC0 optimization algorithm configuration. |
|
||||
|
||||
+36
-6
@@ -18,6 +18,7 @@
|
||||
| provider | `EOS_PVFORECAST__PROVIDER` | `str | None` | `rw` | `None` | PVForecast provider id of provider to be used. |
|
||||
| providers | | `list[str]` | `ro` | `N/A` | Available PVForecast provider ids. |
|
||||
| pvforecastimport | `EOS_PVFORECAST__PVFORECASTIMPORT` | `PVForecastImportCommonSettings` | `rw` | `required` | PV forecast import provider settings |
|
||||
| pvlib | `EOS_PVFORECAST__PVLIB` | `PVForecastPVLibCommonSettings` | `rw` | `required` | PVLib provider settings |
|
||||
| pvnode | `EOS_PVFORECAST__PVNODE` | `PVForecastPVNodeCommonSettings` | `rw` | `required` | PVNode provider settings |
|
||||
| solcast | `EOS_PVFORECAST__SOLCAST` | `PVForecastSolcastCommonSettings` | `rw` | `required` | Solcast provider settings |
|
||||
| vrm | `EOS_PVFORECAST__VRM` | `PVForecastVrmCommonSettings` | `rw` | `required` | Victron Remote Management (VRM) provider settings |
|
||||
@@ -41,6 +42,7 @@
|
||||
"token": "your-token",
|
||||
"site_id": 12345
|
||||
},
|
||||
"pvlib": {},
|
||||
"pvnode": {
|
||||
"api_key": "",
|
||||
"site_id": null,
|
||||
@@ -122,6 +124,7 @@
|
||||
"token": "your-token",
|
||||
"site_id": 12345
|
||||
},
|
||||
"pvlib": {},
|
||||
"pvnode": {
|
||||
"api_key": "",
|
||||
"site_id": null,
|
||||
@@ -183,11 +186,12 @@
|
||||
"max_planes": 1,
|
||||
"providers": [
|
||||
"PVForecastAkkudoktor",
|
||||
"PVForecastVrm",
|
||||
"PVForecastPVNode",
|
||||
"PVForecastForecastSolar",
|
||||
"PVForecastImport",
|
||||
"PVForecastPVLib",
|
||||
"PVForecastPVNode",
|
||||
"PVForecastSolcast",
|
||||
"PVForecastImport"
|
||||
"PVForecastVrm"
|
||||
],
|
||||
"planes_peakpower": [
|
||||
5.0,
|
||||
@@ -317,6 +321,32 @@
|
||||
```
|
||||
<!-- pyml enable line-length -->
|
||||
|
||||
### Common settings for pvforecast data calculation with PVLib
|
||||
|
||||
<!-- pyml disable line-length -->
|
||||
:::{table} pvforecast::pvlib
|
||||
:widths: 10 10 5 5 30
|
||||
:align: left
|
||||
|
||||
| Name | Type | Read-Only | Default | Description |
|
||||
| ---- | ---- | --------- | ------- | ----------- |
|
||||
:::
|
||||
<!-- pyml enable line-length -->
|
||||
|
||||
<!-- pyml disable no-emphasis-as-heading -->
|
||||
**Example Input/Output**
|
||||
<!-- pyml enable no-emphasis-as-heading -->
|
||||
|
||||
<!-- pyml disable line-length -->
|
||||
```json
|
||||
{
|
||||
"pvforecast": {
|
||||
"pvlib": {}
|
||||
}
|
||||
}
|
||||
```
|
||||
<!-- pyml enable line-length -->
|
||||
|
||||
### Common settings for pvforecast data import from file or JSON string
|
||||
|
||||
<!-- pyml disable line-length -->
|
||||
@@ -357,13 +387,13 @@
|
||||
|
||||
| Name | Type | Read-Only | Default | Description |
|
||||
| ---- | ---- | --------- | ------- | ----------- |
|
||||
| albedo | `float | None` | `rw` | `None` | Proportion of the light hitting the ground that it reflects back. |
|
||||
| albedo | `float | None` | `rw` | `0.2` | Proportion of the light hitting the ground that it reflects back. |
|
||||
| inverter_model | `str | None` | `rw` | `None` | Model of the inverter of this plane. |
|
||||
| inverter_paco | `int | None` | `rw` | `None` | AC power rating of the inverter [W]. |
|
||||
| loss | `float | None` | `rw` | `14.0` | Sum of PV system losses in percent |
|
||||
| module_model | `str | None` | `rw` | `None` | Model of the PV modules of this plane. |
|
||||
| modules_per_string | `int | None` | `rw` | `None` | Number of the PV modules of the strings of this plane. |
|
||||
| mountingplace | `str | None` | `rw` | `free` | Type of mounting for PV system. Options are 'free' for free-standing and 'building' for building-integrated. |
|
||||
| mountingplace | `str | None` | `rw` | `building` | Type of mounting for PV system. Options are 'free' for free-standing and 'building' for building-integrated. |
|
||||
| optimal_surface_tilt | `bool | None` | `rw` | `False` | Calculate the optimum tilt angle. Ignored for two-axis tracking. |
|
||||
| optimalangles | `bool | None` | `rw` | `False` | Calculate the optimum tilt and azimuth angles. Ignored for two-axis tracking. |
|
||||
| peakpower | `float | None` | `rw` | `None` | Nominal power of PV system in kW. |
|
||||
@@ -395,7 +425,7 @@
|
||||
],
|
||||
"peakpower": 5.0,
|
||||
"pvtechchoice": "crystSi",
|
||||
"mountingplace": "free",
|
||||
"mountingplace": "building",
|
||||
"loss": 14.0,
|
||||
"trackingtype": 0,
|
||||
"optimal_surface_tilt": false,
|
||||
|
||||
+2
-2
@@ -47,8 +47,8 @@
|
||||
"providers": [
|
||||
"BrightSky",
|
||||
"ClearOutside",
|
||||
"OpenMeteo",
|
||||
"WeatherImport"
|
||||
"WeatherImport",
|
||||
"OpenMeteo"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
BIN
Binary file not shown.
Reference in New Issue
Block a user