🔧 Aktualisierung der Tapo-Steckdosen-Integration: Umstellung auf zentralen tapo_controller für Statusprüfungen und Verbindungs-Tests. Verbesserung der Fehlerbehandlung und Protokollierung. Anpassungen in der Dokumentation und Umbenennung von Funktionen zur besseren Lesbarkeit. 🛠️
This commit is contained in:
parent
502d63bc20
commit
0a1b24c4ef
@ -2217,24 +2217,29 @@ def check_printer_status(ip_address: str, timeout: int = 7) -> Tuple[str, bool]:
|
|||||||
if result == 0:
|
if result == 0:
|
||||||
reachable = True
|
reachable = True
|
||||||
try:
|
try:
|
||||||
# TP-Link Tapo Steckdose mit PyP100 überprüfen
|
# TP-Link Tapo Steckdose mit zentralem tapo_controller überprüfen
|
||||||
from PyP100 import PyP100
|
from utils.tapo_controller import tapo_controller
|
||||||
p100 = PyP100.P100(ip_address, TAPO_USERNAME, TAPO_PASSWORD)
|
reachable, outlet_status = tapo_controller.check_outlet_status(ip_address)
|
||||||
p100.handshake() # Authentifizierung
|
|
||||||
p100.login() # Login
|
|
||||||
|
|
||||||
# Geräteinformationen abrufen
|
|
||||||
device_info = p100.getDeviceInfo()
|
|
||||||
|
|
||||||
# 🎯 KORREKTE LOGIK: Status auswerten
|
# 🎯 KORREKTE LOGIK: Status auswerten
|
||||||
if device_info.get('device_on', False):
|
if reachable:
|
||||||
# Steckdose an = Drucker PRINTING (druckt gerade)
|
if outlet_status == "on":
|
||||||
status = "printing"
|
# Steckdose an = Drucker PRINTING (druckt gerade)
|
||||||
printers_logger.info(f"🖨️ Drucker {ip_address}: PRINTING (Steckdose an - 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:
|
else:
|
||||||
# Steckdose aus = Drucker ONLINE (bereit zum Drucken)
|
# Steckdose nicht erreichbar
|
||||||
status = "online"
|
reachable = False
|
||||||
printers_logger.info(f"[OK] Drucker {ip_address}: ONLINE (Steckdose aus - bereit zum Drucken)")
|
status = "error"
|
||||||
|
printers_logger.error(f"[ERROR] Drucker {ip_address}: Steckdose nicht erreichbar")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
printers_logger.error(f"[ERROR] Fehler bei Tapo-Status-Check für {ip_address}: {str(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()
|
db_session.close()
|
||||||
|
|
||||||
# Tapo-Verbindung testen
|
# Tapo-Verbindung testen
|
||||||
from utils.job_scheduler import test_tapo_connection
|
from utils.tapo_controller import test_tapo_connection
|
||||||
test_result = test_tapo_connection(
|
test_result = test_tapo_connection(
|
||||||
printer.plug_ip,
|
printer.plug_ip,
|
||||||
printer.plug_username,
|
printer.plug_username,
|
||||||
@ -3325,7 +3330,7 @@ def test_all_printers_tapo_connection():
|
|||||||
})
|
})
|
||||||
|
|
||||||
# Alle Drucker testen
|
# Alle Drucker testen
|
||||||
from utils.job_scheduler import test_tapo_connection
|
from utils.tapo_controller import test_tapo_connection
|
||||||
results = []
|
results = []
|
||||||
|
|
||||||
for printer in printers:
|
for printer in printers:
|
||||||
|
Binary file not shown.
@ -3,3 +3,4 @@
|
|||||||
2025-06-05 01:01:11 - [analytics] analytics - [INFO] INFO - 📈 Analytics Engine initialisiert
|
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 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 10:12:41 - [analytics] analytics - [INFO] INFO - 📈 Analytics Engine initialisiert
|
||||||
|
2025-06-05 11:12:32 - [analytics] analytics - [INFO] INFO - 📈 Analytics Engine initialisiert
|
||||||
|
@ -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 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 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 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
|
||||||
|
@ -3,3 +3,4 @@
|
|||||||
2025-06-05 01:01:11 - [backup] backup - [INFO] INFO - BackupManager initialisiert (minimal implementation)
|
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 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 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)
|
||||||
|
@ -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-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
|
||||||
|
@ -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-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 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 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)
|
||||||
|
@ -3,3 +3,4 @@
|
|||||||
2025-06-05 01:01:11 - [database] database - [INFO] INFO - Datenbank-Wartungs-Scheduler gestartet
|
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 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 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
|
||||||
|
@ -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-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 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 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)
|
||||||
|
@ -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 - 🔧 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: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 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
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
2025-06-05 11:12:49 - [jobs] jobs - [INFO] INFO - Jobs abgerufen: 0 von 0 (Seite 1)
|
@ -6,3 +6,5 @@
|
|||||||
2025-06-05 09:31:08 - [maintenance] maintenance - [INFO] INFO - Wartungs-Scheduler gestartet
|
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 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
|
||||||
|
@ -6,3 +6,5 @@
|
|||||||
2025-06-05 09:31:08 - [multi_location] multi_location - [INFO] INFO - Standard-Standort erstellt
|
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 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
|
||||||
|
@ -9,3 +9,4 @@
|
|||||||
2025-06-05 01:01:18 - [permissions] permissions - [INFO] INFO - 🔐 Permission Template Helpers registriert
|
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 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 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
|
||||||
|
@ -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 - ℹ️ 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 - 🔄 Aktualisiere Live-Druckerstatus...
|
||||||
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 - ℹ️ 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
|
||||||
|
@ -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 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 - ✅ 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 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
|
||||||
|
@ -22,3 +22,6 @@
|
|||||||
2025-06-05 10:12:50 - [scheduler] scheduler - [INFO] INFO - Scheduler gestartet
|
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-Thread beendet
|
||||||
2025-06-05 10:14:01 - [scheduler] scheduler - [INFO] INFO - Scheduler gestoppt
|
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
|
||||||
|
@ -9,3 +9,4 @@
|
|||||||
2025-06-05 01:01:18 - [security] security - [INFO] INFO - 🔒 Security System initialisiert
|
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 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 10:12:45 - [security] security - [INFO] INFO - 🔒 Security System initialisiert
|
||||||
|
2025-06-05 11:12:34 - [security] security - [INFO] INFO - 🔒 Security System initialisiert
|
||||||
|
@ -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 - 🔄 Beende Scheduler mit stop()...
|
||||||
2025-06-05 10:14:01 - [shutdown_manager] shutdown_manager - [INFO] INFO - ✅ Scheduler erfolgreich gestoppt
|
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 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
|
||||||
|
@ -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-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 - 🔒 Windows-sichere Log-Rotation: Aktiviert
|
||||||
2025-06-05 10:12:45 - [startup] startup - [INFO] INFO - ==================================================
|
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 - ==================================================
|
||||||
|
@ -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 - [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 - [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 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...
|
||||||
|
12
backend/logs/tapo_controller/tapo_controller.log
Normal file
12
backend/logs/tapo_controller/tapo_controller.log
Normal file
@ -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
|
@ -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: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 - 🔄 Starte Windows Thread-Shutdown...
|
||||||
2025-06-05 10:14:06 - [windows_fixes] windows_fixes - [INFO] INFO - ✅ Windows Thread-Shutdown abgeschlossen
|
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
|
||||||
|
Binary file not shown.
Binary file not shown.
BIN
backend/utils/__pycache__/tapo_controller.cpython-313.pyc
Normal file
BIN
backend/utils/__pycache__/tapo_controller.cpython-313.pyc
Normal file
Binary file not shown.
@ -1,6 +1,6 @@
|
|||||||
"""
|
"""
|
||||||
TP-Link Tapo P110 Zentraler Controller für MYP Platform
|
tp-link tapo p110 zentraler controller für myp platform
|
||||||
Sammelt alle operativen Tapo-Steckdosen-Funktionalitäten an einem Ort.
|
sammelt alle operativen tapo-steckdosen-funktionalitäten an einem ort.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import time
|
import time
|
||||||
@ -15,24 +15,24 @@ from models import get_db_session, Printer, PlugStatusLog
|
|||||||
from utils.logging_config import get_logger
|
from utils.logging_config import get_logger
|
||||||
from utils.settings import TAPO_USERNAME, TAPO_PASSWORD, DEFAULT_TAPO_IPS, TAPO_TIMEOUT, TAPO_RETRY_COUNT
|
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:
|
try:
|
||||||
from PyP100 import PyP100
|
from PyP100 import PyP100
|
||||||
TAPO_AVAILABLE = True
|
TAPO_AVAILABLE = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
TAPO_AVAILABLE = False
|
TAPO_AVAILABLE = False
|
||||||
|
|
||||||
# Logger initialisieren
|
# logger initialisieren
|
||||||
logger = get_logger("tapo_controller")
|
logger = get_logger("tapo_controller")
|
||||||
|
|
||||||
|
|
||||||
class TapoController:
|
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):
|
def __init__(self):
|
||||||
"""Initialisiere den Tapo Controller."""
|
"""initialisiere den tapo controller."""
|
||||||
self.username = TAPO_USERNAME
|
self.username = TAPO_USERNAME
|
||||||
self.password = TAPO_PASSWORD
|
self.password = TAPO_PASSWORD
|
||||||
self.timeout = TAPO_TIMEOUT
|
self.timeout = TAPO_TIMEOUT
|
||||||
@ -40,107 +40,107 @@ class TapoController:
|
|||||||
self.auto_discovered = False
|
self.auto_discovered = False
|
||||||
|
|
||||||
if not TAPO_AVAILABLE:
|
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:
|
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:
|
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:
|
args:
|
||||||
ip: IP-Adresse der Steckdose
|
ip: ip-adresse der steckdose
|
||||||
state: True = Ein, False = Aus
|
state: true = ein, false = aus
|
||||||
username: Benutzername (optional, nutzt Standard wenn nicht angegeben)
|
username: benutzername (optional, nutzt standard wenn nicht angegeben)
|
||||||
password: Passwort (optional, nutzt Standard wenn nicht angegeben)
|
password: passwort (optional, nutzt standard wenn nicht angegeben)
|
||||||
|
|
||||||
Returns:
|
returns:
|
||||||
bool: True wenn erfolgreich geschaltet
|
bool: true wenn erfolgreich geschaltet
|
||||||
"""
|
"""
|
||||||
if not TAPO_AVAILABLE:
|
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
|
return False
|
||||||
|
|
||||||
# IMMER globale Anmeldedaten verwenden
|
# immer globale anmeldedaten verwenden
|
||||||
username = self.username
|
username = self.username
|
||||||
password = self.password
|
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):
|
for attempt in range(self.retry_count):
|
||||||
try:
|
try:
|
||||||
# P100-Verbindung herstellen
|
# p100-verbindung herstellen
|
||||||
p100 = PyP100.P100(ip, username, password)
|
p100 = PyP100.P100(ip, username, password)
|
||||||
p100.handshake()
|
p100.handshake()
|
||||||
p100.login()
|
p100.login()
|
||||||
|
|
||||||
# Steckdose schalten
|
# steckdose schalten
|
||||||
if state:
|
if state:
|
||||||
p100.turnOn()
|
p100.turnOn()
|
||||||
logger.info(f"✅ Tapo-Steckdose {ip} erfolgreich eingeschaltet")
|
logger.info(f"✅ tapo-steckdose {ip} erfolgreich eingeschaltet")
|
||||||
else:
|
else:
|
||||||
p100.turnOff()
|
p100.turnOff()
|
||||||
logger.info(f"✅ Tapo-Steckdose {ip} erfolgreich ausgeschaltet")
|
logger.info(f"✅ tapo-steckdose {ip} erfolgreich ausgeschaltet")
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
action = "ein" if state else "aus"
|
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:
|
if attempt < self.retry_count - 1:
|
||||||
time.sleep(1) # Kurze Pause vor erneutem Versuch
|
time.sleep(1) # kurze pause vor erneutem versuch
|
||||||
else:
|
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
|
return False
|
||||||
|
|
||||||
def turn_off(self, ip: str, username: str = None, password: str = None, printer_id: int = None) -> bool:
|
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:
|
args:
|
||||||
ip: IP-Adresse der Steckdose
|
ip: ip-adresse der steckdose
|
||||||
username: Benutzername (optional)
|
username: benutzername (optional)
|
||||||
password: Passwort (optional)
|
password: passwort (optional)
|
||||||
printer_id: ID des zugehörigen Druckers für Logging (optional)
|
printer_id: id des zugehörigen druckers für logging (optional)
|
||||||
|
|
||||||
Returns:
|
returns:
|
||||||
bool: True wenn erfolgreich ausgeschaltet
|
bool: true wenn erfolgreich ausgeschaltet
|
||||||
"""
|
"""
|
||||||
if not TAPO_AVAILABLE:
|
if not TAPO_AVAILABLE:
|
||||||
logger.error("⚠️ PyP100-Modul nicht verfügbar - kann Tapo-Steckdose nicht schalten")
|
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")
|
self._log_plug_status(printer_id, "disconnected", ip, error_message="PyP100-modul nicht verfügbar")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# IMMER globale Anmeldedaten verwenden
|
# immer globale anmeldedaten verwenden
|
||||||
username = self.username
|
username = self.username
|
||||||
password = self.password
|
password = self.password
|
||||||
|
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# TP-Link Tapo P100 Verbindung herstellen
|
# tp-link tapo p100 verbindung herstellen
|
||||||
p100 = PyP100.P100(ip, username, password)
|
p100 = PyP100.P100(ip, username, password)
|
||||||
p100.handshake()
|
p100.handshake()
|
||||||
p100.login()
|
p100.login()
|
||||||
|
|
||||||
# Steckdose ausschalten
|
# steckdose ausschalten
|
||||||
p100.turnOff()
|
p100.turnOff()
|
||||||
|
|
||||||
response_time = int((time.time() - start_time) * 1000) # in Millisekunden
|
response_time = int((time.time() - start_time) * 1000) # in millisekunden
|
||||||
logger.debug(f"✅ Tapo-Steckdose {ip} erfolgreich ausgeschaltet")
|
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)
|
self._log_plug_status(printer_id, "off", ip, response_time_ms=response_time)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
response_time = int((time.time() - start_time) * 1000)
|
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,
|
self._log_plug_status(printer_id, "disconnected", ip,
|
||||||
response_time_ms=response_time,
|
response_time_ms=response_time,
|
||||||
error_message=str(e))
|
error_message=str(e))
|
||||||
@ -150,83 +150,83 @@ class TapoController:
|
|||||||
def check_outlet_status(self, ip: str, username: str = None, password: str = None,
|
def check_outlet_status(self, ip: str, username: str = None, password: str = None,
|
||||||
printer_id: int = None) -> Tuple[bool, str]:
|
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:
|
args:
|
||||||
ip: IP-Adresse der Steckdose
|
ip: ip-adresse der steckdose
|
||||||
username: Benutzername (optional)
|
username: benutzername (optional)
|
||||||
password: Passwort (optional)
|
password: passwort (optional)
|
||||||
printer_id: ID des zugehörigen Druckers für Logging (optional)
|
printer_id: id des zugehörigen druckers für logging (optional)
|
||||||
|
|
||||||
Returns:
|
returns:
|
||||||
Tuple[bool, str]: (Erreichbar, Status) - Status: "on", "off", "unknown"
|
tuple[bool, str]: (erreichbar, status) - status: "on", "off", "unknown"
|
||||||
"""
|
"""
|
||||||
if not TAPO_AVAILABLE:
|
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,
|
self._log_plug_status(printer_id, "disconnected", ip,
|
||||||
error_message="PyP100-Modul nicht verfügbar",
|
error_message="PyP100-modul nicht verfügbar",
|
||||||
notes="Status-Check fehlgeschlagen")
|
notes="status-check fehlgeschlagen")
|
||||||
return False, "unknown"
|
return False, "unknown"
|
||||||
|
|
||||||
# IMMER globale Anmeldedaten verwenden
|
# immer globale anmeldedaten verwenden
|
||||||
username = self.username
|
username = self.username
|
||||||
password = self.password
|
password = self.password
|
||||||
|
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# TP-Link Tapo P100 Verbindung herstellen
|
# tp-link tapo p100 verbindung herstellen
|
||||||
p100 = PyP100.P100(ip, username, password)
|
p100 = PyP100.P100(ip, username, password)
|
||||||
p100.handshake()
|
p100.handshake()
|
||||||
p100.login()
|
p100.login()
|
||||||
|
|
||||||
# Geräteinformationen abrufen
|
# geräteinformationen abrufen
|
||||||
device_info = p100.getDeviceInfo()
|
device_info = p100.getDeviceInfo()
|
||||||
|
|
||||||
# Status auswerten
|
# status auswerten
|
||||||
device_on = device_info.get('device_on', False)
|
device_on = device_info.get('device_on', False)
|
||||||
status = "on" if device_on else "off"
|
status = "on" if device_on else "off"
|
||||||
|
|
||||||
response_time = int((time.time() - start_time) * 1000)
|
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)
|
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,
|
self._log_plug_status(printer_id, status, ip,
|
||||||
response_time_ms=response_time,
|
response_time_ms=response_time,
|
||||||
power_consumption=extra_info.get('power_consumption'),
|
power_consumption=extra_info.get('power_consumption'),
|
||||||
voltage=extra_info.get('voltage'),
|
voltage=extra_info.get('voltage'),
|
||||||
current=extra_info.get('current'),
|
current=extra_info.get('current'),
|
||||||
firmware_version=extra_info.get('firmware_version'),
|
firmware_version=extra_info.get('firmware_version'),
|
||||||
notes="Automatischer Status-Check")
|
notes="automatischer status-check")
|
||||||
|
|
||||||
return True, status
|
return True, status
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
response_time = int((time.time() - start_time) * 1000)
|
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,
|
self._log_plug_status(printer_id, "disconnected", ip,
|
||||||
response_time_ms=response_time,
|
response_time_ms=response_time,
|
||||||
error_message=str(e),
|
error_message=str(e),
|
||||||
notes="Status-Check fehlgeschlagen")
|
notes="status-check fehlgeschlagen")
|
||||||
|
|
||||||
return False, "unknown"
|
return False, "unknown"
|
||||||
|
|
||||||
def test_connection(self, ip: str, username: str = None, password: str = None) -> dict:
|
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:
|
args:
|
||||||
ip: IP-Adresse der Steckdose
|
ip: ip-adresse der steckdose
|
||||||
username: Benutzername (optional)
|
username: benutzername (optional)
|
||||||
password: Passwort (optional)
|
password: passwort (optional)
|
||||||
|
|
||||||
Returns:
|
returns:
|
||||||
dict: Ergebnis mit Status und Informationen
|
dict: ergebnis mit status und informationen
|
||||||
"""
|
"""
|
||||||
result = {
|
result = {
|
||||||
"success": False,
|
"success": False,
|
||||||
@ -236,58 +236,58 @@ class TapoController:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if not TAPO_AVAILABLE:
|
if not TAPO_AVAILABLE:
|
||||||
result["message"] = "PyP100-Modul nicht verfügbar"
|
result["message"] = "PyP100-modul nicht verfügbar"
|
||||||
result["error"] = "ModuleNotFound"
|
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
|
return result
|
||||||
|
|
||||||
# Verwende globale Anmeldedaten falls nicht angegeben
|
# verwende globale anmeldedaten falls nicht angegeben
|
||||||
if not username or not password:
|
if not username or not password:
|
||||||
username = self.username
|
username = self.username
|
||||||
password = self.password
|
password = self.password
|
||||||
logger.debug(f"Verwende globale Tapo-Anmeldedaten für {ip}")
|
logger.debug(f"verwende globale tapo-anmeldedaten für {ip}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# TP-Link Tapo P100 Verbindung herstellen
|
# tp-link tapo p100 verbindung herstellen
|
||||||
p100 = PyP100.P100(ip, username, password)
|
p100 = PyP100.P100(ip, username, password)
|
||||||
p100.handshake()
|
p100.handshake()
|
||||||
p100.login()
|
p100.login()
|
||||||
|
|
||||||
# Geräteinformationen abrufen
|
# geräteinformationen abrufen
|
||||||
device_info = p100.getDeviceInfo()
|
device_info = p100.getDeviceInfo()
|
||||||
|
|
||||||
result["success"] = True
|
result["success"] = True
|
||||||
result["message"] = "Verbindung erfolgreich"
|
result["message"] = "verbindung erfolgreich"
|
||||||
result["device_info"] = device_info
|
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:
|
except Exception as e:
|
||||||
result["success"] = False
|
result["success"] = False
|
||||||
result["message"] = f"Verbindungsfehler: {str(e)}"
|
result["message"] = f"verbindungsfehler: {str(e)}"
|
||||||
result["error"] = 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
|
return result
|
||||||
|
|
||||||
def ping_address(self, ip: str, timeout: int = 3) -> bool:
|
def ping_address(self, ip: str, timeout: int = 3) -> bool:
|
||||||
"""
|
"""
|
||||||
Führt einen Konnektivitätstest zu einer IP-Adresse durch.
|
führt einen konnektivitätstest zu einer ip-adresse durch.
|
||||||
Verwendet TCP-Verbindung statt Ping für bessere Kompatibilität.
|
verwendet tcp-verbindung statt ping für bessere kompatibilität.
|
||||||
|
|
||||||
Args:
|
args:
|
||||||
ip: Zu testende IP-Adresse
|
ip: zu testende ip-adresse
|
||||||
timeout: Timeout in Sekunden
|
timeout: timeout in sekunden
|
||||||
|
|
||||||
Returns:
|
returns:
|
||||||
bool: True wenn Verbindung erfolgreich
|
bool: true wenn verbindung erfolgreich
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
# IP-Adresse validieren
|
# ip-adresse validieren
|
||||||
ipaddress.ip_address(ip.strip())
|
ipaddress.ip_address(ip.strip())
|
||||||
|
|
||||||
# Standard-Ports für Tapo-Steckdosen testen
|
# standard-ports für tapo-steckdosen testen
|
||||||
test_ports = [9999, 80, 443] # Tapo-Standard, HTTP, HTTPS
|
test_ports = [9999, 80, 443] # tapo-standard, http, https
|
||||||
|
|
||||||
for port in test_ports:
|
for port in test_ports:
|
||||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
@ -296,87 +296,87 @@ class TapoController:
|
|||||||
sock.close()
|
sock.close()
|
||||||
|
|
||||||
if result == 0:
|
if result == 0:
|
||||||
logger.debug(f"✅ Verbindung zu {ip}:{port} erfolgreich")
|
logger.debug(f"✅ verbindung zu {ip}:{port} erfolgreich")
|
||||||
return True
|
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
|
return False
|
||||||
|
|
||||||
except Exception as e:
|
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
|
return False
|
||||||
|
|
||||||
def auto_discover_outlets(self) -> Dict[str, bool]:
|
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:
|
returns:
|
||||||
Dict[str, bool]: Ergebnis der Steckdosenerkennung mit IP als Schlüssel
|
dict[str, bool]: ergebnis der steckdosenerkennung mit ip als schlüssel
|
||||||
"""
|
"""
|
||||||
if self.auto_discovered:
|
if self.auto_discovered:
|
||||||
logger.info("🔍 Tapo-Steckdosen wurden bereits erkannt")
|
logger.info("🔍 tapo-steckdosen wurden bereits erkannt")
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
logger.info("🔍 Starte automatische Tapo-Steckdosenerkennung...")
|
logger.info("🔍 starte automatische tapo-steckdosenerkennung...")
|
||||||
results = {}
|
results = {}
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
|
|
||||||
# Standard-IPs aus der Konfiguration testen
|
# standard-ips aus der konfiguration testen
|
||||||
logger.info(f"🔄 Teste {len(DEFAULT_TAPO_IPS)} Standard-IPs aus der Konfiguration")
|
logger.info(f"🔄 teste {len(DEFAULT_TAPO_IPS)} standard-ips aus der konfiguration")
|
||||||
|
|
||||||
for i, ip in enumerate(DEFAULT_TAPO_IPS):
|
for i, ip in enumerate(DEFAULT_TAPO_IPS):
|
||||||
try:
|
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):
|
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)
|
test_result = self.test_connection(ip)
|
||||||
|
|
||||||
if test_result["success"]:
|
if test_result["success"]:
|
||||||
device_info = test_result["device_info"]
|
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"
|
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
|
results[ip] = True
|
||||||
|
|
||||||
# Steckdose in Datenbank speichern/aktualisieren
|
# steckdose in datenbank speichern/aktualisieren
|
||||||
try:
|
try:
|
||||||
self._ensure_outlet_in_database(ip, nickname)
|
self._ensure_outlet_in_database(ip, nickname)
|
||||||
except Exception as db_error:
|
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:
|
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
|
results[ip] = False
|
||||||
else:
|
else:
|
||||||
logger.debug(f"❌ IP {ip} nicht erreichbar")
|
logger.debug(f"❌ ip {ip} nicht erreichbar")
|
||||||
results[ip] = False
|
results[ip] = False
|
||||||
|
|
||||||
except Exception as e:
|
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
|
results[ip] = False
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Erfolgsstatistik
|
# erfolgsstatistik
|
||||||
success_count = sum(1 for success in results.values() if success)
|
success_count = sum(1 for success in results.values() if success)
|
||||||
elapsed_time = time.time() - start_time
|
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
|
self.auto_discovered = True
|
||||||
return results
|
return results
|
||||||
|
|
||||||
def initialize_all_outlets(self) -> Dict[str, bool]:
|
def initialize_all_outlets(self) -> Dict[str, bool]:
|
||||||
"""
|
"""
|
||||||
Schaltet alle gespeicherten Steckdosen aus (einheitlicher Startzustand).
|
schaltet alle gespeicherten steckdosen aus (einheitlicher startzustand).
|
||||||
|
|
||||||
Returns:
|
returns:
|
||||||
Dict[str, bool]: Ergebnis der Initialisierung pro Drucker
|
dict[str, bool]: ergebnis der initialisierung pro drucker
|
||||||
"""
|
"""
|
||||||
logger.info("🚀 Starte Steckdosen-Initialisierung...")
|
logger.info("🚀 starte steckdosen-initialisierung...")
|
||||||
results = {}
|
results = {}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -384,11 +384,11 @@ class TapoController:
|
|||||||
printers = db_session.query(Printer).filter(Printer.active == True).all()
|
printers = db_session.query(Printer).filter(Printer.active == True).all()
|
||||||
|
|
||||||
if not printers:
|
if not printers:
|
||||||
logger.warning("⚠️ Keine aktiven Drucker zur Initialisierung gefunden")
|
logger.warning("⚠️ keine aktiven drucker zur initialisierung gefunden")
|
||||||
db_session.close()
|
db_session.close()
|
||||||
return results
|
return results
|
||||||
|
|
||||||
# Alle Steckdosen ausschalten
|
# alle steckdosen ausschalten
|
||||||
for printer in printers:
|
for printer in printers:
|
||||||
try:
|
try:
|
||||||
if printer.plug_ip:
|
if printer.plug_ip:
|
||||||
@ -400,39 +400,39 @@ class TapoController:
|
|||||||
results[printer.name] = success
|
results[printer.name] = success
|
||||||
|
|
||||||
if success:
|
if success:
|
||||||
logger.info(f"✅ {printer.name}: Steckdose ausgeschaltet")
|
logger.info(f"✅ {printer.name}: steckdose ausgeschaltet")
|
||||||
printer.status = "offline"
|
printer.status = "offline"
|
||||||
printer.last_checked = datetime.now()
|
printer.last_checked = datetime.now()
|
||||||
else:
|
else:
|
||||||
logger.warning(f"❌ {printer.name}: Steckdose konnte nicht ausgeschaltet werden")
|
logger.warning(f"❌ {printer.name}: steckdose konnte nicht ausgeschaltet werden")
|
||||||
else:
|
else:
|
||||||
logger.warning(f"⚠️ {printer.name}: Keine Steckdosen-IP konfiguriert")
|
logger.warning(f"⚠️ {printer.name}: keine steckdosen-ip konfiguriert")
|
||||||
results[printer.name] = False
|
results[printer.name] = False
|
||||||
|
|
||||||
except Exception as e:
|
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
|
results[printer.name] = False
|
||||||
|
|
||||||
# Änderungen speichern
|
# änderungen speichern
|
||||||
db_session.commit()
|
db_session.commit()
|
||||||
db_session.close()
|
db_session.close()
|
||||||
|
|
||||||
success_count = sum(1 for success in results.values() if success)
|
success_count = sum(1 for success in results.values() if success)
|
||||||
total_count = len(results)
|
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:
|
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
|
return results
|
||||||
|
|
||||||
def get_all_outlet_status(self) -> Dict[str, Dict[str, Any]]:
|
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:
|
returns:
|
||||||
Dict[str, Dict]: Status aller Steckdosen mit IP als Schlüssel
|
dict[str, dict]: status aller steckdosen mit ip als schlüssel
|
||||||
"""
|
"""
|
||||||
status_dict = {}
|
status_dict = {}
|
||||||
|
|
||||||
@ -444,13 +444,13 @@ class TapoController:
|
|||||||
).all()
|
).all()
|
||||||
|
|
||||||
if not printers:
|
if not printers:
|
||||||
logger.info("ℹ️ Keine Drucker mit Tapo-Steckdosen konfiguriert")
|
logger.info("ℹ️ keine drucker mit tapo-steckdosen konfiguriert")
|
||||||
db_session.close()
|
db_session.close()
|
||||||
return status_dict
|
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:
|
with ThreadPoolExecutor(max_workers=min(len(printers), 8)) as executor:
|
||||||
future_to_printer = {
|
future_to_printer = {
|
||||||
executor.submit(
|
executor.submit(
|
||||||
@ -474,7 +474,7 @@ class TapoController:
|
|||||||
"last_checked": datetime.now().isoformat()
|
"last_checked": datetime.now().isoformat()
|
||||||
}
|
}
|
||||||
except Exception as e:
|
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] = {
|
status_dict[printer.plug_ip] = {
|
||||||
"printer_name": printer.name,
|
"printer_name": printer.name,
|
||||||
"printer_id": printer.id,
|
"printer_id": printer.id,
|
||||||
@ -486,31 +486,31 @@ class TapoController:
|
|||||||
}
|
}
|
||||||
|
|
||||||
db_session.close()
|
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:
|
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
|
return status_dict
|
||||||
|
|
||||||
def _collect_device_info(self, p100: PyP100.P100, device_info: dict) -> 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:
|
args:
|
||||||
p100: PyP100-Instanz
|
p100: pyp100-instanz
|
||||||
device_info: Basis-Geräteinformationen
|
device_info: basis-geräteinformationen
|
||||||
|
|
||||||
Returns:
|
returns:
|
||||||
dict: Erweiterte Informationen
|
dict: erweiterte informationen
|
||||||
"""
|
"""
|
||||||
extra_info = {}
|
extra_info = {}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Firmware-Version
|
# firmware-version
|
||||||
extra_info['firmware_version'] = device_info.get('fw_ver', None)
|
extra_info['firmware_version'] = device_info.get('fw_ver', None)
|
||||||
|
|
||||||
# Versuche Energiedaten zu holen (nur P110)
|
# versuche energiedaten zu holen (nur p110)
|
||||||
try:
|
try:
|
||||||
energy_usage = p100.getEnergyUsage()
|
energy_usage = p100.getEnergyUsage()
|
||||||
if energy_usage:
|
if energy_usage:
|
||||||
@ -518,22 +518,22 @@ class TapoController:
|
|||||||
extra_info['voltage'] = energy_usage.get('voltage', None)
|
extra_info['voltage'] = energy_usage.get('voltage', None)
|
||||||
extra_info['current'] = energy_usage.get('current', None)
|
extra_info['current'] = energy_usage.get('current', None)
|
||||||
except:
|
except:
|
||||||
pass # P100 unterstützt keine Energiedaten
|
pass # p100 unterstützt keine energiedaten
|
||||||
|
|
||||||
except Exception as e:
|
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
|
return extra_info
|
||||||
|
|
||||||
def _log_plug_status(self, printer_id: int, status: str, ip_address: str, **kwargs):
|
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:
|
args:
|
||||||
printer_id: ID des Druckers
|
printer_id: id des druckers
|
||||||
status: Status der Steckdose
|
status: status der steckdose
|
||||||
ip_address: IP-Adresse der Steckdose
|
ip_address: ip-adresse der steckdose
|
||||||
**kwargs: Zusätzliche Parameter für das Logging
|
**kwargs: zusätzliche parameter für das logging
|
||||||
"""
|
"""
|
||||||
if not printer_id:
|
if not printer_id:
|
||||||
return
|
return
|
||||||
@ -547,57 +547,57 @@ class TapoController:
|
|||||||
**kwargs
|
**kwargs
|
||||||
)
|
)
|
||||||
except Exception as e:
|
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:
|
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:
|
args:
|
||||||
ip_address: IP-Adresse der Steckdose
|
ip_address: ip-adresse der steckdose
|
||||||
nickname: Name der Steckdose (optional)
|
nickname: name der steckdose (optional)
|
||||||
|
|
||||||
Returns:
|
returns:
|
||||||
bool: True wenn erfolgreich gespeichert/aktualisiert
|
bool: true wenn erfolgreich gespeichert/aktualisiert
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
db_session = get_db_session()
|
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(
|
existing_printer = db_session.query(Printer).filter(
|
||||||
Printer.plug_ip == ip_address
|
Printer.plug_ip == ip_address
|
||||||
).first()
|
).first()
|
||||||
|
|
||||||
if existing_printer:
|
if existing_printer:
|
||||||
# Drucker aktualisieren
|
# drucker aktualisieren
|
||||||
if not existing_printer.plug_username or not existing_printer.plug_password:
|
if not existing_printer.plug_username or not existing_printer.plug_password:
|
||||||
existing_printer.plug_username = self.username
|
existing_printer.plug_username = self.username
|
||||||
existing_printer.plug_password = self.password
|
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:
|
if nickname and existing_printer.name != nickname and "Tapo P110" not in existing_printer.name:
|
||||||
old_name = existing_printer.name
|
old_name = existing_printer.name
|
||||||
existing_printer.name = nickname
|
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:
|
if not existing_printer.active:
|
||||||
existing_printer.active = True
|
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()
|
existing_printer.last_checked = datetime.now()
|
||||||
db_session.commit()
|
db_session.commit()
|
||||||
db_session.close()
|
db_session.close()
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
# Neuen Drucker erstellen
|
# neuen drucker erstellen
|
||||||
printer_name = nickname or f"Tapo P110 ({ip_address})"
|
printer_name = nickname or f"tapo p110 ({ip_address})"
|
||||||
mac_address = f"tapo:{ip_address.replace('.', '-')}"
|
mac_address = f"tapo:{ip_address.replace('.', '-')}"
|
||||||
|
|
||||||
new_printer = Printer(
|
new_printer = Printer(
|
||||||
name=printer_name,
|
name=printer_name,
|
||||||
model="TP-Link Tapo P110",
|
model="TP-Link Tapo P110",
|
||||||
location="Automatisch erkannt",
|
location="automatisch erkannt",
|
||||||
ip_address=ip_address,
|
ip_address=ip_address,
|
||||||
mac_address=mac_address,
|
mac_address=mac_address,
|
||||||
plug_ip=ip_address,
|
plug_ip=ip_address,
|
||||||
@ -610,12 +610,12 @@ class TapoController:
|
|||||||
|
|
||||||
db_session.add(new_printer)
|
db_session.add(new_printer)
|
||||||
db_session.commit()
|
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()
|
db_session.close()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
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:
|
try:
|
||||||
db_session.rollback()
|
db_session.rollback()
|
||||||
db_session.close()
|
db_session.close()
|
||||||
@ -624,32 +624,32 @@ class TapoController:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
# Globale Instanz für einfachen Zugriff
|
# globale instanz für einfachen zugriff
|
||||||
tapo_controller = TapoController()
|
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:
|
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)
|
return tapo_controller.toggle_plug(ip, state, username, password)
|
||||||
|
|
||||||
|
|
||||||
def test_tapo_connection(ip: str, username: str = None, password: str = None) -> dict:
|
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)
|
return tapo_controller.test_connection(ip, username, password)
|
||||||
|
|
||||||
|
|
||||||
def check_outlet_status(ip: str, username: str = None, password: str = None,
|
def check_outlet_status(ip: str, username: str = None, password: str = None,
|
||||||
printer_id: int = None) -> Tuple[bool, str]:
|
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)
|
return tapo_controller.check_outlet_status(ip, username, password, printer_id)
|
||||||
|
|
||||||
|
|
||||||
def auto_discover_tapo_outlets() -> Dict[str, bool]:
|
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()
|
return tapo_controller.auto_discover_outlets()
|
||||||
|
|
||||||
|
|
||||||
def initialize_all_outlets() -> Dict[str, bool]:
|
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()
|
return tapo_controller.initialize_all_outlets()
|
Loading…
x
Reference in New Issue
Block a user