7.4 KiB
Steckdosen-Startup-Initialisierung
Übersicht
Dieses Dokument beschreibt die implementierte Lösung für die automatische Initialisierung aller Tapo-Steckdosen beim Systemstart. Die Lösung stellt sicher, dass alle im Netzwerk erreichbaren Steckdosen beim Start des MYP-Systems in einen einheitlichen Zustand versetzt werden: AUS = FREI.
Zielsetzung
Alle Steckdosen müssen via Scheduler zu Beginn in den selben Zustand versetzt werden (aus = frei), wenn sie im Netzwerk verfügbar / erreichbar sind.
Implementierung
1. Erweiterte Job Scheduler Klasse
Datei: utils/job_scheduler.py
Die BackgroundTaskScheduler
Klasse wurde um eine neue Methode erweitert:
def initialize_all_outlets_on_startup(self) -> Dict[str, bool]:
"""
Initialisiert alle konfigurierten Steckdosen beim Systemstart.
Schaltet alle im Netzwerk erreichbaren Tapo-Steckdosen aus, um einen
einheitlichen Startzustand (aus = frei) zu gewährleisten.
Returns:
Dict[str, bool]: Ergebnis der Initialisierung pro Drucker
"""
Funktionsweise:
- Einmalige Ausführung: Flag
_outlets_initialized
verhindert mehrfache Initialisierung - Datenbankabfrage: Lädt alle aktiven Drucker mit Steckdosen-Konfiguration
- Netzwerk-Check: Prüft Erreichbarkeit jeder Steckdose via Ping
- Status-Prüfung: Ermittelt aktuellen Steckdosen-Status (an/aus)
- Intelligente Schaltung: Schaltet nur die Steckdosen aus, die aktuell eingeschaltet sind
- Datenbank-Update: Aktualisiert Drucker-Status in der Datenbank
- Umfassendes Logging: Detaillierte Protokollierung aller Aktionen
2. Erweiterte Hardware-Integration
Datei: utils/hardware_integration.py
Die DruckerSteuerung
Klasse wurde um folgende Methoden erweitert:
def ping_address(self, ip: str, timeout: int = 5) -> bool:
"""Prüft die Netzwerk-Erreichbarkeit einer IP-Adresse."""
def turn_off(self, ip: str, username: str = None, password: str = None, printer_id: int = None) -> bool:
"""Schaltet eine Tapo-Steckdose aus."""
def turn_on(self, ip: str, username: str = None, password: str = None, printer_id: int = None) -> bool:
"""Schaltet eine Tapo-Steckdose ein."""
Funktionen:
- Netzwerk-Testing: Socket-basierte Erreichbarkeitsprüfung
- Tapo-Steuerung: Native PyP100/PyP110 Bibliothek-Integration
- Fehlerbehandlung: Robuste Exception-Behandlung
- Simulation-Modus: Fallback wenn Tapo-Bibliotheken nicht verfügbar
3. App-Startup-Integration
Datei: app.py
Die Steckdosen-Initialisierung wurde in den App-Startup-Prozess integriert.
Ablauf beim Systemstart
1. System-Boot
[STARTUP] 🚀 Starte MYP System
[STARTUP] Initialisiere Datenbank...
[STARTUP] ✅ Datenbank initialisiert
[STARTUP] Prüfe Initial-Admin...
[STARTUP] ✅ Admin-Benutzer geprüft
[STARTUP] Initialisiere statische Drucker...
[STARTUP] ✅ Statische Drucker konfiguriert
[STARTUP] Starte Queue Manager...
[STARTUP] ✅ Queue Manager gestartet
[STARTUP] Starte Job Scheduler...
[STARTUP] ✅ Job Scheduler gestartet
2. Steckdosen-Initialisierung
[STARTUP] Initialisiere Steckdosen (alle auf 'aus' = frei)...
[scheduler] 🚀 Starte Steckdosen-Initialisierung beim Systemstart...
[scheduler] 🔍 Prüfe 5 konfigurierte Steckdosen...
[scheduler] 🔌 Verarbeite Drucker_1 (192.168.0.100)...
[scheduler] 📡 192.168.0.100: ✅ erreichbar
[scheduler] ✓ Drucker_1: Bereits ausgeschaltet - keine Aktion nötig
[scheduler] 🔌 Verarbeite Drucker_2 (192.168.0.101)...
[scheduler] 📡 192.168.0.101: ✅ erreichbar
[scheduler] 🔄 Drucker_2: Schalte Steckdose von 'an' auf 'aus' um...
[scheduler] ✅ Drucker_2: Erfolgreich ausgeschaltet
3. Abschluss-Zusammenfassung
============================================================
🎯 STECKDOSEN-INITIALISIERUNG ABGESCHLOSSEN
📊 Gesamt: 5 Steckdosen
✅ Erfolgreich: 3
📡 Nicht erreichbar: 1
❌ Fehlgeschlagen: 1
⚡ 3/5 Steckdosen erfolgreich initialisiert
============================================================
[STARTUP] ⚡ 3/5 Steckdosen erfolgreich initialisiert
Technische Details
Netzwerk-Erreichbarkeitsprüfung
def ping_address(self, ip: str, timeout: int = 5) -> bool:
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(timeout)
result = sock.connect_ex((ip, 80))
sock.close()
return (result == 0)
except Exception as e:
return False
- Methode: Socket-basierte Verbindungsprüfung auf Port 80
- Timeout: Standardmäßig 5 Sekunden (für Startup angepasst auf 3 Sekunden)
- Zuverlässigkeit: Erkennt sowohl Netzwerk- als auch Geräteverfügbarkeit
Tapo-Steckdosen-Steuerung
def turn_off(self, ip: str, username: str = None, password: str = None, printer_id: int = None) -> bool:
try:
p100 = PyP100(ip, self.tapo_username, self.tapo_password)
p100.handshake()
p100.login()
p100.turnOff()
return True
except Exception as e:
return False
- Protokoll: Native TP-Link Tapo P100/P110 API
- Authentifizierung: Standard admin/admin Credentials
- Fehlerbehandlung: Robuste Exception-Behandlung mit detailliertem Logging
Fehlerbehandlung
1. Netzwerk-Fehler
- Nicht erreichbare Steckdosen werden übersprungen
- Timeout-Schutz verhindert hängende Operationen
- Detailliertes Logging für Netzwerk-Diagnose
2. Hardware-Fehler
- Tapo-Verbindungsfehler werden protokolliert aber nicht kritisch behandelt
- Simulation-Modus wenn PyP100-Bibliothek nicht verfügbar
- Graceful Degradation bei partiellen Fehlern
3. Datenbank-Fehler
- Rollback-Mechanismus bei Datenbank-Fehlern
- Transaktionale Sicherheit durch Context Manager
- Fehler-Recovery ohne System-Crash
Monitoring und Logging
Log-Kategorien
- Debug-Level: Detaillierte Netzwerk- und Hardware-Operationen
- Info-Level: Erfolgreiche Aktionen und Zusammenfassungen
- Warning-Level: Nicht-kritische Fehler (nicht erreichbare Geräte)
- Error-Level: Kritische Fehler die Intervention erfordern
Log-Dateien
- Scheduler-Log:
logs/scheduler/scheduler.log
- Hardware-Log:
logs/hardware_integration/hardware_integration.log
- App-Startup-Log:
logs/startup/startup.log
Konfiguration
Datenbank-Schema
Die Initialisierung basiert auf der Printer
Tabelle:
SELECT * FROM printers
WHERE active = 1
AND plug_ip IS NOT NULL;
Erforderliche Felder:
id
: Drucker-IDname
: Drucker-Nameplug_ip
: IP-Adresse der Tapo-Steckdoseactive
: Aktiv-Status (muss TRUE sein)
Tapo-Credentials
# Standard-Zugangsdaten in hardware_integration.py
self.tapo_username = "admin"
self.tapo_password = "admin"
Sicherheit
1. Einmalige Ausführung
- Flag-basierte Kontrolle:
_outlets_initialized
verhindert mehrfache Ausführung - Race-Condition-Schutz: Thread-sichere Implementierung
2. Netzwerk-Sicherheit
- Timeout-Schutz: Verhindert hängende Verbindungen
- Local-Network-Only: Funktioniert nur in lokalen Netzwerken
- Keine externe Kommunikation
3. Fehler-Isolation
- Non-Critical-Errors: Einzelne Fehler stoppen nicht das System
- Graceful-Degradation: System funktioniert auch bei partiellen Fehlern
Implementiert von: Till Tomczak - Mercedes-Benz TBA Marienfelde
Datum: 2025-06-19
Version: 1.0.0