"Update printer blueprint and test for Tapo Sofort integration (feat)"

This commit is contained in:
2025-05-29 22:12:30 +02:00
parent a642456d09
commit c7c27452e7
3 changed files with 281 additions and 165 deletions

View File

@@ -17,7 +17,7 @@ import os
from models import get_db_session, Printer
from utils.logging_config import get_logger
from config.settings import PRINTERS, TAPO_USERNAME, TAPO_PASSWORD
from config.settings import PRINTERS, TAPO_USERNAME, TAPO_PASSWORD, DEFAULT_TAPO_IPS, TAPO_AUTO_DISCOVERY
# TP-Link Tapo P110 Unterstützung hinzufügen
try:
@@ -42,12 +42,17 @@ class PrinterMonitor:
self.monitoring_active = False
self.monitor_thread = None
self.startup_initialized = False
self.auto_discovered_tapo = False
# Cache-Konfiguration
self.session_cache_ttl = 30 # 30 Sekunden für Session-Cache
self.db_cache_ttl = 300 # 5 Minuten für DB-Cache
monitor_logger.info("🖨️ Drucker-Monitor initialisiert")
# Automatische Steckdosenerkennung starten, falls aktiviert
if TAPO_AUTO_DISCOVERY:
self.auto_discover_tapo_outlets()
def initialize_all_outlets_on_startup(self) -> Dict[str, bool]:
"""
@@ -450,6 +455,140 @@ class PrinterMonitor:
summary["offline"] += 1
return summary
def auto_discover_tapo_outlets(self) -> Dict[str, bool]:
"""
Automatische Erkennung und Konfiguration von TP-Link Tapo P110-Steckdosen im Netzwerk.
Returns:
Dict[str, bool]: Ergebnis der Steckdosenerkennung mit IP als Schlüssel
"""
if self.auto_discovered_tapo:
monitor_logger.info("🔍 Tapo-Steckdosen wurden bereits erkannt")
return {}
monitor_logger.info("🔍 Starte automatische Tapo-Steckdosenerkennung...")
results = {}
# 1. Zuerst die Standard-IPs aus der Konfiguration testen
monitor_logger.info(f"🔄 Teste {len(DEFAULT_TAPO_IPS)} Standard-IPs aus der Konfiguration")
for ip in DEFAULT_TAPO_IPS:
try:
# Ping-Test für Grundkonnektivität
ping_success = self._ping_address(ip, timeout=2)
if ping_success:
monitor_logger.info(f"✅ Steckdose mit IP {ip} ist pingbar")
# Tapo-Verbindung testen
if TAPO_AVAILABLE:
try:
p110 = PyP110.P110(ip, TAPO_USERNAME, TAPO_PASSWORD)
p110.handshake()
p110.login()
device_info = p110.getDeviceInfo()
# Steckdose gefunden und verbunden
nickname = device_info.get('nickname', f"Tapo P110 ({ip})")
state = "on" if device_info.get('device_on', False) else "off"
monitor_logger.info(f"✅ Tapo-Steckdose '{nickname}' ({ip}) gefunden - Status: {state}")
results[ip] = True
# Steckdose in Datenbank speichern/aktualisieren
self._ensure_tapo_in_database(ip, nickname)
except Exception as e:
monitor_logger.debug(f"❌ IP {ip} ist pingbar, aber keine Tapo-Steckdose: {str(e)}")
results[ip] = False
else:
monitor_logger.warning("⚠️ PyP100-Modul nicht verfügbar - kann Tapo-Verbindung nicht testen")
results[ip] = False
else:
monitor_logger.debug(f"❌ IP {ip} nicht erreichbar")
results[ip] = False
except Exception as e:
monitor_logger.error(f"❌ Fehler bei Steckdosen-Erkennung für IP {ip}: {str(e)}")
results[ip] = False
# Erfolgsstatistik berechnen
success_count = sum(1 for success in results.values() if success)
monitor_logger.info(f"✅ Steckdosen-Erkennung abgeschlossen: {success_count}/{len(results)} Steckdosen gefunden")
# Markieren, dass automatische Erkennung durchgeführt wurde
self.auto_discovered_tapo = True
return results
def _ensure_tapo_in_database(self, ip_address: str, nickname: str = None) -> bool:
"""
Stellt sicher, dass eine erkannte Tapo-Steckdose in der Datenbank existiert.
Args:
ip_address: IP-Adresse der Steckdose
nickname: Name der Steckdose (optional)
Returns:
bool: True wenn erfolgreich in Datenbank gespeichert/aktualisiert
"""
try:
db_session = get_db_session()
# 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, falls nötig
if not existing_printer.plug_username or not existing_printer.plug_password:
existing_printer.plug_username = TAPO_USERNAME
existing_printer.plug_password = TAPO_PASSWORD
monitor_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
monitor_logger.info(f"✅ Drucker {old_name} umbenannt zu {nickname}")
# Status aktualisieren
existing_printer.last_checked = datetime.now()
db_session.commit()
db_session.close()
return True
else:
# Neuen Drucker erstellen, falls keiner existiert
printer_name = nickname or f"Tapo P110 ({ip_address})"
mac_address = f"tapo:{ip_address.replace('.', '-')}" # Pseudo-MAC-Adresse
new_printer = Printer(
name=printer_name,
model="TP-Link Tapo P110",
location="Automatisch erkannt",
ip_address=ip_address, # Drucker-IP setzen wir gleich Steckdosen-IP
mac_address=mac_address,
plug_ip=ip_address,
plug_username=TAPO_USERNAME,
plug_password=TAPO_PASSWORD,
status="offline",
active=True,
last_checked=datetime.now()
)
db_session.add(new_printer)
db_session.commit()
monitor_logger.info(f"✅ Neuer Drucker '{printer_name}' mit Tapo-Steckdose {ip_address} erstellt")
db_session.close()
return True
except Exception as e:
monitor_logger.error(f"❌ Fehler beim Speichern der Tapo-Steckdose {ip_address}: {str(e)}")
try:
db_session.rollback()
db_session.close()
except:
pass
return False
# Globale Instanz
printer_monitor = PrinterMonitor()