Zum Inhalt

Konfiguration - TC100 Display

Detaillierte Konfigurationsoptionen für die Display-Integration.


Übersicht

Die Display-Integration wird an drei Stellen konfiguriert:

  1. Backend .env - Aktivierung und IP-Adresse
  2. Python Config - Erweiterte Einstellungen
  3. Display WebUI - Hardware-Einstellungen

1. Backend-Konfiguration (.env)

Minimale Konfiguration

# /backend/.env

# Display aktivieren
DISPLAY_ENABLED=true

# IP-Adresse des TC100
DISPLAY_IP=192.168.178.48

Erweiterte Konfiguration

# /backend/.env

# === Display Integration ===
# Aktiviert/Deaktiviert die gesamte Display-Integration
DISPLAY_ENABLED=true

# IP-Adresse des AWTRIX3 TC100 Displays
# Format: IPv4 ohne Port
DISPLAY_IP=192.168.178.48

# Timeout für HTTP-Requests in Sekunden (optional)
# Standard: 5 Sekunden
DISPLAY_TIMEOUT=5

# Retry-Versuche bei Fehlern (optional)
# Standard: 3
DISPLAY_RETRIES=3

# Debug-Modus (optional)
# Standard: false
DISPLAY_DEBUG=false

Wichtig

  • Keine Spaces um = Zeichen
  • IP ohne http:// Präfix
  • Kein Port angeben (wird automatisch gesetzt)
  • Nach Änderungen Backend neu starten

2. Python Config (config.py)

Standard-Werte

# /backend/app/config.py

class Settings(BaseSettings):
    """Application settings"""

    # Display Integration
    display_enabled: bool = False  # Deaktiviert per Default
    display_ip: str = ""           # Leer per Default

    class Config:
        env_file = ".env"

Verwendung im Code

from app.config import get_settings

settings = get_settings()

if settings.display_enabled:
    display = DisplayService(
        display_ip=settings.display_ip,
        enabled=settings.display_enabled
    )

Best Practice

Nutzen Sie immer get_settings() statt direkten Import von settings für Testing-Kompatibilität.


3. Display WebUI Konfiguration

WebUI öffnen

# Browser öffnen mit Ihrer Display IP
open http://192.168.178.48

Wichtige Einstellungen

3.1 Matrix Settings

Brightness (Helligkeit):
  Auto:     true      # Nutzt Sensor (empfohlen)
  Day:      150       # Helligkeit tagsüber (0-255)
  Night:    30        # Helligkeit nachts (0-255)

Auto Transition:
  Enabled:  true      # Sanfte Übergänge
  Duration: 350ms     # Übergangszeit

3.2 Temperature Settings

Temperature Unit:
  Celsius: true       # Für °C (Europa)

Temperature Correction:
  Offset: 0.0         # Kalibrierung (falls nötig)

3.3 Time Settings

Time Format:
  24 Hour: true       # 24h Format

Time Zone:
  Europe/Berlin       # Für Deutschland

NTP Server:
  pool.ntp.org        # Standard (empfohlen)

3.4 Network Settings

WiFi:
  SSID:     [Ihr Netzwerk]
  Password: [Verschlüsselt]

Static IP:
  Enabled:  true      # Empfohlen für Server
  IP:       192.168.178.48
  Gateway:  192.168.178.1
  Subnet:   255.255.255.0
  DNS:      192.168.178.1

Statische IP empfohlen

Verwenden Sie eine feste IP, damit die Backend-Konfiguration nicht angepasst werden muss.


4. Display-Service Konfiguration

Standard-Verhalten

# /backend/app/services/display_service.py

class DisplayService:
    DEFAULT_DURATION = 15          # Notifications: 15 Sekunden
    DEFAULT_ICON = 4644            # Blitz-Icon
    DEFAULT_COLOR = [0, 255, 255]  # Cyan

    # Warnung-Farben nach Severity
    SEVERITY_COLORS = {
        'info':     [0, 255, 0],    # Grün
        'warning':  [255, 165, 0],  # Orange
        'critical': [255, 0, 0]     # Rot
    }

Anpassbare Funktionen

send_notification()

await display.send_notification(
    text="Custom Text",
    color=[R, G, B],           # RGB 0-255
    icon=12345,                # AWTRIX Icon ID
    duration=20,               # Sekunden (0 = unendlich)
    hold=False,                # true = bleibt stehen
    rainbow=False,             # Regenbogen-Effekt
    pushIcon=0,                # 0=static, 1=left, 2=right
    repeat=1                   # Wiederholungen
)

Parameter-Details:

Parameter Typ Standard Beschreibung
text str Pflicht Text auf Display
color list [0,255,255] RGB-Farbe
icon int 4644 AWTRIX Icon ID
duration int 15 Anzeigedauer (Sek)
hold bool False Bleibt bis Button-Druck
rainbow bool False Regenbogen-Effekt
pushIcon int 0 Icon-Animation
repeat int 1 Wiederholungen

