You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kmftools/weather forecast/weather.py

120 lines
4.1 KiB

from astral import LocationInfo
from astral.sun import sun
import pytz
from datetime import datetime
import requests
def fetch_weather_data(api_key, location, logger):
"""
Haalt de weersvoorspelling op van OpenWeatherMap.
Parameters:
- api_key: API sleutel voor OpenWeatherMap
- location: Locatienaam (stad)
- logger: Logger instance
Returns:
- JSON data van de weersvoorspelling
"""
base_url = "https://api.openweathermap.org/data/2.5/forecast"
params = {
'q': location,
'appid': api_key,
'units': 'metric'
}
try:
response = requests.get(base_url, params=params)
response.raise_for_status()
logger.info(f"Weather data fetched successfully for {location}.")
return response.json()
except requests.RequestException as e:
logger.error(f"Error fetching weather data: {e}")
return None
def get_sun_times(utc_datetime, location_name="Rijswijk", country="Netherlands", logger=None):
"""
Haalt de zonsopgang en zonsondergang op voor een bepaalde UTC tijd en locatie.
Returns:
- sunrise, sunset (beide datetime objects in UTC).
"""
location = LocationInfo(location_name, country,
"Europe/Amsterdam", 52.0345, 4.3186)
# Bereken zon-op/zon-onder tijden met Astral
sun_times = sun(location.observer,
date=utc_datetime.date(), tzinfo=pytz.utc)
# Overtuig dat het datetime-objecten zijn
sunrise = sun_times["sunrise"]
sunset = sun_times["sunset"]
if isinstance(sunrise, str): # Als het toch een string is, fix het
sunrise = datetime.fromisoformat(sunrise).replace(tzinfo=pytz.utc)
if isinstance(sunset, str):
sunset = datetime.fromisoformat(sunset).replace(tzinfo=pytz.utc)
if logger:
logger.debug(
f"For {utc_datetime.date()} in {location_name}: Sunrise at {sunrise} , Sunset at {sunset} ")
return sunrise, sunset
def estimate_solar_performance(entry, utc_dt, location, sunrise, sunset, logger):
"""
Schat de zonne-energieproductie op basis van de zonshoogte en weersfactoren.
Parameters:
- entry: JSON entry met de weerdata
- utc_dt: Tijdstip van de voorspelling (UTC)
- location: Naam van de locatie voor berekening van zonsopgang/zonsondergang
- logger: Logger voor debugging
Returns:
- Een percentage (0-100) dat de zonne-energieproductie schat.
"""
# 🚀 Zorg ervoor dat sunrise en sunset datetime-objecten zijn
if isinstance(sunrise, str):
sunrise = datetime.fromisoformat(sunrise).replace(tzinfo=pytz.utc)
if isinstance(sunset, str):
sunset = datetime.fromisoformat(sunset).replace(tzinfo=pytz.utc)
# Temperatuur en bewolking ophalen
temperature = entry["main"]["temp"]
cloudiness = entry["clouds"]["all"] # % bewolking
weather_desc = entry["weather"][0]["description"]
# Logging
logger.debug(
f"UTC: {utc_dt}, Temp: {temperature}, Clouds: {cloudiness}%, Weather: {weather_desc}")
# Stap 1: Bereken een initiële waarde op basis van zonshoogte (factor van 0 tot 1)
if utc_dt < sunrise or utc_dt > sunset:
sun_factor = 0.0 # Nacht
elif utc_dt == sunrise or utc_dt == sunset:
sun_factor = 0.1 # 10% bij zonsopkomst/ondergang
else:
# Bereken de relatieve tijd binnen de zonnedag (0 = zonsopgang, 1 = zonsondergang)
day_fraction = (utc_dt - sunrise) / (sunset - sunrise)
# Gebruik een parabolische curve voor maximale intensiteit op het midden van de dag
sun_factor = -4 * (day_fraction - 0.5) ** 2 + 1
sun_factor = max(0, min(sun_factor, 1)) # Beperken tot 0-1
# Stap 2: Pas weerfactoren toe (bewolking beïnvloedt zonne-intensiteit)
# Omrekenen van % naar 0-1 schaal
weather_factor = (100 - cloudiness) / 100
# Totale zonneprestaties berekenen
solar_performance = sun_factor * weather_factor * 100 # Omzetten naar percentage
# Logging
logger.debug(
f"Sun factor: {sun_factor}, Weather factor: {weather_factor}, Solar performance: {solar_performance:.2f}%")
return round(solar_performance, 2)