Files
home-automation/apps/simulator/README.md
2025-11-11 16:38:41 +01:00

7.0 KiB

Device Simulator Web Application

Web-basierte Anwendung zur Simulation von Home-Automation-Geräten mit Echtzeit-Monitoring.

Features

  • Web-Interface: Dashboard mit Echtzeit-Anzeige aller Events
  • Server-Sent Events (SSE): Live-Updates ohne Polling
  • Funktioniert ohne Browser: Simulator läuft im Hintergrund
  • Multi-Device Support: Lights + Thermostats
  • MQTT Integration: Vollständige Kommunikation über MQTT
  • Statistiken: Zähler für Events, Commands und States
  • Event-History: Letzte 50 Events mit Details

Geräte

Lights (3 Stück)

  • test_lampe_1 - Dimmbar
  • test_lampe_2 - Einfach
  • test_lampe_3 - Dimmbar

Thermostats (1 Stück)

  • test_thermo_1 - Auto/Heat/Off Modi, Temperatur-Drift

Installation

Der Simulator ist bereits Teil des Projekts. Keine zusätzlichen Dependencies erforderlich.

Start

Local Development

# Standard-Start (Port 8010)
poetry run uvicorn apps.simulator.main:app --host 0.0.0.0 --port 8010

# Mit Auto-Reload für Entwicklung
poetry run uvicorn apps.simulator.main:app --host 0.0.0.0 --port 8010 --reload

# Im Hintergrund
poetry run uvicorn apps.simulator.main:app --host 0.0.0.0 --port 8010 > /tmp/simulator.log 2>&1 &

Docker Container

Build Image

docker build -t simulator:dev -f apps/simulator/Dockerfile .

Run Container

docker run --rm -p 8010:8010 \
  -e MQTT_BROKER=172.23.1.102 \
  -e MQTT_PORT=1883 \
  -e SIM_PORT=8010 \
  simulator:dev

Note for finch/nerdctl users:

  • finch binds ports to 127.0.0.1 by default
  • The web interface will be accessible at http://127.0.0.1:8010

Environment Variables

Variable Default Description
MQTT_BROKER 172.16.2.16 MQTT broker hostname/IP
MQTT_PORT 1883 MQTT broker port
SIM_PORT 8010 Port for web interface

Web-Interface

Öffne im Browser:

http://localhost:8010

Features im Dashboard

  1. Status-Anzeige

    • MQTT-Verbindungsstatus
    • Anzahl aktiver Geräte
    • Simulator-Status
  2. Geräte-Übersicht

    • Echtzeit-Anzeige aller Light-States
    • Echtzeit-Anzeige aller Thermostat-States
  3. Event-Stream

    • Alle MQTT-Commands
    • Alle State-Updates
    • Temperatur-Drift-Events
    • Fehler und Warnungen
  4. Statistiken

    • Total Events
    • Commands Received
    • States Published
  5. Controls

    • Clear Events
    • Toggle Auto-Scroll

API Endpoints

GET /

Web-Dashboard (HTML)

GET /health

Health-Check

{
  "status": "ok",
  "simulator_running": true,
  "mqtt_connected": true
}

GET /status

Vollständiger Status

{
  "connected": true,
  "running": true,
  "light_states": {...},
  "thermostat_states": {...},
  "broker": "172.16.2.16:1883"
}

GET /events

Letzte Events (JSON)

{
  "events": [...]
}

GET /realtime

Server-Sent Events Stream

Event-Typen

simulator_connected

Simulator hat MQTT-Verbindung hergestellt

{
  "type": "simulator_connected",
  "broker": "172.16.2.16:1883",
  "client_id": "device_simulator-abc123"
}

command_received

SET-Command von MQTT empfangen

{
  "type": "command_received",
  "device_id": "test_lampe_1",
  "topic": "vendor/test_lampe_1/set",
  "payload": {"power": "on"}
}

light_updated

Light-State wurde aktualisiert

{
  "type": "light_updated",
  "device_id": "test_lampe_1",
  "changes": {
    "power": {"old": "off", "new": "on"}
  },
  "new_state": {"power": "on", "brightness": 50}
}

