import sys import mysql.connector as pymysql from mysql.connector import connect, Error import requests import datetime import time import socket import traceback import konfig # MySQL-Datenbankverbindung. Zugangsdaten stehen in config.ini, siehe konfig.py. DB_CONFIG = konfig.datenbank("alarm") wled_url = "http://192.168.179.139/json" # URL zur WLED JSON API LOG_SERVER = ("localhost", 13377) # UDP Logserver # UDP Logging Funktion def send_log(message): sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) log_message = f"{datetime.datetime.now().strftime('%b %d %H:%M:%S')} alarm_scheduler: {message}" sock.sendto(log_message.encode(), LOG_SERVER) sock.close() def is_holiday(): today_str = datetime.datetime.today().strftime("%Y-%m-%d") conn = pymysql.connect(**DB_CONFIG) cursor = conn.cursor() query = "SELECT COUNT(*) FROM feiertage WHERE datetime = %s" cursor.execute(query, (today_str,)) result = cursor.fetchone() conn.close() return result[0] > 0 def is_school_holiday(): today_str = datetime.datetime.today().strftime("%Y-%m-%d") conn = pymysql.connect(**DB_CONFIG) cursor = conn.cursor() query = "SELECT COUNT(*) FROM ferien WHERE date_from <= %s AND date_to >= %s" cursor.execute(query, (today_str, today_str)) result = cursor.fetchone() conn.close() return result[0] > 0 def get_active_alarms(): today = datetime.datetime.today() today_str = today.strftime("%Y-%m-%d") weekday_map = {0: "mo", 1: "di", 2: "mi", 3: "do", 4: "fr", 5: "sa", 6: "so"} weekday_col = weekday_map[today.weekday()] holiday = is_holiday() school_holiday = is_school_holiday() conn = pymysql.connect(**DB_CONFIG) cursor = conn.cursor() query = f""" SELECT id, TIME_FORMAT(time_1, '%H:%i:%s'), mode FROM alarmtime WHERE onoff != -1 AND {weekday_col} != -1 AND (wecked IS NULL OR wecked != '{today_str}') """ if holiday: query += " AND mode NOT IN ('arbeit', 'schule')" elif school_holiday: query += " AND mode != 'schule'" cursor.execute(query) alarms = cursor.fetchall() conn.close() return [(alarm[0], alarm[1]) for alarm in alarms] def trigger_wled_playlist(): data = {"ps": 5} # Beispiel: Playlist 1 aktivieren headers = {"Content-Type": "application/json"} for attempt in range(5): try: response = requests.post(wled_url, json=data, headers=headers) send_log(f"WLED Response (Attempt {attempt + 1}): {response.text}") try: if response.json().get("success"): return except ValueError: send_log(f"Value error: {response.text}") # Falls die Antwort kein gültiges JSON ist, weitermachen except: send_log(f"No response (Attempt {attempt + 1}): {traceback.print_exc()}") time.sleep(4) # Kurze Wartezeit zwischen Versuchen def mark_alarm_as_executed(alarm_id): today_str = datetime.datetime.today().strftime("%Y-%m-%d") conn = pymysql.connect(**DB_CONFIG) cursor = conn.cursor() query = "UPDATE alarmtime SET wecked = %s WHERE id = %s" cursor.execute(query, (today_str, alarm_id)) conn.commit() conn.close() def main(): last_db_check = 0 active_alarms = [] while True: now = time.time() # Nur alle 5 Minuten die Datenbankabfrage ausführen if now - last_db_check >= 300: active_alarms = get_active_alarms() last_db_check = now current_time = datetime.datetime.now().strftime("%H:%M:%S") for alarm_id, alarm_time in active_alarms: if current_time >= alarm_time: send_log(f"Triggering WLED Playlist at {alarm_time}") trigger_wled_playlist() mark_alarm_as_executed(alarm_id) active_alarms = get_active_alarms() time.sleep(20) # Überprüfung alle 20 sec if __name__ == "__main__": main()