--- description: "Formale Projektrichtlinien für das Mercedes-Benz 3D-Druck-Management-System mit Fokus auf Codequalität, deutscher Dokumentation und hardwareoptimierter Implementierung" globs: ["*.py", "*.html", "*.js", "*.sql", "*.md"] alwaysApply: true --- # MYP Druckerverwaltungssystem - Cursor Rules # Mercedes-Benz 3D-Druck-Management-Platform ## 🎯 PROJEKT-KONTEXT Das MYP-System ist eine cyber-physische Lösung zur Verwaltung von 3D-Druckern mit Smart-Plug-Technologie für Mercedes-Benz. **Technischer Stack:** - Backend: Flask + SQLAlchemy + SQLite - Frontend: Jinja2-Templates + CSS/JS - Hardware: Raspberry Pi + TP-Link Tapo P110 - Deployment: Air-Gapped Production Environment ## 🔑 KERN-PRINZIPIEN ### SPRACHE & DOKUMENTATION - **Ausschließlich formales Deutsch** für alle Kommentare, Docstrings, UI-Texte und Dokumentation - **Englisch nur für**: Code-Variablen, Funktionsnamen, Git-Commits - Umfassende Docstrings nach deutschem Standard - Inline-Kommentare für komplexe Logik ### QUALITÄTS-STANDARD - **Produktionsreife** bei jedem Commit - keine experimentellen Features ohne vollständige Tests - **Zero-Downtime-Code** - jede Änderung muss sofort funktionsfähig sein - **Defense Programming** - umfassende Error-Handling und Validation - **Performance-optimiert** für Raspberry Pi Hardware-Umgebung ### CASCADE-ANALYSE PROTOKOLL Vor jeder Änderung ZWINGEND analysieren: ```python # IMPACT-ANALYSE-TEMPLATE: # 1. Betroffene Module: [Liste] # 2. API-Endpunkte: [Liste] # 3. Datenbank-Schema: [Änderungen] # 4. Frontend-Komponenten: [Liste] # 5. Hardware-Integration: [Tapo/Drucker] # 6. Session/Auth: [Auswirkungen] # 7. Background-Jobs: [Timer/Scheduler] ``` ## 📁 PROJEKTSTRUKTUR-REGELN ### CORE-DATEIEN (NIEMALS OHNE CASCADE-ANALYSE ÄNDERN) - `backend/app.py` - Flask-Haupteinstiegspunkt - `backend/models.py` - SQLAlchemy-Datenmodelle - `backend/utils/settings.py` - Zentrale Konfiguration - `backend/blueprints/` - REST-API-Endpunkte ### DATEI-ORGANISIERUNG - **Markdown-Dateien (.md)**: Automatisch in `docs/` speichern (außer README.md) - **Upload-Struktur**: Hierarchisch nach Jahr/Monat - **Logs**: Strukturiert nach Modulen in `backend/logs/` - **Backups**: Automatisch in `database/backups/` ### KEINE WINDOWS-SPEZIFISCHEN DATEIEN - Keine .bat, .ps1, .cmd Dateien - Keine Windows-Registry-Zugriffe - Linux/Unix-Shell-Scripts bevorzugen - Cross-platform Python-Lösungen ## 🏗️ BACKEND-ENTWICKLUNG (FLASK) ### BLUEPRINT-STRUKTUR ```python # Standard Blueprint-Template from flask import Blueprint, request, jsonify, session from backend.models import db, User, Printer, Job from backend.utils.permissions import require_role from backend.utils.logging_config import get_logger # Deutsche Kommentare für Business-Logic blueprint_name = Blueprint('name', __name__) logger = get_logger(__name__) @blueprint_name.route('/endpoint', methods=['POST']) @require_role('admin') # Berechtigungsprüfung def function_name(): """ Funktion-Beschreibung auf Deutsch. Returns: dict: Antwort-Struktur mit Status und Daten """ try: # Geschäftslogik mit deutschen Kommentaren pass except Exception as e: logger.error(f"Fehler in {function_name.__name__}: {str(e)}") return jsonify({'error': 'Detaillierte deutsche Fehlermeldung'}), 500 ``` ### DATENBANK-PATTERNS ```python # SQLAlchemy-Modell-Standard class ModelName(db.Model): """Deutsche Modell-Beschreibung.""" __tablename__ = 'table_name' # Felder mit deutschen Kommentaren id = db.Column(db.Integer, primary_key=True) created_at = db.Column(db.DateTime, default=datetime.utcnow) def to_dict(self): """Konvertierung zu Dictionary für JSON-Serialisierung.""" return { 'id': self.id, 'created_at': self.created_at.isoformat() if self.created_at else None } @classmethod def create_with_validation(cls, **kwargs): """Factory-Methode mit Validierung.""" # Validierungslogik pass ``` ### HARDWARE-INTEGRATION (TAPO) ```python # Tapo-Controller-Pattern from backend.utils.tapo_controller import TapoController async def control_printer_power(printer_id: int, action: str): """ Steuerung der Drucker-Stromversorgung über Smart-Plug. Args: printer_id: Eindeutige Drucker-ID action: 'on', 'off', 'status' Returns: dict: Status und Ergebnis der Operation """ try: controller = TapoController() result = await controller.execute_action(printer_id, action) # Logging für Hardware-Operationen logger.info(f"Drucker {printer_id}: {action} - Status: {result}") return {'success': True, 'data': result} except Exception as e: logger.error(f"Tapo-Steuerung fehlgeschlagen: {str(e)}") return {'success': False, 'error': str(e)} ``` ## 🎨 FRONTEND-ENTWICKLUNG (JINJA2) ### TEMPLATE-STRUKTUR ```html {% extends "base.html" %} {% set page_title = "Deutsche Seitentitel" %} {% set page_description = "Deutsche Beschreibung" %} {% block content %}

