Vielen Dank für dein Interesse, zu FPP Web Control beizutragen! Dieses Dokument erklärt, wie du zum Projekt beitragen kannst.
- Code of Conduct
- Wie kann ich beitragen?
- Entwicklungsumgebung einrichten
- Pull Request Prozess
- Coding Guidelines
- Testing
- Dokumentation
Dieses Projekt folgt dem Grundsatz: Respektvoll, konstruktiv und hilfsbereit.
- Sei respektvoll gegenüber anderen Mitwirkenden
- Konstruktive Kritik ist willkommen
- Hilf Neulingen, sich zurechtzufinden
- Keine Beleidigungen, Diskriminierung oder unangemessenes Verhalten
Wenn du einen Bug findest:
- Prüfe bestehende Issues: Vielleicht wurde der Bug schon gemeldet
- Erstelle ein neues Issue mit:
- Titel: Kurze, präzise Beschreibung
- Beschreibung: Was ist passiert? Was wurde erwartet?
- Schritte zur Reproduktion: Wie kann der Bug nachgestellt werden?
- Umgebung: FPP-Version, Browser, Betriebssystem
- Logs: Relevante Log-Ausgaben (
docker compose logs) - Screenshots: Falls relevant (UI-Bugs)
Beispiel:
### Bug: Liedwunsch-Button bleibt nach Klick deaktiviert
**Beschreibung:**
Nach dem Klick auf einen Liedwunsch-Button bleibt dieser deaktiviert,
auch wenn der Song bereits in der Queue ist.
**Schritte zur Reproduktion:**
1. Öffne die Liedwunsch-Seite
2. Klicke auf einen Song
3. Gehe zurück zur Liedwunsch-Seite
4. Der Button ist immer noch deaktiviert
**Erwartetes Verhalten:**
Button sollte wieder aktiviert werden, sobald der Song in der Queue ist.
**Umgebung:**
- FPP Web Control: v1.0.0
- FPP: 7.5
- Browser: Chrome 120 (Android)
**Logs:**[Logs hier einfügen]
Hast du eine Idee für ein neues Feature?
- Prüfe bestehende Feature Requests: Gibt es bereits einen ähnlichen Vorschlag?
- Erstelle ein Issue mit Label
enhancement - Beschreibe das Feature:
- Problem: Welches Problem löst das Feature?
- Lösung: Wie könnte die Lösung aussehen?
- Alternativen: Gibt es andere Lösungsansätze?
- Use Case: Wofür würdest du das Feature nutzen?
Beispiel:
### Feature Request: Multi-FPP-Unterstützung
**Problem:**
Aktuell kann nur ein FPP pro Instanz gesteuert werden. Bei mehreren
Lichtershows (z.B. Vorgarten + Hinterhof) müsste man mehrere Container laufen lassen.
**Lösung:**
- Dropdown in der UI zur FPP-Auswahl
- Konfiguration mehrerer FPPs in .env
- Separate Queues pro FPP
**Alternativen:**
- Mehrere Container mit verschiedenen Ports
- NGINX Reverse Proxy mit Subdomain pro FPP
**Use Case:**
Ich betreibe zwei Shows (Haupt- und Kindershow) auf separaten FPPs
und möchte beide über eine UI steuern.Dokumentation ist genauso wichtig wie Code!
- Rechtschreibfehler korrigieren
- Unklare Abschnitte verbessern
- Beispiele hinzufügen
- Screenshots aktualisieren
- Übersetzungen (aktuell nur Deutsch)
Kleine Änderungen können direkt als Pull Request eingereicht werden.
Du möchtest Code beitragen? Super!
- Fork das Repository
- Erstelle einen Feature-Branch:
git checkout -b feature/dein-feature - Implementiere deine Änderungen
- Teste deine Änderungen gründlich
- Committe deine Änderungen:
git commit -m 'Add: Dein Feature' - Push den Branch:
git push origin feature/dein-feature - Öffne einen Pull Request
- Python 3.11+ (empfohlen: 3.12)
- Git
- Docker & Docker Compose (optional, für Testing)
- Falcon Player (FPP) im Netzwerk oder Preview-Modus
-
Repository klonen:
git clone https://github.com/TimUx/fpp-web-control.git cd fpp-web-control -
Virtual Environment erstellen:
python3 -m venv venv source venv/bin/activate # Linux/Mac # oder: venv\Scripts\activate # Windows
-
Dependencies installieren:
pip install -r requirements.txt
-
Entwicklungs-.env erstellen:
cp .env.example .env
Für Entwicklung ohne FPP setze:
PREVIEW_MODE=true
-
Config generieren:
Die
config.jswird normalerweise vondocker-entrypoint.shgeneriert. Für manuelle Entwicklung hast du zwei Optionen:Option 1: Script verwenden (empfohlen)
# Führt nur die Config-Generierung aus, nicht Gunicorn bash docker-entrypoint.sh # Nach ca. 1 Sekunde sollte "config.js" erstellt sein # Dann mit STRG+C abbrechen (verhindert Gunicorn-Start) # Erwartete Ausgabe: Eine neue Datei "config.js" wurde erstellt
Option 2: Minimal-Config manuell erstellen
cat > config.js << 'EOF' window.FPP_CONFIG = { "siteName": "FPP Lichtershow", "siteSubtitle": "", "accessCode": "", "clientStatusPollMs": 10000, "previewMode": true }; EOF
Prüfen:
# Config-Datei sollte existieren und valides JSON enthalten cat config.js -
Development Server starten:
python3 app.py
Server läuft unter:
http://localhost:5000
Hot Reload: Flask Development Server hat Auto-Reload aktiviert
export FLASK_ENV=development
python3 app.pyDocker für Testing:
docker compose up --buildLogs verfolgen:
docker compose logs -f fpp-controlVerwende aussagekräftige Branch-Namen:
- Feature:
feature/multi-fpp-support - Bugfix:
fix/request-button-stuck - Dokumentation:
docs/update-faq - Refactoring:
refactor/notification-system
Commit-Nachricht-Format:
<type>: <subject>
<body>
<footer>
Types:
feat: Neues Featurefix: Bugfixdocs: Dokumentationstyle: Formatierung, fehlende Semikolons, etc.refactor: Code-Refactoring ohne Feature-/Bugfix-Änderungtest: Tests hinzufügen oder ändernchore: Build-Prozess, Dependencies, etc.
Beispiele:
feat: Add multi-FPP support
- Add FPP selection dropdown in UI
- Allow multiple FPP configurations in .env
- Separate queues per FPP instance
Closes #42
fix: Request button remains disabled after song added to queue
The button state was not properly reset after successful API call.
Added state refresh after request submission.
Fixes #38
Titel: Kurz und aussagekräftig (z.B. "Add multi-FPP support")
Beschreibung sollte enthalten:
- Was wurde geändert? Kurze Zusammenfassung
- Warum? Welches Problem wird gelöst?
- Wie? Technische Details (bei komplexen Änderungen)
- Screenshots (bei UI-Änderungen)
- Testing: Wie wurde getestet?
- Breaking Changes: Falls vorhanden, klar kennzeichnen
- Related Issues:
Closes #123oderFixes #456
Template:
## Beschreibung
[Kurze Zusammenfassung der Änderungen]
## Motivation
[Welches Problem wird gelöst? Link zu Issue]
## Änderungen
- [ ] Feature A implementiert
- [ ] Bug B gefixt
- [ ] Dokumentation aktualisiert
## Screenshots
[Falls UI-Änderungen]
## Testing
- [ ] Lokal getestet mit Python 3.12
- [ ] Docker-Build erfolgreich
- [ ] Preview-Modus getestet
- [ ] Mit echtem FPP getestet
## Breaking Changes
[Falls vorhanden, klar beschreiben]
## Checklist
- [ ] Code folgt den Coding Guidelines
- [ ] Dokumentation wurde aktualisiert
- [ ] Tests wurden geschrieben (falls zutreffend)
- [ ] Alle Tests laufen durch
- [ ] Commit-Messages sind aussagekräftig- Pull Requests werden vom Maintainer geprüft
- Feedback konstruktiv annehmen
- Änderungen nach Review einarbeiten
- Bei Unklarheiten nachfragen
Nach erfolgreichem Review wird der PR gemerged.
Style Guide: PEP 8
Wichtige Punkte:
- Indentation: 4 Spaces (keine Tabs)
- Line Length: Max. 120 Zeichen (PEP 8: 79, aber bei langen URLs etc. OK)
- Naming:
snake_casefür Funktionen, VariablenPascalCasefür KlassenUPPER_CASEfür Konstanten
- Imports: Gruppiert und alphabetisch sortiert
# Standard library import json import os import threading # Third-party import requests from flask import Flask, jsonify # Local from .utils import helper_function
Type Hints verwenden:
from typing import Dict, List, Optional
def get_songs(playlist: str) -> List[Dict[str, Any]]:
"""
Fetches songs from FPP playlist.
Args:
playlist: Name of the playlist
Returns:
List of song dictionaries
"""
...Docstrings (Google Style):
def send_notification(title: str, message: str,
action_type: str = "info") -> None:
"""
Sends notification via all configured channels.
Args:
title: Short notification title
message: Full notification message
action_type: Type of action (show_start, song_request, info)
Raises:
NotificationError: If all notification channels fail
Example:
>>> send_notification("Show started", "Main show started", "show_start")
"""
...Error Handling:
try:
response = fpp_get("/api/fppd/status")
except requests.exceptions.Timeout:
logger.error("FPP timeout")
return {"error": "timeout"}
except Exception as e:
logger.error(f"Unexpected error: {e}")
return {"error": "unknown"}Logging statt Print:
# Nicht:
print("Show started")
# Sondern:
logger.info("Show started")
logger.error(f"Failed to start show: {error}")Style Guide: Airbnb JavaScript Style Guide (locker angewandt)
Wichtige Punkte:
- Indentation: 2 Spaces
- Semikolons: Verwenden (ASI vermeiden)
- Quotes: Single quotes
'bevorzugt, außer bei JSON - Naming:
camelCasefür Variablen, FunktionenPascalCasefür Klassen (falls verwendet)UPPER_CASEfür Konstanten
Moderne Syntax:
// const/let statt var
const config = window.FPP_CONFIG || {};
let currentState = null;
// Arrow Functions
const updateStatus = (data) => {
// ...
};
// Template Literals
const message = `Next show at ${time}`;
// Destructuring
const { title, message, action_type } = payload;
// Async/Await
const fetchState = async () => {
try {
const response = await fetch('/api/state');
const data = await response.json();
updateUI(data);
} catch (error) {
console.error('Failed to fetch state:', error);
}
};HTML:
- Semantisches HTML verwenden
- ARIA-Labels für Accessibility
- Indentation: 2 Spaces
<button
class="action btn-show"
id="btn-show"
aria-label="Hauptshow starten"
>
Show starten
</button>CSS:
- BEM-ähnliche Namenskonvention (nicht strikt)
- CSS-Variablen für Theme-Werte
- Mobile-First Approach
:root {
--primary-color: #c41e3a;
--spacing-unit: 1rem;
}
.btn-show {
background-color: var(--primary-color);
padding: var(--spacing-unit);
}
@media (min-width: 768px) {
.btn-show {
padding: calc(var(--spacing-unit) * 1.5);
}
}Checklist vor Pull Request:
-
Preview-Modus: Funktioniert ohne FPP?
PREVIEW_MODE=true python3 app.py
-
Mit FPP: Alle Features testen
- Show-Start (Playlist 1 & 2)
- Liedwunsch
- Queue-Verwaltung
- Scheduled Shows
- Statistiken
-
Benachrichtigungen: (wenn geändert)
- MQTT
- ntfy.sh
- Webhooks
-
Browser-Kompatibilität:
- Chrome (Desktop + Mobile)
- Firefox
- Safari (iOS)
-
Docker-Build:
docker compose build docker compose up
Aktuell: Keine Unit-Tests (Future Work)
Geplant:
pytestfür Python Backend- Jest für JavaScript Frontend
Falls du Tests hinzufügen möchtest:
# tests/test_api.py
import pytest
from app import app
@pytest.fixture
def client():
app.config['TESTING'] = True
with app.test_client() as client:
yield client
def test_api_state(client):
response = client.get('/api/state')
assert response.status_code == 200
data = response.get_json()
assert 'queue' in dataBei Code-Änderungen immer Dokumentation prüfen:
- README.md: Features, Configuration, API
- NOTIFICATIONS.md: Benachrichtigungs-Setup
- ARCHITECTURE.md: Technische Details
- Code-Kommentare: Docstrings, Inline-Kommentare
Sprache: Deutsch (primär), Englisch für Code-Kommentare OK
Struktur:
- Klare Überschriften
- Kurze Absätze
- Code-Beispiele
- Screenshots bei UI-Änderungen
Markdown-Style:
- Überschriften:
#,##,###(nicht unterstrichen) - Code: ```python, ```bash, ```javascript
- Links:
[Text](URL) - Listen:
-für unordered,1.für ordered - Tabellen für strukturierte Daten
Beispiele bevorzugen:
Nicht:
Die Funktion send_notification sendet Benachrichtigungen.
Sondern:
# Benachrichtigung senden
send_notification(
title="Show gestartet",
message="Hauptshow wurde gestartet",
action_type="show_start"
)- GitHub Issues: Für Bugs und Feature Requests
- GitHub Discussions: Für allgemeine Fragen und Diskussionen
- Pull Requests: Direkt im PR kommentieren
Vielen Dank für deine Beiträge! 🎉