Skip to content

Commit

Permalink
Update future forecast dampening when set
Browse files Browse the repository at this point in the history
  • Loading branch information
autoSteve committed Oct 24, 2024
1 parent 87f1375 commit 4c86eb8
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 0 deletions.
13 changes: 13 additions & 0 deletions custom_components/solcast_solar/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,14 @@ def update_options():
await solcast.refresh_granular_dampening_data() # Ensure latest file content gets updated
solcast.granular_dampening[site] = [float(sp[i]) for i in range(0,len(sp))]
await solcast.serialise_granular_dampening()
old_damp = opt.get(SITE_DAMP, False)
opt[SITE_DAMP] = True # Set "hidden" option.
if opt[SITE_DAMP] == old_damp:
await solcast.reapply_forward_dampening()
await coordinator.solcast.build_forecast_data()
coordinator.set_data_updated(True)
await coordinator.update_integration_listeners()
coordinator.set_data_updated(False)

hass.config_entries.async_update_entry(entry, options=opt)
except intent.IntentHandleError as e:
Expand Down Expand Up @@ -569,11 +576,13 @@ def changed(config):
# Config changes, which when changed will cause a forecast recalculation only, without reload.
# Dampening must be the first check with the code as-is...
if not reload:
damp_changed = False
d = {}
for i in range(0,24):
d.update({f"{i}": entry.options[f"damp{i:02}"]})
if changed(f"damp{i:02}"):
recalc = True
damp_changed = True
if recalc:
coordinator.solcast.damp = d

Expand All @@ -582,13 +591,17 @@ def changed(config):
respline = changed(BRK_ESTIMATE) or changed(BRK_ESTIMATE10) or changed(BRK_ESTIMATE90) or changed(BRK_SITE) or changed(KEY_ESTIMATE)

if changed(SITE_DAMP):
damp_changed = True
if not entry.options[SITE_DAMP]:
if coordinator.solcast.allow_granular_dampening_reset():
coordinator.solcast.granular_dampening = {}
await coordinator.solcast.serialise_granular_dampening()
_LOGGER.debug("Granular dampening file reset")
else:
_LOGGER.debug("Granular dampening file not reset")
if damp_changed:
recalc = True
await coordinator.solcast.reapply_forward_dampening()

if reload:
determination = 'The integration will reload'
Expand Down
44 changes: 44 additions & 0 deletions custom_components/solcast_solar/solcastapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -2177,6 +2177,50 @@ def __get_dampening_factor(self, site: str, z: int, valid_granular_dampening: bo
else:
return self.damp.get(f"{z.hour}", 1.0)

async def reapply_forward_dampening(self):
"""Re-apply dampening to forward forecasts."""
if not self.__valid_granular_dampening():
_LOGGER.warning("Invalid dampening configuration, so no re-appying dampening to future forecasts")
return
_LOGGER.debug("Re-applying future dampening")
for site in self.sites:
site = site['resource_id']

# Load the forecast history.
try:
forecasts_undampened_future = [
forecast for forecast in self._data_undampened['siteinfo'][site]['forecasts'] if forecast['period_start'] >= dt.now(timezone.utc)
]
except:
forecasts_undampened_future = {}
if forecasts_undampened_future == {}:
return
try:
forecasts = {forecast["period_start"]: forecast for forecast in self._data['siteinfo'][site]['forecasts']}
except:
forecasts = {}
if forecasts == {}:
return

# Apply dampening to the new data
for forecast in sorted(forecasts_undampened_future, key=itemgetter("period_start")):
period_start = forecast["period_start"]
pv = round(forecast["pv_estimate"], 4)
pv10 = round(forecast["pv_estimate10"], 4)
pv90 = round(forecast["pv_estimate90"], 4)

# Retrieve the dampening factor for the period, and dampen the estimates.
dampening_factor = self.__get_dampening_factor(site, period_start.astimezone(self._tz), True)
pv_dampened = round(pv * dampening_factor, 4)
pv10_dampened = round(pv10 * dampening_factor, 4)
pv90_dampened = round(pv90 * dampening_factor, 4)

# Add or update the new entries.
self.__forecast_entry_update(forecasts, period_start, pv_dampened, pv10_dampened, pv90_dampened)

forecasts = sorted(list(forecasts.values()), key=itemgetter("period_start"))
self._data['siteinfo'].update({site:{'forecasts': copy.deepcopy(forecasts)}})

async def __http_data_call(self, site=None, api_key=None, do_past=False, force=False) -> bool:
"""Request forecast data via the Solcast API.
Expand Down

0 comments on commit 4c86eb8

Please sign in to comment.