send_warning()

await display.send_warning(
    message="Fehler aufgetreten",
    severity="critical",       # info/warning/critical
    title="System",            # Optional
    icon=None                  # Auto-select basierend auf Severity
)

Severity Auto-Konfiguration:

Severity Farbe Icon Hold Beschreibung
info 🟢 Grün 4644 False Info-Meldung
warning 🟠 Orange 29105 False Warnung
critical 🔴 Rot 29105 True Kritischer Fehler

update_solar_status()

await display.update_solar_status(
    power_w=3200,              # Aktuelle Leistung (Watt)
    daily_kwh=8.5,             # Tagesproduktion (kWh)
    online_count=2,            # Online Wechselrichter
    total_count=2,             # Gesamt Wechselrichter
    duration=0                 # 0 = permanent
)

Format: ⚡3.2kW | ☀️8.5kWh heute

set_indicator()

await display.set_indicator(
    index=1,                   # 1, 2, oder 3
    color=[0, 255, 0],         # RGB
    fade=1000,                 # Fade-Effekt (ms)
    blink=0                    # Blink-Intervall (ms)
)

Indicator-Positionen:

Display (8×32 Matrix):
┌─────────────────────────┐
│                       🟢 │ ← Indicator 1 (Oben rechts)
│                       🟢 │ ← Indicator 2 (Mitte rechts)
│                       ⚫ │ ← Indicator 3 (Unten rechts)
└─────────────────────────┘

5. Display-Bridge Konfiguration

Event-Handling

# /backend/app/services/display_bridge.py

class DisplayBridge:
    """Event-basierte Display-Integration"""

    # Inverter-Status Tracking
    _inverter_states = {}  # { inverter_id: last_status }

    async def handle_inverter_update(data: dict):
        """Wechselrichter-Status → Display"""
        # Erkennt Online/Offline Übergänge
        # Sendet kritische Warnings bei Offline

    async def handle_production_data(data: dict):
        """Solar-Produktion → Display"""
        # Updates Solar-Status
        # Setzt Indicators (grün/rot)

    async def handle_error(error: dict):
        """System-Fehler → Display"""
        # Kritische Fehler → Display

Integration in WebSocket Manager

# /backend/app/websocket/manager.py

async def broadcast_inverter_update(self, data: dict):
    """Broadcast Inverter Update"""
    # 1. An WebSocket Clients
    await self._send_message("inverter_update", data)

    # 2. An Display (optional)
    try:
        from app.services.display_bridge import handle_inverter_update
        await handle_inverter_update(data)
    except Exception as e:
        logger.warning(f"Display update failed: {e}")

Graceful Degradation

Wenn Display nicht erreichbar, läuft Backend normal weiter.


6. Icon-Konfiguration

AWTRIX Icon Datenbank

Suchen: https://developer.lametric.com/icons

Häufig verwendete Icons

# /backend/app/services/display_service.py

COMMON_ICONS = {
    'lightning':     4644,   # ⚡ Blitz (Solar)
    'sun':           1825,   # ☀️ Sonne
    'warning':       29105,  # ⚠️ Warnung
    'error':         1543,   # ❌ Fehler
    'check':         1363,   # ✅ Erfolg
    'battery':       15223,  # 🔋 Batterie
    'wifi':          1234,   # 📶 WiFi
    'temp':          2055,   # 🌡️ Temperatur
    'info':          6710,   # ℹ️ Information
}

Custom Icons hochladen

# Icon-Datei (8×8 oder 8×32 Pixel)
# Format: PNG, GIF, JPG

# WebUI öffnen
open http://192.168.178.48

# Menü → File Manager → Upload

7. Farb-Konfiguration

RGB Color Codes

COLORS = {
    # Primärfarben
    'red':       [255, 0, 0],
    'green':     [0, 255, 0],
    'blue':      [0, 0, 255],

    # Sekundärfarben
    'yellow':    [255, 255, 0],
    'cyan':      [0, 255, 255],
    'magenta':   [255, 0, 255],

    # Solar-spezifisch
    'orange':    [255, 165, 0],  # Warnung
    'purple':    [128, 0, 128],  # Nacht
    'white':     [255, 255, 255], # Tag

    # System-Status
    'ok':        [0, 255, 0],    # Grün
    'warning':   [255, 165, 0],  # Orange
    'critical':  [255, 0, 0],    # Rot
    'offline':   [128, 128, 128] # Grau
}

Helligkeit anpassen

# RGB-Werte halbieren = halbe Helligkeit
dim_red = [128, 0, 0]  # Statt [255, 0, 0]

# Funktion:
def dim_color(rgb: list, factor: float) -> list:
    """Reduziert Helligkeit um factor (0.0-1.0)"""
    return [int(c * factor) for c in rgb]

