"Refactor app logic using Conventional Commits format (feat)"
This commit is contained in:
parent
fe94a3b58c
commit
698410b7a5
@ -38,7 +38,7 @@ from models import init_database, create_initial_admin, User, Printer, Job, Stat
|
||||
from utils.logging_config import setup_logging, get_logger, measure_execution_time, log_startup_info, debug_request, debug_response
|
||||
from utils.job_scheduler import JobScheduler, get_job_scheduler
|
||||
from utils.queue_manager import start_queue_manager, stop_queue_manager, get_queue_manager
|
||||
from config.settings import SECRET_KEY, UPLOAD_FOLDER, ALLOWED_EXTENSIONS, ENVIRONMENT, SESSION_LIFETIME, SCHEDULER_ENABLED, SCHEDULER_INTERVAL
|
||||
from config.settings import SECRET_KEY, UPLOAD_FOLDER, ALLOWED_EXTENSIONS, ENVIRONMENT, SESSION_LIFETIME, SCHEDULER_ENABLED, SCHEDULER_INTERVAL, TAPO_USERNAME, TAPO_PASSWORD
|
||||
from utils.file_manager import file_manager, save_job_file, save_guest_file, save_avatar_file, delete_file as delete_file_safe
|
||||
|
||||
# Blueprints importieren
|
||||
@ -1300,47 +1300,24 @@ def check_printer_status(ip_address: str, timeout: int = 7) -> Tuple[str, bool]:
|
||||
try:
|
||||
ipaddress.ip_address(ip_address.strip())
|
||||
except ValueError:
|
||||
printers_logger.warning(f"Ungültige IP-Adresse: {ip_address}")
|
||||
printers_logger.debug(f"Ungültige IP-Adresse: {ip_address}")
|
||||
return "offline", False
|
||||
|
||||
# Zuerst prüfen, ob die Steckdose erreichbar ist (Ping)
|
||||
if os.name == 'nt': # Windows
|
||||
cmd = ['ping', '-n', '1', '-w', str(timeout * 1000), ip_address.strip()]
|
||||
else: # Unix/Linux/macOS
|
||||
cmd = ['ping', '-c', '1', '-W', str(timeout), ip_address.strip()]
|
||||
|
||||
printers_logger.debug(f"Ping-Befehl für {ip_address}: {' '.join(cmd)}")
|
||||
|
||||
# Ping ausführen mit Timeout
|
||||
result = subprocess.run(
|
||||
cmd,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
encoding='utf-8',
|
||||
errors='ignore', # Ignoriere Unicode-Fehler
|
||||
timeout=timeout + 2 # Zusätzlicher Timeout für subprocess
|
||||
)
|
||||
|
||||
# Wenn Steckdose nicht erreichbar ist, ist der Drucker offline
|
||||
if result.returncode != 0:
|
||||
printers_logger.debug(f"Ping fehlgeschlagen für {ip_address} (Return Code: {result.returncode})")
|
||||
return "offline", False
|
||||
|
||||
# Drucker-Daten aus Datenbank holen für Anmeldedaten
|
||||
db_session = get_db_session()
|
||||
printer = db_session.query(Printer).filter(Printer.plug_ip == ip_address).first()
|
||||
|
||||
if not printer:
|
||||
printers_logger.warning(f"Kein Drucker mit Steckdosen-IP {ip_address} gefunden")
|
||||
db_session.close()
|
||||
return "offline", False
|
||||
|
||||
# TP-Link Tapo P110 Status mit PyP100 prüfen
|
||||
# Importiere PyP100 für Tapo-Unterstützung
|
||||
try:
|
||||
from PyP100 import PyP110
|
||||
except ImportError:
|
||||
printers_logger.error("⚠️ PyP100-Modul nicht verfügbar - kann Tapo-Steckdosen nicht abfragen")
|
||||
return "offline", False
|
||||
|
||||
# Tapo-Steckdose verbinden
|
||||
p110 = PyP110.P110(ip_address, printer.plug_username, printer.plug_password)
|
||||
# Verwende IMMER die globalen hardkodierten Tapo-Anmeldedaten
|
||||
username = TAPO_USERNAME
|
||||
password = TAPO_PASSWORD
|
||||
|
||||
printers_logger.debug(f"🔌 Teste Tapo-Steckdose {ip_address} mit hardkodierten Anmeldedaten")
|
||||
|
||||
# TP-Link Tapo P110 Verbindung herstellen
|
||||
p110 = PyP110.P110(ip_address.strip(), username, password)
|
||||
p110.handshake() # Authentifizierung
|
||||
p110.login() # Login
|
||||
|
||||
@ -1348,9 +1325,8 @@ def check_printer_status(ip_address: str, timeout: int = 7) -> Tuple[str, bool]:
|
||||
device_info = p110.getDeviceInfo()
|
||||
device_on = device_info.get('device_on', False)
|
||||
|
||||
db_session.close()
|
||||
|
||||
if device_on:
|
||||
printers_logger.debug(f"✅ Drucker {ip_address}: ONLINE (Steckdose eingeschaltet)")
|
||||
printers_logger.debug(f"Tapo-Steckdose {ip_address} ist eingeschaltet - Drucker online")
|
||||
return "online", True
|
||||
else:
|
||||
@ -6293,170 +6269,6 @@ def keep_alive():
|
||||
"error": "Fehler beim Verlängern der Session"
|
||||
}), 500
|
||||
|
||||
# ===== STARTUP UND MAIN =====
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
import signal
|
||||
import os
|
||||
|
||||
# Debug-Modus prüfen
|
||||
debug_mode = len(sys.argv) > 1 and sys.argv[1] == "--debug"
|
||||
|
||||
# Windows-spezifische Umgebungsvariablen setzen für bessere Flask-Kompatibilität
|
||||
if os.name == 'nt' and debug_mode:
|
||||
# Entferne problematische Werkzeug-Variablen
|
||||
os.environ.pop('WERKZEUG_SERVER_FD', None)
|
||||
os.environ.pop('WERKZEUG_RUN_MAIN', None)
|
||||
|
||||
# Setze saubere Umgebung
|
||||
os.environ['FLASK_ENV'] = 'development'
|
||||
os.environ['PYTHONIOENCODING'] = 'utf-8'
|
||||
os.environ['PYTHONUTF8'] = '1'
|
||||
|
||||
# Windows-spezifisches Signal-Handling für ordnungsgemäßes Shutdown
|
||||
def signal_handler(sig, frame):
|
||||
"""Signal-Handler für ordnungsgemäßes Shutdown."""
|
||||
app_logger.warning(f"🛑 Signal {sig} empfangen - fahre System herunter...")
|
||||
try:
|
||||
# Queue Manager stoppen
|
||||
app_logger.info("🔄 Beende Queue Manager...")
|
||||
stop_queue_manager()
|
||||
|
||||
# Scheduler stoppen falls aktiviert
|
||||
if SCHEDULER_ENABLED and scheduler:
|
||||
try:
|
||||
scheduler.stop()
|
||||
app_logger.info("Job-Scheduler gestoppt")
|
||||
except Exception as e:
|
||||
app_logger.error(f"Fehler beim Stoppen des Schedulers: {str(e)}")
|
||||
|
||||
app_logger.info("✅ Shutdown abgeschlossen")
|
||||
sys.exit(0)
|
||||
except Exception as e:
|
||||
app_logger.error(f"❌ Fehler beim Shutdown: {str(e)}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
# Signal-Handler registrieren (Windows-kompatibel)
|
||||
if os.name == 'nt': # Windows
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
signal.signal(signal.SIGTERM, signal_handler)
|
||||
# Zusätzlich für Flask-Development-Server
|
||||
signal.signal(signal.SIGBREAK, signal_handler)
|
||||
else: # Unix/Linux
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
signal.signal(signal.SIGTERM, signal_handler)
|
||||
signal.signal(signal.SIGHUP, signal_handler)
|
||||
|
||||
try:
|
||||
# Datenbank initialisieren
|
||||
init_database()
|
||||
create_initial_admin()
|
||||
|
||||
# Template-Hilfsfunktionen registrieren
|
||||
register_template_helpers(app)
|
||||
|
||||
# Drucker-Monitor Steckdosen-Initialisierung beim Start
|
||||
try:
|
||||
app_logger.info("🖨️ Starte automatische Steckdosen-Initialisierung...")
|
||||
initialization_results = printer_monitor.initialize_all_outlets_on_startup()
|
||||
|
||||
if initialization_results:
|
||||
success_count = sum(1 for success in initialization_results.values() if success)
|
||||
total_count = len(initialization_results)
|
||||
app_logger.info(f"✅ Steckdosen-Initialisierung: {success_count}/{total_count} Drucker erfolgreich")
|
||||
|
||||
if success_count < total_count:
|
||||
app_logger.warning(f"⚠️ {total_count - success_count} Drucker konnten nicht initialisiert werden")
|
||||
else:
|
||||
app_logger.info("ℹ️ Keine Drucker zur Initialisierung gefunden")
|
||||
|
||||
except Exception as e:
|
||||
app_logger.error(f"❌ Fehler bei automatischer Steckdosen-Initialisierung: {str(e)}")
|
||||
|
||||
# Queue-Manager für automatische Drucker-Überwachung starten
|
||||
# Nur im Produktionsmodus starten (nicht im Debug-Modus)
|
||||
if not debug_mode:
|
||||
try:
|
||||
queue_manager = start_queue_manager()
|
||||
app_logger.info("✅ Printer Queue Manager erfolgreich gestartet")
|
||||
|
||||
# Verbesserte Shutdown-Handler registrieren
|
||||
def cleanup_queue_manager():
|
||||
try:
|
||||
app_logger.info("🔄 Beende Queue Manager...")
|
||||
stop_queue_manager()
|
||||
except Exception as e:
|
||||
app_logger.error(f"❌ Fehler beim Queue Manager Cleanup: {str(e)}")
|
||||
|
||||
atexit.register(cleanup_queue_manager)
|
||||
|
||||
except Exception as e:
|
||||
app_logger.error(f"❌ Fehler beim Starten des Queue-Managers: {str(e)}")
|
||||
else:
|
||||
app_logger.info("🔄 Debug-Modus: Queue Manager deaktiviert für Entwicklung")
|
||||
|
||||
# Scheduler starten (falls aktiviert)
|
||||
if SCHEDULER_ENABLED:
|
||||
try:
|
||||
scheduler.start()
|
||||
app_logger.info("Job-Scheduler gestartet")
|
||||
except Exception as e:
|
||||
app_logger.error(f"Fehler beim Starten des Schedulers: {str(e)}")
|
||||
|
||||
if debug_mode:
|
||||
# Debug-Modus: HTTP auf Port 5000
|
||||
app_logger.info("Starte Debug-Server auf 0.0.0.0:5000 (HTTP)")
|
||||
|
||||
# Windows-spezifische Flask-Konfiguration
|
||||
run_kwargs = {
|
||||
"host": "0.0.0.0",
|
||||
"port": 5000,
|
||||
"debug": True,
|
||||
"threaded": True
|
||||
}
|
||||
|
||||
if os.name == 'nt':
|
||||
# Windows: Deaktiviere Auto-Reload um WERKZEUG_SERVER_FD Fehler zu vermeiden
|
||||
run_kwargs["use_reloader"] = False
|
||||
run_kwargs["passthrough_errors"] = False
|
||||
app_logger.info("Windows-Debug-Modus: Auto-Reload deaktiviert")
|
||||
|
||||
app.run(**run_kwargs)
|
||||
else:
|
||||
# Produktions-Modus: HTTPS auf Port 443
|
||||
ssl_context = get_ssl_context()
|
||||
|
||||
if ssl_context:
|
||||
app_logger.info("Starte HTTPS-Server auf 0.0.0.0:443")
|
||||
app.run(
|
||||
host="0.0.0.0",
|
||||
port=443,
|
||||
debug=False,
|
||||
ssl_context=ssl_context,
|
||||
threaded=True
|
||||
)
|
||||
else:
|
||||
app_logger.info("Starte HTTP-Server auf 0.0.0.0:8080")
|
||||
app.run(
|
||||
host="0.0.0.0",
|
||||
port=8080,
|
||||
debug=False,
|
||||
threaded=True
|
||||
)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
app_logger.info("🔄 Tastatur-Unterbrechung empfangen - beende Anwendung...")
|
||||
signal_handler(signal.SIGINT, None)
|
||||
except Exception as e:
|
||||
app_logger.error(f"Fehler beim Starten der Anwendung: {str(e)}")
|
||||
# Cleanup bei Fehler
|
||||
try:
|
||||
stop_queue_manager()
|
||||
except:
|
||||
pass
|
||||
sys.exit(1)
|
||||
|
||||
# ===== FILE-UPLOAD-ROUTEN =====
|
||||
|
||||
@app.route('/api/upload/job', methods=['POST'])
|
||||
@ -7007,3 +6819,168 @@ def admin_create_printer_api():
|
||||
except Exception as e:
|
||||
printers_logger.error(f"Fehler beim Erstellen eines Druckers durch Admin: {str(e)}")
|
||||
return jsonify({"error": "Interner Serverfehler"}), 500
|
||||
|
||||
|
||||
# ===== STARTUP UND MAIN =====
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
import signal
|
||||
import os
|
||||
|
||||
# Debug-Modus prüfen
|
||||
debug_mode = len(sys.argv) > 1 and sys.argv[1] == "--debug"
|
||||
|
||||
# Windows-spezifische Umgebungsvariablen setzen für bessere Flask-Kompatibilität
|
||||
if os.name == 'nt' and debug_mode:
|
||||
# Entferne problematische Werkzeug-Variablen
|
||||
os.environ.pop('WERKZEUG_SERVER_FD', None)
|
||||
os.environ.pop('WERKZEUG_RUN_MAIN', None)
|
||||
|
||||
# Setze saubere Umgebung
|
||||
os.environ['FLASK_ENV'] = 'development'
|
||||
os.environ['PYTHONIOENCODING'] = 'utf-8'
|
||||
os.environ['PYTHONUTF8'] = '1'
|
||||
|
||||
# Windows-spezifisches Signal-Handling für ordnungsgemäßes Shutdown
|
||||
def signal_handler(sig, frame):
|
||||
"""Signal-Handler für ordnungsgemäßes Shutdown."""
|
||||
app_logger.warning(f"🛑 Signal {sig} empfangen - fahre System herunter...")
|
||||
try:
|
||||
# Queue Manager stoppen
|
||||
app_logger.info("🔄 Beende Queue Manager...")
|
||||
stop_queue_manager()
|
||||
|
||||
# Scheduler stoppen falls aktiviert
|
||||
if SCHEDULER_ENABLED and scheduler:
|
||||
try:
|
||||
scheduler.stop()
|
||||
app_logger.info("Job-Scheduler gestoppt")
|
||||
except Exception as e:
|
||||
app_logger.error(f"Fehler beim Stoppen des Schedulers: {str(e)}")
|
||||
|
||||
app_logger.info("✅ Shutdown abgeschlossen")
|
||||
sys.exit(0)
|
||||
except Exception as e:
|
||||
app_logger.error(f"❌ Fehler beim Shutdown: {str(e)}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
# Signal-Handler registrieren (Windows-kompatibel)
|
||||
if os.name == 'nt': # Windows
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
signal.signal(signal.SIGTERM, signal_handler)
|
||||
# Zusätzlich für Flask-Development-Server
|
||||
signal.signal(signal.SIGBREAK, signal_handler)
|
||||
else: # Unix/Linux
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
signal.signal(signal.SIGTERM, signal_handler)
|
||||
signal.signal(signal.SIGHUP, signal_handler)
|
||||
|
||||
try:
|
||||
# Datenbank initialisieren
|
||||
init_database()
|
||||
create_initial_admin()
|
||||
|
||||
# Template-Hilfsfunktionen registrieren
|
||||
register_template_helpers(app)
|
||||
|
||||
# Drucker-Monitor Steckdosen-Initialisierung beim Start
|
||||
try:
|
||||
app_logger.info("🖨️ Starte automatische Steckdosen-Initialisierung...")
|
||||
initialization_results = printer_monitor.initialize_all_outlets_on_startup()
|
||||
|
||||
if initialization_results:
|
||||
success_count = sum(1 for success in initialization_results.values() if success)
|
||||
total_count = len(initialization_results)
|
||||
app_logger.info(f"✅ Steckdosen-Initialisierung: {success_count}/{total_count} Drucker erfolgreich")
|
||||
|
||||
if success_count < total_count:
|
||||
app_logger.warning(f"⚠️ {total_count - success_count} Drucker konnten nicht initialisiert werden")
|
||||
else:
|
||||
app_logger.info("ℹ️ Keine Drucker zur Initialisierung gefunden")
|
||||
|
||||
except Exception as e:
|
||||
app_logger.error(f"❌ Fehler bei automatischer Steckdosen-Initialisierung: {str(e)}")
|
||||
|
||||
# Queue-Manager für automatische Drucker-Überwachung starten
|
||||
# Nur im Produktionsmodus starten (nicht im Debug-Modus)
|
||||
if not debug_mode:
|
||||
try:
|
||||
queue_manager = start_queue_manager()
|
||||
app_logger.info("✅ Printer Queue Manager erfolgreich gestartet")
|
||||
|
||||
# Verbesserte Shutdown-Handler registrieren
|
||||
def cleanup_queue_manager():
|
||||
try:
|
||||
app_logger.info("🔄 Beende Queue Manager...")
|
||||
stop_queue_manager()
|
||||
except Exception as e:
|
||||
app_logger.error(f"❌ Fehler beim Queue Manager Cleanup: {str(e)}")
|
||||
|
||||
atexit.register(cleanup_queue_manager)
|
||||
|
||||
except Exception as e:
|
||||
app_logger.error(f"❌ Fehler beim Starten des Queue-Managers: {str(e)}")
|
||||
else:
|
||||
app_logger.info("🔄 Debug-Modus: Queue Manager deaktiviert für Entwicklung")
|
||||
|
||||
# Scheduler starten (falls aktiviert)
|
||||
if SCHEDULER_ENABLED:
|
||||
try:
|
||||
scheduler.start()
|
||||
app_logger.info("Job-Scheduler gestartet")
|
||||
except Exception as e:
|
||||
app_logger.error(f"Fehler beim Starten des Schedulers: {str(e)}")
|
||||
|
||||
if debug_mode:
|
||||
# Debug-Modus: HTTP auf Port 5000
|
||||
app_logger.info("Starte Debug-Server auf 0.0.0.0:5000 (HTTP)")
|
||||
|
||||
# Windows-spezifische Flask-Konfiguration
|
||||
run_kwargs = {
|
||||
"host": "0.0.0.0",
|
||||
"port": 5000,
|
||||
"debug": True,
|
||||
"threaded": True
|
||||
}
|
||||
|
||||
if os.name == 'nt':
|
||||
# Windows: Deaktiviere Auto-Reload um WERKZEUG_SERVER_FD Fehler zu vermeiden
|
||||
run_kwargs["use_reloader"] = False
|
||||
run_kwargs["passthrough_errors"] = False
|
||||
app_logger.info("Windows-Debug-Modus: Auto-Reload deaktiviert")
|
||||
|
||||
app.run(**run_kwargs)
|
||||
else:
|
||||
# Produktions-Modus: HTTPS auf Port 443
|
||||
ssl_context = get_ssl_context()
|
||||
|
||||
if ssl_context:
|
||||
app_logger.info("Starte HTTPS-Server auf 0.0.0.0:443")
|
||||
app.run(
|
||||
host="0.0.0.0",
|
||||
port=443,
|
||||
debug=False,
|
||||
ssl_context=ssl_context,
|
||||
threaded=True
|
||||
)
|
||||
else:
|
||||
app_logger.info("Starte HTTP-Server auf 0.0.0.0:8080")
|
||||
app.run(
|
||||
host="0.0.0.0",
|
||||
port=8080,
|
||||
debug=False,
|
||||
threaded=True
|
||||
)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
app_logger.info("🔄 Tastatur-Unterbrechung empfangen - beende Anwendung...")
|
||||
signal_handler(signal.SIGINT, None)
|
||||
except Exception as e:
|
||||
app_logger.error(f"Fehler beim Starten der Anwendung: {str(e)}")
|
||||
# Cleanup bei Fehler
|
||||
try:
|
||||
stop_queue_manager()
|
||||
except:
|
||||
pass
|
||||
sys.exit(1)
|
Loading…
x
Reference in New Issue
Block a user