Um den Code mit deinen eigenen Werten zu verwenden, musst du die folgenden Platzhalter in den angegebenen Zeilen ersetzen: Zeile 13: HA_URL = '[YOUR_HA_URL]'Ersetze [YOUR_HA_URL] durch die URL deiner Home Assistant Instanz. Beispiel: HA_URL = 'http://homeassistant.local:8123' Zeile 14: HA_TOKEN = '[YOUR_HA_TOKEN]'Ersetze [YOUR_HA_TOKEN] durch deinen Home Assistant Long-Lived Access Token. Beispiel: HA_TOKEN = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' Zeile 15: WEATHER_ENTITY = '[YOUR_WEATHER_ENTITY]'Ersetze [YOUR_WEATHER_ENTITY] durch die Entität deiner Wettervorhersage in Home Assistant. Beispiel: WEATHER_ENTITY = 'weather.my_city' Zeile 17: CONFIG_FILE = '[YOUR_CONFIG_FILE]'Ersetze [YOUR_CONFIG_FILE] durch den Pfad und Namen deiner MQTT-Konfigurationsdatei (JSON-Format). Beispiel: CONFIG_FILE = 'config.json' Zeile 18: MODEL_FILE = '[YOUR_MODEL_FILE]'Ersetze [YOUR_MODEL_FILE] durch den Pfad und Namen deiner trainierten Modell-Datei (joblib-Format). Beispiel: MODEL_FILE = 'solar_model.joblib' Zeile 49: device_info = { "identifiers": ["[YOUR_DEVICE_IDENTIFIER]"], "name": "[YOUR_DEVICE_NAME]", "manufacturer": "[YOUR_MANUFACTURER]", "model": "[YOUR_MODEL_NAME]" }Ersetze die folgenden Platzhalter in der device_info-Dictionary:[YOUR_DEVICE_IDENTIFIER]: Ein eindeutiger Bezeichner für dein Gerät (z. B. 'solar_forecast_pi_v2'). [YOUR_DEVICE_NAME]: Der Name deines Geräts (z. B. 'Solar Forecast'). [YOUR_MANUFACTURER]: Der Herstellername (z. B. 'Eike/Gemini Project'). [YOUR_MODEL_NAME]: Der Modellname (z. B. 'ML Forecast v2.0'). code import pandas as pd import json import logging import joblib import requests from datetime import datetime, timedelta from paho.mqtt import publish # --- Logging Setup --- logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') # ===== FINALE KONFIGURATION ===== HA_URL = '[YOUR_HA_URL]' HA_TOKEN = '[YOUR_HA_TOKEN]' WEATHER_ENTITY = '[YOUR_WEATHER_ENTITY]' CONFIG_FILE = '[YOUR_CONFIG_FILE]' MODEL_FILE = '[YOUR_MODEL_FILE]' # ================================ # --- Lade MQTT-Konfiguration --- try: with open(CONFIG_FILE, 'r') as f: config = json.load(f) mqtt_config = config['mqtt'] except (FileNotFoundError, KeyError) as e: logging.error(f"Fehler in der Konfigurationsdatei '{CONFIG_FILE}': {e}") exit() # --- Lade das trainierte Modell --- try: model = joblib.load(MODEL_FILE) logging.info(f"Modell '{MODEL_FILE}' erfolgreich geladen.") except FileNotFoundError: logging.error(f"Modell-Datei '{MODEL_FILE}' nicht gefunden. Bitte zuerst train_model.py ausführen.") exit() def publish_mqtt(topic, value, retain=False): """Veröffentlicht einen Wert mit der einfachen 'publish.single' Methode.""" try: auth = {'username': mqtt_config['user'], 'password': mqtt_config['password']} publish.single(topic, payload=value, qos=1, retain=retain, hostname=mqtt_config['broker'], port=mqtt_config['port'], auth=auth) logging.info(f"MQTT: '{topic}' = {str(value)[:70]}... gesendet.") except Exception as e: logging.error(f"MQTT-Fehler: {e}") def publish_discovery_messages(): """Sendet die Konfigurationsnachrichten für MQTT Discovery.""" logging.info("Sende MQTT Discovery Nachrichten für die Sensoren...") device_info = { "identifiers": ["[YOUR_DEVICE_IDENTIFIER]"], "name": "[YOUR_DEVICE_NAME]", "manufacturer": "[YOUR_MANUFACTURER]", "model": "[YOUR_MODEL_NAME]" } today_config = { "name": "Solarprognose Heute", "unique_id": "solar_forecast_today", "state_topic": "solar_forecast/today", "unit_of_measurement": "kWh", "icon": "mdi:solar-power", "state_class": "measurement", "device": device_info } publish_mqtt("homeassistant/sensor/solar_forecast/today/config", json.dumps(today_config), retain=True) tomorrow_config = { "name": "Solarprognose Morgen", "unique_id": "solar_forecast_tomorrow", "state_topic": "solar_forecast/tomorrow", "unit_of_measurement": "kWh", "icon": "mdi:weather-sunny", "state_class": "measurement", "device": device_info } publish_mqtt("homeassistant/sensor/solar_forecast/tomorrow/config", json.dumps(tomorrow_config), retain=True) def get_weather_forecast(): headers = { "Authorization": f"Bearer {HA_TOKEN}", "content-type": "application/json" } url = f"{HA_URL}/api/services/weather/get_forecasts?return_response=true" try: response = requests.post(url, headers=headers, json={"entity_id": WEATHER_ENTITY, "type": "hourly"}) response.raise_for_status() logging.info("Wettervorhersage erfolgreich von HA abgerufen.") return response.json() except requests.exceptions.RequestException as e: logging.error(f"Fehler bei der Wettervorhersage-Abfrage: {e}") if e.response is not None: logging.error(f"Antwort von HA: {e.response.text}") return None def prepare_features(forecast_data): df = pd.DataFrame(forecast_data) df['timestamp'] = pd.to_datetime(df['datetime']) df.set_index('timestamp', inplace=True) df.rename(columns={'temperature': 'temperature_c', 'humidity': 'humidity_percent', 'pressure': 'pressure_hpa', 'wind_speed': 'wind_speed_kmh', 'cloud_coverage': 'cloud_coverage'}, inplace=True) df['hour'] = df.index.hour df['day_of_year'] = df.index.dayofyear df['month'] = df.index.month training_features = ['radiation_wm2', 'temperature_c', 'humidity_percent', 'pressure_hpa', 'wind_speed_kmh', 'lux', 'hour', 'day_of_year', 'month'] if 'cloud_coverage' in df.columns: df['radiation_wm2'] = 1000 - (df['cloud_coverage'] * 9.5) df.loc[df['radiation_wm2'] < 0, 'radiation_wm2'] = 0 df['lux'] = df['radiation_wm2'] * 120 else: df['radiation_wm2'] = 0; df['lux'] = 0 for col in training_features: if col not in df.columns: df[col] = 0 return df[training_features] def main(): """Hauptfunktion des Skripts.""" publish_discovery_messages() forecast_response = get_weather_forecast() if not forecast_response: return try: forecast_data = forecast_response['service_response'][WEATHER_ENTITY]['forecast'] except KeyError: logging.error("Konnte 'forecast' in der API-Antwort nicht finden."); return features_df = prepare_features(forecast_data) predictions_hourly = model.predict(features_df) features_df['predicted_yield'] = predictions_hourly features_df.loc[features_df['predicted_yield'] < 0, 'predicted_yield'] = 0 today = datetime.now().date() tomorrow = today + timedelta(days=1) yield_today = features_df[features_df.index.date == today]['predicted_yield'].sum() yield_tomorrow = features_df[features_df.index.date == tomorrow]['predicted_yield'].sum() logging.info(f"Prognose für HEUTE: {yield_today:.2f} kWh") logging.info(f"Prognose für MORGEN: {yield_tomorrow:.2f} kWh") publish_mqtt("solar_forecast/today", round(yield_today, 2)) publish_mqtt("solar_forecast/tomorrow", round(yield_tomorrow, 2)) if __name__ == '__main__': main()