# Beispiel:
dark_green = dim_color([0, 255, 0], 0.5)  # [0, 127, 0]

8. Timing-Konfiguration

Notification Durations

DURATIONS = {
    'flash':     3,   # Kurz (Info)
    'default':   15,  # Standard
    'long':      30,  # Länger (Warnung)
    'permanent': 0    # Bis Button-Druck
}
# Sanftes Pulsieren (empfohlen)
await display.set_indicator(
    index=1,
    color=[0, 255, 0],
    fade=1000,    # 1 Sekunde Fade
    blink=0       # Kein Blink
)

# Schnelles Blinken (Alarm)
await display.set_indicator(
    index=1,
    color=[255, 0, 0],
    fade=0,       # Kein Fade
    blink=500     # 500ms Intervall
)

9. Erweiterte Features

Auto-Brightness

# Display WebUI → Settings → Matrix

Auto-Brightness:
  Enabled: true
  Sensor: LDR (Light Dependent Resistor)

Day Threshold:
  Start: 06:00
  End:   22:00

Night Threshold:
  Start: 22:00
  End:   06:00

Temperature Sensor

# Display WebUI → Settings → Temperature

Sensor: AHT20 (on-board)
Unit:   Celsius
Update: 60 seconds

Correction:
  Offset: -2.0  # Falls Display zu warm (intern)

Sound/Buzzer

# Via API: Ton abspielen
curl -X POST http://192.168.178.48/api/rtttl \
  -H "Content-Type: application/json" \
  -d '{"rtttl":"two_short:d=4,o=5,b=100:16e6,16e6"}'

Sound bei kritischen Fehlern

Kann in display_service.py bei send_warning() mit severity=critical integriert werden.


10. Performance-Tuning

Request Timeout

# /backend/app/services/display_service.py

class DisplayService:
    def __init__(self, display_ip: str, enabled: bool = True):
        self.timeout = httpx.Timeout(
            connect=2.0,   # Verbindungsaufbau
            read=5.0,      # Lese-Timeout
            write=5.0,     # Schreib-Timeout
            pool=10.0      # Connection Pool
        )

Empfehlungen:

Netzwerk Connect Read/Write Pool
LAN 2s 5s 10s
WiFi 3s 7s 15s
Unstabil 5s 10s 20s

Retry-Logik

async def _send_request(self, endpoint: str, data: dict) -> bool:
    """Send request with retry logic"""
    for attempt in range(3):  # 3 Versuche
        try:
            response = await self.client.post(
                f"http://{self.display_ip}{endpoint}",
                json=data,
                timeout=self.timeout
            )
            return response.status_code == 200
        except Exception as e:
            if attempt < 2:  # Nicht beim letzten Versuch
                await asyncio.sleep(1)  # 1 Sekunde warten
            else:
                logger.error(f"Display request failed: {e}")
    return False

11. Debugging

Backend-Logs

# Alle Display-Logs anzeigen
docker compose logs -f backend | grep -i display

# Nur Fehler
docker compose logs -f backend | grep -E "(ERROR|FAILED)" | grep -i display

# Live-Modus
docker compose logs -f backend

Display-Logs

# WebUI öffnen
open http://192.168.178.48

# Menü → Console
# Zeigt:
# - API Requests
# - Fehler
# - WiFi Status

Test-Requests

# Notification senden und Response prüfen
curl -v -X POST http://192.168.178.48/api/notify \
  -H "Content-Type: application/json" \
  -d '{"text":"Test"}'

# Erwartete Response:
# HTTP/1.1 200 OK
# {"success": true}

Python Debug-Modus

# /backend/app/services/display_service.py

import logging
logging.basicConfig(level=logging.DEBUG)

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

# Oder in .env:
# LOG_LEVEL=DEBUG

12. Backup & Restore

Display-Konfiguration sichern

# Settings exportieren
curl http://192.168.178.48/api/settings > display_backup.json

# Später wiederherstellen
curl -X POST http://192.168.178.48/api/settings \
  -H "Content-Type: application/json" \
  -d @display_backup.json

Backend-Konfiguration

# .env Backup
cp backend/.env backend/.env.backup

# Bei Problemen wiederherstellen
cp backend/.env.backup backend/.env
docker compose restart backend

Zusammenfassung

Minimale Konfiguration:

# backend/.env
DISPLAY_ENABLED=true
DISPLAY_IP=192.168.178.48

Empfohlene Konfiguration: - ✅ Statische IP am Display - ✅ Auto-Brightness aktiviert - ✅ 24h Zeit-Format - ✅ Europe/Berlin Zeitzone - ✅ Backend Timeout: 5s - ✅ Retry: 3 Versuche

Optionale Features: - 🔔 Sound/Buzzer bei Kritisch - 🌈 Rainbow-Effekte - 🎨 Custom Icons - 📊 Temperature Display


Nächste Schritte: