Es scheint, dass Sie eine Reihe von Dateien und Verzeichnissen in einem Backend-Projekt bearbeitet haben. Hier ist eine Zusammenfassung der Änderungen:
This commit is contained in:
232
backend/app.py
232
backend/app.py
@@ -13,7 +13,7 @@ import signal
|
||||
import pickle
|
||||
import hashlib
|
||||
from datetime import datetime, timedelta
|
||||
from flask import Flask, render_template, request, jsonify, redirect, url_for, session, abort, send_from_directory
|
||||
from flask import Flask, render_template, request, jsonify, redirect, url_for, session, abort, send_from_directory, flash
|
||||
from flask_login import LoginManager, current_user, logout_user, login_required
|
||||
from flask_wtf import CSRFProtect
|
||||
from flask_wtf.csrf import CSRFError
|
||||
@@ -932,15 +932,15 @@ def admin():
|
||||
def printers_page():
|
||||
"""Zeigt die Übersichtsseite für Drucker an mit Server-Side Rendering."""
|
||||
try:
|
||||
from utils.hardware_integration import printer_monitor
|
||||
from utils.hardware_integration import get_tapo_controller
|
||||
from models import get_db_session, Printer
|
||||
|
||||
# Drucker-Daten server-side laden
|
||||
db_session = get_db_session()
|
||||
all_printers = db_session.query(Printer).filter(Printer.active == True).all()
|
||||
|
||||
# Live-Status für alle Drucker abrufen
|
||||
status_data = printer_monitor.get_live_printer_status()
|
||||
# Live-Status direkt über TapoController abrufen
|
||||
tapo_controller = get_tapo_controller()
|
||||
|
||||
# Drucker-Daten mit Status anreichern
|
||||
printers_with_status = []
|
||||
@@ -956,30 +956,100 @@ def printers_page():
|
||||
'status': 'offline'
|
||||
}
|
||||
|
||||
# Status aus LiveData hinzufügen
|
||||
if printer.id in status_data:
|
||||
live_data = status_data[printer.id]
|
||||
printer_info.update({
|
||||
'plug_status': live_data.get('plug_status', 'unknown'),
|
||||
'plug_reachable': live_data.get('plug_reachable', False),
|
||||
'can_control': live_data.get('can_control', False),
|
||||
'last_checked': live_data.get('last_checked'),
|
||||
'error': live_data.get('error')
|
||||
})
|
||||
|
||||
# Status-Display für UI
|
||||
if live_data.get('plug_status') in printer_monitor.STATUS_DISPLAY:
|
||||
printer_info['status_display'] = printer_monitor.STATUS_DISPLAY[live_data.get('plug_status')]
|
||||
# Status direkt über TapoController prüfen und in DB persistieren
|
||||
if printer.plug_ip:
|
||||
try:
|
||||
reachable, plug_status = tapo_controller.check_outlet_status(
|
||||
printer.plug_ip, printer_id=printer.id
|
||||
)
|
||||
|
||||
# Drucker-Status basierend auf Steckdosen-Status aktualisieren
|
||||
if not reachable:
|
||||
# Nicht erreichbar = offline
|
||||
printer.status = 'offline'
|
||||
status_text = 'Offline'
|
||||
status_color = 'red'
|
||||
elif plug_status == 'on':
|
||||
# Steckdose an = belegt
|
||||
printer.status = 'busy'
|
||||
status_text = 'Belegt'
|
||||
status_color = 'green'
|
||||
elif plug_status == 'off':
|
||||
# Steckdose aus = verfügbar
|
||||
printer.status = 'idle'
|
||||
status_text = 'Verfügbar'
|
||||
status_color = 'gray'
|
||||
else:
|
||||
# Unbekannter Status = offline
|
||||
printer.status = 'offline'
|
||||
status_text = 'Unbekannt'
|
||||
status_color = 'red'
|
||||
|
||||
# Zeitstempel aktualisieren und in DB speichern
|
||||
printer.last_checked = datetime.now()
|
||||
printer.updated_at = datetime.now()
|
||||
|
||||
# Status-Änderung protokollieren (nur bei tatsächlicher Änderung)
|
||||
from models import PlugStatusLog
|
||||
current_db_status = printer.status
|
||||
log_status = 'connected' if reachable else 'disconnected'
|
||||
if plug_status == 'on':
|
||||
log_status = 'on'
|
||||
elif plug_status == 'off':
|
||||
log_status = 'off'
|
||||
|
||||
# Nur loggen wenn sich der Status geändert hat (vereinfachte Prüfung)
|
||||
try:
|
||||
PlugStatusLog.log_status_change(
|
||||
printer_id=printer.id,
|
||||
status=log_status,
|
||||
source='system',
|
||||
ip_address=printer.plug_ip,
|
||||
notes="Automatische Status-Prüfung beim Laden der Drucker-Seite"
|
||||
)
|
||||
app_logger.debug(f"📊 Auto-Status protokolliert: Drucker {printer.id} -> {log_status}")
|
||||
except Exception as log_error:
|
||||
app_logger.error(f"❌ Fehler beim Auto-Protokollieren: {str(log_error)}")
|
||||
|
||||
printer_info.update({
|
||||
'plug_status': plug_status,
|
||||
'plug_reachable': reachable,
|
||||
'can_control': reachable,
|
||||
'status': printer.status,
|
||||
'last_checked': datetime.now().isoformat()
|
||||
})
|
||||
|
||||
# Status-Display für UI
|
||||
printer_info['status_display'] = {
|
||||
'text': status_text,
|
||||
'color': status_color
|
||||
}
|
||||
except Exception as e:
|
||||
printer_info.update({
|
||||
'plug_status': 'unknown',
|
||||
'plug_reachable': False,
|
||||
'can_control': False,
|
||||
'error': str(e),
|
||||
'status_display': {'text': 'Fehler', 'color': 'red'}
|
||||
})
|
||||
else:
|
||||
printer_info.update({
|
||||
'plug_status': 'unknown',
|
||||
'plug_status': 'no_plug',
|
||||
'plug_reachable': False,
|
||||
'can_control': False,
|
||||
'status_display': {'text': 'Unbekannt', 'color': 'gray', 'icon': 'question'}
|
||||
'status_display': {'text': 'Keine Steckdose', 'color': 'gray'}
|
||||
})
|
||||
|
||||
printers_with_status.append(printer_info)
|
||||
|
||||
# Alle Status-Updates in die Datenbank committen
|
||||
try:
|
||||
db_session.commit()
|
||||
app_logger.debug(f"✅ Status-Updates für {len(printers_with_status)} Drucker erfolgreich gespeichert")
|
||||
except Exception as commit_error:
|
||||
app_logger.error(f"❌ Fehler beim Speichern der Status-Updates: {str(commit_error)}")
|
||||
db_session.rollback()
|
||||
|
||||
# Einzigartige Werte für Filter
|
||||
models = list(set([p['model'] for p in printers_with_status if p['model'] != 'Unbekannt']))
|
||||
locations = list(set([p['location'] for p in printers_with_status if p['location'] != 'Unbekannt']))
|
||||
@@ -1006,7 +1076,8 @@ def printers_page():
|
||||
def printer_control():
|
||||
"""Server-Side Drucker-Steuerung ohne JavaScript."""
|
||||
try:
|
||||
from utils.hardware_integration import printer_monitor
|
||||
from utils.hardware_integration import get_tapo_controller
|
||||
from models import get_db_session, Printer
|
||||
|
||||
printer_id = request.form.get('printer_id')
|
||||
action = request.form.get('action') # 'on' oder 'off'
|
||||
@@ -1019,16 +1090,123 @@ def printer_control():
|
||||
flash('Ungültige Aktion. Nur "on" oder "off" erlaubt.', 'error')
|
||||
return redirect(url_for('printers_page'))
|
||||
|
||||
# Drucker steuern
|
||||
success, message = printer_monitor.control_plug(int(printer_id), action)
|
||||
# Drucker aus Datenbank laden
|
||||
db_session = get_db_session()
|
||||
printer = db_session.query(Printer).filter(Printer.id == int(printer_id)).first()
|
||||
|
||||
if not printer:
|
||||
flash('Drucker nicht gefunden', 'error')
|
||||
db_session.close()
|
||||
return redirect(url_for('printers_page'))
|
||||
|
||||
if not printer.plug_ip:
|
||||
flash('Keine Steckdose für diesen Drucker konfiguriert', 'error')
|
||||
db_session.close()
|
||||
return redirect(url_for('printers_page'))
|
||||
|
||||
# Erst Erreichbarkeit der Steckdose prüfen
|
||||
tapo_controller = get_tapo_controller()
|
||||
|
||||
# Prüfe ob Steckdose erreichbar ist
|
||||
if not tapo_controller.is_plug_reachable(printer.plug_ip):
|
||||
# Steckdose nicht erreichbar = Drucker offline
|
||||
printer.status = 'offline'
|
||||
printer.last_checked = datetime.now()
|
||||
printer.updated_at = datetime.now()
|
||||
|
||||
# Status-Änderung protokollieren
|
||||
from models import PlugStatusLog
|
||||
try:
|
||||
PlugStatusLog.log_status_change(
|
||||
printer_id=int(printer_id),
|
||||
status='disconnected',
|
||||
source='system',
|
||||
user_id=current_user.id,
|
||||
ip_address=printer.plug_ip,
|
||||
error_message=f"Steckdose {printer.plug_ip} nicht erreichbar",
|
||||
notes=f"Erreichbarkeitsprüfung durch {current_user.name} fehlgeschlagen"
|
||||
)
|
||||
app_logger.debug(f"📊 Offline-Status protokolliert: Drucker {printer_id} -> disconnected")
|
||||
except Exception as log_error:
|
||||
app_logger.error(f"❌ Fehler beim Protokollieren des Offline-Status: {str(log_error)}")
|
||||
|
||||
db_session.commit()
|
||||
|
||||
flash(f'Steckdose nicht erreichbar - Drucker als offline markiert', 'error')
|
||||
app_logger.warning(f"⚠️ Steckdose {printer.plug_ip} für Drucker {printer_id} nicht erreichbar")
|
||||
db_session.close()
|
||||
return redirect(url_for('printers_page'))
|
||||
|
||||
# Steckdose erreichbar - Steuerung ausführen
|
||||
state = action == 'on'
|
||||
success = tapo_controller.toggle_plug(printer.plug_ip, state)
|
||||
|
||||
if success:
|
||||
# Drucker-Status basierend auf Steckdosen-Aktion aktualisieren
|
||||
if action == 'on':
|
||||
# Steckdose an = Drucker belegt (busy)
|
||||
printer.status = 'busy'
|
||||
status_text = "belegt"
|
||||
plug_status = 'on'
|
||||
else:
|
||||
# Steckdose aus = Drucker verfügbar (idle)
|
||||
printer.status = 'idle'
|
||||
status_text = "verfügbar"
|
||||
plug_status = 'off'
|
||||
|
||||
# Zeitstempel der letzten Überprüfung aktualisieren
|
||||
printer.last_checked = datetime.now()
|
||||
printer.updated_at = datetime.now()
|
||||
|
||||
# Status-Änderung in PlugStatusLog protokollieren mit Energiedaten
|
||||
from models import PlugStatusLog
|
||||
try:
|
||||
# Energiedaten abrufen falls verfügbar
|
||||
energy_data = {}
|
||||
try:
|
||||
reachable, current_status = tapo_controller.check_outlet_status(printer.plug_ip, printer_id=int(printer_id))
|
||||
if reachable:
|
||||
# Versuche Energiedaten zu holen (falls P110)
|
||||
extra_info = tapo_controller._get_extra_device_info(printer.plug_ip)
|
||||
if extra_info:
|
||||
energy_data = {
|
||||
'power_consumption': extra_info.get('power_consumption'),
|
||||
'voltage': extra_info.get('voltage'),
|
||||
'current': extra_info.get('current'),
|
||||
'firmware_version': extra_info.get('firmware_version')
|
||||
}
|
||||
except Exception as energy_error:
|
||||
app_logger.debug(f"⚡ Energiedaten für {printer.plug_ip} nicht verfügbar: {str(energy_error)}")
|
||||
|
||||
action_text = "eingeschaltet" if action == 'on' else "ausgeschaltet"
|
||||
PlugStatusLog.log_status_change(
|
||||
printer_id=int(printer_id),
|
||||
status=plug_status,
|
||||
source='manual',
|
||||
user_id=current_user.id,
|
||||
ip_address=printer.plug_ip,
|
||||
power_consumption=energy_data.get('power_consumption'),
|
||||
voltage=energy_data.get('voltage'),
|
||||
current=energy_data.get('current'),
|
||||
firmware_version=energy_data.get('firmware_version'),
|
||||
notes=f"Manuell {action_text} durch {current_user.name}"
|
||||
)
|
||||
app_logger.debug(f"📊 Status-Änderung mit Energiedaten protokolliert: Drucker {printer_id} -> {plug_status}")
|
||||
except Exception as log_error:
|
||||
app_logger.error(f"❌ Fehler beim Protokollieren der Status-Änderung: {str(log_error)}")
|
||||
|
||||
# Änderungen in Datenbank speichern
|
||||
db_session.commit()
|
||||
|
||||
action_text = "eingeschaltet" if action == 'on' else "ausgeschaltet"
|
||||
flash(f'Drucker erfolgreich {action_text}', 'success')
|
||||
app_logger.info(f"✅ Drucker {printer_id} erfolgreich {action_text} durch {current_user.name}")
|
||||
flash(f'Drucker erfolgreich {action_text} - Status: {status_text}', 'success')
|
||||
app_logger.info(f"✅ Drucker {printer_id} erfolgreich {action_text} durch {current_user.name} - Status: {status_text}")
|
||||
else:
|
||||
flash(f'Fehler bei Drucker-Steuerung: {message}', 'error')
|
||||
app_logger.error(f"❌ Fehler bei Drucker {printer_id} Steuerung: {message}")
|
||||
action_text = "einschalten" if action == 'on' else "ausschalten"
|
||||
flash(f'Fehler beim {action_text} der Steckdose', 'error')
|
||||
app_logger.error(f"❌ Fehler beim {action_text} von Drucker {printer_id}")
|
||||
|
||||
db_session.close()
|
||||
|
||||
return redirect(url_for('printers_page'))
|
||||
|
||||
|
Reference in New Issue
Block a user