Skip to content

Commit 799e153

Browse files
committed
Simplify detection whether future or past data shall be collected from the solcast API
1 parent da16661 commit 799e153

File tree

3 files changed

+15
-47
lines changed

3 files changed

+15
-47
lines changed

source/inverter_charge_controller.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -676,7 +676,7 @@ def _get_solar_data(
676676
if not timeframe_start or not timeframe_end:
677677
raise ValueError("Timeframe start and end must be provided to retrieve solar data if the cache is empty")
678678

679-
solar_data = self.sun_forecast_handler.retrieve_solar_data(timeframe_start, timeframe_end)
679+
solar_data = self.sun_forecast_handler.retrieve_solar_data(True)
680680
self._set_cache_key(cache_key, solar_data)
681681
return solar_data
682682

source/main.py

+4-7
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,13 @@ def write_solar_forecast_and_history_to_db() -> None:
4747
logger.log.info(f"Next wakeup time to log solar forecast data is at {next_wakeup_time}")
4848
pause.until(next_wakeup_time)
4949

50-
start, end = _get_morning_and_evening_timestamp_of_today(morning_time, evening_time)
5150
logger.write_newlines_to_log_file()
52-
logger.log.info(f"Waking up to log solar forecast data from {start} to {end}")
53-
if TimeHandler.get_time().hour == morning_time.hour:
54-
start += timedelta(minutes=2)
55-
else:
56-
end -= timedelta(minutes=2)
51+
logger.log.info("Waking up to log solar data of today")
5752

5853
try:
59-
sun_forecast_handler.retrieve_solar_data_from_api(start, end)
54+
# We call this function instead of retrieve_solar_data to ensure not writing debug data into the DB
55+
need_to_retrieve_future_data = next_wakeup_time.hour == morning_time.hour
56+
sun_forecast_handler.retrieve_solar_data_from_api(need_to_retrieve_future_data)
6057
except requests.exceptions.HTTPError as e:
6158
if e.response.status_code != 429:
6259
raise e

source/sun_forecast_handler.py

+10-39
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ def calculate_min_and_max_of_soc_in_timeframe(
129129
)
130130
return minimum_soc, maximum_soc
131131

132-
def retrieve_solar_data(self, timeframe_start: datetime, timeframe_end: datetime) -> dict[str, Power]:
132+
def retrieve_solar_data(self, retrieve_future_data: bool) -> dict[str, Power]:
133133
"""
134134
Retrieves solar data for a specified timeframe either from the solar forecast API or a debug solar output
135135
depending on the configuration and API response.
@@ -138,8 +138,7 @@ def retrieve_solar_data(self, timeframe_start: datetime, timeframe_end: datetime
138138
(too many requests) from the solar forecast API, the method falls back to using a debug solar data output.
139139
140140
Args:
141-
timeframe_start: Start date and time of the timeframe for which solar data is requested.
142-
timeframe_end: End date and time of the timeframe for which solar data is requested.
141+
retrieve_future_data: Whether to retrieve data for the future or the past.
143142
144143
Returns:
145144
A dictionary where keys represent specific times and values represent the forecasted power at those times.
@@ -152,42 +151,39 @@ def retrieve_solar_data(self, timeframe_start: datetime, timeframe_end: datetime
152151
return self._get_debug_solar_data()
153152

154153
try:
155-
return self.retrieve_solar_data_from_api(timeframe_start, timeframe_end)
154+
return self.retrieve_solar_data_from_api(retrieve_future_data)
156155
except requests.exceptions.HTTPError as e:
157156
if e.response.status_code != 429:
158157
raise e
159158
self.log.warning("Too many requests to the solar forecast API, using the debug solar output instead")
160159
return self._get_debug_solar_data()
161160

162-
def retrieve_solar_data_from_api(self, timeframe_start: datetime, timeframe_end: datetime) -> dict[str, Power]:
161+
def retrieve_solar_data_from_api(self, retrieve_future_data: bool) -> dict[str, Power]:
163162
"""
164163
Retrieves solar data from an API over a specified timeframe. The function collects photovoltaic forecasts and/or
165164
historic data for multiple rooftops, processes the data into a dictionary mapping timestamps to cumulative power
166165
values, and writes relevant data to a database.
167166
168167
Args:
169-
timeframe_start (datetime): The start of the timeframe for which to retrieve solar data.
170-
timeframe_end (datetime): The end of the timeframe for which to retrieve solar data.
168+
retrieve_future_data: Whether to retrieve data for the future or the past.
171169
172170
Returns:
173171
dict[str, Power]: A dictionary where keys represent timestamps (as ISO format strings) and values are Power
174172
objects corresponding to the cumulative power generation.
175173
"""
176174
rooftop_ids = self._get_rooftop_ids()
177175

178-
need_to_retrieve_forecast_data, need_to_retrieve_historic_data = self._need_to_retrieve_data(
179-
timeframe_start, timeframe_end
180-
)
181-
182176
solar_data = {}
183177

184178
now = TimeHandler.get_time().isoformat()
185179
for rooftop_id in rooftop_ids:
186180
data_for_rooftop = []
187-
if need_to_retrieve_historic_data:
188-
data_for_rooftop += self.retrieve_historic_data_from_api(rooftop_id)
189-
if need_to_retrieve_forecast_data:
181+
if retrieve_future_data:
182+
self.log.debug("Need to retrieve forecast data")
190183
data_for_rooftop += self.retrieve_forecast_data_from_api(rooftop_id)
184+
else:
185+
self.log.debug("Need to retrieve historic data")
186+
data_for_rooftop += self.retrieve_historic_data_from_api(rooftop_id)
191187
self.timeframe_duration = parse_duration(data_for_rooftop[0]["period"])
192188
for timeslot in data_for_rooftop:
193189
period_start = (
@@ -248,31 +244,6 @@ def _get_rooftop_ids() -> list[str]:
248244
rooftop_ids.append(rooftop_id_2)
249245
return rooftop_ids
250246

251-
def _need_to_retrieve_data(self, timeframe_start: datetime, timeframe_end: datetime) -> tuple[bool, bool]:
252-
"""
253-
This method evaluates whether either historic data or forecast data needs to be retrieved based on the given
254-
start and end timeframes in comparison to the current time.
255-
256-
Args:
257-
timeframe_start (datetime): The start of the timeframe for evaluation.
258-
timeframe_end (datetime): The end of the timeframe for evaluation.
259-
260-
Returns:
261-
tuple[bool, bool]: A tuple containing two boolean values:
262-
- The first boolean indicates whether retrieval of forecast data is required.
263-
- The second boolean indicates whether retrieval of historic data is required.
264-
"""
265-
need_to_retrieve_historic_data = False
266-
need_to_retrieve_forecast_data = False
267-
now_minus_offset = TimeHandler.get_time(sanitize_seconds=True) - timedelta(seconds=1)
268-
if timeframe_start >= now_minus_offset or timeframe_end >= now_minus_offset:
269-
self.log.debug("Need to retrieve forecast data")
270-
need_to_retrieve_forecast_data = True
271-
if timeframe_start <= now_minus_offset:
272-
self.log.debug("Need to retrieve historic data")
273-
need_to_retrieve_historic_data = True
274-
return need_to_retrieve_forecast_data, need_to_retrieve_historic_data
275-
276247
@staticmethod
277248
def _calculate_energy_usage_in_timeframe(
278249
timeframe_start: datetime,

0 commit comments

Comments
 (0)