🎉 Feature: Enhanced Admin Guest Requests API & Startup Initialization Documentation 📚

This commit is contained in:
Till Tomczak
2025-06-20 08:36:07 +02:00
parent 939f14199d
commit cbea4cb765
27 changed files with 1653 additions and 52 deletions

View File

@ -0,0 +1,281 @@
#!/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()