{{ page_title }}

{% with messages = get_flashed_messages(with_categories=true) %} {% if messages %} {% for category, message in messages %}
{{ message }}
{% endfor %} {% endif %} {% endwith %}
{% endblock %} {% block scripts %} {% endblock %} ``` ### CSS/STYLING-REGELN - **Mercedes-Designsprache** befolgen - **Responsive Design** für Touch-Interfaces (Kiosk-Modus) - **Accessibility** (WCAG 2.1 AA) - **Performance** für Raspberry Pi optimiert ## 🔧 UTILITY-ENTWICKLUNG ### LOGGING-STANDARD ```python from backend.utils.logging_config import get_logger logger = get_logger(__name__) def business_function(): """Deutsche Funktionsbeschreibung.""" logger.info("Vorgang gestartet: {function_name}") try: # Geschäftslogik logger.debug("Zwischenschritt erfolgreich") except ValidationError as e: logger.warning(f"Validierungsfehler: {str(e)}") raise except Exception as e: logger.error(f"Unerwarteter Fehler in {function_name}: {str(e)}") # Error-Recovery-Logik raise finally: logger.info("Vorgang abgeschlossen: {function_name}") ``` ### PERMISSION-SYSTEM ```python from functools import wraps from flask import session, abort def require_role(required_role: str): """Decorator für rollenbasierte Zugriffskontrolle.""" def decorator(f): @wraps(f) def decorated_function(*args, **kwargs): if 'user_id' not in session: abort(401) # Nicht authentifiziert user = User.query.get(session['user_id']) if not user or user.role != required_role: logger.warning(f"Unauthorisierter Zugriff: {session.get('username', 'Unknown')} -> {f.__name__}") abort(403) # Nicht autorisiert return f(*args, **kwargs) return decorated_function return decorator ``` ## 📊 DATENBANK-STANDARDS ### MIGRATION-PATTERN ```python # Sichere Schema-Änderungen def upgrade_database(): """Database-Schema-Upgrade mit Backup.""" try: # 1. Backup erstellen backup_manager.create_backup() # 2. Schema-Änderungen db.engine.execute("ALTER TABLE...") # 3. Daten-Migration migrate_existing_data() # 4. Validierung validate_schema_integrity() logger.info("Database-Upgrade erfolgreich") except Exception as e: logger.error(f"Database-Upgrade fehlgeschlagen: {str(e)}") # Rollback-Mechanismus backup_manager.restore_latest() raise ``` ### CONNECTION-MANAGEMENT ```python # SQLite-optimiert für Air-Gapped-Umgebung def get_db_connection(): """Thread-safe Database-Connection mit Connection-Pooling.""" return db.engine.connect() @contextmanager def transaction_scope(): """Transaction-Manager mit automatischem Rollback.""" connection = get_db_connection() trans = connection.begin() try: yield connection trans.commit() except Exception: trans.rollback() raise finally: connection.close() ``` ## 🚀 DEPLOYMENT & PRODUCTION ### SYSTEMD-SERVICE-PATTERN ```ini # Produktions-Service-Template [Unit] Description=MYP Druckerverwaltungssystem After=network.target [Service] Type=notify User=myp Group=myp WorkingDirectory=/opt/myp Environment=FLASK_ENV=production ExecStart=/opt/myp/venv/bin/python app.py Restart=always RestartSec=5 [Install] WantedBy=multi-user.target ``` ### KIOSK-MODUS-SETUP ```bash #!/bin/bash # Raspberry Pi Kiosk-Setup # Deutsche Kommentare für Setup-Scripts # Display-Konfiguration für Touch-Interface export DISPLAY=:0 xset s off xset -dpms xset s noblank # Browser-Start mit MYP-Interface chromium-browser \ --kiosk \ --disable-infobars \ --disable-session-crashed-bubble \ https://localhost/kiosk ``` ## 🧪 TESTING-STANDARDS ### UNIT-TEST-TEMPLATE ```python import pytest from backend.app import create_app from backend.models import db, User, Printer class TestDruckerVerwaltung: """Test-Suite für Drucker-Management-Funktionen.""" def setup_method(self): """Test-Environment-Setup.""" self.app = create_app('testing') self.client = self.app.test_client() with self.app.app_context(): db.create_all() self.create_test_data() def test_drucker_erstellen(self): """Test: Neuen Drucker erfolgreich erstellen.""" # Given: Test-Daten drucker_daten = { 'name': 'Test-Drucker-001', 'standort': 'Berlin-Marienfelde', 'tapo_ip': '192.168.1.100' } # When: API-Aufruf response = self.client.post('/api/printers', json=drucker_daten) # Then: Erfolgreiche Erstellung assert response.status_code == 201 assert 'id' in response.json def teardown_method(self): """Test-Environment-Cleanup.""" with self.app.app_context(): db.drop_all() ``` ## 🔒 SECURITY-REQUIREMENTS ### AUTHENTICATION-FLOW ```python # Sichere Session-Verwaltung @auth_bp.route('/login', methods=['POST']) def login(): """Benutzer-Authentifizierung mit Rate-Limiting.""" # Rate-Limiting für Brute-Force-Schutz if not rate_limiter.check_limit(request.remote_addr): logger.warning(f"Rate-Limit erreicht: {request.remote_addr}") return jsonify({'error': 'Zu viele Anmeldeversuche'}), 429 # Credential-Validierung username = request.json.get('username') password = request.json.get('password') user = User.authenticate(username, password) if not user: logger.warning(f"Fehlgeschlagene Anmeldung: {username}") return jsonify({'error': 'Ungültige Anmeldedaten'}), 401 # Session-Erstellung mit CSRF-Token session['user_id'] = user.id session['csrf_token'] = generate_csrf_token() logger.info(f"Erfolgreiche Anmeldung: {username}") return jsonify({'success': True, 'user': user.to_dict()}) ``` ### INPUT-VALIDATION ```python from marshmallow import Schema, fields, validate class DruckerCreateSchema(Schema): """Validierungsschema für Drucker-Erstellung.""" name = fields.Str(required=True, validate=validate.Length(min=3, max=50)) standort = fields.Str(required=True, validate=validate.Length(min=5, max=100)) tapo_ip = fields.IP(required=True) beschreibung = fields.Str(validate=validate.Length(max=500)) def validate_drucker_data(data): """Zentrale Validierung für Drucker-Daten.""" schema = DruckerCreateSchema() errors = schema.validate(data) if errors: logger.warning(f"Validierungsfehler: {errors}") raise ValidationError(errors) return schema.load(data) ``` ## ⚡ PERFORMANCE-OPTIMIERUNG ### DATABASE-QUERIES ```python # Optimierte Queries für Raspberry Pi def get_active_jobs_optimized(): """Performance-optimierte Abfrage aktiver Jobs.""" return db.session.query(Job)\ .options(joinedload(Job.printer))\ .options(joinedload(Job.user))\ .filter(Job.status.in_(['running', 'scheduled']))\ .order_by(Job.start_time.asc())\ .limit(50)\ .all() # Caching für häufige Abfragen from functools import lru_cache @lru_cache(maxsize=128) def get_drucker_statistics(drucker_id: int): """Gecachte Drucker-Statistiken.""" return db.session.query(Job)\ .filter(Job.printer_id == drucker_id)\ .filter(Job.status == 'completed')\ .count() ``` ### FRONTEND-PERFORMANCE ```javascript // Optimiertes JavaScript für Touch-Interface class MYPDashboard { constructor() { this.updateInterval = 30000; // 30 Sekunden this.maxRetries = 3; this.retryCount = 0; this.initializeEventListeners(); this.startAutoUpdate(); } async updateDashboard() { try { const response = await fetch('/api/dashboard-data'); const data = await response.json(); this.renderDashboardData(data); this.retryCount = 0; // Reset bei Erfolg } catch (error) { console.error('Dashboard-Update fehlgeschlagen:', error); this.handleUpdateError(); } } handleUpdateError() { this.retryCount++; if (this.retryCount < this.maxRetries) { // Exponential Backoff setTimeout(() => this.updateDashboard(), Math.pow(2, this.retryCount) * 1000); } else { this.showOfflineMode(); } } } ``` ## 📝 DOKUMENTATIONS-STANDARD ### FUNCTION-DOCSTRINGS ```python def schedule_print_job(drucker_id: int, start_time: datetime, duration_minutes: int, user_id: int) -> Dict[str, Any]: """ Planen eines Druckauftrags mit automatischer Smart-Plug-Steuerung. Diese Funktion erstellt einen neuen Druckauftrag und konfiguriert die automatische Ein-/Ausschaltung des zugeordneten Druckers über das Tapo-Smart-Plug-System. Args: drucker_id: Eindeutige ID des Zieldruckers start_time: Geplanter Start des Druckauftrags (UTC) duration_minutes: Geschätzte Druckdauer in Minuten user_id: ID des anfragenden Benutzers Returns: dict: Enthält Job-ID, Status und Scheduler-Informationen { 'job_id': int, 'status': str, 'scheduled_power_on': datetime, 'scheduled_power_off': datetime, 'tapo_status': str } Raises: ValidationError: Bei ungültigen Eingabedaten ConflictError: Bei Zeitkonflikten mit anderen Jobs HardwareError: Bei Tapo-Kommunikationsfehlern Example: >>> result = schedule_print_job( ... drucker_id=1, ... start_time=datetime(2025, 1, 15, 14, 0), ... duration_minutes=120, ... user_id=42 ... ) >>> print(result['job_id']) 157 """ ``` ## 🚨 ERROR-HANDLING-STANDARD ### EXCEPTION-HIERARCHY ```python # Projekt-spezifische Exception-Klassen class MYPBaseException(Exception): """Basis-Exception für MYP-System.""" def __init__(self, message: str, error_code: str = None): self.message = message self.error_code = error_code super().__init__(self.message) class HardwareError(MYPBaseException): """Fehler bei Hardware-Kommunikation (Tapo, Drucker).""" pass class SchedulingConflictError(MYPBaseException): """Zeitkonflikt bei Job-Planung.""" pass class ValidationError(MYPBaseException): """Eingabe-Validierungsfehler.""" pass # Global Error Handler @app.errorhandler(Exception) def handle_global_exception(error): """Globaler Exception-Handler mit Logging.""" logger.error(f"Unbehandelte Exception: {str(error)}", exc_info=True) if isinstance(error, MYPBaseException): return jsonify({ 'error': error.message, 'error_code': error.error_code }), 400 # Generischer Server-Fehler return jsonify({ 'error': 'Ein unerwarteter Fehler ist aufgetreten.', 'error_code': 'INTERNAL_ERROR' }), 500 ``` ## 🔄 SELF-VERIFICATION-CHECKLIST Nach jeder größeren Änderung ZWINGEND prüfen: ### ✅ FUNKTIONALE KORREKTHEIT - [ ] Alle API-Endpunkte reagieren korrekt - [ ] Datenbank-Operationen funktionieren - [ ] Frontend lädt ohne JavaScript-Fehler - [ ] Hardware-Integration (Tapo) erreichbar ### ✅ STRUKTURELLE INTEGRITÄT - [ ] Imports funktionieren in allen Modulen - [ ] Keine zirkulären Dependencies - [ ] Database-Schema konsistent - [ ] Session-Management intakt ### ✅ VOLLSTÄNDIGE DOKUMENTATION - [ ] Deutsche Docstrings für neue Funktionen - [ ] Inline-Kommentare für komplexe Logik - [ ] API-Dokumentation aktualisiert - [ ] Changelog-Einträge ### ✅ CASCADE-KONSISTENZ - [ ] Alle abhängigen Module getestet - [ ] Berechtigungen weiterhin gültig - [ ] Logging funktioniert in allen Bereichen - [ ] Error-Handling vollständig ## 🎯 ZUSÄTZLICHE REGELN ### GIT-WORKFLOW - **Commit-Messages**: Englisch, aussagekräftig - **Branch-Naming**: `feature/deutsche-beschreibung`, `bugfix/issue-nummer` - **Pull-Requests**: Mit deutscher Beschreibung und Impact-Analyse ### CODE-REVIEW-KRITERIEN - Deutsche Kommentare und Dokumentation - Performance-Impact für Raspberry Pi - Security-Implications - Hardware-Integration-Auswirkungen - Offline-Funktionalität erhalten ### EMERGENCY-PROCEDURES ```python # Notfall-Shutdown-Prozedur def emergency_shutdown(): """Kontrolliertes System-Shutdown bei kritischen Fehlern.""" logger.critical("NOTFALL-SHUTDOWN initiiert") # 1. Alle aktiven Jobs sicher beenden active_jobs = Job.query.filter(Job.status == 'running').all() for job in active_jobs: job.force_complete_with_reason("Notfall-Shutdown") # 2. Smart-Plugs ausschalten tapo_controller.emergency_power_off_all() # 3. Database-Backup erstellen backup_manager.create_emergency_backup() # 4. System-Status auf Wartung setzen system_status.set_maintenance_mode(True) logger.critical("NOTFALL-SHUTDOWN abgeschlossen") ``` --- ## 🏆 QUALITÄTSZIELE **Code-Qualität**: Produktionsreif, keine Experimente **Performance**: Optimiert für Raspberry Pi 4 **Reliability**: 99.9% Uptime in Air-Gapped-Umgebung **Security**: Keine Schwachstellen, umfassende Validierung **Maintainability**: Selbstdokumentierend, modular aufgebaut **User Experience**: Intuitive deutsche Benutzerführung --- **Version**: 1.0.0 **Gültig für**: MYP Druckerverwaltungssystem v2.0+ **Letzte Aktualisierung**: $(date +%Y-%m-%d) **Entwicklungsstandard**: IHK-Projektarbeit Mercedes-Benz