🎉 Updated documentation and requirements for optimized corrections → renamed 'SETUP_OPTIMIERUNGEN.md' to 'SETUP_KORREKTUREN.md', modified 'requirements.txt' and 'setup.sh'. 🖥️📚
This commit is contained in:
parent
4d9daff491
commit
cd281647e2
@ -1,126 +1,134 @@
|
||||
# MYP Platform - Python Dependencies
|
||||
# Aktualisiert: 2025-01-12
|
||||
# Kompatibel mit Python 3.8+
|
||||
# Produktions-optimierte Versionen mit Kompatibilitätsgarantie
|
||||
|
||||
# ===== CORE FRAMEWORK =====
|
||||
Flask==3.1.1
|
||||
Werkzeug>=2.3.0,<3.0.0
|
||||
Werkzeug==3.1.3
|
||||
Jinja2==3.1.4
|
||||
|
||||
# ===== FLASK EXTENSIONS =====
|
||||
Flask-Login==0.6.3
|
||||
Flask-WTF==1.2.1
|
||||
Flask-SocketIO
|
||||
WTForms
|
||||
Flask-CORS
|
||||
Flask-SocketIO==5.4.1
|
||||
WTForms==3.1.2
|
||||
Flask-CORS==5.0.0
|
||||
Flask-Compress==1.15
|
||||
|
||||
# ===== DATABASE =====
|
||||
SQLAlchemy>=2.0.0,<3.0.0
|
||||
SQLAlchemy==2.0.36
|
||||
|
||||
# ===== SECURITY =====
|
||||
cryptography>=41.0.0
|
||||
bcrypt
|
||||
PyJWT
|
||||
itsdangerous
|
||||
cryptography==44.0.0
|
||||
bcrypt==4.2.1
|
||||
PyJWT==2.10.1
|
||||
itsdangerous==2.2.0
|
||||
|
||||
# ===== HTTP REQUESTS =====
|
||||
requests
|
||||
urllib3
|
||||
requests==2.32.3
|
||||
urllib3==2.2.3
|
||||
|
||||
# ===== HARDWARE INTEGRATION =====
|
||||
PyP100
|
||||
pyserial
|
||||
pyusb
|
||||
PyP100==0.0.8
|
||||
pyserial==3.5
|
||||
pyusb==1.2.1
|
||||
|
||||
# ===== REAL-TIME FEATURES =====
|
||||
eventlet
|
||||
python-socketio
|
||||
eventlet==0.37.0
|
||||
python-socketio==5.13.2
|
||||
|
||||
# ===== SCHEDULING =====
|
||||
schedule
|
||||
APScheduler
|
||||
schedule==1.2.2
|
||||
APScheduler==3.10.4
|
||||
|
||||
# ===== GIS & LOCATION =====
|
||||
geocoder
|
||||
geocoder==1.38.1
|
||||
|
||||
# ===== DATA PROCESSING & EXPORT =====
|
||||
openpyxl
|
||||
xlsxwriter
|
||||
pandas
|
||||
chardet
|
||||
python-magic
|
||||
python-magic-bin; sys_platform == "win32"
|
||||
openpyxl==3.1.5
|
||||
xlsxwriter==3.2.0
|
||||
pandas==2.2.3
|
||||
chardet==5.2.0
|
||||
python-magic==0.4.27
|
||||
python-magic-bin==0.4.14; sys_platform == "win32"
|
||||
|
||||
# ===== EMAIL & VALIDATION =====
|
||||
email-validator
|
||||
email-validator==2.2.0
|
||||
|
||||
# ===== IMAGE PROCESSING =====
|
||||
Pillow
|
||||
qrcode[pil]
|
||||
Pillow==11.0.0
|
||||
qrcode[pil]==8.0
|
||||
|
||||
# ===== PDF & REPORT GENERATION =====
|
||||
reportlab
|
||||
weasyprint
|
||||
reportlab==4.2.5
|
||||
weasyprint==63.1
|
||||
|
||||
# ===== DATE/TIME HANDLING =====
|
||||
python-dateutil
|
||||
pytz
|
||||
python-dateutil==2.9.0
|
||||
pytz==2024.2
|
||||
|
||||
# ===== LOGGING & MONITORING =====
|
||||
colorlog
|
||||
psutil
|
||||
colorlog==6.9.0
|
||||
psutil==6.1.1
|
||||
|
||||
# ===== FILE SYSTEM OPERATIONS =====
|
||||
watchdog
|
||||
Send2Trash
|
||||
watchdog==6.0.0
|
||||
Send2Trash==1.8.3
|
||||
|
||||
# ===== DATA VALIDATION =====
|
||||
cerberus
|
||||
marshmallow
|
||||
validators
|
||||
cerberus==1.3.5
|
||||
marshmallow==3.23.2
|
||||
validators==0.34.0
|
||||
|
||||
# ===== UTILITIES =====
|
||||
python-slugify
|
||||
click
|
||||
humanize
|
||||
python-dotenv
|
||||
python-slugify==8.0.4
|
||||
click==8.1.7
|
||||
humanize==4.11.0
|
||||
python-dotenv==1.0.1
|
||||
|
||||
# ===== NETWORK & API =====
|
||||
ping3
|
||||
netifaces
|
||||
ping3==4.0.8
|
||||
netifaces==0.11.0
|
||||
|
||||
# ===== CACHING =====
|
||||
cachelib
|
||||
cachelib==0.13.0
|
||||
|
||||
# ===== COMPRESSION =====
|
||||
py7zr
|
||||
py7zr==0.22.0
|
||||
|
||||
# ===== WINDOWS COMPATIBILITY =====
|
||||
pywin32; sys_platform == "win32"
|
||||
wmi; sys_platform == "win32"
|
||||
colorama; sys_platform == "win32"
|
||||
pywin32==308; sys_platform == "win32"
|
||||
wmi==1.5.1; sys_platform == "win32"
|
||||
colorama==0.4.6; sys_platform == "win32"
|
||||
|
||||
# ===== LINUX COMPATIBILITY =====
|
||||
RPi.GPIO; sys_platform == "linux"
|
||||
RPi.GPIO==0.7.1; sys_platform == "linux"
|
||||
|
||||
# ===== PRODUCTION DEPLOYMENT =====
|
||||
gunicorn; sys_platform != "win32"
|
||||
waitress
|
||||
gunicorn==23.0.0; sys_platform != "win32"
|
||||
waitress==3.0.2
|
||||
|
||||
# ===== TESTING & DEVELOPMENT =====
|
||||
pytest
|
||||
pytest-flask
|
||||
pytest-cov
|
||||
coverage
|
||||
pytest==8.3.4
|
||||
pytest-flask==1.3.0
|
||||
pytest-cov==6.0.0
|
||||
coverage==7.6.9
|
||||
|
||||
# ===== CODE QUALITY =====
|
||||
flake8
|
||||
black
|
||||
isort
|
||||
flake8==7.1.1
|
||||
black==24.10.0
|
||||
isort==5.13.2
|
||||
|
||||
# ===== DEPENDENCY COMPATIBILITY =====
|
||||
MarkupSafe==3.0.2
|
||||
setuptools==75.6.0
|
||||
wheel==0.45.1
|
||||
pip==24.3.1
|
||||
|
||||
# ===== OPTIONAL PERFORMANCE ENHANCEMENTS =====
|
||||
# Uncomment for better performance:
|
||||
# uwsgi; sys_platform != "win32"
|
||||
# gevent
|
||||
# redis
|
||||
# celery
|
||||
# Auskommentiert für Stabilität - bei Bedarf aktivieren:
|
||||
# uwsgi==2.0.26; sys_platform != "win32"
|
||||
# gevent==24.11.1
|
||||
# redis==5.2.1
|
||||
# celery==5.4.0
|
||||
|
599
backend/setup.sh
599
backend/setup.sh
@ -6,16 +6,14 @@
|
||||
# Optimiert für Debian/Linux (Raspberry Pi OS) - KEIN Windows-Support
|
||||
# HTTPS auf Port 443 mit automatischer SSL-Zertifikat-Generierung
|
||||
# Kiosk-Modus mit Chromium-Autostart ohne Desktop-Environment
|
||||
# RASPBERRY PI CSS/JS PERFORMANCE-OPTIMIERUNGEN INTEGRIERT
|
||||
# Automatische Hardware-Erkennung und spezifische Browser-Optimierungen
|
||||
# Version: 4.1.0 - Raspberry Pi CSS-Optimiert
|
||||
# Version: 4.0.0
|
||||
# ===================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# =========================== GLOBALE KONFIGURATION ===========================
|
||||
readonly APP_NAME="MYP Druckerverwaltung"
|
||||
readonly APP_VERSION="4.1.0"
|
||||
readonly APP_VERSION="4.0.0"
|
||||
readonly APP_DIR="/opt/myp"
|
||||
readonly HTTPS_SERVICE_NAME="myp-https"
|
||||
readonly KIOSK_SERVICE_NAME="myp-kiosk"
|
||||
@ -86,15 +84,6 @@ check_debian_system() {
|
||||
if [ -f /proc/device-tree/model ]; then
|
||||
local pi_model=$(cat /proc/device-tree/model 2>/dev/null || echo "Unbekannt")
|
||||
info "Raspberry Pi Modell: $pi_model"
|
||||
|
||||
# Exportiere Raspberry Pi Detection für spätere Verwendung
|
||||
export IS_RASPBERRY_PI=true
|
||||
export PI_MODEL="$pi_model"
|
||||
|
||||
# Raspberry Pi spezifische Optimierungen aktivieren
|
||||
log "✅ Raspberry Pi Hardware erkannt - CSS-Optimierungen werden aktiviert"
|
||||
else
|
||||
export IS_RASPBERRY_PI=false
|
||||
fi
|
||||
}
|
||||
|
||||
@ -566,23 +555,6 @@ if [ -z "$DISPLAY" ] && [ "$XDG_VTNR" = "1" ]; then
|
||||
--disable-web-security \
|
||||
--allow-running-insecure-content \
|
||||
--unsafely-treat-insecure-origin-as-secure=https://localhost:443 \
|
||||
--disable-gpu-compositing \
|
||||
--enable-gpu-rasterization \
|
||||
--disable-smooth-scrolling \
|
||||
--disable-2d-canvas-image-chromium \
|
||||
--disable-accelerated-2d-canvas \
|
||||
--num-raster-threads=2 \
|
||||
--enable-zero-copy \
|
||||
--disable-gpu-sandbox \
|
||||
--disable-software-rasterizer \
|
||||
--enable-low-end-device-mode \
|
||||
--disable-features=VizHitTestSurfaceLayer \
|
||||
--disable-partial-raster \
|
||||
--disable-threaded-animation \
|
||||
--disable-checker-imaging \
|
||||
--disable-new-content-rendering-timeout \
|
||||
--run-all-compositor-stages-before-draw \
|
||||
--disable-ipc-flooding-protection \
|
||||
https://localhost:443
|
||||
else
|
||||
exec firefox-esr \
|
||||
@ -608,68 +580,6 @@ EOF
|
||||
mkdir -p "$kiosk_home/.chromium-kiosk"
|
||||
chown -R "$KIOSK_USER:$KIOSK_USER" "$kiosk_home/.chromium-kiosk"
|
||||
|
||||
# Raspberry Pi spezifische Chromium-Konfiguration
|
||||
if [ "${IS_RASPBERRY_PI:-false}" = "true" ]; then
|
||||
progress "Konfiguriere Chromium für Raspberry Pi Hardware..."
|
||||
|
||||
# Erstelle Raspberry Pi optimierte Chromium Preferences
|
||||
cat > "$kiosk_home/.chromium-kiosk/Default/Preferences" << 'EOF'
|
||||
{
|
||||
"browser" : {
|
||||
"check_default_browser" : false,
|
||||
"show_home_button" : false
|
||||
},
|
||||
"profile" : {
|
||||
"default_content_setting_values" : {
|
||||
"notifications" : 2
|
||||
},
|
||||
"password_manager_enabled" : false
|
||||
},
|
||||
"translate" : {
|
||||
"enabled" : false
|
||||
},
|
||||
"extensions" : {
|
||||
"ui" : {
|
||||
"developer_mode" : false
|
||||
}
|
||||
},
|
||||
"browser_switcher" : {
|
||||
"enabled" : false
|
||||
},
|
||||
"performance_tuning" : {
|
||||
"high_efficiency_mode" : {
|
||||
"enabled" : true
|
||||
},
|
||||
"battery_saver_mode" : {
|
||||
"enabled" : false
|
||||
}
|
||||
},
|
||||
"privacy" : {
|
||||
"ad_measurement_enabled" : false,
|
||||
"enable_do_not_track" : true
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
# Erstelle Raspberry Pi optimierte Local State
|
||||
cat > "$kiosk_home/.chromium-kiosk/Local State" << 'EOF'
|
||||
{
|
||||
"background_mode" : {
|
||||
"enabled" : false
|
||||
},
|
||||
"browser" : {
|
||||
"enabled_labs_experiments" : [ ]
|
||||
},
|
||||
"user_experience_metrics" : {
|
||||
"reporting_enabled" : false
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
chown -R "$KIOSK_USER:$KIOSK_USER" "$kiosk_home/.chromium-kiosk"
|
||||
log "✅ Raspberry Pi optimierte Chromium-Konfiguration erstellt"
|
||||
fi
|
||||
|
||||
log "✅ Automatischer Kiosk-Start konfiguriert"
|
||||
info "Der Kiosk-Modus startet automatisch beim Login des $KIOSK_USER"
|
||||
}
|
||||
@ -761,32 +671,82 @@ install_nodejs_npm() {
|
||||
install_python_packages() {
|
||||
log "=== PYTHON-PAKETE INSTALLATION ==="
|
||||
|
||||
local pip_opts="--break-system-packages --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org --timeout 60 --retries 3"
|
||||
local pip_opts="--break-system-packages --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org --timeout 120 --retries 5 --no-cache-dir"
|
||||
|
||||
progress "Installiere Flask-Framework..."
|
||||
pip3 install $pip_opts Flask==3.1.1 || pip3 install $pip_opts Flask || error "Flask Installation fehlgeschlagen"
|
||||
pip3 install $pip_opts Flask-Login==0.6.3 || pip3 install $pip_opts Flask-Login || error "Flask-Login Installation fehlgeschlagen"
|
||||
pip3 install $pip_opts Flask-WTF==1.2.1 || pip3 install $pip_opts Flask-WTF || error "Flask-WTF Installation fehlgeschlagen"
|
||||
progress "Installiere requirements.txt direkt..."
|
||||
if [ -f "$CURRENT_DIR/requirements.txt" ]; then
|
||||
# Kopiere requirements.txt zum App-Verzeichnis
|
||||
cp "$CURRENT_DIR/requirements.txt" "$APP_DIR/" 2>/dev/null || true
|
||||
|
||||
progress "Installiere Datenbank-Komponenten..."
|
||||
pip3 install $pip_opts SQLAlchemy==2.0.36 || pip3 install $pip_opts SQLAlchemy || error "SQLAlchemy Installation fehlgeschlagen"
|
||||
# Installiere direkt aus requirements.txt (robusteste Methode)
|
||||
if pip3 install $pip_opts -r "$CURRENT_DIR/requirements.txt"; then
|
||||
success "✅ Requirements.txt erfolgreich installiert"
|
||||
else
|
||||
warning "⚠️ Requirements.txt Installation fehlgeschlagen - verwende Fallback-Installation"
|
||||
|
||||
progress "Installiere Sicherheits-Komponenten..."
|
||||
pip3 install $pip_opts bcrypt==4.2.1 || pip3 install $pip_opts bcrypt || error "bcrypt Installation fehlgeschlagen"
|
||||
pip3 install $pip_opts cryptography==44.0.0 || pip3 install $pip_opts cryptography || error "cryptography Installation fehlgeschlagen"
|
||||
pip3 install $pip_opts Werkzeug==3.1.3 || pip3 install $pip_opts Werkzeug || error "Werkzeug Installation fehlgeschlagen"
|
||||
# Fallback: Core-Pakete einzeln installieren
|
||||
progress "Installiere Core-Framework (Fallback)..."
|
||||
pip3 install $pip_opts Flask==3.1.1 || error "Flask Installation fehlgeschlagen"
|
||||
pip3 install $pip_opts Werkzeug==3.1.3 || error "Werkzeug Installation fehlgeschlagen"
|
||||
pip3 install $pip_opts Jinja2==3.1.4 || error "Jinja2 Installation fehlgeschlagen"
|
||||
|
||||
progress "Installiere weitere Abhängigkeiten..."
|
||||
pip3 install $pip_opts requests==2.32.3 || pip3 install $pip_opts requests || error "requests Installation fehlgeschlagen"
|
||||
pip3 install $pip_opts psutil==6.1.1 || pip3 install $pip_opts psutil || error "psutil Installation fehlgeschlagen"
|
||||
pip3 install $pip_opts MarkupSafe==3.0.2 || pip3 install $pip_opts MarkupSafe || error "MarkupSafe Installation fehlgeschlagen"
|
||||
pip3 install $pip_opts gunicorn==23.0.0 || pip3 install $pip_opts gunicorn || error "gunicorn Installation fehlgeschlagen"
|
||||
progress "Installiere Flask-Extensions (Fallback)..."
|
||||
pip3 install $pip_opts Flask-Login==0.6.3 || error "Flask-Login Installation fehlgeschlagen"
|
||||
pip3 install $pip_opts Flask-WTF==1.2.1 || error "Flask-WTF Installation fehlgeschlagen"
|
||||
pip3 install $pip_opts WTForms==3.1.2 || error "WTForms Installation fehlgeschlagen"
|
||||
|
||||
# Optionale Pakete
|
||||
pip3 install $pip_opts PyP100 || warning "PyP100 Installation fehlgeschlagen (optional)"
|
||||
pip3 install $pip_opts redis==5.2.1 || warning "redis Installation fehlgeschlagen (optional)"
|
||||
progress "Installiere Datenbank-Komponenten (Fallback)..."
|
||||
pip3 install $pip_opts SQLAlchemy==2.0.36 || error "SQLAlchemy Installation fehlgeschlagen"
|
||||
|
||||
log "✅ Python-Pakete erfolgreich installiert"
|
||||
progress "Installiere Sicherheits-Komponenten (Fallback)..."
|
||||
pip3 install $pip_opts cryptography==44.0.0 || error "cryptography Installation fehlgeschlagen"
|
||||
pip3 install $pip_opts bcrypt==4.2.1 || error "bcrypt Installation fehlgeschlagen"
|
||||
pip3 install $pip_opts itsdangerous==2.2.0 || error "itsdangerous Installation fehlgeschlagen"
|
||||
|
||||
progress "Installiere System-Abhängigkeiten (Fallback)..."
|
||||
pip3 install $pip_opts requests==2.32.3 || error "requests Installation fehlgeschlagen"
|
||||
pip3 install $pip_opts psutil==6.1.1 || error "psutil Installation fehlgeschlagen"
|
||||
pip3 install $pip_opts MarkupSafe==3.0.2 || error "MarkupSafe Installation fehlgeschlagen"
|
||||
pip3 install $pip_opts gunicorn==23.0.0 || error "gunicorn Installation fehlgeschlagen"
|
||||
|
||||
# Kritische Abhängigkeiten für App-Funktionalität
|
||||
pip3 install $pip_opts python-dateutil==2.9.0 || warning "python-dateutil Installation fehlgeschlagen"
|
||||
pip3 install $pip_opts click==8.1.7 || warning "click Installation fehlgeschlagen"
|
||||
pip3 install $pip_opts colorlog==6.9.0 || warning "colorlog Installation fehlgeschlagen"
|
||||
fi
|
||||
else
|
||||
error "requirements.txt nicht gefunden: $CURRENT_DIR/requirements.txt"
|
||||
fi
|
||||
|
||||
# Validiere kritische Imports nach Installation
|
||||
progress "Validiere kritische Python-Abhängigkeiten..."
|
||||
local validation_errors=0
|
||||
|
||||
if ! python3 -c "import flask; print(f'✅ Flask {flask.__version__} verfügbar')" 2>/dev/null; then
|
||||
error "❌ Flask-Import fehlgeschlagen"
|
||||
((validation_errors++))
|
||||
fi
|
||||
|
||||
if ! python3 -c "import werkzeug; print(f'✅ Werkzeug {werkzeug.__version__} verfügbar')" 2>/dev/null; then
|
||||
error "❌ Werkzeug-Import fehlgeschlagen"
|
||||
((validation_errors++))
|
||||
fi
|
||||
|
||||
if ! python3 -c "import sqlalchemy; print(f'✅ SQLAlchemy {sqlalchemy.__version__} verfügbar')" 2>/dev/null; then
|
||||
error "❌ SQLAlchemy-Import fehlgeschlagen"
|
||||
((validation_errors++))
|
||||
fi
|
||||
|
||||
if ! python3 -c "import bcrypt; print('✅ bcrypt verfügbar')" 2>/dev/null; then
|
||||
error "❌ bcrypt-Import fehlgeschlagen"
|
||||
((validation_errors++))
|
||||
fi
|
||||
|
||||
if [ $validation_errors -gt 0 ]; then
|
||||
error "❌ $validation_errors kritische Python-Abhängigkeiten fehlen!"
|
||||
fi
|
||||
|
||||
log "✅ Python-Pakete erfolgreich installiert und validiert"
|
||||
}
|
||||
|
||||
# =========================== SSL-ZERTIFIKATE ===========================
|
||||
@ -881,7 +841,40 @@ deploy_application() {
|
||||
chmod 750 "$APP_DIR"/{database,logs,certs}
|
||||
chmod +x "$APP_DIR/app.py"
|
||||
|
||||
log "✅ Anwendung erfolgreich deployed"
|
||||
# Python-Pfad-Konfiguration erstellen
|
||||
progress "Konfiguriere Python-Umgebung..."
|
||||
|
||||
# .pth-Datei für automatischen Python-Pfad erstellen
|
||||
local python_site_packages=$(python3 -c "import site; print(site.getsitepackages()[0])" 2>/dev/null || echo "/usr/local/lib/python3/dist-packages")
|
||||
if [ -d "$python_site_packages" ]; then
|
||||
echo "$APP_DIR" > "$python_site_packages/myp-app.pth"
|
||||
log "✅ Python-Pfad konfiguriert: $python_site_packages/myp-app.pth"
|
||||
fi
|
||||
|
||||
# Systemweite Umgebungsvariablen setzen
|
||||
cat >> /etc/environment << EOF
|
||||
|
||||
# MYP Application Environment
|
||||
MYP_APP_DIR=$APP_DIR
|
||||
PYTHONPATH=$APP_DIR:\$PYTHONPATH
|
||||
EOF
|
||||
|
||||
# Bash-Profile für Root und Standard-User aktualisieren
|
||||
for user_home in "/root" "/home/"*; do
|
||||
if [ -d "$user_home" ] && [ "$user_home" != "/home/lost+found" ]; then
|
||||
cat >> "$user_home/.bashrc" << 'EOF'
|
||||
|
||||
# MYP Application Environment
|
||||
if [ -d "/opt/myp" ]; then
|
||||
export MYP_APP_DIR="/opt/myp"
|
||||
export PYTHONPATH="/opt/myp:$PYTHONPATH"
|
||||
fi
|
||||
EOF
|
||||
log "✅ Bash-Profile aktualisiert: $user_home/.bashrc"
|
||||
fi
|
||||
done
|
||||
|
||||
log "✅ Anwendung erfolgreich deployed mit korrekter Python-Umgebung"
|
||||
}
|
||||
|
||||
install_npm_dependencies() {
|
||||
@ -1107,19 +1100,142 @@ install_dependencies_only() {
|
||||
optimize_webapp_performance
|
||||
optimize_static_assets
|
||||
|
||||
# Minimaler Test
|
||||
progress "Starte minimalen Test..."
|
||||
cd "$APP_DIR"
|
||||
# Erweiterter Systemtest mit robuster Fehlerbehandlung
|
||||
progress "Starte erweiterten Systemtest..."
|
||||
|
||||
# Teste Python-Import
|
||||
if python3 -c "import sys; sys.path.insert(0, '$APP_DIR'); from app import app; print('✅ Flask-App erfolgreich importiert')" 2>/dev/null; then
|
||||
success "✅ Python-Abhängigkeiten funktionieren"
|
||||
# 1. Teste kritische Python-Imports (außerhalb der App)
|
||||
progress "Teste kritische Python-Module..."
|
||||
local import_test_errors=0
|
||||
|
||||
# Core-Framework-Tests
|
||||
if ! python3 -c "import flask, werkzeug, jinja2; print('✅ Core-Framework verfügbar')" 2>/dev/null; then
|
||||
warning "⚠️ Core-Framework Import-Problem"
|
||||
((import_test_errors++))
|
||||
fi
|
||||
|
||||
# Datenbank-Tests
|
||||
if ! python3 -c "import sqlalchemy; print('✅ Datenbank-Module verfügbar')" 2>/dev/null; then
|
||||
warning "⚠️ Datenbank-Module Import-Problem"
|
||||
((import_test_errors++))
|
||||
fi
|
||||
|
||||
# Security-Tests
|
||||
if ! python3 -c "import bcrypt, cryptography; print('✅ Security-Module verfügbar')" 2>/dev/null; then
|
||||
warning "⚠️ Security-Module Import-Problem"
|
||||
((import_test_errors++))
|
||||
fi
|
||||
|
||||
# 2. Teste App-Struktur
|
||||
progress "Validiere App-Struktur..."
|
||||
local structure_errors=0
|
||||
|
||||
required_files=(
|
||||
"$APP_DIR/app.py"
|
||||
"$APP_DIR/models.py"
|
||||
"$APP_DIR/requirements.txt"
|
||||
"$APP_DIR/config"
|
||||
"$APP_DIR/blueprints"
|
||||
"$APP_DIR/utils"
|
||||
"$APP_DIR/static"
|
||||
"$APP_DIR/templates"
|
||||
)
|
||||
|
||||
for required_file in "${required_files[@]}"; do
|
||||
if [ ! -e "$required_file" ]; then
|
||||
warning "⚠️ Fehlende App-Komponente: $required_file"
|
||||
((structure_errors++))
|
||||
fi
|
||||
done
|
||||
|
||||
# 3. Teste Datenbank-Initialisierung (sicher)
|
||||
progress "Teste Datenbank-Grundfunktionen..."
|
||||
|
||||
cd "$APP_DIR"
|
||||
if python3 -c "
|
||||
import sys
|
||||
import os
|
||||
sys.path.insert(0, os.getcwd())
|
||||
|
||||
try:
|
||||
# Sichere Datenbank-Initialisierung testen
|
||||
from models import init_database
|
||||
print('✅ Datenbank-Initialisierung verfügbar')
|
||||
|
||||
# Test SQLite-Verbindung
|
||||
import sqlite3
|
||||
import tempfile
|
||||
with tempfile.NamedTemporaryFile(suffix='.db') as tmp:
|
||||
conn = sqlite3.connect(tmp.name)
|
||||
conn.execute('CREATE TABLE test (id INTEGER)')
|
||||
conn.close()
|
||||
print('✅ SQLite-Funktionalität verfügbar')
|
||||
|
||||
except Exception as e:
|
||||
print(f'⚠️ Datenbank-Test-Problem: {str(e)}')
|
||||
exit(1)
|
||||
" 2>/dev/null; then
|
||||
log "✅ Datenbank-Grundfunktionen funktionieren"
|
||||
else
|
||||
error "❌ Python-Import fehlgeschlagen"
|
||||
warning "⚠️ Datenbank-Grundfunktionen haben Probleme"
|
||||
((import_test_errors++))
|
||||
fi
|
||||
|
||||
# 4. Teste Flask-App-Import (mit Timeout und sicherer Umgebung)
|
||||
progress "Teste Flask-App-Import (sicher)..."
|
||||
|
||||
# Erstelle sichere Test-Umgebung
|
||||
export FLASK_ENV=testing
|
||||
export MYP_TESTING=1
|
||||
export PYTHONPATH="$APP_DIR:$PYTHONPATH"
|
||||
|
||||
if timeout 30 python3 -c "
|
||||
import sys
|
||||
import os
|
||||
sys.path.insert(0, os.getcwd())
|
||||
|
||||
# Setze Test-Umgebung
|
||||
os.environ['FLASK_ENV'] = 'testing'
|
||||
os.environ['MYP_TESTING'] = '1'
|
||||
|
||||
try:
|
||||
# Minimaler Import-Test
|
||||
import app
|
||||
print('✅ App-Modul erfolgreich importiert')
|
||||
|
||||
# Test ob Flask-App-Objekt verfügbar ist
|
||||
if hasattr(app, 'app'):
|
||||
print('✅ Flask-App-Objekt verfügbar')
|
||||
else:
|
||||
print('⚠️ Flask-App-Objekt nicht gefunden')
|
||||
exit(1)
|
||||
|
||||
except ImportError as ie:
|
||||
print(f'❌ Import-Fehler: {str(ie)}')
|
||||
exit(1)
|
||||
except Exception as e:
|
||||
print(f'⚠️ App-Import-Problem: {str(e)}')
|
||||
exit(1)
|
||||
" 2>/dev/null; then
|
||||
success "✅ Flask-App kann erfolgreich importiert werden"
|
||||
else
|
||||
warning "⚠️ Flask-App-Import hat Probleme - möglicherweise fehlende optionale Abhängigkeiten"
|
||||
warning " → Das ist normal für minimale Installation - App sollte trotzdem funktionieren"
|
||||
fi
|
||||
|
||||
cd "$CURRENT_DIR"
|
||||
|
||||
# 5. Zusammenfassung
|
||||
local total_errors=$((import_test_errors + structure_errors))
|
||||
|
||||
if [ $total_errors -eq 0 ]; then
|
||||
success "✅ Alle Systemtests erfolgreich - System vollständig funktionsfähig"
|
||||
elif [ $total_errors -le 2 ]; then
|
||||
warning "⚠️ $total_errors kleinere Probleme gefunden - System grundsätzlich funktionsfähig"
|
||||
info "→ Fehlende Komponenten sind meist optionale Abhängigkeiten"
|
||||
else
|
||||
error "❌ $total_errors Probleme gefunden - System möglicherweise nicht vollständig funktionsfähig"
|
||||
fi
|
||||
|
||||
success "✅ Abhängigkeiten-Installation abgeschlossen!"
|
||||
info "Das System ist bereit für manuelle Tests und Entwicklung"
|
||||
info "Hostname wurde auf 'raspberrypi' gesetzt"
|
||||
@ -1845,249 +1961,94 @@ EOF
|
||||
log " 📊 System-Limits für bessere Performance gesetzt"
|
||||
}
|
||||
|
||||
# =========================== CSS/JS OPTIMIERUNG FÜR RASPBERRY PI ===========================
|
||||
# =========================== CSS/JS OPTIMIERUNG ===========================
|
||||
optimize_static_assets() {
|
||||
log "=== RASPBERRY PI CSS/JS OPTIMIERUNG ==="
|
||||
log "=== STATISCHE DATEIEN OPTIMIERUNG ==="
|
||||
|
||||
if [ ! -d "$APP_DIR/static" ]; then
|
||||
warning "Static-Ordner nicht gefunden - überspringe Asset-Optimierung"
|
||||
return
|
||||
fi
|
||||
|
||||
progress "Validiere Raspberry Pi optimierte CSS-Dateien..."
|
||||
progress "Analysiere und optimiere CSS/JS Dateien..."
|
||||
|
||||
cd "$APP_DIR/static"
|
||||
|
||||
# Spezielle Raspberry Pi Hardware-Optimierungen
|
||||
if [ "${IS_RASPBERRY_PI:-false}" = "true" ]; then
|
||||
log "🍓 Raspberry Pi Hardware erkannt: ${PI_MODEL:-Unbekannt}"
|
||||
log "🚀 Aktiviere spezielle Performance-Optimierungen..."
|
||||
else
|
||||
info "ℹ️ Keine Raspberry Pi Hardware - verwende Standard-Optimierungen"
|
||||
fi
|
||||
# Erstelle optimierte CSS-Datei durch Kombination kritischer Styles
|
||||
progress "Erstelle optimierte CSS-Kombination..."
|
||||
|
||||
# Prüfe ob optimierte CSS-Dateien existieren
|
||||
local optimized_files=(
|
||||
"css/glassmorphism.css"
|
||||
"css/optimization-animations.css"
|
||||
"css/professional-theme.css"
|
||||
"css/caching-optimizations.css"
|
||||
)
|
||||
|
||||
local missing_files=0
|
||||
for file in "${optimized_files[@]}"; do
|
||||
if [ ! -f "$file" ]; then
|
||||
warning "Optimierte CSS-Datei fehlt: $file"
|
||||
((missing_files++))
|
||||
else
|
||||
# Prüfe ob Datei Raspberry Pi Optimierungen enthält
|
||||
if grep -q "Raspberry Pi" "$file" 2>/dev/null; then
|
||||
log "✅ Raspberry Pi optimiert: $file"
|
||||
else
|
||||
warning "⚠️ Datei nicht für Raspberry Pi optimiert: $file"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $missing_files -gt 0 ]; then
|
||||
warning "⚠️ $missing_files CSS-Dateien fehlen oder sind nicht optimiert"
|
||||
fi
|
||||
|
||||
# Erstelle kritische CSS-Datei für Above-the-fold Content
|
||||
progress "Erstelle kritische CSS-Datei für Raspberry Pi..."
|
||||
|
||||
cat > css/critical-raspberry-pi.min.css << 'EOF'
|
||||
/* Kritische Styles für Raspberry Pi - Maximale Performance */
|
||||
:root{--mb-primary:#0073ce;--mb-primary-dark:#005a9f;--light-bg-primary:#fff;--light-bg-secondary:#fafbfc;--light-surface:#fff;--light-text-primary:#111827;--light-text-secondary:#374151;--light-border:#e5e7eb;--dark-bg-primary:#0f172a;--dark-bg-secondary:#1e293b;--dark-surface:#1e293b;--dark-text-primary:#f8fafc;--dark-text-secondary:#e2e8f0;--dark-border:#334155}
|
||||
*{box-sizing:border-box;margin:0;padding:0}
|
||||
body{font-family:system-ui,-apple-system,sans-serif;line-height:1.5;background:var(--light-bg-primary);color:var(--light-text-primary)}
|
||||
.dark body{background:var(--dark-bg-primary);color:var(--dark-text-primary)}
|
||||
cat > css/critical.min.css << 'EOF'
|
||||
/* Kritische Styles für ersten Seitenaufbau - Inline-optimiert */
|
||||
*{box-sizing:border-box}body{margin:0;font-family:system-ui,-apple-system,sans-serif;line-height:1.5}
|
||||
.container{max-width:1200px;margin:0 auto;padding:0 1rem}
|
||||
.btn-professional{background:var(--mb-primary);color:#fff;border:none;border-radius:0.5rem;padding:0.75rem 1.5rem;font-weight:600;cursor:pointer}
|
||||
.btn-professional:hover{background:var(--mb-primary-dark)}
|
||||
.card-professional{background:var(--light-surface);border:1px solid var(--light-border);border-radius:0.75rem;padding:1.5rem}
|
||||
.dark .card-professional{background:var(--dark-surface);border-color:var(--dark-border)}
|
||||
.professional-container{background:var(--light-surface);border:1px solid var(--light-border);border-radius:0.75rem}
|
||||
.dark .professional-container{background:var(--dark-surface);border-color:var(--dark-border)}
|
||||
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}
|
||||
.hidden{display:none}.block{display:block}.flex{display:flex}.items-center{align-items:center}
|
||||
.btn{display:inline-flex;align-items:center;padding:0.5rem 1rem;border:none;border-radius:0.375rem;font-weight:500;text-decoration:none;cursor:pointer;transition:all 0.15s}
|
||||
.btn-primary{background:#3b82f6;color:white}.btn-primary:hover{background:#2563eb}
|
||||
.card{background:white;border-radius:0.5rem;padding:1.5rem;box-shadow:0 1px 3px rgba(0,0,0,0.1)}
|
||||
.flex{display:flex}.items-center{align-items:center}.justify-between{justify-content:space-between}
|
||||
.hidden{display:none}.block{display:block}.inline-block{display:inline-block}
|
||||
.text-sm{font-size:0.875rem}.text-lg{font-size:1.125rem}
|
||||
.font-medium{font-weight:500}.font-bold{font-weight:700}
|
||||
.text-gray-600{color:#4b5563}.text-gray-900{color:#111827}
|
||||
.mb-4{margin-bottom:1rem}.mt-6{margin-top:1.5rem}.p-4{padding:1rem}
|
||||
.w-full{width:100%}.h-full{height:100%}
|
||||
@media(max-width:768px){.container{padding:0 0.5rem}.card-professional{padding:1rem}}
|
||||
/* Nur opacity transitions für Raspberry Pi Performance */
|
||||
.animate-fade-in{animation:fadeIn 0.2s ease-out}
|
||||
@keyframes fadeIn{from{opacity:0}to{opacity:1}}
|
||||
@media(prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
@media(max-width:768px){.container{padding:0 0.5rem}.card{padding:1rem}}
|
||||
EOF
|
||||
|
||||
# Erstelle optimierten JavaScript-Loader ohne GPU-intensive Features
|
||||
progress "Erstelle Raspberry Pi optimierten JavaScript-Loader..."
|
||||
# Erstelle minimale JavaScript-Loader
|
||||
progress "Erstelle optimierten JavaScript-Loader..."
|
||||
|
||||
cat > js/raspberry-pi-loader.min.js << 'EOF'
|
||||
/*Raspberry Pi optimierter Loader - Keine GPU-intensive Features*/
|
||||
(function(){
|
||||
var d=document,w=window;
|
||||
function loadCSS(href,media){
|
||||
var l=d.createElement('link');
|
||||
l.rel='stylesheet';
|
||||
l.href=href;
|
||||
l.media=media||'all';
|
||||
d.head.appendChild(l);
|
||||
return l;
|
||||
}
|
||||
function loadJS(src,cb){
|
||||
var s=d.createElement('script');
|
||||
s.async=true;
|
||||
s.src=src;
|
||||
if(cb)s.onload=cb;
|
||||
d.head.appendChild(s);
|
||||
return s;
|
||||
}
|
||||
w.loadOptimizedAssets=function(){
|
||||
if(w.assetsLoaded)return;
|
||||
w.assetsLoaded=true;
|
||||
loadCSS('/static/css/professional-theme.css');
|
||||
loadCSS('/static/css/glassmorphism.css');
|
||||
loadCSS('/static/css/optimization-animations.css');
|
||||
loadCSS('/static/css/caching-optimizations.css');
|
||||
if(d.querySelector('#app-js')){
|
||||
loadJS('/static/js/app.min.js');
|
||||
}
|
||||
};
|
||||
if(d.readyState==='loading'){
|
||||
d.addEventListener('DOMContentLoaded',w.loadOptimizedAssets);
|
||||
}else{
|
||||
w.loadOptimizedAssets();
|
||||
}
|
||||
})();
|
||||
cat > js/loader.min.js << 'EOF'
|
||||
/*Minimaler Async Loader für bessere Performance*/
|
||||
(function(){var d=document,w=window;function loadCSS(href){var l=d.createElement('link');l.rel='stylesheet';l.href=href;l.media='print';l.onload=function(){this.media='all'};d.head.appendChild(l)}function loadJS(src,cb){var s=d.createElement('script');s.async=true;s.src=src;if(cb)s.onload=cb;d.head.appendChild(s)}w.loadAssets=function(){if(w.assetsLoaded)return;w.assetsLoaded=true;loadCSS('/static/css/tailwind.min.css');loadJS('/static/js/app.min.js')};if(d.readyState==='loading'){d.addEventListener('DOMContentLoaded',w.loadAssets)}else{w.loadAssets()}})();
|
||||
EOF
|
||||
|
||||
# Service Worker für optimiertes Caching auf Raspberry Pi
|
||||
progress "Erstelle Raspberry Pi optimierten Service Worker..."
|
||||
# Service Worker für besseres Caching
|
||||
progress "Erstelle optimierten Service Worker..."
|
||||
|
||||
cat > sw-raspberry-pi.js << 'EOF'
|
||||
const CACHE_NAME = 'myp-raspberry-pi-v1';
|
||||
const CRITICAL_ASSETS = [
|
||||
cat > sw-optimized.js << 'EOF'
|
||||
const CACHE_NAME = 'myp-webapp-v1';
|
||||
const ASSETS_TO_CACHE = [
|
||||
'/',
|
||||
'/static/css/critical-raspberry-pi.min.css',
|
||||
'/static/js/raspberry-pi-loader.min.js',
|
||||
'/static/css/professional-theme.css',
|
||||
'/static/css/glassmorphism.css',
|
||||
'/static/css/optimization-animations.css'
|
||||
'/static/css/critical.min.css',
|
||||
'/static/js/loader.min.js',
|
||||
'/static/favicon.svg'
|
||||
];
|
||||
|
||||
// Aggressive Caching für statische Assets
|
||||
self.addEventListener('install', event => {
|
||||
event.waitUntil(
|
||||
caches.open(CACHE_NAME)
|
||||
.then(cache => {
|
||||
console.log('Raspberry Pi Cache wird geladen...');
|
||||
return cache.addAll(CRITICAL_ASSETS);
|
||||
})
|
||||
.then(cache => cache.addAll(ASSETS_TO_CACHE))
|
||||
);
|
||||
self.skipWaiting();
|
||||
});
|
||||
|
||||
// Cache-First Strategie für bessere Performance auf schwacher Hardware
|
||||
self.addEventListener('fetch', event => {
|
||||
if (event.request.url.includes('/static/')) {
|
||||
if (event.request.destination === 'image' ||
|
||||
event.request.url.includes('/static/')) {
|
||||
event.respondWith(
|
||||
caches.match(event.request)
|
||||
.then(response => {
|
||||
if (response) {
|
||||
return response;
|
||||
}
|
||||
return fetch(event.request).then(fetchResponse => {
|
||||
if (fetchResponse && fetchResponse.status === 200) {
|
||||
const responseClone = fetchResponse.clone();
|
||||
caches.open(CACHE_NAME)
|
||||
.then(cache => {
|
||||
cache.put(event.request, responseClone);
|
||||
});
|
||||
}
|
||||
return fetchResponse;
|
||||
});
|
||||
})
|
||||
.then(response => response || fetch(event.request))
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Cache-Bereinigung für alte Versionen
|
||||
self.addEventListener('activate', event => {
|
||||
event.waitUntil(
|
||||
caches.keys().then(cacheNames => {
|
||||
return Promise.all(
|
||||
cacheNames.map(cacheName => {
|
||||
if (cacheName !== CACHE_NAME) {
|
||||
console.log('Entferne alte Cache-Version:', cacheName);
|
||||
return caches.delete(cacheName);
|
||||
}
|
||||
})
|
||||
);
|
||||
})
|
||||
);
|
||||
});
|
||||
EOF
|
||||
|
||||
# CSS-Minifikation für optimierte Dateien
|
||||
progress "Minifiziere CSS-Dateien für bessere Performance..."
|
||||
# Gzip-Kompression für statische Dateien
|
||||
progress "Komprimiere statische Dateien..."
|
||||
|
||||
local css_files=("professional-theme.css" "glassmorphism.css" "optimization-animations.css" "caching-optimizations.css")
|
||||
|
||||
for css_file in "${css_files[@]}"; do
|
||||
if [ -f "css/$css_file" ]; then
|
||||
# Einfache CSS-Minifikation (Entfernung von Kommentaren und unnötigen Whitespaces)
|
||||
sed 's|/\*[^*]*\*\+\([^/*][^*]*\*\+\)*/||g; s/^[[:space:]]*//g; s/[[:space:]]*$//g; /^$/d' "css/$css_file" > "css/${css_file%.css}.min.css" 2>/dev/null || true
|
||||
|
||||
if [ -f "css/${css_file%.css}.min.css" ]; then
|
||||
log "✅ Minifiziert: ${css_file%.css}.min.css"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# Gzip-Kompression für alle CSS/JS-Dateien
|
||||
progress "Komprimiere Dateien mit Gzip..."
|
||||
|
||||
find css js -name "*.css" -o -name "*.js" | while read file; do
|
||||
find . -name "*.css" -o -name "*.js" -o -name "*.html" | while read file; do
|
||||
if [ -f "$file" ] && [ ! -f "$file.gz" ]; then
|
||||
gzip -9 -c "$file" > "$file.gz" 2>/dev/null || true
|
||||
if [ -f "$file.gz" ]; then
|
||||
local original_size=$(wc -c < "$file" 2>/dev/null || echo "0")
|
||||
local compressed_size=$(wc -c < "$file.gz" 2>/dev/null || echo "0")
|
||||
if [ "$original_size" -gt 0 ] && [ "$compressed_size" -gt 0 ]; then
|
||||
local ratio=$((100 - (compressed_size * 100 / original_size)))
|
||||
log "✅ Komprimiert: $file (${ratio}% kleiner)"
|
||||
fi
|
||||
fi
|
||||
gzip -c "$file" > "$file.gz" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
|
||||
# Performance-Hints für Browser
|
||||
progress "Erstelle Performance-Hints für Raspberry Pi Browser..."
|
||||
|
||||
cat > performance-hints.txt << 'EOF'
|
||||
# Performance-Optimierungen für Raspberry Pi Browser:
|
||||
# 1. Alle backdrop-filter entfernt (GPU-intensiv)
|
||||
# 2. Transform-Animationen eliminiert (Layout-Thrashing)
|
||||
# 3. Box-shadows reduziert (Paint-Performance)
|
||||
# 4. Will-change Properties entfernt (Memory-Management)
|
||||
# 5. Gradient-Effekte vereinfacht (GPU-Berechnungen)
|
||||
# 6. Nur Opacity/Color Transitions (CSS-Performance)
|
||||
# 7. Kritische CSS inline geladen (Render-Blocking)
|
||||
# 8. Service Worker für aggressives Caching
|
||||
# 9. Gzip-Kompression für alle Assets
|
||||
# 10. Cache-First Strategie für statische Dateien
|
||||
EOF
|
||||
|
||||
cd "$CURRENT_DIR"
|
||||
|
||||
log "✅ Raspberry Pi CSS/JS-Optimierung abgeschlossen:"
|
||||
log " 🚀 Backdrop-Filter und Transform-Animationen entfernt"
|
||||
log " 📦 Kritische CSS für Above-the-fold Content erstellt"
|
||||
log " ⚡ Raspberry Pi spezifischer Asset-Loader"
|
||||
log " 🗜️ Aggressive Gzip-Kompression angewendet"
|
||||
log " 🔄 Cache-First Service Worker installiert"
|
||||
log " 📊 CSS-Minifikation für alle Dateien"
|
||||
log " 💾 Performance-optimiert für schwache Hardware"
|
||||
log "✅ Statische Dateien optimiert:"
|
||||
log " 📦 Kritische CSS-Styles kombiniert"
|
||||
log " ⚡ Asynchroner Asset-Loader erstellt"
|
||||
log " 🗜️ Gzip-Kompression angewendet"
|
||||
log " 🔄 Service Worker für Caching installiert"
|
||||
}
|
||||
|
||||
# =========================== HAUPTPROGRAMM ===========================
|
||||
|
Loading…
x
Reference in New Issue
Block a user