thermostat_updated

Thermostat-State wurde aktualisiert

{
  "type": "thermostat_updated",
  "device_id": "test_thermo_1",
  "changes": {
    "mode": {"old": "off", "new": "heat"}
  },
  "new_state": {...}
}

temperature_drift

Temperatur-Drift simuliert (alle 5 Sekunden)

{
  "type": "temperature_drift",
  "device_id": "test_thermo_1",
  "old_temp": 20.5,
  "new_temp": 20.7,
  "target": 21.0,
  "mode": "auto"
}

state_published

State wurde nach MQTT publiziert

{
  "type": "state_published",
  "device_id": "test_lampe_1",
  "device_type": "light",
  "topic": "vendor/test_lampe_1/state",
  "payload": {"power": "on", "brightness": 50}
}

MQTT Topics

Subscribe

  • vendor/test_lampe_1/set
  • vendor/test_lampe_2/set
  • vendor/test_lampe_3/set
  • vendor/test_thermo_1/set

Publish (retained, QoS 1)

  • vendor/test_lampe_1/state
  • vendor/test_lampe_2/state
  • vendor/test_lampe_3/state
  • vendor/test_thermo_1/state

Integration mit anderen Services

Der Simulator funktioniert nahtlos mit:

  1. Abstraction Layer (apps.abstraction.main)

    • Empfängt Commands über MQTT
    • Sendet States zurück
  2. API (apps.api.main)

    • Commands werden via API gesendet
    • Simulator reagiert automatisch
  3. UI (apps.ui.main)

    • UI zeigt Simulator-States in Echtzeit
    • Bedienung über UI beeinflusst Simulator

Deployment

Systemd Service

[Unit]
Description=Device Simulator
After=network.target

[Service]
Type=simple
User=homeautomation
WorkingDirectory=/path/to/home-automation
ExecStart=/path/to/.venv/bin/uvicorn apps.simulator.main:app --host 0.0.0.0 --port 8003
Restart=always

[Install]
WantedBy=multi-user.target

Docker

FROM python:3.14
WORKDIR /app
COPY . .
RUN pip install poetry && poetry install
EXPOSE 8003
CMD ["poetry", "run", "uvicorn", "apps.simulator.main:app", "--host", "0.0.0.0", "--port", "8003"]

Troubleshooting

Simulator startet nicht

# Check logs
tail -f /tmp/simulator.log

# Verify MQTT broker
mosquitto_sub -h 172.16.2.16 -t '#' -v

Keine Events im Dashboard

  1. Browser-Console öffnen (F12)
  2. Prüfe SSE-Verbindung
  3. Reload Seite (F5)

MQTT-Verbindung fehlgeschlagen

# Test broker connection
mosquitto_pub -h 172.16.2.16 -t test -m hello

# Check broker status
systemctl status mosquitto

Unterschied zum alten Simulator

Alt (tools/device_simulator.py)

  • Reine CLI-Anwendung
  • Logging nur in stdout
  • Keine Web-UI
  • Keine Live-Monitoring

Neu (apps/simulator/main.py)

  • FastAPI Web-Application
  • Logging + Web-Dashboard
  • SSE für Echtzeit-Updates
  • REST API für Status
  • Funktioniert auch ohne Browser
  • Statistiken und Event-History

Entwicklung

Code-Struktur

apps/simulator/
├── __init__.py
├── main.py              # FastAPI app + Simulator logic
└── templates/
    └── index.html       # Web dashboard

Logging

logger.info()   # Wird in stdout UND als Event gestreamt
add_event({})   # Wird nur als Event gestreamt

Neue Event-Typen hinzufügen

  1. Event in main.py erstellen: add_event({...})
  2. Optional: CSS-Klasse in index.html für Farbe
  3. Event wird automatisch im Dashboard angezeigt

Performance

  • Memory: ~50 MB
  • CPU: <1% idle, ~5% bei Commands
  • SSE Connections: Unbegrenzt
  • Event Queue: Max 100 Events (rolling)
  • Per-Client Queue: Unbegrenzt

License

Teil des Home-Automation Projekts.