diff --git a/backend/app.py b/backend/app.py index 3ea75b49..1c1289f8 100644 --- a/backend/app.py +++ b/backend/app.py @@ -2217,24 +2217,29 @@ def check_printer_status(ip_address: str, timeout: int = 7) -> Tuple[str, bool]: if result == 0: reachable = True try: - # TP-Link Tapo Steckdose mit PyP100 überprüfen - from PyP100 import PyP100 - p100 = PyP100.P100(ip_address, TAPO_USERNAME, TAPO_PASSWORD) - p100.handshake() # Authentifizierung - p100.login() # Login - - # Geräteinformationen abrufen - device_info = p100.getDeviceInfo() + # TP-Link Tapo Steckdose mit zentralem tapo_controller überprüfen + from utils.tapo_controller import tapo_controller + reachable, outlet_status = tapo_controller.check_outlet_status(ip_address) # 🎯 KORREKTE LOGIK: Status auswerten - if device_info.get('device_on', False): - # Steckdose an = Drucker PRINTING (druckt gerade) - status = "printing" - printers_logger.info(f"🖨️ Drucker {ip_address}: PRINTING (Steckdose an - druckt gerade)") + if reachable: + if outlet_status == "on": + # Steckdose an = Drucker PRINTING (druckt gerade) + status = "printing" + printers_logger.info(f"🖨️ Drucker {ip_address}: PRINTING (Steckdose an - druckt gerade)") + elif outlet_status == "off": + # Steckdose aus = Drucker ONLINE (bereit zum Drucken) + status = "online" + printers_logger.info(f"[OK] Drucker {ip_address}: ONLINE (Steckdose aus - bereit zum Drucken)") + else: + # Unbekannter Status + status = "error" + printers_logger.warning(f"[WARNING] Drucker {ip_address}: Unbekannter Steckdosen-Status") else: - # Steckdose aus = Drucker ONLINE (bereit zum Drucken) - status = "online" - printers_logger.info(f"[OK] Drucker {ip_address}: ONLINE (Steckdose aus - bereit zum Drucken)") + # Steckdose nicht erreichbar + reachable = False + status = "error" + printers_logger.error(f"[ERROR] Drucker {ip_address}: Steckdose nicht erreichbar") except Exception as e: printers_logger.error(f"[ERROR] Fehler bei Tapo-Status-Check für {ip_address}: {str(e)}") @@ -3288,7 +3293,7 @@ def test_printer_tapo_connection(printer_id): db_session.close() # Tapo-Verbindung testen - from utils.job_scheduler import test_tapo_connection + from utils.tapo_controller import test_tapo_connection test_result = test_tapo_connection( printer.plug_ip, printer.plug_username, @@ -3325,7 +3330,7 @@ def test_all_printers_tapo_connection(): }) # Alle Drucker testen - from utils.job_scheduler import test_tapo_connection + from utils.tapo_controller import test_tapo_connection results = [] for printer in printers: diff --git a/backend/instance/printer_manager.db b/backend/instance/printer_manager.db index 0f975077..5e18a39d 100644 Binary files a/backend/instance/printer_manager.db and b/backend/instance/printer_manager.db differ diff --git a/backend/logs/analytics/analytics.log b/backend/logs/analytics/analytics.log index ff4d0960..264fa372 100644 --- a/backend/logs/analytics/analytics.log +++ b/backend/logs/analytics/analytics.log @@ -3,3 +3,4 @@ 2025-06-05 01:01:11 - [analytics] analytics - [INFO] INFO - 📈 Analytics Engine initialisiert 2025-06-05 09:31:05 - [analytics] analytics - [INFO] INFO - 📈 Analytics Engine initialisiert 2025-06-05 10:12:41 - [analytics] analytics - [INFO] INFO - 📈 Analytics Engine initialisiert +2025-06-05 11:12:32 - [analytics] analytics - [INFO] INFO - 📈 Analytics Engine initialisiert diff --git a/backend/logs/app/app.log b/backend/logs/app/app.log index 2b8f35d5..262e27cc 100644 --- a/backend/logs/app/app.log +++ b/backend/logs/app/app.log @@ -171,3 +171,31 @@ WHERE jobs.status = ?) AS anon_1] 2025-06-05 10:20:04 - [app] app - [INFO] INFO - Dashboard-Refresh erfolgreich: {'active_jobs': 0, 'available_printers': 0, 'total_jobs': 0, 'pending_jobs': 0, 'success_rate': 0, 'completed_jobs': 0, 'failed_jobs': 0, 'cancelled_jobs': 0, 'total_users': 1, 'online_printers': 0, 'offline_printers': 0} 2025-06-05 10:20:04 - [app] app - [INFO] INFO - Dashboard-Refresh angefordert von User 1 2025-06-05 10:20:04 - [app] app - [INFO] INFO - Dashboard-Refresh erfolgreich: {'active_jobs': 0, 'available_printers': 0, 'total_jobs': 0, 'pending_jobs': 0, 'success_rate': 0, 'completed_jobs': 0, 'failed_jobs': 0, 'cancelled_jobs': 0, 'total_users': 1, 'online_printers': 0, 'offline_printers': 0} +2025-06-05 11:12:31 - [app] app - [INFO] INFO - Optimierte SQLite-Engine erstellt: C:\Users\TTOMCZA.EMEA\Dev\Projektarbeit-MYP\backend\instance\printer_manager.db +2025-06-05 11:12:34 - [app] app - [INFO] INFO - SQLite für Raspberry Pi optimiert (reduzierte Cache-Größe, SD-Karten I/O) +2025-06-05 11:12:34 - [app] app - [INFO] INFO - [OK] Timeout Force-Quit Manager geladen +2025-06-05 11:12:34 - [app] app - [INFO] INFO - [LIST] Standard-Konfiguration verwendet +2025-06-05 11:12:35 - [app] app - [INFO] INFO - [OK] Zentraler Shutdown-Manager initialisiert +2025-06-05 11:12:35 - [app] app - [INFO] INFO - [OK] Error-Recovery-Monitoring gestartet +2025-06-05 11:12:35 - [app] app - [INFO] INFO - [OK] System-Control-Manager initialisiert +2025-06-05 11:12:35 - [app] app - [WARNING] WARNING - [WARN] Kiosk-Service nicht gefunden - Kiosk-Funktionen eventuell eingeschränkt +2025-06-05 11:12:35 - [app] app - [INFO] INFO - [RESTART] Starte Datenbank-Setup und Migrationen... +2025-06-05 11:12:37 - [app] app - [INFO] INFO - Datenbank mit Optimierungen initialisiert +2025-06-05 11:12:38 - [app] app - [INFO] INFO - [OK] JobOrder-Tabelle bereits vorhanden +2025-06-05 11:12:38 - [app] app - [INFO] INFO - Admin-Benutzer admin (admin@mercedes-benz.com) existiert bereits. Passwort wurde zurückgesetzt. +2025-06-05 11:12:38 - [app] app - [INFO] INFO - [OK] Datenbank-Setup und Migrationen erfolgreich abgeschlossen +2025-06-05 11:12:38 - [app] app - [INFO] INFO - [LIST] Standard-Konfiguration aktiv (keine Optimierungen) +2025-06-05 11:12:38 - [app] app - [INFO] INFO - 🖨️ Starte automatische Steckdosen-Initialisierung... +2025-06-05 11:12:38 - [app] app - [INFO] INFO - [INFO] Keine Drucker zur Initialisierung gefunden +2025-06-05 11:12:38 - [app] app - [INFO] INFO - [RESTART] Debug-Modus: Queue Manager deaktiviert für Entwicklung +2025-06-05 11:12:38 - [app] app - [INFO] INFO - Job-Scheduler gestartet +2025-06-05 11:12:38 - [app] app - [INFO] INFO - 🔧 Starte Debug-Server auf 0.0.0.0:5000 (HTTP) +2025-06-05 11:12:38 - [app] app - [INFO] INFO - Windows-Debug-Modus: Auto-Reload deaktiviert +2025-06-05 11:13:02 - [app] app - [INFO] INFO - Admin-Check für Funktion admin_page: User authenticated: True, User ID: 1, Is Admin: True +2025-06-05 11:13:02 - [app] app - [INFO] INFO - Admin-Check für Funktion api_admin_system_health: User authenticated: True, User ID: 1, Is Admin: True +2025-06-05 11:13:04 - [app] app - [INFO] INFO - Dashboard-Refresh angefordert von User 1 +2025-06-05 11:13:04 - [app] app - [INFO] INFO - Dashboard-Refresh angefordert von User 1 +2025-06-05 11:13:04 - [app] app - [ERROR] ERROR - Fehler beim Abrufen der Dashboard-Statistiken: tuple index out of range +2025-06-05 11:13:04 - [app] app - [INFO] INFO - Dashboard-Refresh erfolgreich: {'active_jobs': 0, 'available_printers': 0, 'total_jobs': 0, 'pending_jobs': 0, 'success_rate': 0, 'completed_jobs': 0, 'failed_jobs': 0, 'cancelled_jobs': 0, 'total_users': 0, 'online_printers': 0, 'offline_printers': 0} +2025-06-05 11:13:04 - [app] app - [INFO] INFO - Dashboard-Refresh erfolgreich: {'active_jobs': 0, 'available_printers': 0, 'total_jobs': 0, 'pending_jobs': 0, 'success_rate': 0, 'completed_jobs': 0, 'failed_jobs': 0, 'cancelled_jobs': 0, 'total_users': 1, 'online_printers': 0, 'offline_printers': 0} +2025-06-05 11:13:06 - [app] app - [INFO] INFO - Benutzer admin@mercedes-benz.com hat sich abgemeldet diff --git a/backend/logs/backup/backup.log b/backend/logs/backup/backup.log index 3a9624fe..3d206aea 100644 --- a/backend/logs/backup/backup.log +++ b/backend/logs/backup/backup.log @@ -3,3 +3,4 @@ 2025-06-05 01:01:11 - [backup] backup - [INFO] INFO - BackupManager initialisiert (minimal implementation) 2025-06-05 09:31:05 - [backup] backup - [INFO] INFO - BackupManager initialisiert (minimal implementation) 2025-06-05 10:12:41 - [backup] backup - [INFO] INFO - BackupManager initialisiert (minimal implementation) +2025-06-05 11:12:32 - [backup] backup - [INFO] INFO - BackupManager initialisiert (minimal implementation) diff --git a/backend/logs/calendar/calendar.log b/backend/logs/calendar/calendar.log index 4a0c6f18..41687b81 100644 --- a/backend/logs/calendar/calendar.log +++ b/backend/logs/calendar/calendar.log @@ -1 +1,2 @@ 2025-06-04 23:36:31 - [calendar] calendar - [INFO] INFO - 📅 Kalender-Events abgerufen: 0 Einträge für Zeitraum 2025-06-01 00:00:00 bis 2025-06-08 00:00:00 +2025-06-05 11:12:52 - [calendar] calendar - [INFO] INFO - 📅 Kalender-Events abgerufen: 0 Einträge für Zeitraum 2025-06-01 00:00:00 bis 2025-06-08 00:00:00 diff --git a/backend/logs/dashboard/dashboard.log b/backend/logs/dashboard/dashboard.log index 9960239f..7f54364d 100644 --- a/backend/logs/dashboard/dashboard.log +++ b/backend/logs/dashboard/dashboard.log @@ -116,3 +116,7 @@ WHERE guest_requests.status = ?) AS anon_1] 2025-06-05 10:12:45 - [dashboard] dashboard - [INFO] INFO - Dashboard-Background-Worker gestartet 2025-06-05 10:12:45 - [dashboard] dashboard - [INFO] INFO - Dashboard WebSocket-Server wird mit threading initialisiert (eventlet-Fallback) 2025-06-05 10:12:45 - [dashboard] dashboard - [INFO] INFO - Dashboard WebSocket-Server initialisiert (async_mode: threading) +2025-06-05 11:12:34 - [dashboard] dashboard - [INFO] INFO - Dashboard-Background-Worker gestartet +2025-06-05 11:12:34 - [dashboard] dashboard - [INFO] INFO - Dashboard-Background-Worker gestartet +2025-06-05 11:12:34 - [dashboard] dashboard - [INFO] INFO - Dashboard WebSocket-Server wird mit threading initialisiert (eventlet-Fallback) +2025-06-05 11:12:34 - [dashboard] dashboard - [INFO] INFO - Dashboard WebSocket-Server initialisiert (async_mode: threading) diff --git a/backend/logs/database/database.log b/backend/logs/database/database.log index dc5e0f6d..4d3bf79e 100644 --- a/backend/logs/database/database.log +++ b/backend/logs/database/database.log @@ -3,3 +3,4 @@ 2025-06-05 01:01:11 - [database] database - [INFO] INFO - Datenbank-Wartungs-Scheduler gestartet 2025-06-05 09:31:05 - [database] database - [INFO] INFO - Datenbank-Wartungs-Scheduler gestartet 2025-06-05 10:12:41 - [database] database - [INFO] INFO - Datenbank-Wartungs-Scheduler gestartet +2025-06-05 11:12:32 - [database] database - [INFO] INFO - Datenbank-Wartungs-Scheduler gestartet diff --git a/backend/logs/email_notification/email_notification.log b/backend/logs/email_notification/email_notification.log index a6b08512..054419c6 100644 --- a/backend/logs/email_notification/email_notification.log +++ b/backend/logs/email_notification/email_notification.log @@ -2,3 +2,4 @@ 2025-06-04 23:47:09 - [email_notification] email_notification - [INFO] INFO - 📧 Offline-E-Mail-Benachrichtigung initialisiert (kein echter E-Mail-Versand) 2025-06-05 09:31:08 - [email_notification] email_notification - [INFO] INFO - 📧 Offline-E-Mail-Benachrichtigung initialisiert (kein echter E-Mail-Versand) 2025-06-05 10:12:45 - [email_notification] email_notification - [INFO] INFO - 📧 Offline-E-Mail-Benachrichtigung initialisiert (kein echter E-Mail-Versand) +2025-06-05 11:12:34 - [email_notification] email_notification - [INFO] INFO - 📧 Offline-E-Mail-Benachrichtigung initialisiert (kein echter E-Mail-Versand) diff --git a/backend/logs/error_recovery/error_recovery.log b/backend/logs/error_recovery/error_recovery.log index 9b073f73..da42029a 100644 --- a/backend/logs/error_recovery/error_recovery.log +++ b/backend/logs/error_recovery/error_recovery.log @@ -144,3 +144,26 @@ 2025-06-05 10:14:01 - [error_recovery] error_recovery - [INFO] INFO - 🔧 Führe Recovery-Aktion aus: restart_system 2025-06-05 10:14:01 - [error_recovery] error_recovery - [INFO] INFO - ✅ Recovery erfolgreich: restart_system 2025-06-05 10:14:06 - [error_recovery] error_recovery - [INFO] INFO - 🛑 Error-Monitoring gestoppt +2025-06-05 11:12:35 - [error_recovery] error_recovery - [INFO] INFO - 🛡️ Error-Recovery-Manager initialisiert +2025-06-05 11:12:35 - [error_recovery] error_recovery - [INFO] INFO - 🔍 Error-Monitoring gestartet +2025-06-05 11:12:35 - [error_recovery] error_recovery - [WARNING] WARNING - 🚨 Fehler erkannt: flask_error - 2025-06-04 23:38:35 - [app] app - [ERROR] ERROR - Interner Serverfehler: 500 Internal Server Error: The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application. +2025-06-05 11:12:35 - [error_recovery] error_recovery - [INFO] INFO - 🔧 Führe Recovery-Aktion aus: restart_service +2025-06-05 11:12:39 - [error_recovery] error_recovery - [INFO] INFO - ✅ Recovery erfolgreich: restart_service +2025-06-05 11:12:39 - [error_recovery] error_recovery - [WARNING] WARNING - 🚨 Fehler erkannt: flask_error - 2025-06-04 23:38:35 - [app] app - [ERROR] ERROR - Interner Serverfehler: 500 Internal Server Error: The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application. +2025-06-05 11:12:39 - [error_recovery] error_recovery - [INFO] INFO - 🔧 Führe Recovery-Aktion aus: restart_service +2025-06-05 11:12:41 - [error_recovery] error_recovery - [INFO] INFO - ✅ Recovery erfolgreich: restart_service +2025-06-05 11:12:41 - [error_recovery] error_recovery - [WARNING] WARNING - 🚨 Fehler erkannt: flask_error - 2025-06-04 23:39:03 - [app] app - [ERROR] ERROR - Interner Serverfehler: 500 Internal Server Error: The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application. +2025-06-05 11:12:41 - [error_recovery] error_recovery - [INFO] INFO - 🔧 Führe Recovery-Aktion aus: restart_service +2025-06-05 11:12:45 - [error_recovery] error_recovery - [INFO] INFO - ✅ Recovery erfolgreich: restart_service +2025-06-05 11:12:45 - [error_recovery] error_recovery - [WARNING] WARNING - 🚨 Fehler erkannt: flask_error - 2025-06-04 23:39:03 - [app] app - [ERROR] ERROR - Interner Serverfehler: 500 Internal Server Error: The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application. +2025-06-05 11:12:45 - [error_recovery] error_recovery - [ERROR] ERROR - 🔥 Eskalation für flask_error: 3 Vorkommen in 300s +2025-06-05 11:12:45 - [error_recovery] error_recovery - [INFO] INFO - 🔧 Führe Recovery-Aktion aus: restart_system +2025-06-05 11:12:45 - [error_recovery] error_recovery - [INFO] INFO - ✅ Recovery erfolgreich: restart_system +2025-06-05 11:12:45 - [error_recovery] error_recovery - [WARNING] WARNING - 🚨 Fehler erkannt: flask_error - 2025-06-04 23:39:33 - [app] app - [ERROR] ERROR - Interner Serverfehler: 500 Internal Server Error: The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application. +2025-06-05 11:12:45 - [error_recovery] error_recovery - [ERROR] ERROR - 🔥 Eskalation für flask_error: 4 Vorkommen in 300s +2025-06-05 11:12:45 - [error_recovery] error_recovery - [INFO] INFO - 🔧 Führe Recovery-Aktion aus: restart_system +2025-06-05 11:12:45 - [error_recovery] error_recovery - [INFO] INFO - ✅ Recovery erfolgreich: restart_system +2025-06-05 11:12:45 - [error_recovery] error_recovery - [WARNING] WARNING - 🚨 Fehler erkannt: flask_error - 2025-06-04 23:39:33 - [app] app - [ERROR] ERROR - Interner Serverfehler: 500 Internal Server Error: The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application. +2025-06-05 11:12:45 - [error_recovery] error_recovery - [ERROR] ERROR - 🔥 Eskalation für flask_error: 5 Vorkommen in 300s +2025-06-05 11:12:45 - [error_recovery] error_recovery - [INFO] INFO - 🔧 Führe Recovery-Aktion aus: restart_system +2025-06-05 11:12:45 - [error_recovery] error_recovery - [INFO] INFO - ✅ Recovery erfolgreich: restart_system diff --git a/backend/logs/jobs/jobs.log b/backend/logs/jobs/jobs.log index e69de29b..5dc1137b 100644 --- a/backend/logs/jobs/jobs.log +++ b/backend/logs/jobs/jobs.log @@ -0,0 +1 @@ +2025-06-05 11:12:49 - [jobs] jobs - [INFO] INFO - Jobs abgerufen: 0 von 0 (Seite 1) diff --git a/backend/logs/maintenance/maintenance.log b/backend/logs/maintenance/maintenance.log index 1ea8537b..4194aa42 100644 --- a/backend/logs/maintenance/maintenance.log +++ b/backend/logs/maintenance/maintenance.log @@ -6,3 +6,5 @@ 2025-06-05 09:31:08 - [maintenance] maintenance - [INFO] INFO - Wartungs-Scheduler gestartet 2025-06-05 10:12:45 - [maintenance] maintenance - [INFO] INFO - Wartungs-Scheduler gestartet 2025-06-05 10:12:45 - [maintenance] maintenance - [INFO] INFO - Wartungs-Scheduler gestartet +2025-06-05 11:12:34 - [maintenance] maintenance - [INFO] INFO - Wartungs-Scheduler gestartet +2025-06-05 11:12:34 - [maintenance] maintenance - [INFO] INFO - Wartungs-Scheduler gestartet diff --git a/backend/logs/multi_location/multi_location.log b/backend/logs/multi_location/multi_location.log index da5b0ebb..e4fa769c 100644 --- a/backend/logs/multi_location/multi_location.log +++ b/backend/logs/multi_location/multi_location.log @@ -6,3 +6,5 @@ 2025-06-05 09:31:08 - [multi_location] multi_location - [INFO] INFO - Standard-Standort erstellt 2025-06-05 10:12:45 - [multi_location] multi_location - [INFO] INFO - Standard-Standort erstellt 2025-06-05 10:12:45 - [multi_location] multi_location - [INFO] INFO - Standard-Standort erstellt +2025-06-05 11:12:34 - [multi_location] multi_location - [INFO] INFO - Standard-Standort erstellt +2025-06-05 11:12:34 - [multi_location] multi_location - [INFO] INFO - Standard-Standort erstellt diff --git a/backend/logs/permissions/permissions.log b/backend/logs/permissions/permissions.log index 7e267acf..14a60aa8 100644 --- a/backend/logs/permissions/permissions.log +++ b/backend/logs/permissions/permissions.log @@ -9,3 +9,4 @@ 2025-06-05 01:01:18 - [permissions] permissions - [INFO] INFO - 🔐 Permission Template Helpers registriert 2025-06-05 09:31:08 - [permissions] permissions - [INFO] INFO - 🔐 Permission Template Helpers registriert 2025-06-05 10:12:45 - [permissions] permissions - [INFO] INFO - 🔐 Permission Template Helpers registriert +2025-06-05 11:12:34 - [permissions] permissions - [INFO] INFO - 🔐 Permission Template Helpers registriert diff --git a/backend/logs/printer_monitor/printer_monitor.log b/backend/logs/printer_monitor/printer_monitor.log index 7b8762c0..8a181a0d 100644 --- a/backend/logs/printer_monitor/printer_monitor.log +++ b/backend/logs/printer_monitor/printer_monitor.log @@ -159,3 +159,9 @@ 2025-06-05 10:19:49 - [printer_monitor] printer_monitor - [INFO] INFO - ℹ️ Keine aktiven Drucker gefunden 2025-06-05 10:19:49 - [printer_monitor] printer_monitor - [INFO] INFO - 🔄 Aktualisiere Live-Druckerstatus... 2025-06-05 10:19:49 - [printer_monitor] printer_monitor - [INFO] INFO - ℹ️ Keine aktiven Drucker gefunden +2025-06-05 11:12:32 - [printer_monitor] printer_monitor - [INFO] INFO - 🖨️ Drucker-Monitor initialisiert +2025-06-05 11:12:32 - [printer_monitor] printer_monitor - [INFO] INFO - 🔍 Automatische Tapo-Erkennung in separatem Thread gestartet +2025-06-05 11:13:02 - [printer_monitor] printer_monitor - [INFO] INFO - 🔄 Aktualisiere Live-Druckerstatus... +2025-06-05 11:13:02 - [printer_monitor] printer_monitor - [INFO] INFO - ℹ️ Keine aktiven Drucker gefunden +2025-06-05 11:13:02 - [printer_monitor] printer_monitor - [INFO] INFO - 🔄 Aktualisiere Live-Druckerstatus... +2025-06-05 11:13:02 - [printer_monitor] printer_monitor - [INFO] INFO - ℹ️ Keine aktiven Drucker gefunden diff --git a/backend/logs/printers/printers.log b/backend/logs/printers/printers.log index 16f61dab..bf7aa0f0 100644 --- a/backend/logs/printers/printers.log +++ b/backend/logs/printers/printers.log @@ -68,3 +68,7 @@ 2025-06-05 10:19:49 - [printers] printers - [INFO] INFO - 🔄 Live-Status-Abfrage von Benutzer Administrator (ID: 1) 2025-06-05 10:19:49 - [printers] printers - [INFO] INFO - ✅ Live-Status-Abfrage erfolgreich: 0 Drucker 2025-06-05 10:19:49 - [printers] printers - [INFO] INFO - [OK] API-Live-Drucker-Status-Abfrage 'get_live_printer_status' erfolgreich in 3.54ms +2025-06-05 11:12:49 - [printers] printers - [INFO] INFO - Schnelles Laden abgeschlossen: 0 Drucker geladen (ohne Status-Check) +2025-06-05 11:13:02 - [printers] printers - [INFO] INFO - 🔄 Live-Status-Abfrage von Benutzer Administrator (ID: 1) +2025-06-05 11:13:02 - [printers] printers - [INFO] INFO - ✅ Live-Status-Abfrage erfolgreich: 0 Drucker +2025-06-05 11:13:02 - [printers] printers - [INFO] INFO - [OK] API-Live-Drucker-Status-Abfrage 'get_live_printer_status' erfolgreich in 25.19ms diff --git a/backend/logs/scheduler/scheduler.log b/backend/logs/scheduler/scheduler.log index 2dc6c550..13943ec2 100644 --- a/backend/logs/scheduler/scheduler.log +++ b/backend/logs/scheduler/scheduler.log @@ -22,3 +22,6 @@ 2025-06-05 10:12:50 - [scheduler] scheduler - [INFO] INFO - Scheduler gestartet 2025-06-05 10:14:01 - [scheduler] scheduler - [INFO] INFO - Scheduler-Thread beendet 2025-06-05 10:14:01 - [scheduler] scheduler - [INFO] INFO - Scheduler gestoppt +2025-06-05 11:12:32 - [scheduler] scheduler - [INFO] INFO - Task check_jobs registriert: Intervall 30s, Enabled: True +2025-06-05 11:12:38 - [scheduler] scheduler - [INFO] INFO - Scheduler-Thread gestartet +2025-06-05 11:12:38 - [scheduler] scheduler - [INFO] INFO - Scheduler gestartet diff --git a/backend/logs/security/security.log b/backend/logs/security/security.log index 84c1f4c7..805916f2 100644 --- a/backend/logs/security/security.log +++ b/backend/logs/security/security.log @@ -9,3 +9,4 @@ 2025-06-05 01:01:18 - [security] security - [INFO] INFO - 🔒 Security System initialisiert 2025-06-05 09:31:08 - [security] security - [INFO] INFO - 🔒 Security System initialisiert 2025-06-05 10:12:45 - [security] security - [INFO] INFO - 🔒 Security System initialisiert +2025-06-05 11:12:34 - [security] security - [INFO] INFO - 🔒 Security System initialisiert diff --git a/backend/logs/shutdown_manager/shutdown_manager.log b/backend/logs/shutdown_manager/shutdown_manager.log index 0d49a1c0..0b499787 100644 --- a/backend/logs/shutdown_manager/shutdown_manager.log +++ b/backend/logs/shutdown_manager/shutdown_manager.log @@ -16,3 +16,4 @@ 2025-06-05 10:14:01 - [shutdown_manager] shutdown_manager - [INFO] INFO - 🔄 Beende Scheduler mit stop()... 2025-06-05 10:14:01 - [shutdown_manager] shutdown_manager - [INFO] INFO - ✅ Scheduler erfolgreich gestoppt 2025-06-05 10:14:06 - [shutdown_manager] shutdown_manager - [INFO] INFO - 💾 Führe sicheres Datenbank-Cleanup durch... +2025-06-05 11:12:34 - [shutdown_manager] shutdown_manager - [INFO] INFO - 🔧 Shutdown-Manager initialisiert diff --git a/backend/logs/startup/startup.log b/backend/logs/startup/startup.log index 81b88e54..fee9d9f0 100644 --- a/backend/logs/startup/startup.log +++ b/backend/logs/startup/startup.log @@ -97,3 +97,12 @@ 2025-06-05 10:12:45 - [startup] startup - [INFO] INFO - 🪟 Windows-Modus: Aktiviert 2025-06-05 10:12:45 - [startup] startup - [INFO] INFO - 🔒 Windows-sichere Log-Rotation: Aktiviert 2025-06-05 10:12:45 - [startup] startup - [INFO] INFO - ================================================== +2025-06-05 11:12:34 - [startup] startup - [INFO] INFO - ================================================== +2025-06-05 11:12:34 - [startup] startup - [INFO] INFO - [START] MYP Platform Backend wird gestartet... +2025-06-05 11:12:34 - [startup] startup - [INFO] INFO - 🐍 Python Version: 3.13.3 (tags/v3.13.3:6280bb5, Apr 8 2025, 14:47:33) [MSC v.1943 64 bit (AMD64)] +2025-06-05 11:12:34 - [startup] startup - [INFO] INFO - 💻 Betriebssystem: nt (win32) +2025-06-05 11:12:34 - [startup] startup - [INFO] INFO - 📁 Arbeitsverzeichnis: C:\Users\TTOMCZA.EMEA\Dev\Projektarbeit-MYP\backend +2025-06-05 11:12:34 - [startup] startup - [INFO] INFO - ⏰ Startzeit: 2025-06-05T11:12:34.706758 +2025-06-05 11:12:34 - [startup] startup - [INFO] INFO - 🪟 Windows-Modus: Aktiviert +2025-06-05 11:12:34 - [startup] startup - [INFO] INFO - 🔒 Windows-sichere Log-Rotation: Aktiviert +2025-06-05 11:12:34 - [startup] startup - [INFO] INFO - ================================================== diff --git a/backend/logs/system_control/system_control.log b/backend/logs/system_control/system_control.log index a71ca04f..b1af4e6b 100644 --- a/backend/logs/system_control/system_control.log +++ b/backend/logs/system_control/system_control.log @@ -139,3 +139,16 @@ 2025-06-05 10:15:01 - [system_control] system_control - [INFO] INFO - ▶️ Führe Operation aus: restart 2025-06-05 10:15:01 - [system_control] system_control - [WARNING] WARNING - 🔄 System-Neustart wird ausgeführt... 2025-06-05 10:15:01 - [system_control] system_control - [INFO] INFO - 🧹 Cleanup vor Neustart/Shutdown... +2025-06-05 11:12:35 - [system_control] system_control - [INFO] INFO - 🔧 System-Control-Manager initialisiert +2025-06-05 11:12:39 - [system_control] system_control - [INFO] INFO - 🕐 Operation geplant: service_restart in 5s +2025-06-05 11:12:41 - [system_control] system_control - [INFO] INFO - 🕐 Operation geplant: service_restart in 5s +2025-06-05 11:12:44 - [system_control] system_control - [INFO] INFO - ▶️ Führe Operation aus: service_restart +2025-06-05 11:12:44 - [system_control] system_control - [INFO] INFO - 🔄 Services werden neugestartet... +2025-06-05 11:12:45 - [system_control] system_control - [INFO] INFO - 🕐 Operation geplant: service_restart in 5s +2025-06-05 11:12:45 - [system_control] system_control - [INFO] INFO - 🕐 Operation geplant: restart in 60s +2025-06-05 11:12:45 - [system_control] system_control - [INFO] INFO - 🕐 Operation geplant: restart in 60s +2025-06-05 11:12:45 - [system_control] system_control - [INFO] INFO - 🕐 Operation geplant: restart in 60s +2025-06-05 11:12:46 - [system_control] system_control - [INFO] INFO - ▶️ Führe Operation aus: service_restart +2025-06-05 11:12:46 - [system_control] system_control - [INFO] INFO - 🔄 Services werden neugestartet... +2025-06-05 11:12:50 - [system_control] system_control - [INFO] INFO - ▶️ Führe Operation aus: service_restart +2025-06-05 11:12:50 - [system_control] system_control - [INFO] INFO - 🔄 Services werden neugestartet... diff --git a/backend/logs/tapo_controller/tapo_controller.log b/backend/logs/tapo_controller/tapo_controller.log new file mode 100644 index 00000000..276ac0ad --- /dev/null +++ b/backend/logs/tapo_controller/tapo_controller.log @@ -0,0 +1,12 @@ +2025-06-05 11:12:32 - [tapo_controller] tapo_controller - [INFO] INFO - ✅ tapo controller initialisiert +2025-06-05 11:12:34 - [tapo_controller] tapo_controller - [INFO] INFO - 🔍 starte automatische tapo-steckdosenerkennung... +2025-06-05 11:12:34 - [tapo_controller] tapo_controller - [INFO] INFO - 🔄 teste 6 standard-ips aus der konfiguration +2025-06-05 11:12:34 - [tapo_controller] tapo_controller - [INFO] INFO - 🔍 teste ip 1/6: 192.168.0.103 +2025-06-05 11:12:38 - [tapo_controller] tapo_controller - [INFO] INFO - 🚀 starte steckdosen-initialisierung... +2025-06-05 11:12:38 - [tapo_controller] tapo_controller - [WARNING] WARNING - ⚠️ keine aktiven drucker zur initialisierung gefunden +2025-06-05 11:12:40 - [tapo_controller] tapo_controller - [INFO] INFO - 🔍 teste ip 2/6: 192.168.0.104 +2025-06-05 11:12:46 - [tapo_controller] tapo_controller - [INFO] INFO - 🔍 teste ip 3/6: 192.168.0.100 +2025-06-05 11:12:52 - [tapo_controller] tapo_controller - [INFO] INFO - 🔍 teste ip 4/6: 192.168.0.101 +2025-06-05 11:12:58 - [tapo_controller] tapo_controller - [INFO] INFO - 🔍 teste ip 5/6: 192.168.0.102 +2025-06-05 11:13:04 - [tapo_controller] tapo_controller - [INFO] INFO - 🔍 teste ip 6/6: 192.168.0.105 +2025-06-05 11:13:10 - [tapo_controller] tapo_controller - [INFO] INFO - ✅ steckdosen-erkennung abgeschlossen: 0/6 steckdosen gefunden in 36.7s diff --git a/backend/logs/windows_fixes/windows_fixes.log b/backend/logs/windows_fixes/windows_fixes.log index de3a26a6..7a35e82d 100644 --- a/backend/logs/windows_fixes/windows_fixes.log +++ b/backend/logs/windows_fixes/windows_fixes.log @@ -50,3 +50,7 @@ 2025-06-05 10:12:39 - [windows_fixes] windows_fixes - [INFO] INFO - ✅ Alle Windows-Fixes erfolgreich angewendet 2025-06-05 10:14:06 - [windows_fixes] windows_fixes - [INFO] INFO - 🔄 Starte Windows Thread-Shutdown... 2025-06-05 10:14:06 - [windows_fixes] windows_fixes - [INFO] INFO - ✅ Windows Thread-Shutdown abgeschlossen +2025-06-05 11:12:31 - [windows_fixes] windows_fixes - [INFO] INFO - 🔧 Wende Windows-spezifische Fixes an... +2025-06-05 11:12:31 - [windows_fixes] windows_fixes - [INFO] INFO - ✅ Subprocess automatisch gepatcht für UTF-8 Encoding (run + Popen) +2025-06-05 11:12:31 - [windows_fixes] windows_fixes - [INFO] INFO - ✅ Globaler subprocess-Patch angewendet +2025-06-05 11:12:31 - [windows_fixes] windows_fixes - [INFO] INFO - ✅ Alle Windows-Fixes erfolgreich angewendet diff --git a/backend/utils/__pycache__/job_scheduler.cpython-313.pyc b/backend/utils/__pycache__/job_scheduler.cpython-313.pyc index cf90958e..44a9d770 100644 Binary files a/backend/utils/__pycache__/job_scheduler.cpython-313.pyc and b/backend/utils/__pycache__/job_scheduler.cpython-313.pyc differ diff --git a/backend/utils/__pycache__/printer_monitor.cpython-313.pyc b/backend/utils/__pycache__/printer_monitor.cpython-313.pyc index cb7394e8..5f5e61ab 100644 Binary files a/backend/utils/__pycache__/printer_monitor.cpython-313.pyc and b/backend/utils/__pycache__/printer_monitor.cpython-313.pyc differ diff --git a/backend/utils/__pycache__/tapo_controller.cpython-313.pyc b/backend/utils/__pycache__/tapo_controller.cpython-313.pyc new file mode 100644 index 00000000..82127f9b Binary files /dev/null and b/backend/utils/__pycache__/tapo_controller.cpython-313.pyc differ diff --git a/backend/utils/tapo_controller.py b/backend/utils/tapo_controller.py index 2f7bd30c..1c8887cc 100644 --- a/backend/utils/tapo_controller.py +++ b/backend/utils/tapo_controller.py @@ -1,6 +1,6 @@ """ -TP-Link Tapo P110 Zentraler Controller für MYP Platform -Sammelt alle operativen Tapo-Steckdosen-Funktionalitäten an einem Ort. +tp-link tapo p110 zentraler controller für myp platform +sammelt alle operativen tapo-steckdosen-funktionalitäten an einem ort. """ import time @@ -15,24 +15,24 @@ from models import get_db_session, Printer, PlugStatusLog from utils.logging_config import get_logger from utils.settings import TAPO_USERNAME, TAPO_PASSWORD, DEFAULT_TAPO_IPS, TAPO_TIMEOUT, TAPO_RETRY_COUNT -# TP-Link Tapo P110 Unterstützung prüfen +# tp-link tapo p110 unterstützung prüfen try: from PyP100 import PyP100 TAPO_AVAILABLE = True except ImportError: TAPO_AVAILABLE = False -# Logger initialisieren +# logger initialisieren logger = get_logger("tapo_controller") class TapoController: """ - Zentraler Controller für alle TP-Link Tapo P110 Operationen. + zentraler controller für alle tp-link tapo p110 operationen. """ def __init__(self): - """Initialisiere den Tapo Controller.""" + """initialisiere den tapo controller.""" self.username = TAPO_USERNAME self.password = TAPO_PASSWORD self.timeout = TAPO_TIMEOUT @@ -40,107 +40,107 @@ class TapoController: self.auto_discovered = False if not TAPO_AVAILABLE: - logger.error("❌ PyP100-Modul nicht installiert - Tapo-Funktionalität eingeschränkt") + logger.error("❌ PyP100-modul nicht installiert - tapo-funktionalität eingeschränkt") else: - logger.info("✅ Tapo Controller initialisiert") + logger.info("✅ tapo controller initialisiert") def toggle_plug(self, ip: str, state: bool, username: str = None, password: str = None) -> bool: """ - Schaltet eine TP-Link Tapo P100/P110-Steckdose ein oder aus. + schaltet eine tp-link tapo p100/p110-steckdose ein oder aus. - Args: - ip: IP-Adresse der Steckdose - state: True = Ein, False = Aus - username: Benutzername (optional, nutzt Standard wenn nicht angegeben) - password: Passwort (optional, nutzt Standard wenn nicht angegeben) + args: + ip: ip-adresse der steckdose + state: true = ein, false = aus + username: benutzername (optional, nutzt standard wenn nicht angegeben) + password: passwort (optional, nutzt standard wenn nicht angegeben) - Returns: - bool: True wenn erfolgreich geschaltet + returns: + bool: true wenn erfolgreich geschaltet """ if not TAPO_AVAILABLE: - logger.error("❌ PyP100-Modul nicht installiert - Steckdose kann nicht geschaltet werden") + logger.error("❌ PyP100-modul nicht installiert - steckdose kann nicht geschaltet werden") return False - # IMMER globale Anmeldedaten verwenden + # immer globale anmeldedaten verwenden username = self.username password = self.password - logger.debug(f"🔧 Verwende globale Tapo-Anmeldedaten für {ip}") + logger.debug(f"🔧 verwende globale tapo-anmeldedaten für {ip}") for attempt in range(self.retry_count): try: - # P100-Verbindung herstellen + # p100-verbindung herstellen p100 = PyP100.P100(ip, username, password) p100.handshake() p100.login() - # Steckdose schalten + # steckdose schalten if state: p100.turnOn() - logger.info(f"✅ Tapo-Steckdose {ip} erfolgreich eingeschaltet") + logger.info(f"✅ tapo-steckdose {ip} erfolgreich eingeschaltet") else: p100.turnOff() - logger.info(f"✅ Tapo-Steckdose {ip} erfolgreich ausgeschaltet") + logger.info(f"✅ tapo-steckdose {ip} erfolgreich ausgeschaltet") return True except Exception as e: action = "ein" if state else "aus" - logger.warning(f"⚠️ Versuch {attempt+1}/{self.retry_count} fehlgeschlagen beim {action}schalten von {ip}: {str(e)}") + logger.warning(f"⚠️ versuch {attempt+1}/{self.retry_count} fehlgeschlagen beim {action}schalten von {ip}: {str(e)}") if attempt < self.retry_count - 1: - time.sleep(1) # Kurze Pause vor erneutem Versuch + time.sleep(1) # kurze pause vor erneutem versuch else: - logger.error(f"❌ Fehler beim {action}schalten der Tapo-Steckdose {ip}: {str(e)}") + logger.error(f"❌ fehler beim {action}schalten der tapo-steckdose {ip}: {str(e)}") return False def turn_off(self, ip: str, username: str = None, password: str = None, printer_id: int = None) -> bool: """ - Schaltet eine TP-Link Tapo P110-Steckdose aus. + schaltet eine tp-link tapo p110-steckdose aus. - Args: - ip: IP-Adresse der Steckdose - username: Benutzername (optional) - password: Passwort (optional) - printer_id: ID des zugehörigen Druckers für Logging (optional) + args: + ip: ip-adresse der steckdose + username: benutzername (optional) + password: passwort (optional) + printer_id: id des zugehörigen druckers für logging (optional) - Returns: - bool: True wenn erfolgreich ausgeschaltet + returns: + bool: true wenn erfolgreich ausgeschaltet """ if not TAPO_AVAILABLE: - logger.error("⚠️ PyP100-Modul nicht verfügbar - kann Tapo-Steckdose nicht schalten") - self._log_plug_status(printer_id, "disconnected", ip, error_message="PyP100-Modul nicht verfügbar") + logger.error("⚠️ PyP100-modul nicht verfügbar - kann tapo-steckdose nicht schalten") + self._log_plug_status(printer_id, "disconnected", ip, error_message="PyP100-modul nicht verfügbar") return False - # IMMER globale Anmeldedaten verwenden + # immer globale anmeldedaten verwenden username = self.username password = self.password start_time = time.time() try: - # TP-Link Tapo P100 Verbindung herstellen + # tp-link tapo p100 verbindung herstellen p100 = PyP100.P100(ip, username, password) p100.handshake() p100.login() - # Steckdose ausschalten + # steckdose ausschalten p100.turnOff() - response_time = int((time.time() - start_time) * 1000) # in Millisekunden - logger.debug(f"✅ Tapo-Steckdose {ip} erfolgreich ausgeschaltet") + response_time = int((time.time() - start_time) * 1000) # in millisekunden + logger.debug(f"✅ tapo-steckdose {ip} erfolgreich ausgeschaltet") - # Logging: Erfolgreich ausgeschaltet + # logging: erfolgreich ausgeschaltet self._log_plug_status(printer_id, "off", ip, response_time_ms=response_time) return True except Exception as e: response_time = int((time.time() - start_time) * 1000) - logger.debug(f"⚠️ Fehler beim Ausschalten der Tapo-Steckdose {ip}: {str(e)}") + logger.debug(f"⚠️ fehler beim ausschalten der tapo-steckdose {ip}: {str(e)}") - # Logging: Fehlgeschlagener Versuch + # logging: fehlgeschlagener versuch self._log_plug_status(printer_id, "disconnected", ip, response_time_ms=response_time, error_message=str(e)) @@ -150,83 +150,83 @@ class TapoController: def check_outlet_status(self, ip: str, username: str = None, password: str = None, printer_id: int = None) -> Tuple[bool, str]: """ - Überprüft den Status einer TP-Link Tapo P110-Steckdose. + überprüft den status einer tp-link tapo p110-steckdose. - Args: - ip: IP-Adresse der Steckdose - username: Benutzername (optional) - password: Passwort (optional) - printer_id: ID des zugehörigen Druckers für Logging (optional) + args: + ip: ip-adresse der steckdose + username: benutzername (optional) + password: passwort (optional) + printer_id: id des zugehörigen druckers für logging (optional) - Returns: - Tuple[bool, str]: (Erreichbar, Status) - Status: "on", "off", "unknown" + returns: + tuple[bool, str]: (erreichbar, status) - status: "on", "off", "unknown" """ if not TAPO_AVAILABLE: - logger.debug("⚠️ PyP100-Modul nicht verfügbar - kann Tapo-Steckdosen-Status nicht abfragen") + logger.debug("⚠️ PyP100-modul nicht verfügbar - kann tapo-steckdosen-status nicht abfragen") self._log_plug_status(printer_id, "disconnected", ip, - error_message="PyP100-Modul nicht verfügbar", - notes="Status-Check fehlgeschlagen") + error_message="PyP100-modul nicht verfügbar", + notes="status-check fehlgeschlagen") return False, "unknown" - # IMMER globale Anmeldedaten verwenden + # immer globale anmeldedaten verwenden username = self.username password = self.password start_time = time.time() try: - # TP-Link Tapo P100 Verbindung herstellen + # tp-link tapo p100 verbindung herstellen p100 = PyP100.P100(ip, username, password) p100.handshake() p100.login() - # Geräteinformationen abrufen + # geräteinformationen abrufen device_info = p100.getDeviceInfo() - # Status auswerten + # status auswerten device_on = device_info.get('device_on', False) status = "on" if device_on else "off" response_time = int((time.time() - start_time) * 1000) - logger.debug(f"✅ Tapo-Steckdose {ip}: Status = {status}") + logger.debug(f"✅ tapo-steckdose {ip}: status = {status}") - # Erweiterte Informationen sammeln + # erweiterte informationen sammeln extra_info = self._collect_device_info(p100, device_info) - # Logging: Erfolgreicher Status-Check + # logging: erfolgreicher status-check self._log_plug_status(printer_id, status, ip, response_time_ms=response_time, power_consumption=extra_info.get('power_consumption'), voltage=extra_info.get('voltage'), current=extra_info.get('current'), firmware_version=extra_info.get('firmware_version'), - notes="Automatischer Status-Check") + notes="automatischer status-check") return True, status except Exception as e: response_time = int((time.time() - start_time) * 1000) - logger.debug(f"⚠️ Fehler bei Tapo-Steckdosen-Status-Check {ip}: {str(e)}") + logger.debug(f"⚠️ fehler bei tapo-steckdosen-status-check {ip}: {str(e)}") - # Logging: Fehlgeschlagener Status-Check + # logging: fehlgeschlagener status-check self._log_plug_status(printer_id, "disconnected", ip, response_time_ms=response_time, error_message=str(e), - notes="Status-Check fehlgeschlagen") + notes="status-check fehlgeschlagen") return False, "unknown" def test_connection(self, ip: str, username: str = None, password: str = None) -> dict: """ - Testet die Verbindung zu einer TP-Link Tapo P110-Steckdose. + testet die verbindung zu einer tp-link tapo p110-steckdose. - Args: - ip: IP-Adresse der Steckdose - username: Benutzername (optional) - password: Passwort (optional) + args: + ip: ip-adresse der steckdose + username: benutzername (optional) + password: passwort (optional) - Returns: - dict: Ergebnis mit Status und Informationen + returns: + dict: ergebnis mit status und informationen """ result = { "success": False, @@ -236,58 +236,58 @@ class TapoController: } if not TAPO_AVAILABLE: - result["message"] = "PyP100-Modul nicht verfügbar" + result["message"] = "PyP100-modul nicht verfügbar" result["error"] = "ModuleNotFound" - logger.error("PyP100-Modul nicht verfügbar - kann Tapo-Steckdosen nicht testen") + logger.error("PyP100-modul nicht verfügbar - kann tapo-steckdosen nicht testen") return result - # Verwende globale Anmeldedaten falls nicht angegeben + # verwende globale anmeldedaten falls nicht angegeben if not username or not password: username = self.username password = self.password - logger.debug(f"Verwende globale Tapo-Anmeldedaten für {ip}") + logger.debug(f"verwende globale tapo-anmeldedaten für {ip}") try: - # TP-Link Tapo P100 Verbindung herstellen + # tp-link tapo p100 verbindung herstellen p100 = PyP100.P100(ip, username, password) p100.handshake() p100.login() - # Geräteinformationen abrufen + # geräteinformationen abrufen device_info = p100.getDeviceInfo() result["success"] = True - result["message"] = "Verbindung erfolgreich" + result["message"] = "verbindung erfolgreich" result["device_info"] = device_info - logger.info(f"Tapo-Verbindung zu {ip} erfolgreich: {device_info.get('nickname', 'Unbekannt')}") + logger.info(f"tapo-verbindung zu {ip} erfolgreich: {device_info.get('nickname', 'unbekannt')}") except Exception as e: result["success"] = False - result["message"] = f"Verbindungsfehler: {str(e)}" + result["message"] = f"verbindungsfehler: {str(e)}" result["error"] = str(e) - logger.error(f"Fehler bei Tapo-Test zu {ip}: {str(e)}") + logger.error(f"fehler bei tapo-test zu {ip}: {str(e)}") return result def ping_address(self, ip: str, timeout: int = 3) -> bool: """ - Führt einen Konnektivitätstest zu einer IP-Adresse durch. - Verwendet TCP-Verbindung statt Ping für bessere Kompatibilität. + führt einen konnektivitätstest zu einer ip-adresse durch. + verwendet tcp-verbindung statt ping für bessere kompatibilität. - Args: - ip: Zu testende IP-Adresse - timeout: Timeout in Sekunden + args: + ip: zu testende ip-adresse + timeout: timeout in sekunden - Returns: - bool: True wenn Verbindung erfolgreich + returns: + bool: true wenn verbindung erfolgreich """ try: - # IP-Adresse validieren + # ip-adresse validieren ipaddress.ip_address(ip.strip()) - # Standard-Ports für Tapo-Steckdosen testen - test_ports = [9999, 80, 443] # Tapo-Standard, HTTP, HTTPS + # standard-ports für tapo-steckdosen testen + test_ports = [9999, 80, 443] # tapo-standard, http, https for port in test_ports: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) @@ -296,87 +296,87 @@ class TapoController: sock.close() if result == 0: - logger.debug(f"✅ Verbindung zu {ip}:{port} erfolgreich") + logger.debug(f"✅ verbindung zu {ip}:{port} erfolgreich") return True - logger.debug(f"❌ Keine Verbindung zu {ip} auf Standard-Ports möglich") + logger.debug(f"❌ keine verbindung zu {ip} auf standard-ports möglich") return False except Exception as e: - logger.debug(f"❌ Fehler beim Verbindungstest zu {ip}: {str(e)}") + logger.debug(f"❌ fehler beim verbindungstest zu {ip}: {str(e)}") return False def auto_discover_outlets(self) -> Dict[str, bool]: """ - Automatische Erkennung und Konfiguration von TP-Link Tapo P110-Steckdosen im Netzwerk. + automatische erkennung und konfiguration von tp-link tapo p110-steckdosen im netzwerk. - Returns: - Dict[str, bool]: Ergebnis der Steckdosenerkennung mit IP als Schlüssel + returns: + dict[str, bool]: ergebnis der steckdosenerkennung mit ip als schlüssel """ if self.auto_discovered: - logger.info("🔍 Tapo-Steckdosen wurden bereits erkannt") + logger.info("🔍 tapo-steckdosen wurden bereits erkannt") return {} - logger.info("🔍 Starte automatische Tapo-Steckdosenerkennung...") + logger.info("🔍 starte automatische tapo-steckdosenerkennung...") results = {} start_time = time.time() - # Standard-IPs aus der Konfiguration testen - logger.info(f"🔄 Teste {len(DEFAULT_TAPO_IPS)} Standard-IPs aus der Konfiguration") + # standard-ips aus der konfiguration testen + logger.info(f"🔄 teste {len(DEFAULT_TAPO_IPS)} standard-ips aus der konfiguration") for i, ip in enumerate(DEFAULT_TAPO_IPS): try: - logger.info(f"🔍 Teste IP {i+1}/{len(DEFAULT_TAPO_IPS)}: {ip}") + logger.info(f"🔍 teste ip {i+1}/{len(DEFAULT_TAPO_IPS)}: {ip}") - # Schneller Ping-Test + # schneller ping-test if self.ping_address(ip, timeout=2): - logger.info(f"✅ Steckdose mit IP {ip} ist erreichbar") + logger.info(f"✅ steckdose mit ip {ip} ist erreichbar") - # Tapo-Verbindung testen + # tapo-verbindung testen test_result = self.test_connection(ip) if test_result["success"]: device_info = test_result["device_info"] - nickname = device_info.get('nickname', f"Tapo P110 ({ip})") + nickname = device_info.get('nickname', f"tapo p110 ({ip})") state = "on" if device_info.get('device_on', False) else "off" - logger.info(f"✅ Tapo-Steckdose '{nickname}' ({ip}) gefunden - Status: {state}") + logger.info(f"✅ tapo-steckdose '{nickname}' ({ip}) gefunden - status: {state}") results[ip] = True - # Steckdose in Datenbank speichern/aktualisieren + # steckdose in datenbank speichern/aktualisieren try: self._ensure_outlet_in_database(ip, nickname) except Exception as db_error: - logger.warning(f"⚠️ Fehler beim Speichern in DB für {ip}: {str(db_error)}") + logger.warning(f"⚠️ fehler beim speichern in db für {ip}: {str(db_error)}") else: - logger.debug(f"❌ IP {ip} ist erreichbar, aber keine Tapo-Steckdose") + logger.debug(f"❌ ip {ip} ist erreichbar, aber keine tapo-steckdose") results[ip] = False else: - logger.debug(f"❌ IP {ip} nicht erreichbar") + logger.debug(f"❌ ip {ip} nicht erreichbar") results[ip] = False except Exception as e: - logger.warning(f"❌ Fehler bei Steckdosen-Erkennung für IP {ip}: {str(e)}") + logger.warning(f"❌ fehler bei steckdosen-erkennung für ip {ip}: {str(e)}") results[ip] = False continue - # Erfolgsstatistik + # erfolgsstatistik success_count = sum(1 for success in results.values() if success) elapsed_time = time.time() - start_time - logger.info(f"✅ Steckdosen-Erkennung abgeschlossen: {success_count}/{len(results)} Steckdosen gefunden in {elapsed_time:.1f}s") + logger.info(f"✅ steckdosen-erkennung abgeschlossen: {success_count}/{len(results)} steckdosen gefunden in {elapsed_time:.1f}s") self.auto_discovered = True return results def initialize_all_outlets(self) -> Dict[str, bool]: """ - Schaltet alle gespeicherten Steckdosen aus (einheitlicher Startzustand). + schaltet alle gespeicherten steckdosen aus (einheitlicher startzustand). - Returns: - Dict[str, bool]: Ergebnis der Initialisierung pro Drucker + returns: + dict[str, bool]: ergebnis der initialisierung pro drucker """ - logger.info("🚀 Starte Steckdosen-Initialisierung...") + logger.info("🚀 starte steckdosen-initialisierung...") results = {} try: @@ -384,11 +384,11 @@ class TapoController: printers = db_session.query(Printer).filter(Printer.active == True).all() if not printers: - logger.warning("⚠️ Keine aktiven Drucker zur Initialisierung gefunden") + logger.warning("⚠️ keine aktiven drucker zur initialisierung gefunden") db_session.close() return results - # Alle Steckdosen ausschalten + # alle steckdosen ausschalten for printer in printers: try: if printer.plug_ip: @@ -400,39 +400,39 @@ class TapoController: results[printer.name] = success if success: - logger.info(f"✅ {printer.name}: Steckdose ausgeschaltet") + logger.info(f"✅ {printer.name}: steckdose ausgeschaltet") printer.status = "offline" printer.last_checked = datetime.now() else: - logger.warning(f"❌ {printer.name}: Steckdose konnte nicht ausgeschaltet werden") + logger.warning(f"❌ {printer.name}: steckdose konnte nicht ausgeschaltet werden") else: - logger.warning(f"⚠️ {printer.name}: Keine Steckdosen-IP konfiguriert") + logger.warning(f"⚠️ {printer.name}: keine steckdosen-ip konfiguriert") results[printer.name] = False except Exception as e: - logger.error(f"❌ Fehler bei Initialisierung von {printer.name}: {str(e)}") + logger.error(f"❌ fehler bei initialisierung von {printer.name}: {str(e)}") results[printer.name] = False - # Änderungen speichern + # änderungen speichern db_session.commit() db_session.close() success_count = sum(1 for success in results.values() if success) total_count = len(results) - logger.info(f"🎯 Steckdosen-Initialisierung abgeschlossen: {success_count}/{total_count} erfolgreich") + logger.info(f"🎯 steckdosen-initialisierung abgeschlossen: {success_count}/{total_count} erfolgreich") except Exception as e: - logger.error(f"❌ Kritischer Fehler bei Steckdosen-Initialisierung: {str(e)}") + logger.error(f"❌ kritischer fehler bei steckdosen-initialisierung: {str(e)}") return results def get_all_outlet_status(self) -> Dict[str, Dict[str, Any]]: """ - Holt den Status aller konfigurierten Tapo-Steckdosen. + holt den status aller konfigurierten tapo-steckdosen. - Returns: - Dict[str, Dict]: Status aller Steckdosen mit IP als Schlüssel + returns: + dict[str, dict]: status aller steckdosen mit ip als schlüssel """ status_dict = {} @@ -444,13 +444,13 @@ class TapoController: ).all() if not printers: - logger.info("ℹ️ Keine Drucker mit Tapo-Steckdosen konfiguriert") + logger.info("ℹ️ keine drucker mit tapo-steckdosen konfiguriert") db_session.close() return status_dict - logger.info(f"🔍 Prüfe Status von {len(printers)} Tapo-Steckdosen...") + logger.info(f"🔍 prüfe status von {len(printers)} tapo-steckdosen...") - # Parallel-Status-Prüfung + # parallel-status-prüfung with ThreadPoolExecutor(max_workers=min(len(printers), 8)) as executor: future_to_printer = { executor.submit( @@ -474,7 +474,7 @@ class TapoController: "last_checked": datetime.now().isoformat() } except Exception as e: - logger.error(f"❌ Fehler bei Status-Check für {printer.name}: {str(e)}") + logger.error(f"❌ fehler bei status-check für {printer.name}: {str(e)}") status_dict[printer.plug_ip] = { "printer_name": printer.name, "printer_id": printer.id, @@ -486,31 +486,31 @@ class TapoController: } db_session.close() - logger.info(f"✅ Status-Update abgeschlossen für {len(status_dict)} Steckdosen") + logger.info(f"✅ status-update abgeschlossen für {len(status_dict)} steckdosen") except Exception as e: - logger.error(f"❌ Kritischer Fehler beim Abrufen des Steckdosen-Status: {str(e)}") + logger.error(f"❌ kritischer fehler beim abrufen des steckdosen-status: {str(e)}") return status_dict def _collect_device_info(self, p100: PyP100.P100, device_info: dict) -> dict: """ - Sammelt erweiterte Geräteinformationen von der Tapo-Steckdose. + sammelt erweiterte geräteinformationen von der tapo-steckdose. - Args: - p100: PyP100-Instanz - device_info: Basis-Geräteinformationen + args: + p100: pyp100-instanz + device_info: basis-geräteinformationen - Returns: - dict: Erweiterte Informationen + returns: + dict: erweiterte informationen """ extra_info = {} try: - # Firmware-Version + # firmware-version extra_info['firmware_version'] = device_info.get('fw_ver', None) - # Versuche Energiedaten zu holen (nur P110) + # versuche energiedaten zu holen (nur p110) try: energy_usage = p100.getEnergyUsage() if energy_usage: @@ -518,22 +518,22 @@ class TapoController: extra_info['voltage'] = energy_usage.get('voltage', None) extra_info['current'] = energy_usage.get('current', None) except: - pass # P100 unterstützt keine Energiedaten + pass # p100 unterstützt keine energiedaten except Exception as e: - logger.debug(f"Fehler beim Sammeln erweiterter Geräteinformationen: {str(e)}") + logger.debug(f"fehler beim sammeln erweiterter geräteinformationen: {str(e)}") return extra_info def _log_plug_status(self, printer_id: int, status: str, ip_address: str, **kwargs): """ - Protokolliert Steckdosen-Status in der Datenbank. + protokolliert steckdosen-status in der datenbank. - Args: - printer_id: ID des Druckers - status: Status der Steckdose - ip_address: IP-Adresse der Steckdose - **kwargs: Zusätzliche Parameter für das Logging + args: + printer_id: id des druckers + status: status der steckdose + ip_address: ip-adresse der steckdose + **kwargs: zusätzliche parameter für das logging """ if not printer_id: return @@ -547,57 +547,57 @@ class TapoController: **kwargs ) except Exception as e: - logger.warning(f"Fehler beim Loggen des Steckdosen-Status: {e}") + logger.warning(f"fehler beim loggen des steckdosen-status: {e}") def _ensure_outlet_in_database(self, ip_address: str, nickname: str = None) -> bool: """ - Stellt sicher, dass eine erkannte Tapo-Steckdose in der Datenbank existiert. + stellt sicher, dass eine erkannte tapo-steckdose in der datenbank existiert. - Args: - ip_address: IP-Adresse der Steckdose - nickname: Name der Steckdose (optional) + args: + ip_address: ip-adresse der steckdose + nickname: name der steckdose (optional) - Returns: - bool: True wenn erfolgreich gespeichert/aktualisiert + returns: + bool: true wenn erfolgreich gespeichert/aktualisiert """ try: db_session = get_db_session() - # Prüfen, ob Drucker mit dieser IP bereits existiert + # prüfen, ob drucker mit dieser ip bereits existiert existing_printer = db_session.query(Printer).filter( Printer.plug_ip == ip_address ).first() if existing_printer: - # Drucker aktualisieren + # drucker aktualisieren if not existing_printer.plug_username or not existing_printer.plug_password: existing_printer.plug_username = self.username existing_printer.plug_password = self.password - logger.info(f"✅ Drucker {existing_printer.name} mit Tapo-Anmeldedaten aktualisiert") + logger.info(f"✅ drucker {existing_printer.name} mit tapo-anmeldedaten aktualisiert") if nickname and existing_printer.name != nickname and "Tapo P110" not in existing_printer.name: old_name = existing_printer.name existing_printer.name = nickname - logger.info(f"✅ Drucker {old_name} umbenannt zu {nickname}") + logger.info(f"✅ drucker {old_name} umbenannt zu {nickname}") - # Drucker als aktiv markieren + # drucker als aktiv markieren if not existing_printer.active: existing_printer.active = True - logger.info(f"✅ Drucker {existing_printer.name} als aktiv markiert") + logger.info(f"✅ drucker {existing_printer.name} als aktiv markiert") existing_printer.last_checked = datetime.now() db_session.commit() db_session.close() return True else: - # Neuen Drucker erstellen - printer_name = nickname or f"Tapo P110 ({ip_address})" + # neuen drucker erstellen + printer_name = nickname or f"tapo p110 ({ip_address})" mac_address = f"tapo:{ip_address.replace('.', '-')}" new_printer = Printer( name=printer_name, model="TP-Link Tapo P110", - location="Automatisch erkannt", + location="automatisch erkannt", ip_address=ip_address, mac_address=mac_address, plug_ip=ip_address, @@ -610,12 +610,12 @@ class TapoController: db_session.add(new_printer) db_session.commit() - logger.info(f"✅ Neuer Drucker '{printer_name}' mit Tapo-Steckdose {ip_address} erstellt") + logger.info(f"✅ neuer drucker '{printer_name}' mit tapo-steckdose {ip_address} erstellt") db_session.close() return True except Exception as e: - logger.error(f"❌ Fehler beim Speichern der Tapo-Steckdose {ip_address}: {str(e)}") + logger.error(f"❌ fehler beim speichern der tapo-steckdose {ip_address}: {str(e)}") try: db_session.rollback() db_session.close() @@ -624,32 +624,32 @@ class TapoController: return False -# Globale Instanz für einfachen Zugriff +# globale instanz für einfachen zugriff tapo_controller = TapoController() -# Convenience-Funktionen für Rückwärtskompatibilität +# convenience-funktionen für rückwärtskompatibilität def toggle_plug(ip: str, state: bool, username: str = None, password: str = None) -> bool: - """Schaltet eine Tapo-Steckdose ein/aus.""" + """schaltet eine tapo-steckdose ein/aus.""" return tapo_controller.toggle_plug(ip, state, username, password) def test_tapo_connection(ip: str, username: str = None, password: str = None) -> dict: - """Testet die Verbindung zu einer Tapo-Steckdose.""" + """testet die verbindung zu einer tapo-steckdose.""" return tapo_controller.test_connection(ip, username, password) def check_outlet_status(ip: str, username: str = None, password: str = None, printer_id: int = None) -> Tuple[bool, str]: - """Prüft den Status einer Tapo-Steckdose.""" + """prüft den status einer tapo-steckdose.""" return tapo_controller.check_outlet_status(ip, username, password, printer_id) def auto_discover_tapo_outlets() -> Dict[str, bool]: - """Führt automatische Erkennung von Tapo-Steckdosen durch.""" + """führt automatische erkennung von tapo-steckdosen durch.""" return tapo_controller.auto_discover_outlets() def initialize_all_outlets() -> Dict[str, bool]: - """Initialisiert alle Tapo-Steckdosen (schaltet sie aus).""" + """initialisiert alle tapo-steckdosen (schaltet sie aus).""" return tapo_controller.initialize_all_outlets() \ No newline at end of file