From a0cdfee4866594b3147aebe990fb3091beaa2bf4 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 26 May 2026 19:45:07 +0000 Subject: [PATCH 1/3] forecastsolar: increase refresh interval to ~80 min (18 calls/day) Providers like fcsolar and solarprognose allow only 20 API calls per day. The previous setting shared TIME_BETWEEN_UTILITY_API_CALLS (15 min) with tariff APIs, which could exhaust the daily quota in ~5 hours. A dedicated TIME_BETWEEN_SOLAR_API_CALLS constant (24/18 * 60 * 60 = 4800 s, ~80 min) limits solar fetches to 18 per day, leaving 2 requests in reserve for restarts or transient errors. https://claude.ai/code/session_01Fje2KBxRp5jHNSsSvEFwUp --- src/batcontrol/core.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/batcontrol/core.py b/src/batcontrol/core.py index b318711..99609fb 100644 --- a/src/batcontrol/core.py +++ b/src/batcontrol/core.py @@ -43,6 +43,9 @@ # Interval between evaluations in seconds TIME_BETWEEN_EVALUATIONS = EVALUATIONS_EVERY_MINUTES * 60 TIME_BETWEEN_UTILITY_API_CALLS = 900 # 15 Minutes +# 18 calls/day leaves 2 in reserve (providers allow 20/day). +# Formula: 24h / 18 calls * 60 min/h * 60 s/min +TIME_BETWEEN_SOLAR_API_CALLS = int(24 / 18 * 60 * 60) # ~80 min MIN_FORECAST_HOURS = 1 # Minimum required forecast hours FORECAST_TOLERANCE = 3 # Acceptable tolerance for forecast hours @@ -208,7 +211,7 @@ def __init__(self, configdict: dict): self.fc_solar = solar_factory.create_solar_provider( self.pvsettings, self.timezone, - TIME_BETWEEN_UTILITY_API_CALLS, + TIME_BETWEEN_SOLAR_API_CALLS, DELAY_EVALUATION_BY_SECONDS, requested_provider=config.get( 'solar_forecast_provider', 'fcsolarapi'), From 4d326fc39e5befb1fadb1df4ff3423cf7f3373db Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 26 May 2026 19:46:41 +0000 Subject: [PATCH 2/3] forecastsolar/solarprognose: enforce 80 min refresh interval SolarPrognose allows only 20 API calls per day. Using 18 of them leaves 2 in reserve for restarts or errors (24h / 18 calls = ~80 min interval). The rate-limit constraint belongs to the provider class, not to core.py, so the interval is hardcoded in the super().__init__ call rather than relying on the generic TIME_BETWEEN_UTILITY_API_CALLS. https://claude.ai/code/session_01Fje2KBxRp5jHNSsSvEFwUp --- src/batcontrol/core.py | 5 +---- src/batcontrol/forecastsolar/solarprognose.py | 5 ++++- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/batcontrol/core.py b/src/batcontrol/core.py index 99609fb..b318711 100644 --- a/src/batcontrol/core.py +++ b/src/batcontrol/core.py @@ -43,9 +43,6 @@ # Interval between evaluations in seconds TIME_BETWEEN_EVALUATIONS = EVALUATIONS_EVERY_MINUTES * 60 TIME_BETWEEN_UTILITY_API_CALLS = 900 # 15 Minutes -# 18 calls/day leaves 2 in reserve (providers allow 20/day). -# Formula: 24h / 18 calls * 60 min/h * 60 s/min -TIME_BETWEEN_SOLAR_API_CALLS = int(24 / 18 * 60 * 60) # ~80 min MIN_FORECAST_HOURS = 1 # Minimum required forecast hours FORECAST_TOLERANCE = 3 # Acceptable tolerance for forecast hours @@ -211,7 +208,7 @@ def __init__(self, configdict: dict): self.fc_solar = solar_factory.create_solar_provider( self.pvsettings, self.timezone, - TIME_BETWEEN_SOLAR_API_CALLS, + TIME_BETWEEN_UTILITY_API_CALLS, DELAY_EVALUATION_BY_SECONDS, requested_provider=config.get( 'solar_forecast_provider', 'fcsolarapi'), diff --git a/src/batcontrol/forecastsolar/solarprognose.py b/src/batcontrol/forecastsolar/solarprognose.py index 0f8ee4f..17effc9 100644 --- a/src/batcontrol/forecastsolar/solarprognose.py +++ b/src/batcontrol/forecastsolar/solarprognose.py @@ -62,8 +62,11 @@ def __init__(self, pvinstallations, timezone, min_time_between_api_calls, delay_evaluation_by_seconds: Delay for API evaluation target_resolution: Target resolution in minutes (15 or 60) """ + # 18 calls/day leaves 2 in reserve out of the 20 allowed per day. + # Ignore the generic interval from core and enforce the provider limit here. + min_refresh = int(24 / 18 * 60 * 60) # ~80 min super().__init__(pvinstallations, timezone, - min_time_between_api_calls, delay_evaluation_by_seconds, + min_refresh, delay_evaluation_by_seconds, target_resolution=target_resolution, native_resolution=60) # SolarPrognose provides hourly data From 85078e573cf6fefb1b6c0a3240bf1b9b54a0b9da Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 27 May 2026 04:59:50 +0000 Subject: [PATCH 3/3] forecastsolar/solarprognose: fix interval arithmetic and respect caller minimum - Replace float expression int(24/18*60*60) with integer floor division (24 * 60 * 60 // 18 = 4800 s exactly) to avoid IEEE 754 rounding risk. - Use max(min_time_between_api_calls, _provider_min) so the provider's rate-limit floor is enforced while larger values from the caller are still respected. https://claude.ai/code/session_01Fje2KBxRp5jHNSsSvEFwUp --- src/batcontrol/forecastsolar/solarprognose.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/batcontrol/forecastsolar/solarprognose.py b/src/batcontrol/forecastsolar/solarprognose.py index 17effc9..3ece764 100644 --- a/src/batcontrol/forecastsolar/solarprognose.py +++ b/src/batcontrol/forecastsolar/solarprognose.py @@ -62,11 +62,11 @@ def __init__(self, pvinstallations, timezone, min_time_between_api_calls, delay_evaluation_by_seconds: Delay for API evaluation target_resolution: Target resolution in minutes (15 or 60) """ - # 18 calls/day leaves 2 in reserve out of the 20 allowed per day. - # Ignore the generic interval from core and enforce the provider limit here. - min_refresh = int(24 / 18 * 60 * 60) # ~80 min + # Provider allows 20 calls/day; use 18 to leave 2 in reserve (~80 min). + # Integer arithmetic avoids float rounding; max() respects larger caller values. + _provider_min = 24 * 60 * 60 // 18 # 4800 s super().__init__(pvinstallations, timezone, - min_refresh, delay_evaluation_by_seconds, + max(min_time_between_api_calls, _provider_min), delay_evaluation_by_seconds, target_resolution=target_resolution, native_resolution=60) # SolarPrognose provides hourly data