Files
energy_price_model_prediction/update_weather.py
2025-11-14 10:33:23 +01:00

201 lines
7.0 KiB
Python
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Script voor het INCREMENTEEL ophalen van weerdata voor Amersfoort
en dit direct in MySQL op te slaan (met 'Upsert' logica).
Het vult de database aan vanaf de laatst bekende datum tot NU.
"""
import requests
import mysql.connector
from mysql.connector import Error
import pandas as pd
from datetime import datetime, timedelta
import time
# ===== CONFIGURATIE =====
LOCATIE = "Amersfoort"
LATITUDE = 52.15
LONGITUDE = 5.39
# --- MySQL Database Config ---
# VUL DIT IN MET JOUW GEGEVENS
DB_CONFIG = {
'host': '192.168.178.201',
'user': 'energy_prices_user',
'password': 'kS9R*xp17ZwCD@CV&E^N',
'database': 'energy_prices',
'port': 3307
}
# ========================
def haal_recente_weerdata_op(aantal_dagen_terug):
"""
Haal recente/huidige weerdata op via de Open-Meteo FORECAST API
"""
url = "https://api.open-meteo.com/v1/forecast" # Dit is de Forecast API
params = {
"latitude": LATITUDE,
"longitude": LONGITUDE,
"hourly": [
"temperature_2m",
"apparent_temperature",
"precipitation",
"wind_speed_10m",
"wind_direction_10m",
"relative_humidity_2m",
"cloud_cover",
"surface_pressure",
"shortwave_radiation"
],
"timezone": "Europe/Amsterdam",
"past_days": int(aantal_dagen_terug) # Vraag data op van de afgelopen X dagen
}
print(f"\n📡 Data ophalen voor de afgelopen {aantal_dagen_terug} dagen (tot nu)...")
try:
response = requests.get(url, params=params, timeout=60)
response.raise_for_status()
print(f"✅ Data succesvol opgehaald van Open-Meteo!")
return response.json()
except requests.exceptions.RequestException as e:
print(f"❌ Fout bij ophalen data: {e}")
return None
def parse_api_data(data):
"""Converteer de JSON response van de Forecast API naar een DataFrame"""
hourly = data['hourly']
df = pd.DataFrame({
"datum_tijd": pd.to_datetime(hourly['time']),
"locatie": LOCATIE,
"temperatuur": hourly['temperature_2m'],
"gevoelstemperatuur": hourly['apparent_temperature'],
"neerslag": hourly['precipitation'],
"wind_snelheid": hourly['wind_speed_10m'],
"wind_richting": hourly['wind_direction_10m'],
"luchtvochtigheid": hourly['relative_humidity_2m'],
"bewolking": hourly['cloud_cover'],
"luchtdruk": hourly['surface_pressure'],
"zonnestraling": hourly['shortwave_radiation']
})
# Vervang 'None' of 'NaN' door None (dat MySQL als NULL begrijpt)
df = df.where(pd.notnull(df), None)
return df
def sla_data_op_mysql(conn, data_df):
"""Sla data op in MySQL database met 'Upsert' logica"""
if data_df.empty:
print("Geen data om op te slaan.")
return 0
cursor = conn.cursor()
print(f" ----------------------------------------------------------------------")
print(f"   {len(data_df)} uurlijkse records voor MySQL verwerken (Upsert)...")
# Maak een lijst van tuples voor de 'executemany'
batch = [tuple(row) for row in data_df.itertuples(index=False)]
# De "Upsert" query.
# Dit werkt perfect omdat 'datum_tijd' je PRIMARY KEY is.
query = """
INSERT INTO amersfoort_weer_uurlijks
(datum_tijd, locatie, temperatuur, gevoelstemperatuur, neerslag,
wind_snelheid, wind_richting, luchtvochtigheid, bewolking, luchtdruk, zonnestraling)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
ON DUPLICATE KEY UPDATE
locatie = VALUES(locatie),
temperatuur = VALUES(temperatuur),
gevoelstemperatuur = VALUES(gevoelstemperatuur),
neerslag = VALUES(neerslag),
wind_snelheid = VALUES(wind_snelheid),
wind_richting = VALUES(wind_richting),
luchtvochtigheid = VALUES(luchtvochtigheid),
bewolking = VALUES(bewolking),
luchtdruk = VALUES(luchtdruk),
zonnestraling = VALUES(zonnestraling);
"""
try:
cursor.executemany(query, batch)
conn.commit()
# rowcount bij 'upsert' telt 1 voor een INSERT, en 2 voor een UPDATE
print(f"{cursor.rowcount} records succesvol verwerkt (inserted/updated).")
return cursor.rowcount
except Error as e:
print(f"❌ Fout bij opslaan naar MySQL: {e}")
conn.rollback()
return 0
def main():
"""Hoofdfunctie"""
print("="*70)
print(f"INCREMENTELE WEERDATA UPDATE VOOR {LOCATIE} -> MYSQL")
print("="*70)
conn = None
try:
# 1. Verbind met DB en vind laatste datum
print("💾 Verbinden met MySQL database...")
conn = mysql.connector.connect(**DB_CONFIG)
cursor = conn.cursor()
print("✅ Succesvol verbonden met MySQL.")
cursor.execute("SELECT MAX(datum_tijd) FROM amersfoort_weer_uurlijks")
result = cursor.fetchone()
last_date_in_db = result[0] if result[0] else None
aantal_dagen_terug = 1
if last_date_in_db is None:
print("Database is leeg. 16 dagen data wordt opgehaald.")
aantal_dagen_terug = 16 # Maximaal wat de API toestaat
else:
print(f"Laatste datum in database: {last_date_in_db}")
# Bereken hoeveel dagen we terug moeten kijken
# +1 voor veiligheid, +1 omdat 'past_days' geen 'vandaag' meerekent
dagen_verschil = (datetime.now() - last_date_in_db).days + 2
aantal_dagen_terug = min(max(1, dagen_verschil), 16)
print(f"Database is {dagen_verschil-2} dagen oud. We halen {aantal_dagen_terug} dag(en) op.")
# 2. Haal recente data op
data = haal_recente_weerdata_op(aantal_dagen_terug)
if data:
# 3. Parse de data naar een DataFrame
all_data_df = parse_api_data(data)
# 4. Filter ALLEEN de data die we nog niet hebben
# We filteren alle data *na* de laatste datum in de DB
""" if last_date_in_db is not None:
# We pakken alle data *na* onze laatste meting
# De 'upsert' query handelt eventuele overlap af
data_om_op_te_slaan = all_data_df[all_data_df['datum_tijd'] > last_date_in_db].copy()
else:
data_om_op_te_slaan = all_data_df.copy() # Alles is nieuw """
# 4. Stuur *alle* opgehaalde data naar MySQL.
# De 'ON DUPLICATE KEY' query regelt de updates en inserts.
data_om_op_te_slaan = all_data_df.copy()
# 5. Sla de data op
if not data_om_op_te_slaan.empty:
sla_data_op_mysql(conn, data_om_op_te_slaan)
else:
print("\n✅ Je database is al volledig up-to-date.")
except Error as e:
print(f"❌ Hoofdfout: {e}")
finally:
if conn and conn.is_connected():
conn.close()
print("Verbinding met MySQL gesloten.")
print(f"\n✅ Klaar! Script voltooid.")
if __name__ == "__main__":
main()