348 lines
6.9 KiB
Markdown
348 lines
6.9 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
docker build -t simulator:dev -f apps/simulator/Dockerfile .
|
|
```
|
|
|
|
#### Run Container
|
|
|
|
```bash
|
|
docker run --rm -p 8010:8010 \
|
|
-e MQTT_BROKER=172.16.2.16 \
|
|
-e MQTT_PORT=1883 \
|
|
-e SIM_PORT=8010 \
|
|
simulator:dev
|
|
```
|
|
|
|
#### 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
|
|
```json
|
|
{
|
|
"status": "ok",
|
|
"simulator_running": true,
|
|
"mqtt_connected": true
|
|
}
|
|
```
|
|
|
|
### `GET /status`
|
|
Vollständiger Status
|
|
```json
|
|
{
|
|
"connected": true,
|
|
"running": true,
|
|
"light_states": {...},
|
|
"thermostat_states": {...},
|
|
"broker": "172.16.2.16:1883"
|
|
}
|
|
```
|
|
|
|
### `GET /events`
|
|
Letzte Events (JSON)
|
|
```json
|
|
{
|
|
"events": [...]
|
|
}
|
|
```
|
|
|
|
### `GET /realtime`
|
|
Server-Sent Events Stream
|
|
|
|
## Event-Typen
|
|
|
|
### `simulator_connected`
|
|
Simulator hat MQTT-Verbindung hergestellt
|
|
```json
|
|
{
|
|
"type": "simulator_connected",
|
|
"broker": "172.16.2.16:1883",
|
|
"client_id": "device_simulator-abc123"
|
|
}
|
|
```
|
|
|
|
### `command_received`
|
|
SET-Command von MQTT empfangen
|
|
```json
|
|
{
|
|
"type": "command_received",
|
|
"device_id": "test_lampe_1",
|
|
"topic": "vendor/test_lampe_1/set",
|
|
"payload": {"power": "on"}
|
|
}
|
|
```
|
|
|
|
### `light_updated`
|
|
Light-State wurde aktualisiert
|
|
```json
|
|
{
|
|
"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
|
|
```json
|
|
{
|
|
"type": "thermostat_updated",
|
|
"device_id": "test_thermo_1",
|
|
"changes": {
|
|
"mode": {"old": "off", "new": "heat"}
|
|
},
|
|
"new_state": {...}
|
|
}
|
|
```
|
|
|
|
### `temperature_drift`
|
|
Temperatur-Drift simuliert (alle 5 Sekunden)
|
|
```json
|
|
{
|
|
"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
|
|
```json
|
|
{
|
|
"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
|
|
```ini
|
|
[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
|
|
```dockerfile
|
|
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
|
|
```bash
|
|
# 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
|
|
```bash
|
|
# 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
|
|
```python
|
|
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.
|