Files
Projektarbeit-MYP/backend/scripts/diagnose_tapo.py

281 lines
8.9 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
Tapo Steckdosen Diagnose-Tool
============================
Dieses Script hilft bei der Diagnose von Verbindungsproblemen mit Tapo-Steckdosen.
Autor: Till Tomczak
Datum: 2025-06-20
"""
import sys
import socket
import subprocess
import time
import os
from datetime import datetime
# Farben für Terminal-Ausgabe
class Colors:
GREEN = '\033[92m'
YELLOW = '\033[93m'
RED = '\033[91m'
BLUE = '\033[94m'
ENDC = '\033[0m'
BOLD = '\033[1m'
def print_header(text):
"""Druckt eine formatierte Überschrift"""
print(f"\n{Colors.BOLD}{Colors.BLUE}{'=' * 60}{Colors.ENDC}")
print(f"{Colors.BOLD}{Colors.BLUE}{text:^60}{Colors.ENDC}")
print(f"{Colors.BOLD}{Colors.BLUE}{'=' * 60}{Colors.ENDC}\n")
def print_success(text):
"""Druckt eine Erfolgsmeldung"""
print(f"{Colors.GREEN}{text}{Colors.ENDC}")
def print_warning(text):
"""Druckt eine Warnung"""
print(f"{Colors.YELLOW}⚠️ {text}{Colors.ENDC}")
def print_error(text):
"""Druckt eine Fehlermeldung"""
print(f"{Colors.RED}{text}{Colors.ENDC}")
def print_info(text):
"""Druckt eine Info-Meldung"""
print(f"{Colors.BLUE} {text}{Colors.ENDC}")
def test_port_connection(ip, port, timeout=3):
"""
Testet die Verbindung zu einem bestimmten Port.
Args:
ip: IP-Adresse
port: Port-Nummer
timeout: Timeout in Sekunden
Returns:
bool: True wenn Verbindung möglich
"""
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(timeout)
result = sock.connect_ex((ip, port))
sock.close()
return result == 0
except Exception as e:
print_error(f"Socket-Fehler: {e}")
return False
def test_icmp_ping(ip):
"""
Führt einen ICMP Ping durch.
Args:
ip: IP-Adresse
Returns:
bool: True wenn Ping erfolgreich
"""
try:
# Windows und Linux kompatibel
param = '-n' if os.name == 'nt' else '-c'
command = ['ping', param, '1', '-w', '2000', ip]
result = subprocess.run(command, capture_output=True, text=True, timeout=5)
return result.returncode == 0
except Exception as e:
print_error(f"Ping-Fehler: {e}")
return False
def test_dns_resolution(hostname):
"""
Testet die DNS-Auflösung eines Hostnamens.
Args:
hostname: Hostname zum Auflösen
Returns:
str: Aufgelöste IP oder None
"""
try:
ip = socket.gethostbyname(hostname)
return ip
except Exception as e:
print_error(f"DNS-Auflösung fehlgeschlagen: {e}")
return None
def test_tapo_connection(ip, username="admin", password="admin"):
"""
Testet die Tapo-Verbindung.
Args:
ip: IP-Adresse der Steckdose
username: Tapo-Benutzername
password: Tapo-Passwort
Returns:
dict: Ergebnis der Tests
"""
results = {
"timestamp": datetime.now().isoformat(),
"ip": ip,
"tests": {}
}
# Test 1: ICMP Ping
print_info(f"Teste ICMP Ping zu {ip}...")
ping_result = test_icmp_ping(ip)
results["tests"]["icmp_ping"] = ping_result
if ping_result:
print_success(f"ICMP Ping zu {ip} erfolgreich")
else:
print_warning(f"ICMP Ping zu {ip} fehlgeschlagen (kann durch Firewall blockiert sein)")
# Test 2: Port 80 (HTTP)
print_info(f"Teste Port 80 (HTTP) auf {ip}...")
port80_result = test_port_connection(ip, 80)
results["tests"]["port_80"] = port80_result
if port80_result:
print_success(f"Port 80 auf {ip} ist erreichbar")
else:
print_error(f"Port 80 auf {ip} ist NICHT erreichbar")
# Test 3: Port 9999 (Tapo-spezifisch)
print_info(f"Teste Port 9999 (Tapo) auf {ip}...")
port9999_result = test_port_connection(ip, 9999)
results["tests"]["port_9999"] = port9999_result
if port9999_result:
print_success(f"Port 9999 auf {ip} ist erreichbar")
else:
print_warning(f"Port 9999 auf {ip} ist nicht erreichbar")
# Test 4: PyP100 Verbindung
try:
print_info("Teste PyP100 Bibliothek...")
from PyP100.PyP100 import P100
print_info(f"Versuche Tapo-Handshake mit {ip}...")
p100 = P100(ip, username, password)
# Handshake
p100.handshake()
print_success("Tapo-Handshake erfolgreich")
results["tests"]["tapo_handshake"] = True
# Login
p100.login()
print_success("Tapo-Login erfolgreich")
results["tests"]["tapo_login"] = True
# Device Info
device_info = p100.getDeviceInfo()
if device_info and 'error_code' in device_info and device_info['error_code'] == 0:
print_success("Tapo-Geräteinformationen erfolgreich abgerufen")
results["tests"]["tapo_device_info"] = True
results["device_info"] = device_info.get('result', {})
# Status anzeigen
device_on = device_info.get('result', {}).get('device_on', False)
print_info(f"Steckdosen-Status: {'EIN' if device_on else 'AUS'}")
else:
print_error("Konnte Geräteinformationen nicht abrufen")
results["tests"]["tapo_device_info"] = False
except ImportError:
print_error("PyP100 Bibliothek nicht installiert!")
print_info("Installiere mit: pip install PyP100")
results["tests"]["pyp100_available"] = False
except Exception as e:
print_error(f"Tapo-Verbindung fehlgeschlagen: {e}")
results["tests"]["tapo_connection"] = False
results["error"] = str(e)
return results
def diagnose_network():
"""Führt eine allgemeine Netzwerk-Diagnose durch"""
print_header("Netzwerk-Diagnose")
# Lokale IP-Adresse ermitteln
try:
hostname = socket.gethostname()
local_ip = socket.gethostbyname(hostname)
print_info(f"Lokaler Hostname: {hostname}")
print_info(f"Lokale IP-Adresse: {local_ip}")
except Exception as e:
print_error(f"Konnte lokale IP nicht ermitteln: {e}")
# Gateway ermitteln (nur Linux/Unix)
if os.name != 'nt':
try:
result = subprocess.run(['ip', 'route', 'show'], capture_output=True, text=True)
if result.returncode == 0:
lines = result.stdout.strip().split('\n')
for line in lines:
if 'default' in line:
gateway = line.split()[2]
print_info(f"Standard-Gateway: {gateway}")
break
except:
pass
# DNS-Test
print_info("Teste DNS-Auflösung...")
google_ip = test_dns_resolution("google.com")
if google_ip:
print_success(f"DNS funktioniert (google.com -> {google_ip})")
else:
print_error("DNS-Auflösung fehlgeschlagen")
def main():
"""Hauptfunktion"""
print_header("Tapo Steckdosen Diagnose-Tool")
print_info(f"Start: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
# Argumente prüfen
if len(sys.argv) < 2:
print_error("Verwendung: python diagnose_tapo.py <IP-Adresse> [username] [password]")
print_info("Beispiel: python diagnose_tapo.py 192.168.1.100")
print_info("Beispiel: python diagnose_tapo.py 192.168.1.100 admin admin")
sys.exit(1)
ip_address = sys.argv[1]
username = sys.argv[2] if len(sys.argv) > 2 else "admin"
password = sys.argv[3] if len(sys.argv) > 3 else "admin"
# Netzwerk-Diagnose
diagnose_network()
# Tapo-Diagnose
print_header(f"Teste Tapo-Steckdose: {ip_address}")
results = test_tapo_connection(ip_address, username, password)
# Zusammenfassung
print_header("Diagnose-Zusammenfassung")
successful_tests = sum(1 for test, result in results["tests"].items() if result is True)
total_tests = len(results["tests"])
print_info(f"Erfolgreiche Tests: {successful_tests}/{total_tests}")
# Empfehlungen
if not results["tests"].get("port_80", False):
print_warning("\nEmpfehlungen:")
print_warning("1. Stelle sicher, dass die Steckdose eingeschaltet ist")
print_warning("2. Prüfe, ob die IP-Adresse korrekt ist")
print_warning("3. Stelle sicher, dass sich die Steckdose im gleichen Netzwerk befindet")
print_warning("4. Prüfe Firewall-Einstellungen")
print_warning("5. Versuche die Steckdose zurückzusetzen (Reset-Knopf)")
if results["tests"].get("port_80", False) and not results["tests"].get("tapo_login", False):
print_warning("\nAuthentifizierungsproblem:")
print_warning("1. Prüfe Benutzername und Passwort")
print_warning("2. Standard-Credentials sind meist 'admin'/'admin'")
print_warning("3. Wurden die Credentials in der Tapo-App geändert?")
print_info(f"\nEnde: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
if __name__ == "__main__":
main()