🎉 Improved Dockerfile and documentation files for better OTP Drucker Verf/Gbarkeitsverbesserung and Template Backend Zuordnung. 📚 Updated various log files for enhanced monitoring and debugging capabilities. 🐛 Refactored guest blueprint and related logs for improved performance. 💄 Fixed minor issues in templates and job queue system logs.

This commit is contained in:
Till Tomczak
2025-06-20 12:05:58 +02:00
parent 19a9c64e66
commit 025ec1f240
27 changed files with 2101 additions and 8 deletions

View File

@ -14,6 +14,7 @@ from sqlalchemy.orm import joinedload
from models import GuestRequest, Job, Printer, User, UserPermission, Notification, get_cached_session
from utils.logging_config import get_logger
from utils.hardware_integration import get_drucker_steuerung
guest_blueprint = Blueprint('guest', __name__)
logger = get_logger("guest")
@ -425,6 +426,131 @@ def api_start_job_with_code():
"error": f"Job kann im Status '{job.status}' nicht gestartet werden"
}), 400
# ===== NEUE DRUCKER-VERFÜGBARKEITSPRÜFUNG =====
drucker_steuerung = get_drucker_steuerung()
# 1. Prüfen ob ein spezifischer Drucker dem Job zugewiesen ist
if job.printer and job.printer.plug_ip:
# Spezifischen Drucker-Status prüfen
try:
reachable, power_status = drucker_steuerung.check_outlet_status(
job.printer.plug_ip, job.printer.id
)
if not reachable:
return jsonify({
"success": False,
"error": f"Drucker '{job.printer.name}' ist nicht erreichbar und kann nicht gestartet werden",
"error_details": {
"type": "printer_offline",
"printer_name": job.printer.name,
"printer_id": job.printer.id,
"reason": "Drucker ist im Netzwerk nicht erreichbar"
}
}), 400
# Drucker ist erreichbar - kann gestartet werden
logger.info(f"✅ Drucker-Verfügbarkeitsprüfung bestanden: {job.printer.name} (Status: {power_status})")
except Exception as e:
logger.error(f"❌ Fehler bei Drucker-Status-Prüfung für {job.printer.name}: {e}")
return jsonify({
"success": False,
"error": f"Drucker-Status für '{job.printer.name}' konnte nicht geprüft werden",
"error_details": {
"type": "printer_check_failed",
"printer_name": job.printer.name,
"printer_id": job.printer.id,
"reason": "Technischer Fehler bei der Status-Prüfung"
}
}), 500
else:
# 2. Kein spezifischer Drucker zugewiesen - prüfen ob IRGENDEIN Drucker verfügbar ist
logger.info("🔍 Kein spezifischer Drucker zugewiesen - prüfe alle verfügbaren Drucker")
# Alle aktiven Drucker mit Steckdosen laden
available_printers = db_session.query(Printer).filter(
Printer.active == True,
Printer.plug_ip.isnot(None)
).all()
if not available_printers:
return jsonify({
"success": False,
"error": "Keine konfigurierten Drucker verfügbar",
"error_details": {
"type": "no_printers_configured",
"reason": "Es sind keine aktiven Drucker mit Steckdosen-Steuerung konfiguriert"
}
}), 400
# Status aller verfügbaren Drucker prüfen
reachable_printers = []
offline_printers = []
for printer in available_printers:
try:
reachable, power_status = drucker_steuerung.check_outlet_status(
printer.plug_ip, printer.id
)
if reachable:
reachable_printers.append({
'id': printer.id,
'name': printer.name,
'status': power_status
})
else:
offline_printers.append({
'id': printer.id,
'name': printer.name
})
except Exception as e:
logger.warning(f"⚠️ Status-Prüfung für Drucker {printer.name} fehlgeschlagen: {e}")
offline_printers.append({
'id': printer.id,
'name': printer.name,
'error': str(e)
})
# Prüfen ob mindestens ein Drucker erreichbar ist
if not reachable_printers:
total_printers = len(available_printers)
offline_count = len(offline_printers)
offline_names = [p['name'] for p in offline_printers[:3]] # Max 3 Namen
offline_list = ', '.join(offline_names)
if offline_count > 3:
offline_list += f" und {offline_count - 3} weitere"
return jsonify({
"success": False,
"error": f"Alle {total_printers} Drucker sind offline und können nicht gestartet werden",
"error_details": {
"type": "all_printers_offline",
"total_printers": total_printers,
"offline_printers": offline_count,
"offline_list": offline_list,
"reason": "Keine Drucker sind derzeit erreichbar oder einsatzbereit"
}
}), 400
# Mindestens ein Drucker ist verfügbar
reachable_count = len(reachable_printers)
total_count = len(available_printers)
logger.info(f"✅ Drucker-Verfügbarkeitsprüfung bestanden: {reachable_count}/{total_count} Drucker erreichbar")
# Optional: Ersten verfügbaren Drucker automatisch zuweisen wenn keiner zugewiesen
if not job.printer_id and reachable_printers:
best_printer = reachable_printers[0] # Ersten verfügbaren nehmen
job.printer_id = best_printer['id']
logger.info(f"🎯 Drucker automatisch zugewiesen: {best_printer['name']} (ID: {best_printer['id']})")
# ===== JOB STARTEN (bestehender Code) =====
# Job starten
now = datetime.now()
job.status = "running"
@ -835,20 +961,87 @@ def api_approve_request(request_id):
if guest_request.status != "pending":
return jsonify({"error": "Anfrage wurde bereits bearbeitet"}), 400
# ===== ERWEITERTE DRUCKER-VALIDIERUNG UND -ZUWEISUNG =====
from utils.hardware_integration import get_drucker_steuerung
drucker_steuerung = get_drucker_steuerung()
# Drucker validieren oder automatisch zuweisen
if printer_id:
printer = db_session.query(Printer).filter_by(id=printer_id, active=True).first()
if not printer:
return jsonify({"error": "Ungültiger Drucker ausgewählt"}), 400
# Status des ausgewählten Druckers prüfen
if printer.plug_ip:
try:
reachable, power_status = drucker_steuerung.check_outlet_status(
printer.plug_ip, printer.id
)
if not reachable:
return jsonify({
"error": f"Drucker '{printer.name}' ist derzeit offline und kann nicht zugewiesen werden",
"warning": "Der Drucker ist im Netzwerk nicht erreichbar. Die Genehmigung kann trotzdem erfolgen, aber der Job kann erst gestartet werden, wenn der Drucker wieder online ist."
}), 400
logger.info(f"✅ Admin-Drucker-Zuweisung validiert: {printer.name} (Status: {power_status})")
except Exception as e:
logger.warning(f"⚠️ Status-Prüfung für zugewiesenen Drucker {printer.name} fehlgeschlagen: {e}")
# Warnung, aber Genehmigung trotzdem fortsetzen
guest_request.printer_id = printer_id
elif not guest_request.printer_id:
# Automatisch ersten verfügbaren Drucker zuweisen
available_printer = db_session.query(Printer).filter_by(active=True).first()
if available_printer:
guest_request.printer_id = available_printer.id
logger.info(f"Automatisch Drucker {available_printer.id} ({available_printer.name}) für Gastanfrage {request_id} zugewiesen")
# Automatisch besten verfügbaren Drucker zuweisen
available_printers = db_session.query(Printer).filter(
Printer.active == True,
Printer.plug_ip.isnot(None)
).all()
if not available_printers:
return jsonify({
"error": "Kein aktiver Drucker mit Steckdosen-Steuerung verfügbar",
"details": "Bitte aktivieren Sie mindestens einen Drucker mit konfigurierter Tapo-Steckdose."
}), 400
# Status aller verfügbaren Drucker prüfen
online_printers = []
offline_printers = []
for printer in available_printers:
try:
reachable, power_status = drucker_steuerung.check_outlet_status(
printer.plug_ip, printer.id
)
if reachable:
online_printers.append({
'printer': printer,
'status': power_status
})
else:
offline_printers.append(printer)
except Exception as e:
logger.warning(f"⚠️ Status-Prüfung für Drucker {printer.name} fehlgeschlagen: {e}")
offline_printers.append(printer)
# Bevorzuge online Drucker, aber fallback auf offline Drucker
if online_printers:
best_printer = online_printers[0]['printer']
guest_request.printer_id = best_printer.id
logger.info(f"✅ Automatisch ONLINE-Drucker zugewiesen: {best_printer.name} (Status: {online_printers[0]['status']})")
elif available_printers:
# Fallback: Ersten verfügbaren Drucker nehmen, auch wenn offline
fallback_printer = available_printers[0]
guest_request.printer_id = fallback_printer.id
logger.warning(f"⚠️ Automatisch OFFLINE-Drucker zugewiesen: {fallback_printer.name} (alle Drucker sind offline)")
else:
return jsonify({"error": "Kein aktiver Drucker verfügbar. Bitte aktivieren Sie mindestens einen Drucker."}), 400
return jsonify({
"error": "Kein Drucker verfügbar",
"details": "Es sind keine aktiven Drucker konfiguriert."
}), 400
# Drucker-Objekt für Job-Erstellung laden
printer = db_session.query(Printer).filter_by(id=guest_request.printer_id).first()
@ -1143,4 +1336,130 @@ def api_guest_status_by_otp():
@guest_blueprint.route('/status-check')
def guest_status_check_page():
"""Status-Check-Seite für Gäste."""
return render_template('guest_status_check.html')
return render_template('guest_status_check.html')
@guest_blueprint.route('/api/admin/printer-status', methods=['GET'])
@approver_required
def api_get_printer_status_for_admin():
"""
Drucker-Status für Admin-Oberfläche abrufen.
Zeigt welche Drucker verfügbar sind für die Zuweisung bei Gastanfragen.
"""
try:
from utils.hardware_integration import get_drucker_steuerung
with get_cached_session() as db_session:
# Alle aktiven Drucker laden
printers = db_session.query(Printer).filter(Printer.active == True).all()
if not printers:
return jsonify({
"success": True,
"printers": [],
"summary": {
"total": 0,
"online": 0,
"offline": 0,
"unconfigured": 0
},
"message": "Keine aktiven Drucker konfiguriert"
})
drucker_steuerung = get_drucker_steuerung()
printer_status_list = []
summary = {
"total": len(printers),
"online": 0,
"offline": 0,
"unconfigured": 0
}
for printer in printers:
printer_info = {
"id": printer.id,
"name": printer.name,
"model": printer.model or "Unbekannt",
"location": printer.location or "TBA Marienfelde",
"ip_address": printer.ip_address,
"plug_ip": printer.plug_ip,
"active": printer.active,
"status": "unknown",
"reachable": False,
"power_state": "unknown",
"can_be_assigned": False,
"status_message": "",
"last_checked": datetime.now().isoformat()
}
if printer.plug_ip:
try:
# Echtzeit-Status prüfen
reachable, power_status = drucker_steuerung.check_outlet_status(
printer.plug_ip, printer.id
)
printer_info["reachable"] = reachable
printer_info["power_state"] = power_status
if reachable:
printer_info["status"] = "online"
printer_info["can_be_assigned"] = True
printer_info["status_message"] = f"Online ({power_status.upper()})"
summary["online"] += 1
else:
printer_info["status"] = "offline"
printer_info["can_be_assigned"] = False
printer_info["status_message"] = "Offline - Nicht erreichbar"
summary["offline"] += 1
except Exception as e:
printer_info["status"] = "error"
printer_info["can_be_assigned"] = False
printer_info["status_message"] = f"Fehler: {str(e)}"
printer_info["error"] = str(e)
summary["offline"] += 1
logger.warning(f"⚠️ Admin-Status-Prüfung für {printer.name} fehlgeschlagen: {e}")
else:
printer_info["status"] = "unconfigured"
printer_info["can_be_assigned"] = False
printer_info["status_message"] = "Keine Steckdose konfiguriert"
summary["unconfigured"] += 1
printer_status_list.append(printer_info)
# Nach Status sortieren: Online zuerst, dann offline, dann unkonfiguriert
printer_status_list.sort(key=lambda x: (
0 if x["status"] == "online" else
1 if x["status"] == "offline" else
2 # unconfigured oder error
))
# Empfehlung für Admin generieren
recommendations = []
if summary["online"] == 0:
if summary["unconfigured"] > 0:
recommendations.append("Konfigurieren Sie Tapo-Steckdosen für die Drucker ohne Steuerung")
if summary["offline"] > 0:
recommendations.append("Prüfen Sie die Netzwerkverbindungen der offline Drucker")
recommendations.append("Aktuell können keine Gastanfragen automatisch gestartet werden")
elif summary["online"] < summary["total"]:
recommendations.append(f"Nur {summary['online']} von {summary['total']} Druckern sind verfügbar")
return jsonify({
"success": True,
"printers": printer_status_list,
"summary": summary,
"recommendations": recommendations,
"timestamp": datetime.now().isoformat(),
"message": f"Status von {len(printer_status_list)} Druckern abgerufen"
})
except Exception as e:
logger.error(f"Fehler beim Abrufen des Admin-Drucker-Status: {str(e)}")
return jsonify({
"success": False,
"error": "Fehler beim Abrufen des Drucker-Status",
"details": str(e)
}), 500