2025-11-13 22:53:46 +01:00
## PV Forecast Configuration
<!-- pyml disable line-length -->
:::{table} pvforecast
:widths: 10 20 10 5 5 30
:align: left
| Name | Environment Variable | Type | Read-Only | Default | Description |
| ---- | -------------------- | ---- | --------- | ------- | ----------- |
2026-11-03 15:31:32 +01:00
| adaptive | `EOS_PVFORECAST__ADAPTIVE` | `PVForecastAdaptiveAkkudoktorCommonSettings` | `rw` | `required` | Adaptive Akkudoktor: configure string measurements and independent reference flags on the planes. |
2026-09-16 18:25:20 +02:00
| akkudoktor | `EOS_PVFORECAST__AKKUDOKTOR` | `PVForecastAkkudoktorLocalCommonSettings` | `rw` | `required` | Akkudoktor forecast backend and local calibration settings |
2026-07-20 14:37:03 +02:00
| forecastsolar | `EOS_PVFORECAST__FORECASTSOLAR` | `PVForecastForecastSolarCommonSettings` | `rw` | `required` | ForecastSolar provider settings |
2026-09-03 00:15:40 +02:00
| homeassistant | `EOS_PVFORECAST__HOMEASSISTANT` | `PVForecastHomeAssistantCommonSettings` | `rw` | `required` | Home Assistant provider settings |
2026-09-10 23:20:35 +02:00
| max_planes | `EOS_PVFORECAST__MAX_PLANES` | `Optional[int]` | `rw` | `0` | Maximum number of planes that can be set |
| planes | `EOS_PVFORECAST__PLANES` | `Optional[list[akkudoktoreos.prediction.pvforecast.PVForecastPlaneSetting]]` | `rw` | `None` | Plane configuration. |
2025-12-30 22:08:21 +01:00
| planes_azimuth | | `List[float]` | `ro` | `N/A` | Compute a list of the azimuths per active planes. |
| planes_inverter_paco | | `Any` | `ro` | `N/A` | Compute a list of the maximum power rating of the inverter per active planes. |
| planes_peakpower | | `List[float]` | `ro` | `N/A` | Compute a list of the peak power per active planes. |
| planes_tilt | | `List[float]` | `ro` | `N/A` | Compute a list of the tilts per active planes. |
| planes_userhorizon | | `Any` | `ro` | `N/A` | Compute a list of the user horizon per active planes. |
2026-09-10 23:20:35 +02:00
| provider | `EOS_PVFORECAST__PROVIDER` | `Optional[str]` | `rw` | `None` | PVForecast provider id of provider to be used. |
2025-12-30 22:08:21 +01:00
| providers | | `list[str]` | `ro` | `N/A` | Available PVForecast provider ids. |
2026-07-20 14:37:03 +02:00
| pvforecastimport | `EOS_PVFORECAST__PVFORECASTIMPORT` | `PVForecastImportCommonSettings` | `rw` | `required` | PV forecast import provider settings |
2026-08-07 13:13:17 +02:00
| pvlib | `EOS_PVFORECAST__PVLIB` | `PVForecastPVLibCommonSettings` | `rw` | `required` | PVLib provider settings |
2026-07-20 14:37:03 +02:00
| 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 |
2025-11-13 22:53:46 +01:00
:::
<!-- pyml enable line-length -->
<!-- pyml disable no-emphasis-as-heading -->
**Example Input**
<!-- pyml enable no-emphasis-as-heading -->
<!-- pyml disable line-length -->
```json
{
"pvforecast" : {
"provider" : "PVForecastAkkudoktor" ,
2026-09-16 18:25:20 +02:00
"akkudoktor" : {
"backend" : "remote" ,
"resolution_minutes" : 15 ,
"forecast_days" : null ,
"past_days" : null ,
"weather_models" : [
"best_match"
],
"transposition_model" : "perez" ,
"albedo" : 0.25 ,
"inverter_efficiency" : 0.96 ,
"temperature_coefficient" : -0.36 ,
"apply_iam" : true ,
"shift_to_interval_start" : true ,
"calibration_enabled" : false ,
"calibration_days" : 30 ,
"calibration_reference_days" : 30 ,
"calibration_outage_filter_enabled" : true ,
"calibration_outage_threshold" : 0.55 ,
"calibration_min_healthy_days" : 3 ,
"calibration_azimuth_bin_degrees" : 45 ,
"calibration_prior_kwh" : 5.0 ,
"calibration_min_factor" : 0.5 ,
"calibration_max_factor" : 1.5
},
2026-11-03 15:31:32 +01:00
"adaptive" : {
"backend" : "local" ,
"resolution_minutes" : 15 ,
"forecast_days" : null ,
"past_days" : null ,
"weather_models" : [
"best_match" ,
"icon_d2"
],
"transposition_model" : "perez" ,
"albedo" : 0.25 ,
"inverter_efficiency" : 0.96 ,
"temperature_coefficient" : -0.36 ,
"apply_iam" : true ,
"shift_to_interval_start" : true ,
"calibration_enabled" : false ,
"calibration_days" : 30 ,
"calibration_reference_days" : 30 ,
"calibration_outage_filter_enabled" : true ,
"calibration_outage_threshold" : 0.55 ,
"calibration_min_healthy_days" : 3 ,
"calibration_azimuth_bin_degrees" : 45 ,
"calibration_prior_kwh" : 5.0 ,
"calibration_min_factor" : 0.5 ,
"calibration_max_factor" : 1.5 ,
"regional_weather_model" : "icon_d2" ,
"regional_horizon_hours" : 6 ,
"learning_days" : 21 ,
"min_training_days" : 5 ,
"max_ac_power_w" : 0 ,
"nominal_total_peakpower_kw" : null ,
"diagnostics_days" : 7 ,
"archive_retention_days" : 60 ,
"nowcast_enabled" : true ,
"trend_enabled" : true ,
"solar_response_enabled" : true ,
"weather_response_enabled" : true ,
"correction_mode" : "auto" ,
"validation_days" : 7 ,
"min_validation_days" : 3 ,
"min_validation_samples" : 32 ,
"min_validation_improvement" : 0.02 ,
"training_delay_minutes" : 15 ,
"total_measurement_key" : null ,
"total_curtailment_sensitive" : false ,
"total_curtailment_key" : null ,
"total_learning_guard_key" : null ,
"total_learning_guard_max" : null ,
"total_learning_guard_max_gap_seconds" : 600
},
2026-07-20 14:37:03 +02:00
"pvforecastimport" : {
"import_file_path" : null ,
"import_json" : null
},
"vrm" : {
"token" : "your-token" ,
"site_id" : 12345
},
2026-09-03 00:15:40 +02:00
"homeassistant" : {
"entity_id" : "sensor.pv_forecast" ,
"attribute" : "forecast" ,
"datetime_key" : "datetime" ,
"value_key" : "watts" ,
"value_unit" : "W" ,
"base_url" : null ,
"token" : null
},
2026-08-07 13:13:17 +02:00
"pvlib" : {},
2026-07-20 14:37:03 +02:00
"pvnode" : {
"api_key" : "" ,
"site_id" : null ,
"forecast_days" : 2
},
"forecastsolar" : {
"api_key" : null
},
"solcast" : {
"api_key" : "" ,
"site_id" : ""
2025-11-13 22:53:46 +01:00
},
"planes" : [
{
2026-11-03 15:31:32 +01:00
"name" : null ,
"measurement_key" : null ,
"nowcast_reference" : false ,
"curtailment_sensitive" : false ,
"parameters_estimated" : false ,
"correction_group" : null ,
"curtailment_key" : null ,
"learning_guard_key" : null ,
"learning_guard_max" : null ,
"learning_guard_max_gap_seconds" : 600 ,
2025-11-13 22:53:46 +01:00
"surface_tilt" : 10.0 ,
"surface_azimuth" : 180.0 ,
"userhorizon" : [
10.0 ,
20.0 ,
30.0
],
"peakpower" : 5.0 ,
"pvtechchoice" : "crystSi" ,
"mountingplace" : "free" ,
"loss" : 14.0 ,
"trackingtype" : 0 ,
"optimal_surface_tilt" : false ,
"optimalangles" : false ,
"albedo" : null ,
"module_model" : null ,
"inverter_model" : null ,
"inverter_paco" : 6000 ,
"modules_per_string" : 20 ,
"strings_per_inverter" : 2
},
{
2026-11-03 15:31:32 +01:00
"name" : null ,
"measurement_key" : null ,
"nowcast_reference" : false ,
"curtailment_sensitive" : false ,
"parameters_estimated" : false ,
"correction_group" : null ,
"curtailment_key" : null ,
"learning_guard_key" : null ,
"learning_guard_max" : null ,
"learning_guard_max_gap_seconds" : 600 ,
2025-11-13 22:53:46 +01:00
"surface_tilt" : 20.0 ,
"surface_azimuth" : 90.0 ,
"userhorizon" : [
5.0 ,
15.0 ,
25.0
],
"peakpower" : 3.5 ,
"pvtechchoice" : "crystSi" ,
"mountingplace" : "free" ,
"loss" : 14.0 ,
"trackingtype" : 1 ,
"optimal_surface_tilt" : false ,
"optimalangles" : false ,
"albedo" : null ,
"module_model" : null ,
"inverter_model" : null ,
"inverter_paco" : 4000 ,
"modules_per_string" : 20 ,
"strings_per_inverter" : 2
}
],
"max_planes" : 1
}
}
```
<!-- pyml enable line-length -->
<!-- pyml disable no-emphasis-as-heading -->
**Example Output**
<!-- pyml enable no-emphasis-as-heading -->
<!-- pyml disable line-length -->
```json
{
"pvforecast" : {
"provider" : "PVForecastAkkudoktor" ,
2026-09-16 18:25:20 +02:00
"akkudoktor" : {
"backend" : "remote" ,
"resolution_minutes" : 15 ,
"forecast_days" : null ,
"past_days" : null ,
"weather_models" : [
"best_match"
],
"transposition_model" : "perez" ,
"albedo" : 0.25 ,
"inverter_efficiency" : 0.96 ,
"temperature_coefficient" : -0.36 ,
"apply_iam" : true ,
"shift_to_interval_start" : true ,
"calibration_enabled" : false ,
"calibration_days" : 30 ,
"calibration_reference_days" : 30 ,
"calibration_outage_filter_enabled" : true ,
"calibration_outage_threshold" : 0.55 ,
"calibration_min_healthy_days" : 3 ,
"calibration_azimuth_bin_degrees" : 45 ,
"calibration_prior_kwh" : 5.0 ,
"calibration_min_factor" : 0.5 ,
"calibration_max_factor" : 1.5
},
2026-11-03 15:31:32 +01:00
"adaptive" : {
"backend" : "local" ,
"resolution_minutes" : 15 ,
"forecast_days" : null ,
"past_days" : null ,
"weather_models" : [
"best_match" ,
"icon_d2"
],
"transposition_model" : "perez" ,
"albedo" : 0.25 ,
"inverter_efficiency" : 0.96 ,
"temperature_coefficient" : -0.36 ,
"apply_iam" : true ,
"shift_to_interval_start" : true ,
"calibration_enabled" : false ,
"calibration_days" : 30 ,
"calibration_reference_days" : 30 ,
"calibration_outage_filter_enabled" : true ,
"calibration_outage_threshold" : 0.55 ,
"calibration_min_healthy_days" : 3 ,
"calibration_azimuth_bin_degrees" : 45 ,
"calibration_prior_kwh" : 5.0 ,
"calibration_min_factor" : 0.5 ,
"calibration_max_factor" : 1.5 ,
"regional_weather_model" : "icon_d2" ,
"regional_horizon_hours" : 6 ,
"learning_days" : 21 ,
"min_training_days" : 5 ,
"max_ac_power_w" : 0 ,
"nominal_total_peakpower_kw" : null ,
"diagnostics_days" : 7 ,
"archive_retention_days" : 60 ,
"nowcast_enabled" : true ,
"trend_enabled" : true ,
"solar_response_enabled" : true ,
"weather_response_enabled" : true ,
"correction_mode" : "auto" ,
"validation_days" : 7 ,
"min_validation_days" : 3 ,
"min_validation_samples" : 32 ,
"min_validation_improvement" : 0.02 ,
"training_delay_minutes" : 15 ,
"total_measurement_key" : null ,
"total_curtailment_sensitive" : false ,
"total_curtailment_key" : null ,
"total_learning_guard_key" : null ,
"total_learning_guard_max" : null ,
"total_learning_guard_max_gap_seconds" : 600
},
2026-07-20 14:37:03 +02:00
"pvforecastimport" : {
"import_file_path" : null ,
"import_json" : null
},
"vrm" : {
"token" : "your-token" ,
"site_id" : 12345
},
2026-09-03 00:15:40 +02:00
"homeassistant" : {
"entity_id" : "sensor.pv_forecast" ,
"attribute" : "forecast" ,
"datetime_key" : "datetime" ,
"value_key" : "watts" ,
"value_unit" : "W" ,
"base_url" : null ,
"token" : null
},
2026-08-07 13:13:17 +02:00
"pvlib" : {},
2026-07-20 14:37:03 +02:00
"pvnode" : {
"api_key" : "" ,
"site_id" : null ,
"forecast_days" : 2
},
"forecastsolar" : {
"api_key" : null
},
"solcast" : {
"api_key" : "" ,
"site_id" : ""
2025-11-13 22:53:46 +01:00
},
"planes" : [
{
2026-11-03 15:31:32 +01:00
"name" : null ,
"measurement_key" : null ,
"nowcast_reference" : false ,
"curtailment_sensitive" : false ,
"parameters_estimated" : false ,
"correction_group" : null ,
"curtailment_key" : null ,
"learning_guard_key" : null ,
"learning_guard_max" : null ,
"learning_guard_max_gap_seconds" : 600 ,
2025-11-13 22:53:46 +01:00
"surface_tilt" : 10.0 ,
"surface_azimuth" : 180.0 ,
"userhorizon" : [
10.0 ,
20.0 ,
30.0
],
"peakpower" : 5.0 ,
"pvtechchoice" : "crystSi" ,
"mountingplace" : "free" ,
"loss" : 14.0 ,
"trackingtype" : 0 ,
"optimal_surface_tilt" : false ,
"optimalangles" : false ,
"albedo" : null ,
"module_model" : null ,
"inverter_model" : null ,
"inverter_paco" : 6000 ,
"modules_per_string" : 20 ,
"strings_per_inverter" : 2
},
{
2026-11-03 15:31:32 +01:00
"name" : null ,
"measurement_key" : null ,
"nowcast_reference" : false ,
"curtailment_sensitive" : false ,
"parameters_estimated" : false ,
"correction_group" : null ,
"curtailment_key" : null ,
"learning_guard_key" : null ,
"learning_guard_max" : null ,
"learning_guard_max_gap_seconds" : 600 ,
2025-11-13 22:53:46 +01:00
"surface_tilt" : 20.0 ,
"surface_azimuth" : 90.0 ,
"userhorizon" : [
5.0 ,
15.0 ,
25.0
],
"peakpower" : 3.5 ,
"pvtechchoice" : "crystSi" ,
"mountingplace" : "free" ,
"loss" : 14.0 ,
"trackingtype" : 1 ,
"optimal_surface_tilt" : false ,
"optimalangles" : false ,
"albedo" : null ,
"module_model" : null ,
"inverter_model" : null ,
"inverter_paco" : 4000 ,
"modules_per_string" : 20 ,
"strings_per_inverter" : 2
}
],
"max_planes" : 1 ,
2025-12-30 22:08:21 +01:00
"providers" : [
"PVForecastAkkudoktor" ,
2026-11-03 15:31:32 +01:00
"PVForecastAdaptiveAkkudoktor" ,
2026-07-17 16:51:00 +02:00
"PVForecastForecastSolar" ,
2026-09-10 23:20:35 +02:00
"PVForecastHomeAssistant" ,
2026-08-07 13:13:17 +02:00
"PVForecastImport" ,
"PVForecastPVLib" ,
"PVForecastPVNode" ,
2026-07-17 16:51:00 +02:00
"PVForecastSolcast" ,
2026-08-07 13:13:17 +02:00
"PVForecastVrm"
2025-12-30 22:08:21 +01:00
],
2025-11-13 22:53:46 +01:00
"planes_peakpower" : [
5.0 ,
3.5
],
"planes_azimuth" : [
180.0 ,
90.0
],
"planes_tilt" : [
10.0 ,
20.0
],
"planes_userhorizon" : [
[
10.0 ,
20.0 ,
30.0
],
[
5.0 ,
15.0 ,
25.0
]
],
"planes_inverter_paco" : [
6000.0 ,
4000.0
]
}
}
```
<!-- pyml enable line-length -->
2026-07-20 14:37:03 +02:00
### Common settings for PV forecast VRM API
<!-- pyml disable line-length -->
:::{table} pvforecast::vrm
:widths: 10 10 5 5 30
:align: left
| Name | Type | Read-Only | Default | Description |
| ---- | ---- | --------- | ------- | ----------- |
| site_id | `int` | `rw` | `12345` | VRM-Installation-ID |
| token | `str` | `rw` | `your-token` | Access token for connecting to the Victron Remote Management (VRM) API |
:::
<!-- 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" : {
"vrm" : {
"token" : "your-token" ,
"site_id" : 12345
}
}
}
```
<!-- pyml enable line-length -->
2026-07-17 16:51:00 +02:00
### Common settings for the Solcast PV forecast provider
<!-- pyml disable line-length -->
2026-07-20 14:37:03 +02:00
:::{table} pvforecast::solcast
2026-07-17 16:51:00 +02:00
:widths: 10 10 5 5 30
:align: left
| Name | Type | Read-Only | Default | Description |
| ---- | ---- | --------- | ------- | ----------- |
| api_key | `str` | `rw` | `` | Solcast API key (Bearer auth). Required. |
| site_id | ` str` | ` rw` | `` | Solcast rooftop site (resource) id. Required. |
:::
<!-- 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": {
2026-07-20 14:37:03 +02:00
"solcast": {
"api_key": "your-solcast-key",
"site_id": "abcd-1234-efgh-5678"
2026-07-17 16:51:00 +02:00
}
}
}
` ``
<!-- pyml enable line-length -->
### Common settings for the pvnode.com PV forecast provider
<!-- pyml disable line-length -->
2026-07-20 14:37:03 +02:00
:::{table} pvforecast::pvnode
2026-07-17 16:51:00 +02:00
:widths: 10 10 5 5 30
:align: left
| Name | Type | Read-Only | Default | Description |
| ---- | ---- | --------- | ------- | ----------- |
| api_key | ` str` | ` rw` | `` | pvnode.com API key (Bearer auth). Required. |
| forecast_days | ` int` | ` rw` | ` 2` | Forecast horizon in days (1-7, capped by the pvnode plan). |
2026-09-10 23:20:35 +02:00
| site_id | ` Optional[str]` | ` rw` | ` None` | pvnode.com site id of the saved plant ('Anlagen-ID'). When set, the saved (possibly calibrated) site is used. Leave empty to send the configured pvforecast.planes inline instead. |
2026-07-17 16:51:00 +02:00
:::
<!-- 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": {
2026-07-20 14:37:03 +02:00
"pvnode": {
"api_key": "pvn_live_xxxxxxxxxxxxxxxx",
"site_id": "abcd-1234",
"forecast_days": 2
2025-11-13 22:53:46 +01:00
}
}
}
` ``
<!-- pyml enable line-length -->
2026-08-07 13:13:17 +02:00
### 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 -->
2025-11-13 22:53:46 +01:00
### Common settings for pvforecast data import from file or JSON string
<!-- pyml disable line-length -->
2026-07-20 14:37:03 +02:00
:::{table} pvforecast::pvforecastimport
2025-11-13 22:53:46 +01:00
:widths: 10 10 5 5 30
:align: left
| Name | Type | Read-Only | Default | Description |
| ---- | ---- | --------- | ------- | ----------- |
2026-09-10 23:20:35 +02:00
| import_file_path | ` Union[str, pathlib.Path, NoneType]` | ` rw` | ` None` | Path to the file to import PV forecast data from. |
| import_json | ` Optional[str]` | ` rw` | ` None` | JSON string, dictionary of PV forecast value lists. |
2025-11-13 22:53:46 +01:00
:::
<!-- 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": {
2026-07-20 14:37:03 +02:00
"pvforecastimport": {
"import_file_path": null,
"import_json": "{\"pvforecast_ac_power\": [0, 8.05, 352.91]}"
2025-11-13 22:53:46 +01:00
}
}
}
` ``
<!-- pyml enable line-length -->
### PV Forecast Plane Configuration
<!-- pyml disable line-length -->
:::{table} pvforecast::planes::list
:widths: 10 10 5 5 30
:align: left
| Name | Type | Read-Only | Default | Description |
| ---- | ---- | --------- | ------- | ----------- |
2026-09-10 23:20:35 +02:00
| albedo | ` Optional[float]` | ` rw` | ` 0.2` | Proportion of the light hitting the ground that it reflects back. |
2026-11-03 15:31:32 +01:00
| correction_group | ` Optional[str]` | ` rw` | ` None` | Optional group of planes sharing short-term validation. Unset independent references share one group; other planes are separate. |
| curtailment_key | ` Optional[str]` | ` rw` | ` None` | Optional measured flag: 0 explicitly unrestricted, 1 curtailed. Missing or stale flags never authorize learning a curtailment-sensitive plane. |
| curtailment_sensitive | ` bool` | ` rw` | ` False` | Battery-full curtailment possible; exclude from unrestricted weather learning. |
2026-09-10 23:20:35 +02:00
| inverter_model | ` Optional[str]` | ` rw` | ` None` | Model of the inverter of this plane. |
| inverter_paco | ` Optional[int]` | ` rw` | ` None` | AC power rating of the inverter [W]. |
2026-11-03 15:31:32 +01:00
| learning_guard_key | ` Optional[str]` | ` rw` | ` None` | Optional site-specific positive learning guard, e.g. battery SoC, as an alternative to a binary curtailment flag. |
| learning_guard_max | ` Optional[float]` | ` rw` | ` None` | Learn only while every supported guard value is below this bound. This is an explicit site assumption, not automatic curtailment detection. |
| learning_guard_max_gap_seconds | ` int` | ` rw` | ` 600` | None |
2026-09-10 23:20:35 +02:00
| loss | ` Optional[float]` | ` rw` | ` 14.0` | Sum of PV system losses in percent |
2026-11-03 15:31:32 +01:00
| measurement_key | ` Optional[str]` | ` rw` | ` None` | Matching EOS power measurement key for adaptive learning. |
2026-09-10 23:20:35 +02:00
| module_model | ` Optional[str]` | ` rw` | ` None` | Model of the PV modules of this plane. |
| modules_per_string | ` Optional[int]` | ` rw` | ` None` | Number of the PV modules of the strings of this plane. |
| mountingplace | ` Optional[str]` | ` rw` | ` building` | Type of mounting for PV system. Options are 'free' for free-standing and 'building' for building-integrated. |
2026-11-03 15:31:32 +01:00
| name | ` Optional[str]` | ` rw` | ` None` | Readable PV string name. |
| nowcast_reference | ` bool` | ` rw` | ` False` | Use this independent array as a local weather reference. |
2026-09-10 23:20:35 +02:00
| optimal_surface_tilt | ` Optional[bool]` | ` rw` | ` False` | Calculate the optimum tilt angle. Ignored for two-axis tracking. |
| optimalangles | ` Optional[bool]` | ` rw` | ` False` | Calculate the optimum tilt and azimuth angles. Ignored for two-axis tracking. |
2026-11-03 15:31:32 +01:00
| parameters_estimated | ` bool` | ` rw` | ` False` | Geometry and peak power are effective fitted model estimates, not verified nameplate data. |
2026-09-10 23:20:35 +02:00
| peakpower | ` Optional[float]` | ` rw` | ` None` | Nominal power of PV system in kW. |
| pvtechchoice | ` Optional[str]` | ` rw` | ` crystSi` | PV technology. One of 'crystSi', 'CIS', 'CdTe', 'Unknown'. |
| strings_per_inverter | ` Optional[int]` | ` rw` | ` None` | Number of the strings of the inverter of this plane. |
| surface_azimuth | ` Optional[float]` | ` rw` | ` 180.0` | Orientation (azimuth angle) of the (fixed) plane. Clockwise from north (north=0, east=90, south=180, west=270). |
| surface_tilt | ` Optional[float]` | ` rw` | ` 30.0` | Tilt angle from horizontal plane. Ignored for two-axis tracking. |
| trackingtype | ` Optional[int]` | ` rw` | ` None` | Type of suntracking. 0=fixed, 1=single horizontal axis aligned north-south, 2=two-axis tracking, 3=vertical axis tracking, 4=single horizontal axis aligned east-west, 5=single inclined axis aligned north-south. |
| userhorizon | ` Optional[List[float]]` | ` rw` | ` None` | Elevation of horizon in degrees, at equally spaced azimuth clockwise from north. |
2025-11-13 22:53:46 +01:00
:::
<!-- 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": {
"planes": [
{
2026-11-03 15:31:32 +01:00
"name": null,
"measurement_key": null,
"nowcast_reference": false,
"curtailment_sensitive": false,
"parameters_estimated": false,
"correction_group": null,
"curtailment_key": null,
"learning_guard_key": null,
"learning_guard_max": null,
"learning_guard_max_gap_seconds": 600,
2025-11-13 22:53:46 +01:00
"surface_tilt": 10.0,
"surface_azimuth": 180.0,
"userhorizon": [
10.0,
20.0,
30.0
],
"peakpower": 5.0,
"pvtechchoice": "crystSi",
2026-08-07 13:13:17 +02:00
"mountingplace": "building",
2025-11-13 22:53:46 +01:00
"loss": 14.0,
"trackingtype": 0,
"optimal_surface_tilt": false,
"optimalangles": false,
"albedo": null,
"module_model": null,
"inverter_model": null,
"inverter_paco": 6000,
"modules_per_string": 20,
"strings_per_inverter": 2
}
]
}
}
` ``
<!-- pyml enable line-length -->
2026-07-20 14:37:03 +02:00
2026-09-10 23:20:35 +02:00
### Common settings for pvforecast data from a Home Assistant entity
<!-- pyml disable line-length -->
:::{table} pvforecast::homeassistant
:widths: 10 10 5 5 30
:align: left
| Name | Type | Read-Only | Default | Description |
| ---- | ---- | --------- | ------- | ----------- |
| attribute | ` str` | ` rw` | ` forecast` | Entity attribute holding the forecast list. |
| base_url | ` Optional[str]` | ` rw` | ` None` | Base URL of the Home Assistant instance. Only required when EOS is not running as a Home Assistant add-on (no SUPERVISOR_TOKEN available). |
| datetime_key | ` str` | ` rw` | ` datetime` | Key for the timestamp in each forecast entry. |
| entity_id | ` str` | ` rw` | ` sensor.pv_forecast` | Home Assistant entity providing the PV forecast. |
| token | ` Optional[str]` | ` rw` | ` None` | Long-lived access token for the Home Assistant instance. Only required when EOS is not running as a Home Assistant add-on. |
| value_key | ` str` | ` rw` | ` watts` | Key for the AC power value in each forecast entry. |
| value_unit | ` Literal['W', 'kW']` | ` rw` | ` W` | Unit of the forecast value. Converted to W internally. |
:::
<!-- 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": {
"homeassistant": {
"entity_id": "sensor.pv1_power_now",
"attribute": "forecast",
"datetime_key": "datetime",
"value_key": "watts",
"value_unit": "W",
"base_url": "http://homeassistant.local:8123",
"token": null
}
}
}
` ``
<!-- pyml enable line-length -->
2026-07-20 14:37:03 +02:00
### Common settings for the Forecast.Solar PV forecast provider
<!-- pyml disable line-length -->
:::{table} pvforecast::forecastsolar
:widths: 10 10 5 5 30
:align: left
| Name | Type | Read-Only | Default | Description |
| ---- | ---- | --------- | ------- | ----------- |
2026-09-10 23:20:35 +02:00
| api_key | ` Optional[str]` | ` rw` | ` None` | Forecast.Solar API key. Optional — the public endpoint works without a key (lower rate limit). |
2026-07-20 14:37:03 +02:00
:::
<!-- 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": {
"forecastsolar": {
"api_key": null
}
}
}
` ``
<!-- pyml enable line-length -->
2026-09-16 18:25:20 +02:00
### Common settings for the local (pvlib) PV forecast provider
<!-- pyml disable line-length -->
:::{table} pvforecast::akkudoktor
:widths: 10 10 5 5 30
:align: left
| Name | Type | Read-Only | Default | Description |
| ---- | ---- | --------- | ------- | ----------- |
| albedo | ` float` | ` rw` | ` 0.25` | Ground albedo used for planes that do not set their own. |
| apply_iam | ` bool` | ` rw` | ` True` | Apply the ASHRAE incidence-angle modifier to the beam component. |
| backend | ` Literal['remote', 'local']` | ` rw` | ` remote` | Akkudoktor forecast backend: remote API or local Open-Meteo/pvlib model. |
| calibration_azimuth_bin_degrees | ` int` | ` rw` | ` 45` | Width of the solar-azimuth bins for the correction. 0 fits a single global factor only. |
| calibration_days | ` int` | ` rw` | ` 30` | Length of the measurement window used to fit the correction. |
| calibration_enabled | ` bool` | ` rw` | ` False` | Correct systematic model error against measured PV production. Requires ` measurement.pv_production_emr_keys` to be configured and fed. Fits a global scale factor plus per-solar-azimuth factors, which is what catches near-field shading the horizon profile misses. |
| calibration_max_factor | ` float` | ` rw` | ` 1.5` | Upper clamp on any fitted correction factor. |
| calibration_min_factor | ` float` | ` rw` | ` 0.5` | Lower clamp on any fitted correction factor. |
| calibration_min_healthy_days | ` int` | ` rw` | ` 3` | Minimum number of healthy days used for a fit. Older healthy days from the reference window are added when the recent window contains fewer. |
| calibration_outage_filter_enabled | ` bool` | ` rw` | ` True` | Exclude days whose measured production is far below the recent healthy plant level. This prevents inverter, battery and curtailment events from being learned as permanent PV model losses. |
| calibration_outage_threshold | ` float` | ` rw` | ` 0.55` | A day is treated as unavailable when its measured/modelled energy ratio is below this fraction of the robust healthy reference ratio. |
| calibration_prior_kwh | ` float` | ` rw` | ` 5.0` | Shrinkage strength: a bin needs this much modelled energy before its own factor outweighs the global one. Higher is more conservative. |
| calibration_reference_days | ` int` | ` rw` | ` 30` | Lookback used to distinguish healthy production from outages or curtailment. If the calibration window contains too few healthy days, the most recent healthy days from this reference window are used. |
| forecast_days | ` Optional[int]` | ` rw` | ` None` | Forecast horizon in days (1-16). Leave empty to derive it from ` prediction.hours`, which is what keeps the optimizer's tail horizon fed. |
| inverter_efficiency | ` float` | ` rw` | ` 0.96` | Nominal inverter efficiency (PVWatts eta_inv_nom). |
| past_days | ` Optional[int]` | ` rw` | ` None` | Days of past data to request (0-92). Leave empty to derive it from ` prediction.historic_hours`. |
| resolution_minutes | ` int` | ` rw` | ` 15` | Forecast resolution in minutes. 15 requests Open-Meteo's ` minutely_15` block (natively resolved over Central Europe and North America, interpolated from hourly elsewhere); 60 requests the ` hourly` block. |
| shift_to_interval_start | ` bool` | ` rw` | ` True` | Open-Meteo stamps an interval mean with the interval END. EOS labels an interval by its START, so records are shifted back by one interval. Disable only to compare like-for-like against a provider that does not. |
| temperature_coefficient | ` float` | ` rw` | ` -0.36` | Module power temperature coefficient in %/degC (negative). Matches the ` cellCoEff` the akkudoktor.net forecast uses. |
| transposition_model | ` str` | ` rw` | ` perez` | pvlib sky-diffuse transposition model: isotropic, klucher, haydavies, reindl, king or perez. |
| weather_models | ` list[str]` | ` rw` | ` ['best_match']` | Open-Meteo weather models to request. Listing more than one turns the input into a poor-man's ensemble: the members are averaged per variable, which is the cheapest reliable way to cut irradiance forecast error. Costs no extra API calls. |
:::
<!-- 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": {
"akkudoktor": {
"backend": "remote",
"resolution_minutes": 15,
"forecast_days": null,
"past_days": null,
"weather_models": [
"best_match"
],
"transposition_model": "perez",
"albedo": 0.25,
"inverter_efficiency": 0.96,
"temperature_coefficient": -0.36,
"apply_iam": true,
"shift_to_interval_start": true,
"calibration_enabled": true,
"calibration_days": 30,
"calibration_reference_days": 30,
"calibration_outage_filter_enabled": true,
"calibration_outage_threshold": 0.55,
"calibration_min_healthy_days": 3,
"calibration_azimuth_bin_degrees": 45,
"calibration_prior_kwh": 5.0,
"calibration_min_factor": 0.5,
"calibration_max_factor": 1.5
}
}
}
` ``
<!-- pyml enable line-length -->
2026-11-03 15:31:32 +01:00
### Automatic defaults; configure measurements and reference flags on each plane
<!-- pyml disable line-length -->
:::{table} pvforecast::adaptive
:widths: 10 10 5 5 30
:align: left
| Name | Type | Read-Only | Default | Description |
| ---- | ---- | --------- | ------- | ----------- |
| albedo | ` float` | ` rw` | ` 0.25` | Ground albedo used for planes that do not set their own. |
| apply_iam | ` bool` | ` rw` | ` True` | Apply the ASHRAE incidence-angle modifier to the beam component. |
| archive_retention_days | ` int` | ` rw` | ` 60` | None |
| backend | ` Literal['remote', 'local']` | ` rw` | ` local` | None |
| calibration_azimuth_bin_degrees | ` int` | ` rw` | ` 45` | Width of the solar-azimuth bins for the correction. 0 fits a single global factor only. |
| calibration_days | ` int` | ` rw` | ` 30` | Length of the measurement window used to fit the correction. |
| calibration_enabled | ` bool` | ` rw` | ` False` | None |
| calibration_max_factor | ` float` | ` rw` | ` 1.5` | Upper clamp on any fitted correction factor. |
| calibration_min_factor | ` float` | ` rw` | ` 0.5` | Lower clamp on any fitted correction factor. |
| calibration_min_healthy_days | ` int` | ` rw` | ` 3` | Minimum number of healthy days used for a fit. Older healthy days from the reference window are added when the recent window contains fewer. |
| calibration_outage_filter_enabled | ` bool` | ` rw` | ` True` | Exclude days whose measured production is far below the recent healthy plant level. This prevents inverter, battery and curtailment events from being learned as permanent PV model losses. |
| calibration_outage_threshold | ` float` | ` rw` | ` 0.55` | A day is treated as unavailable when its measured/modelled energy ratio is below this fraction of the robust healthy reference ratio. |
| calibration_prior_kwh | ` float` | ` rw` | ` 5.0` | Shrinkage strength: a bin needs this much modelled energy before its own factor outweighs the global one. Higher is more conservative. |
| calibration_reference_days | ` int` | ` rw` | ` 30` | Lookback used to distinguish healthy production from outages or curtailment. If the calibration window contains too few healthy days, the most recent healthy days from this reference window are used. |
| correction_mode | ` Literal['auto', 'calibrated', 'local', 'trend']` | ` rw` | ` auto` | Choose validated short-term candidates per group/lead, or explicitly fix a correction stage. |
| diagnostics_days | ` int` | ` rw` | ` 7` | None |
| forecast_days | ` Optional[int]` | ` rw` | ` None` | Forecast horizon in days (1-16). Leave empty to derive it from ` prediction.hours`, which is what keeps the optimizer's tail horizon fed. |
| inverter_efficiency | ` float` | ` rw` | ` 0.96` | Nominal inverter efficiency (PVWatts eta_inv_nom). |
| learning_days | ` int` | ` rw` | ` 21` | None |
| max_ac_power_w | ` float` | ` rw` | ` 0` | None |
| min_training_days | ` int` | ` rw` | ` 5` | None |
| min_validation_days | ` int` | ` rw` | ` 3` | None |
| min_validation_improvement | ` float` | ` rw` | ` 0.02` | None |
| min_validation_samples | ` int` | ` rw` | ` 32` | None |
| nominal_total_peakpower_kw | ` Optional[float]` | ` rw` | ` None` | Known installed nameplate total; fitted plane powers may be effective estimates. |
| nowcast_enabled | ` bool` | ` rw` | ` True` | None |
| past_days | ` Optional[int]` | ` rw` | ` None` | Days of past data to request (0-92). Leave empty to derive it from ` prediction.historic_hours`. |
| regional_horizon_hours | ` float` | ` rw` | ` 6` | None |
| regional_weather_model | ` Optional[str]` | ` rw` | ` icon_d2` | None |
| resolution_minutes | ` int` | ` rw` | ` 15` | Forecast resolution in minutes. 15 requests Open-Meteo's ` minutely_15` block (natively resolved over Central Europe and North America, interpolated from hourly elsewhere); 60 requests the ` hourly` block. |
| shift_to_interval_start | ` bool` | ` rw` | ` True` | Open-Meteo stamps an interval mean with the interval END. EOS labels an interval by its START, so records are shifted back by one interval. Disable only to compare like-for-like against a provider that does not. |
| solar_response_enabled | ` bool` | ` rw` | ` True` | Learn empirical angular response relative to separate, eligible reference arrays; activate only after issued-candidate validation. |
| temperature_coefficient | ` float` | ` rw` | ` -0.36` | Module power temperature coefficient in %/degC (negative). Matches the ` cellCoEff` the akkudoktor.net forecast uses. |
| total_curtailment_key | ` Optional[str]` | ` rw` | ` None` | None |
| total_curtailment_sensitive | ` bool` | ` rw` | ` False` | None |
| total_learning_guard_key | ` Optional[str]` | ` rw` | ` None` | None |
| total_learning_guard_max | ` Optional[float]` | ` rw` | ` None` | None |
| total_learning_guard_max_gap_seconds | ` int` | ` rw` | ` 600` | None |
| total_measurement_key | ` Optional[str]` | ` rw` | ` None` | Optional whole-plant power channel when individual plane measurements are unavailable. |
| training_delay_minutes | ` int` | ` rw` | ` 15` | None |
| transposition_model | ` str` | ` rw` | ` perez` | pvlib sky-diffuse transposition model: isotropic, klucher, haydavies, reindl, king or perez. |
| trend_enabled | ` bool` | ` rw` | ` True` | None |
| validation_days | ` int` | ` rw` | ` 7` | None |
| weather_models | ` list[str]` | ` rw` | ` ['best_match']` | Open-Meteo weather models to request. Listing more than one turns the input into a poor-man's ensemble: the members are averaged per variable, which is the cheapest reliable way to cut irradiance forecast error. Costs no extra API calls. |
| weather_response_enabled | ` bool` | ` rw` | ` True` | Archive received model weather and learn horizon/regime corrections; activate only after issued-candidate validation. |
:::
<!-- 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": {
"adaptive": {
"backend": "local",
"resolution_minutes": 15,
"forecast_days": null,
"past_days": null,
"weather_models": [
"best_match",
"icon_d2"
],
"transposition_model": "perez",
"albedo": 0.25,
"inverter_efficiency": 0.96,
"temperature_coefficient": -0.36,
"apply_iam": true,
"shift_to_interval_start": true,
"calibration_enabled": false,
"calibration_days": 30,
"calibration_reference_days": 30,
"calibration_outage_filter_enabled": true,
"calibration_outage_threshold": 0.55,
"calibration_min_healthy_days": 3,
"calibration_azimuth_bin_degrees": 45,
"calibration_prior_kwh": 5.0,
"calibration_min_factor": 0.5,
"calibration_max_factor": 1.5,
"regional_weather_model": "icon_d2",
"regional_horizon_hours": 6.0,
"learning_days": 21,
"min_training_days": 5,
"max_ac_power_w": 0.0,
"nominal_total_peakpower_kw": null,
"diagnostics_days": 7,
"archive_retention_days": 60,
"nowcast_enabled": true,
"trend_enabled": true,
"solar_response_enabled": true,
"weather_response_enabled": true,
"correction_mode": "auto",
"validation_days": 7,
"min_validation_days": 3,
"min_validation_samples": 32,
"min_validation_improvement": 0.02,
"training_delay_minutes": 15,
"total_measurement_key": null,
"total_curtailment_sensitive": false,
"total_curtailment_key": null,
"total_learning_guard_key": null,
"total_learning_guard_max": null,
"total_learning_guard_max_gap_seconds": 600
}
}
}
` ``
<!-- pyml enable line-length -->