diff --git a/backend/app/README_RASPBERRY_PI.md b/backend/app/README_RASPBERRY_PI.md new file mode 100644 index 00000000..0519ecba --- /dev/null +++ b/backend/app/README_RASPBERRY_PI.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/backend/app/app.py b/backend/app/app.py index 7e6164fc..185b37da 100644 --- a/backend/app/app.py +++ b/backend/app/app.py @@ -1684,19 +1684,28 @@ def get_printers(): db_session = get_db_session() try: - # Set timeout for database query - import signal + # Windows-kompatible Timeout-Implementierung + import threading + import time - def timeout_handler(signum, frame): - raise TimeoutError("Database query timeout") + printers = None + timeout_occurred = False - signal.signal(signal.SIGALRM, timeout_handler) - signal.alarm(5) # 5 second timeout for basic printer loading (reduziert) + def fetch_printers(): + nonlocal printers, timeout_occurred + try: + printers = db_session.query(Printer).all() + except Exception as e: + printers_logger.error(f"Datenbankfehler beim Laden der Drucker: {str(e)}") + timeout_occurred = True - try: - printers = db_session.query(Printer).all() - signal.alarm(0) # Clear alarm - except TimeoutError: + # Starte Datenbankabfrage in separatem Thread + thread = threading.Thread(target=fetch_printers) + thread.daemon = True + thread.start() + thread.join(timeout=5) # 5 Sekunden Timeout + + if thread.is_alive() or timeout_occurred or printers is None: printers_logger.warning("Database timeout when fetching printers for basic loading") return jsonify({ 'error': 'Database timeout beim Laden der Drucker', @@ -1734,7 +1743,6 @@ def get_printers(): }) except Exception as e: - signal.alarm(0) # Clear any remaining alarm db_session.rollback() db_session.close() printers_logger.error(f"Fehler beim Abrufen der Drucker: {str(e)}") @@ -1750,19 +1758,28 @@ def get_printers_with_status(): db_session = get_db_session() try: - # Set timeout for database query - import signal + # Windows-kompatible Timeout-Implementierung + import threading + import time - def timeout_handler(signum, frame): - raise TimeoutError("Database query timeout") + printers = None + timeout_occurred = False - signal.signal(signal.SIGALRM, timeout_handler) - signal.alarm(8) # 8 second timeout for status check loading + def fetch_printers(): + nonlocal printers, timeout_occurred + try: + printers = db_session.query(Printer).all() + except Exception as e: + printers_logger.error(f"Datenbankfehler beim Status-Check: {str(e)}") + timeout_occurred = True - try: - printers = db_session.query(Printer).all() - signal.alarm(0) # Clear alarm - except TimeoutError: + # Starte Datenbankabfrage in separatem Thread + thread = threading.Thread(target=fetch_printers) + thread.daemon = True + thread.start() + thread.join(timeout=8) # 8 Sekunden Timeout für Status-Check + + if thread.is_alive() or timeout_occurred or printers is None: printers_logger.warning("Database timeout when fetching printers for status check") return jsonify({ 'error': 'Database timeout beim Status-Check der Drucker', @@ -1852,7 +1869,6 @@ def get_printers_with_status(): return jsonify(status_data) except Exception as e: - signal.alarm(0) # Clear any remaining alarm db_session.rollback() db_session.close() printers_logger.error(f"Fehler beim Status-Check der Drucker: {str(e)}") diff --git a/backend/app/database/myp.db b/backend/app/database/myp.db index c10a58b4..76d9f410 100644 Binary files a/backend/app/database/myp.db and b/backend/app/database/myp.db differ diff --git a/backend/app/database/myp.db-shm b/backend/app/database/myp.db-shm index 4fd95972..2ae2b3ba 100644 Binary files a/backend/app/database/myp.db-shm and b/backend/app/database/myp.db-shm differ diff --git a/backend/app/database/myp.db-wal b/backend/app/database/myp.db-wal index a0611478..48e56b7f 100644 Binary files a/backend/app/database/myp.db-wal and b/backend/app/database/myp.db-wal differ diff --git a/backend/app/debug_drucker_erkennung.py b/backend/app/debug_drucker_erkennung.py new file mode 100644 index 00000000..cf0b31ff --- /dev/null +++ b/backend/app/debug_drucker_erkennung.py @@ -0,0 +1,314 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +""" +Debug-Skript für Druckererkennung +Testet die Druckererkennung und identifiziert Probleme +""" + +import sys +import os +import requests +import json +import time +import threading +from datetime import datetime +import sqlite3 +import subprocess +import platform + +# Füge das Anwendungsverzeichnis zum Python-Pfad hinzu +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +def log_message(message, level="INFO"): + """Logge eine Nachricht mit Zeitstempel""" + timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + print(f"[{timestamp}] [{level}] {message}") + +def test_database_connection(): + """Teste die Datenbankverbindung""" + log_message("Teste Datenbankverbindung...") + + try: + # Versuche SQLite-Datenbank zu öffnen + db_files = ['database.db', 'app.db', 'myp.db'] + + for db_file in db_files: + if os.path.exists(db_file): + log_message(f"Gefundene Datenbankdatei: {db_file}") + + conn = sqlite3.connect(db_file) + cursor = conn.cursor() + + # Prüfe ob Printer-Tabelle existiert + cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='printer';") + if cursor.fetchone(): + log_message("✅ Printer-Tabelle gefunden") + + # Zähle Drucker + cursor.execute("SELECT COUNT(*) FROM printer;") + count = cursor.fetchone()[0] + log_message(f"📊 Anzahl Drucker in Datenbank: {count}") + + # Zeige Drucker-Details + cursor.execute("SELECT id, name, plug_ip, status FROM printer;") + printers = cursor.fetchall() + + for printer in printers: + log_message(f" Drucker {printer[0]}: {printer[1]} ({printer[2]}) - Status: {printer[3]}") + + conn.close() + return True + else: + log_message("❌ Printer-Tabelle nicht gefunden") + conn.close() + + log_message("❌ Keine gültige Datenbank gefunden") + return False + + except Exception as e: + log_message(f"❌ Datenbankfehler: {str(e)}", "ERROR") + return False + +def test_api_endpoints(): + """Teste die API-Endpunkte""" + log_message("Teste API-Endpunkte...") + + base_url = "http://localhost:5000" + endpoints = [ + "/api/printers", + "/api/printers/status" + ] + + for endpoint in endpoints: + try: + log_message(f"Teste {endpoint}...") + + response = requests.get(f"{base_url}{endpoint}", timeout=10) + + log_message(f" Status Code: {response.status_code}") + + if response.status_code == 200: + try: + data = response.json() + if endpoint == "/api/printers": + if 'printers' in data: + log_message(f" ✅ {len(data['printers'])} Drucker geladen") + else: + log_message(f" ⚠️ Unerwartete Antwortstruktur: {list(data.keys())}") + else: + if isinstance(data, list): + log_message(f" ✅ {len(data)} Drucker mit Status geladen") + else: + log_message(f" ⚠️ Unerwartete Antwortstruktur: {type(data)}") + except json.JSONDecodeError: + log_message(f" ❌ Ungültige JSON-Antwort", "ERROR") + else: + log_message(f" ❌ HTTP-Fehler: {response.status_code}", "ERROR") + try: + error_data = response.json() + log_message(f" Fehlermeldung: {error_data.get('error', 'Unbekannt')}", "ERROR") + except: + log_message(f" Antwort: {response.text[:200]}", "ERROR") + + except requests.exceptions.ConnectionError: + log_message(f" ❌ Verbindung zu {base_url} fehlgeschlagen", "ERROR") + log_message(" Ist die Flask-Anwendung gestartet?", "ERROR") + except requests.exceptions.Timeout: + log_message(f" ❌ Timeout bei {endpoint}", "ERROR") + except Exception as e: + log_message(f" ❌ Fehler: {str(e)}", "ERROR") + +def test_network_connectivity(): + """Teste Netzwerkverbindung zu Druckern""" + log_message("Teste Netzwerkverbindung zu Druckern...") + + # Lade Drucker aus Datenbank + try: + db_files = ['database.db', 'app.db', 'myp.db'] + printers = [] + + for db_file in db_files: + if os.path.exists(db_file): + conn = sqlite3.connect(db_file) + cursor = conn.cursor() + cursor.execute("SELECT name, plug_ip FROM printer WHERE plug_ip IS NOT NULL;") + printers = cursor.fetchall() + conn.close() + break + + if not printers: + log_message("❌ Keine Drucker mit IP-Adressen gefunden") + return + + for name, ip in printers: + log_message(f"Teste Verbindung zu {name} ({ip})...") + + # Ping-Test + try: + if platform.system().lower() == "windows": + result = subprocess.run(['ping', '-n', '1', '-w', '3000', ip], + capture_output=True, text=True, timeout=5) + else: + result = subprocess.run(['ping', '-c', '1', '-W', '3', ip], + capture_output=True, text=True, timeout=5) + + if result.returncode == 0: + log_message(f" ✅ Ping erfolgreich") + else: + log_message(f" ❌ Ping fehlgeschlagen") + + except subprocess.TimeoutExpired: + log_message(f" ❌ Ping-Timeout") + except Exception as e: + log_message(f" ❌ Ping-Fehler: {str(e)}") + + # HTTP-Test (falls Drucker Webinterface hat) + try: + response = requests.get(f"http://{ip}", timeout=3) + log_message(f" ✅ HTTP-Verbindung erfolgreich (Status: {response.status_code})") + except requests.exceptions.Timeout: + log_message(f" ⚠️ HTTP-Timeout (normal für Drucker ohne Webinterface)") + except requests.exceptions.ConnectionError: + log_message(f" ⚠️ HTTP-Verbindung fehlgeschlagen (normal für Drucker ohne Webinterface)") + except Exception as e: + log_message(f" ⚠️ HTTP-Fehler: {str(e)}") + + except Exception as e: + log_message(f"❌ Fehler beim Testen der Netzwerkverbindung: {str(e)}", "ERROR") + +def test_flask_app_status(): + """Teste den Status der Flask-Anwendung""" + log_message("Teste Flask-Anwendung...") + + try: + # Teste Hauptseite + response = requests.get("http://localhost:5000", timeout=5) + if response.status_code == 200: + log_message("✅ Flask-Anwendung läuft") + else: + log_message(f"⚠️ Flask-Anwendung antwortet mit Status {response.status_code}") + + except requests.exceptions.ConnectionError: + log_message("❌ Flask-Anwendung nicht erreichbar", "ERROR") + log_message(" Starte die Anwendung mit: python app.py", "INFO") + except Exception as e: + log_message(f"❌ Fehler beim Testen der Flask-Anwendung: {str(e)}", "ERROR") + +def test_threading_timeout(): + """Teste die Threading-basierte Timeout-Implementierung""" + log_message("Teste Threading-Timeout-Implementierung...") + + def test_function(): + """Simuliere eine langsame Datenbankabfrage""" + time.sleep(2) + return "Erfolgreich" + + try: + result = None + timeout_occurred = False + + def run_test(): + nonlocal result, timeout_occurred + try: + result = test_function() + except Exception as e: + log_message(f"Fehler in Test-Thread: {str(e)}", "ERROR") + timeout_occurred = True + + # Starte Test in separatem Thread + thread = threading.Thread(target=run_test) + thread.daemon = True + thread.start() + thread.join(timeout=3) # 3 Sekunden Timeout + + if thread.is_alive() or timeout_occurred or result is None: + log_message("❌ Threading-Timeout-Test fehlgeschlagen", "ERROR") + else: + log_message("✅ Threading-Timeout-Implementierung funktioniert") + + except Exception as e: + log_message(f"❌ Fehler beim Threading-Test: {str(e)}", "ERROR") + +def check_system_requirements(): + """Prüfe Systemanforderungen""" + log_message("Prüfe Systemanforderungen...") + + # Python-Version + python_version = sys.version_info + log_message(f"Python-Version: {python_version.major}.{python_version.minor}.{python_version.micro}") + + if python_version.major >= 3 and python_version.minor >= 7: + log_message("✅ Python-Version ist kompatibel") + else: + log_message("❌ Python 3.7+ erforderlich", "ERROR") + + # Erforderliche Module + required_modules = ['flask', 'requests', 'sqlite3', 'threading'] + + for module in required_modules: + try: + __import__(module) + log_message(f"✅ Modul {module} verfügbar") + except ImportError: + log_message(f"❌ Modul {module} nicht verfügbar", "ERROR") + + # Betriebssystem + os_name = platform.system() + log_message(f"Betriebssystem: {os_name}") + + if os_name == "Windows": + log_message("✅ Windows-spezifische Fixes wurden angewendet") + else: + log_message("ℹ️ Unix-basiertes System erkannt") + +def run_comprehensive_test(): + """Führe alle Tests aus""" + log_message("=== MYP Druckerverwaltung - Diagnose-Tool ===") + log_message("Starte umfassende Systemdiagnose...") + print() + + # Systemanforderungen prüfen + check_system_requirements() + print() + + # Threading-Test + test_threading_timeout() + print() + + # Datenbanktest + test_database_connection() + print() + + # Flask-App-Test + test_flask_app_status() + print() + + # API-Tests + test_api_endpoints() + print() + + # Netzwerk-Tests + test_network_connectivity() + print() + + log_message("=== Diagnose abgeschlossen ===") + print() + + # Empfehlungen + log_message("📋 Empfehlungen:") + log_message("1. Stelle sicher, dass die Flask-Anwendung läuft: python app.py") + log_message("2. Prüfe die Datenbankverbindung und Drucker-Konfiguration") + log_message("3. Teste die Netzwerkverbindung zu den Druckern") + log_message("4. Bei Windows: Threading-basierte Timeouts wurden implementiert") + log_message("5. Überprüfe die Logs in logs/app/ für weitere Details") + +if __name__ == "__main__": + try: + run_comprehensive_test() + except KeyboardInterrupt: + log_message("Diagnose durch Benutzer abgebrochen", "INFO") + except Exception as e: + log_message(f"Unerwarteter Fehler: {str(e)}", "ERROR") + import traceback + traceback.print_exc() \ No newline at end of file diff --git a/backend/app/install_raspberry_pi.sh b/backend/app/install_raspberry_pi.sh new file mode 100644 index 00000000..f47212a0 --- /dev/null +++ b/backend/app/install_raspberry_pi.sh @@ -0,0 +1,517 @@ +#!/bin/bash + +# =================================================================== +# Raspberry Pi Vollautomatische Installation - MYP Druckerverwaltung +# Für Debian 12 (Bookworm) auf Raspberry Pi +# =================================================================== + +set -e # Beende bei Fehlern + +# Farben für Ausgabe +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Logging-Funktion +log() { + echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')] $1${NC}" +} + +error() { + echo -e "${RED}[FEHLER] $1${NC}" + exit 1 +} + +warning() { + echo -e "${YELLOW}[WARNUNG] $1${NC}" +} + +info() { + echo -e "${BLUE}[INFO] $1${NC}" +} + +# Prüfe ob als Root ausgeführt +if [ "$EUID" -ne 0 ]; then + error "Dieses Skript muss als Root ausgeführt werden. Verwende: sudo $0" +fi + +log "=== MYP Druckerverwaltung - Raspberry Pi Installation ===" +log "Debian 12 (Bookworm) Vollautomatische Einrichtung" +echo + +# Konfigurationsvariablen +APP_USER="myp" +APP_DIR="/opt/myp-druckerverwaltung" +SERVICE_NAME="myp-druckerverwaltung" +KIOSK_SERVICE_NAME="myp-kiosk" +GITHUB_REPO="https://github.com/your-repo/myp-druckerverwaltung.git" # Anpassen! +DISPLAY_PORT=":0" + +# Systemupdate +log "Aktualisiere Paketlisten und System..." +export DEBIAN_FRONTEND=noninteractive +apt-get update -y +apt-get upgrade -y --allow-downgrades --allow-remove-essential --allow-change-held-packages + +# Installiere erforderliche Pakete +log "Installiere Systempakete..." +apt-get install -y \ + python3 \ + python3-pip \ + python3-venv \ + python3-dev \ + git \ + curl \ + wget \ + unzip \ + sqlite3 \ + nginx \ + supervisor \ + chromium-browser \ + xorg \ + openbox \ + lightdm \ + x11-xserver-utils \ + unclutter \ + build-essential \ + libssl-dev \ + libffi-dev \ + libjpeg-dev \ + zlib1g-dev \ + nodejs \ + npm \ + --break-system-packages || true + +# Erstelle Anwendungsbenutzer +log "Erstelle Anwendungsbenutzer '$APP_USER'..." +if ! id "$APP_USER" &>/dev/null; then + useradd -m -s /bin/bash "$APP_USER" + usermod -aG sudo "$APP_USER" + log "Benutzer '$APP_USER' erstellt" +else + log "Benutzer '$APP_USER' existiert bereits" +fi + +# Erstelle Anwendungsverzeichnis +log "Erstelle Anwendungsverzeichnis..." +mkdir -p "$APP_DIR" +chown "$APP_USER:$APP_USER" "$APP_DIR" + +# Klone Repository (falls nicht lokal vorhanden) +if [ ! -d "$APP_DIR/.git" ]; then + log "Klone Anwendung von Repository..." + # Für lokale Installation: kopiere aktuelles Verzeichnis + if [ -f "app.py" ]; then + log "Kopiere lokale Anwendung..." + cp -r . "$APP_DIR/" + chown -R "$APP_USER:$APP_USER" "$APP_DIR" + else + error "Anwendungsdateien nicht gefunden. Führe das Skript im Anwendungsverzeichnis aus." + fi +else + log "Repository bereits vorhanden, aktualisiere..." + cd "$APP_DIR" + sudo -u "$APP_USER" git pull +fi + +cd "$APP_DIR" + +# Python Virtual Environment erstellen +log "Erstelle Python Virtual Environment..." +sudo -u "$APP_USER" python3 -m venv venv +sudo -u "$APP_USER" ./venv/bin/pip install --upgrade pip + +# Installiere Python-Abhängigkeiten +log "Installiere Python-Abhängigkeiten..." +if [ -f "requirements.txt" ]; then + sudo -u "$APP_USER" ./venv/bin/pip install -r requirements.txt --break-system-packages || true +else + # Fallback: Installiere grundlegende Pakete + sudo -u "$APP_USER" ./venv/bin/pip install \ + flask \ + flask-login \ + flask-sqlalchemy \ + werkzeug \ + requests \ + python-dotenv \ + gunicorn \ + --break-system-packages || true +fi + +# Node.js Abhängigkeiten installieren (falls package.json vorhanden) +if [ -f "package.json" ]; then + log "Installiere Node.js Abhängigkeiten..." + sudo -u "$APP_USER" npm install --unsafe-perm=true --allow-root + + # Baue Frontend-Assets + if [ -f "tailwind.config.js" ]; then + log "Baue Frontend-Assets..." + sudo -u "$APP_USER" npm run build || true + fi +fi + +# Datenbank initialisieren +log "Initialisiere Datenbank..." +if [ -f "init_db.py" ]; then + sudo -u "$APP_USER" ./venv/bin/python init_db.py +else + # Erstelle einfache SQLite-Datenbank + sudo -u "$APP_USER" touch database.db +fi + +# Erstelle Konfigurationsdatei +log "Erstelle Anwendungskonfiguration..." +cat > "$APP_DIR/.env" << EOF +# MYP Druckerverwaltung Konfiguration +FLASK_ENV=production +SECRET_KEY=$(openssl rand -hex 32) +DATABASE_URL=sqlite:///database.db +HOST=0.0.0.0 +PORT=5000 +DEBUG=False + +# Kiosk-Modus +KIOSK_MODE=true +AUTO_LOGIN=true +EOF + +chown "$APP_USER:$APP_USER" "$APP_DIR/.env" + +# Erstelle Systemd-Service für die Anwendung +log "Erstelle Systemd-Service..." +cat > "/etc/systemd/system/$SERVICE_NAME.service" << EOF +[Unit] +Description=MYP Druckerverwaltung Flask Application +After=network.target + +[Service] +Type=simple +User=$APP_USER +Group=$APP_USER +WorkingDirectory=$APP_DIR +Environment=PATH=$APP_DIR/venv/bin +ExecStart=$APP_DIR/venv/bin/python app.py +Restart=always +RestartSec=10 +StandardOutput=journal +StandardError=journal + +[Install] +WantedBy=multi-user.target +EOF + +# Nginx-Konfiguration +log "Konfiguriere Nginx..." +cat > "/etc/nginx/sites-available/myp-druckerverwaltung" << EOF +server { + listen 80 default_server; + listen [::]:80 default_server; + + server_name _; + + location / { + proxy_pass http://127.0.0.1:5000; + proxy_set_header Host \$host; + proxy_set_header X-Real-IP \$remote_addr; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto \$scheme; + + # WebSocket-Support + proxy_http_version 1.1; + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection "upgrade"; + } + + # Statische Dateien direkt servieren + location /static/ { + alias $APP_DIR/static/; + expires 1y; + add_header Cache-Control "public, immutable"; + } +} +EOF + +# Aktiviere Nginx-Site +rm -f /etc/nginx/sites-enabled/default +ln -sf /etc/nginx/sites-available/myp-druckerverwaltung /etc/nginx/sites-enabled/ + +# Kiosk-Modus konfigurieren +log "Konfiguriere Kiosk-Modus..." + +# Erstelle Kiosk-Benutzer +if ! id "kiosk" &>/dev/null; then + useradd -m -s /bin/bash kiosk + usermod -aG audio,video kiosk +fi + +# Erstelle Kiosk-Startskript +cat > "/home/kiosk/start-kiosk.sh" << 'EOF' +#!/bin/bash + +# Warte auf Netzwerk +sleep 10 + +# Setze Display +export DISPLAY=:0 + +# Deaktiviere Bildschirmschoner und Energiesparmodus +xset s off +xset -dpms +xset s noblank + +# Verstecke Mauszeiger +unclutter -idle 0.5 -root & + +# Starte Chromium im Kiosk-Modus +chromium-browser \ + --kiosk \ + --no-sandbox \ + --disable-web-security \ + --disable-features=TranslateUI \ + --disable-ipc-flooding-protection \ + --disable-renderer-backgrounding \ + --disable-backgrounding-occluded-windows \ + --disable-background-timer-throttling \ + --disable-background-networking \ + --disable-breakpad \ + --disable-component-extensions-with-background-pages \ + --disable-dev-shm-usage \ + --disable-extensions \ + --disable-features=TranslateUI,BlinkGenPropertyTrees \ + --disable-hang-monitor \ + --disable-ipc-flooding-protection \ + --disable-popup-blocking \ + --disable-prompt-on-repost \ + --disable-renderer-backgrounding \ + --disable-sync \ + --disable-translate \ + --disable-windows10-custom-titlebar \ + --force-color-profile=srgb \ + --metrics-recording-only \ + --no-first-run \ + --safebrowsing-disable-auto-update \ + --enable-automation \ + --password-store=basic \ + --use-mock-keychain \ + --autoplay-policy=no-user-gesture-required \ + --start-fullscreen \ + --window-position=0,0 \ + --window-size=1920,1080 \ + http://localhost/ +EOF + +chmod +x /home/kiosk/start-kiosk.sh +chown kiosk:kiosk /home/kiosk/start-kiosk.sh + +# Erstelle Systemd-Service für Kiosk +cat > "/etc/systemd/system/$KIOSK_SERVICE_NAME.service" << EOF +[Unit] +Description=MYP Kiosk Mode +After=graphical-session.target network.target $SERVICE_NAME.service +Wants=graphical-session.target + +[Service] +Type=simple +User=kiosk +Group=kiosk +Environment=DISPLAY=:0 +ExecStart=/home/kiosk/start-kiosk.sh +Restart=always +RestartSec=10 + +[Install] +WantedBy=graphical.target +EOF + +# Konfiguriere LightDM für automatischen Login +log "Konfiguriere automatischen Login..." +cat > "/etc/lightdm/lightdm.conf" << EOF +[Seat:*] +autologin-user=kiosk +autologin-user-timeout=0 +user-session=openbox +EOF + +# Erstelle Openbox-Konfiguration für Kiosk-Benutzer +mkdir -p /home/kiosk/.config/openbox +cat > "/home/kiosk/.config/openbox/autostart" << EOF +# Starte Kiosk-Anwendung +/home/kiosk/start-kiosk.sh & +EOF + +chown -R kiosk:kiosk /home/kiosk/.config + +# Erstelle Wartungsskript +log "Erstelle Wartungsskript..." +cat > "/usr/local/bin/myp-maintenance" << 'EOF' +#!/bin/bash + +# MYP Druckerverwaltung Wartungsskript + +case "$1" in + start) + echo "Starte MYP Druckerverwaltung..." + systemctl start myp-druckerverwaltung + systemctl start nginx + systemctl start myp-kiosk + ;; + stop) + echo "Stoppe MYP Druckerverwaltung..." + systemctl stop myp-kiosk + systemctl stop myp-druckerverwaltung + systemctl stop nginx + ;; + restart) + echo "Starte MYP Druckerverwaltung neu..." + systemctl restart myp-druckerverwaltung + systemctl restart nginx + systemctl restart myp-kiosk + ;; + status) + echo "=== MYP Druckerverwaltung Status ===" + systemctl status myp-druckerverwaltung --no-pager + echo + echo "=== Nginx Status ===" + systemctl status nginx --no-pager + echo + echo "=== Kiosk Status ===" + systemctl status myp-kiosk --no-pager + ;; + logs) + echo "=== Anwendungslogs ===" + journalctl -u myp-druckerverwaltung -f + ;; + update) + echo "Aktualisiere MYP Druckerverwaltung..." + cd /opt/myp-druckerverwaltung + sudo -u myp git pull + sudo -u myp ./venv/bin/pip install -r requirements.txt --break-system-packages + systemctl restart myp-druckerverwaltung + ;; + *) + echo "Verwendung: $0 {start|stop|restart|status|logs|update}" + exit 1 + ;; +esac +EOF + +chmod +x /usr/local/bin/myp-maintenance + +# Aktiviere und starte Services +log "Aktiviere und starte Services..." +systemctl daemon-reload +systemctl enable "$SERVICE_NAME" +systemctl enable nginx +systemctl enable "$KIOSK_SERVICE_NAME" + +# Starte Services +systemctl start "$SERVICE_NAME" +systemctl start nginx + +# Warte kurz und prüfe Status +sleep 5 + +if systemctl is-active --quiet "$SERVICE_NAME"; then + log "✅ MYP Druckerverwaltung Service läuft" +else + warning "⚠️ MYP Druckerverwaltung Service nicht aktiv" +fi + +if systemctl is-active --quiet nginx; then + log "✅ Nginx läuft" +else + warning "⚠️ Nginx nicht aktiv" +fi + +# Konfiguriere Firewall (falls ufw installiert) +if command -v ufw &> /dev/null; then + log "Konfiguriere Firewall..." + ufw --force enable + ufw allow 80/tcp + ufw allow 22/tcp +fi + +# Erstelle Desktop-Verknüpfung für Wartung +cat > "/home/$APP_USER/Desktop/MYP-Wartung.desktop" << EOF +[Desktop Entry] +Version=1.0 +Type=Application +Name=MYP Wartung +Comment=MYP Druckerverwaltung Wartung +Exec=gnome-terminal -- sudo myp-maintenance status +Icon=applications-system +Terminal=true +Categories=System; +EOF + +chown "$APP_USER:$APP_USER" "/home/$APP_USER/Desktop/MYP-Wartung.desktop" +chmod +x "/home/$APP_USER/Desktop/MYP-Wartung.desktop" + +# Erstelle Backup-Skript +cat > "/usr/local/bin/myp-backup" << 'EOF' +#!/bin/bash + +BACKUP_DIR="/opt/myp-backups" +DATE=$(date +%Y%m%d_%H%M%S) +APP_DIR="/opt/myp-druckerverwaltung" + +mkdir -p "$BACKUP_DIR" + +echo "Erstelle Backup: $DATE" + +# Stoppe Anwendung +systemctl stop myp-druckerverwaltung + +# Erstelle Backup +tar -czf "$BACKUP_DIR/myp_backup_$DATE.tar.gz" \ + -C "$APP_DIR" \ + database.db \ + .env \ + uploads/ \ + logs/ 2>/dev/null || true + +# Starte Anwendung +systemctl start myp-druckerverwaltung + +echo "Backup erstellt: $BACKUP_DIR/myp_backup_$DATE.tar.gz" + +# Lösche alte Backups (älter als 30 Tage) +find "$BACKUP_DIR" -name "myp_backup_*.tar.gz" -mtime +30 -delete +EOF + +chmod +x /usr/local/bin/myp-backup + +# Erstelle Cron-Job für automatische Backups +echo "0 2 * * * root /usr/local/bin/myp-backup" > /etc/cron.d/myp-backup + +# Abschlussmeldung +log "=== Installation abgeschlossen! ===" +echo +info "🎉 MYP Druckerverwaltung wurde erfolgreich installiert!" +echo +info "📋 Wichtige Informationen:" +info " • Anwendung läuft auf: http://$(hostname -I | awk '{print $1}')" +info " • Anwendungsverzeichnis: $APP_DIR" +info " • Anwendungsbenutzer: $APP_USER" +info " • Service-Name: $SERVICE_NAME" +info " • Kiosk-Service: $KIOSK_SERVICE_NAME" +echo +info "🔧 Wartungskommandos:" +info " • Status prüfen: myp-maintenance status" +info " • Neustart: myp-maintenance restart" +info " • Logs anzeigen: myp-maintenance logs" +info " • Update: myp-maintenance update" +info " • Backup erstellen: myp-backup" +echo +info "🖥️ Kiosk-Modus:" +info " • Wird beim nächsten Neustart automatisch gestartet" +info " • Vollbild-Browser auf http://localhost" +info " • Automatischer Login als 'kiosk' Benutzer" +echo +warning "⚠️ Wichtiger Hinweis:" +warning " Starte das System neu, um den Kiosk-Modus zu aktivieren:" +warning " sudo reboot" +echo +log "Installation erfolgreich abgeschlossen! 🚀" \ No newline at end of file diff --git a/backend/install/install-kiosk.sh b/backend/install/install-kiosk.sh index cf08ee4a..e2352a80 100644 --- a/backend/install/install-kiosk.sh +++ b/backend/install/install-kiosk.sh @@ -16,7 +16,19 @@ fi # Installiere benötigte Pakete echo "Installiere Pakete..." apt update -apt install -y python3.11 python3-pip chromium-browser lightdm openbox curl + +# Basis-Pakete +apt install -y python3.11 python3-pip curl + +# Browser +apt install -y chromium-browser || apt install -y chromium || apt install -y firefox-esr + +# Display Manager und Window Manager +apt install -y lightdm +apt install -y openbox || apt install -y xfce4 || apt install -y lxde + +# X11 falls nicht vorhanden +apt install -y xorg xinit # Erstelle Verzeichnisse echo "Erstelle Verzeichnisse..." @@ -58,6 +70,20 @@ systemctl daemon-reload systemctl enable myp-backend.service systemctl enable myp-kiosk.service +# Erstelle Benutzer 'user' falls nicht vorhanden +echo "Erstelle Benutzer 'user'..." +if ! id "user" &>/dev/null; then + useradd -m -s /bin/bash user + echo "user:user" | chpasswd +fi + +# Setze Openbox als Standard-Session +echo "Setze Openbox als Standard..." +echo "openbox-session" > /home/user/.xsession +echo "openbox-session" > /home/user/.xinitrc +chmod +x /home/user/.xsession +chmod +x /home/user/.xinitrc + # Konfiguriere automatischen Login echo "Konfiguriere automatischen Login..." cat > /etc/lightdm/lightdm.conf.d/10-autologin.conf << EOF @@ -65,17 +91,48 @@ cat > /etc/lightdm/lightdm.conf.d/10-autologin.conf << EOF autologin-user=user autologin-user-timeout=0 user-session=openbox +greeter-session=lightdm-gtk-greeter EOF # Konfiguriere Openbox für Kiosk-Start echo "Konfiguriere Openbox..." +mkdir -p /home/user/.config/openbox + cat > /home/user/.config/openbox/autostart << EOF +# Warte kurz bis System bereit ist +sleep 3 + # Starte Kiosk-Service automatisch systemctl --user start myp-kiosk.service & EOF +# Openbox-Menü deaktivieren (Kiosk-Modus) +cat > /home/user/.config/openbox/rc.xml << EOF + + + + + + + + + + + + + + yes + yes + + + +EOF + chmod 755 /home/user/.config/openbox/autostart -chown user:user /home/user/.config/openbox/autostart +chmod 644 /home/user/.config/openbox/rc.xml +chown -R user:user /home/user/.config +chown -R user:user /home/user/.xsession +chown -R user:user /home/user/.xinitrc echo "=== Installation abgeschlossen ===" echo "System wird in 5 Sekunden neu gestartet..."