https://github.com/abeggled/openbridgeserver
Open Source Multiprotocol AI Server for Building Automation (KNX/Modbus/1-Wire via MQTT)
https://github.com/abeggled/openbridgeserver
1wire building-automation homeautomation homeautomationsystem knx modbus mqtt
Last synced: 5 days ago
JSON representation
Open Source Multiprotocol AI Server for Building Automation (KNX/Modbus/1-Wire via MQTT)
- Host: GitHub
- URL: https://github.com/abeggled/openbridgeserver
- Owner: abeggled
- License: mit
- Created: 2026-03-26T20:16:38.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2026-06-13T20:51:43.000Z (6 days ago)
- Last Synced: 2026-06-13T22:24:06.645Z (6 days ago)
- Topics: 1wire, building-automation, homeautomation, homeautomationsystem, knx, modbus, mqtt
- Language: Python
- Homepage: https://open-bridge.io
- Size: 9.64 MB
- Stars: 16
- Watchers: 0
- Forks: 8
- Open Issues: 75
-
Metadata Files:
- Readme: README.de.md
- Changelog: CHANGELOG.md
- License: LICENSE
- Agents: AGENTS.MD
Awesome Lists containing this project
README
# open bridge multiprotocol ai server


[![Tests][tests-badge]][tests]
[![Coverage][coverage-badge]][coverage]
> đŹđ§ [English version](/README.md)
**Offene GebĂ€udeautomations-Plattform â verbindet KNX, Modbus, MQTT, Home Assistant und mehr**
open bridge verbindet verschiedene GebĂ€udetechnik-Protokolle zu einem einheitlichen System. Alle Werte lassen sich ĂŒber eine WeboberflĂ€che ĂŒberwachen, per Logik verknĂŒpfen und ĂŒber MQTT weitergeben â ohne proprietĂ€re Konfigurationsdateien.
---
## Was kann open bridge?
| Funktion | Beschreibung |
|---|---|
| **Protokolle** | KNX/IP (Tunneling + Routing + KNX IP Secure), Modbus TCP, Modbus RTU, 1-Wire, externes MQTT, Home Assistant, ioBroker, SNMP, Anwesenheitssimulation, Zeitschaltuhr |
| **Mehrere Instanzen** | Beliebig viele Instanzen pro Protokoll (z. B. 2Ă KNX, 3Ă Modbus TCP) |
| **Protokoll-BrĂŒcke** | Ein KNX-Wert wird automatisch in ein Modbus-Register geschrieben â und umgekehrt |
| **Logik-Editor** | Visuelle Automatisierungslogik ohne Programmierung: 35+ Blocktypen, ZeitplÀne, Formeln, Python-Skripte, Benachrichtigungen, HTTP-Anfragen, Sonnenstand |
| **MQTT** | Stabiler UUID-Topic + lesbarer Alias-Topic; Retain-UnterstĂŒtzung |
| **WeboberflĂ€che** | VollstĂ€ndige Bedienung ĂŒber den Browser â kein separates Programm nötig |
| **Datenbank** | SQLite â keine externe Datenbank erforderlich |
| **Verlauf** | Werteverlauf mit Diagramm, Aggregation nach Zeit (Std / Tag / Woche âŠ); pro Datenpunkt konfigurierbar |
| **Ănderungsprotokoll** | Letzten N WertĂ€nderungen einsehbar (RingBuffer) â aktualisiert sich live |
| **Alles sofort** | Ănderungen greifen ohne Neustart |
| **Installation** | Docker Compose, direkt als Python-Programm oder als Proxmox LXC-Template |
| **Lizenz** | MIT (kostenlos und quelloffen) |
---
## Inhaltsverzeichnis
1. [Schnellstart â Proxmox LXC](#schnellstart--proxmox-lxc)
2. [Konfiguration](#konfiguration)
3. [Wie funktioniert open bridge?](#wie-funktioniert-open-bridge)
4. [Datenpunkte](#datenpunkte)
5. [VerknĂŒpfungen (Bindings)](#verknĂŒpfungen-bindings)
6. [Suche](#suche)
7. [Adapter](#adapter)
8. [Verlauf (History)](#verlauf-history)
9. [Ănderungsprotokoll (RingBuffer)](#Ă€nderungsprotokoll-ringbuffer)
10. [Sicherung & Wiederherstellung](#sicherung--wiederherstellung)
11. [Systemstatus](#systemstatus)
12. [Log-Viewer](#log-viewer)
13. [Live-Verbindung (WebSocket)](#live-verbindung-websocket)
14. [Logik-Editor](#logik-editor)
15. [Adapter-Konfiguration](#adapter-konfiguration)
16. [MQTT-Topics](#mqtt-topics)
17. [Datentypen](#datentypen)
18. [Einstellungen](#einstellungen)
19. [Hilfsskripte](#hilfsskripte)
20. [Visualisierung (Visu)](#visualisierung-visu)
- [Grundriss- und Anlagenschema-Widget](#grundriss--und-anlagenschema-widget)
21. [Entwicklung](#entwicklung)
- [Lokale Entwicklung mit PyCharm](#lokale-entwicklung-mit-pycharm)
- [Lokale Git-Hooks (Pre-Push Gate)](#lokale-git-hooks-pre-push-gate)
---
## Schnellstart â Proxmox LXC
Das LXC-Template enthÀlt ein vollstÀndiges Ubuntu 26.04-System mit **open bridge server** und startet den Dienst automatisch beim Hochfahren des Containers.
**Schritt 1 â Template herunterladen**
1. Auf der [Release-Seite](../../releases/latest) die URL der `.tar.zst`-Datei sowie den SHA512-Hash aus dem Abschnitt **LXC Template** kopieren.
2. In der Proxmox-WeboberflĂ€che zu **Datacenter â Storage â local â CT Templates** navigieren.
3. **Download from URL** klicken.
4. Die kopierte URL einfĂŒgen und auf **Query URL** klicken.
5. Als Hash-Algorithmus **SHA512** auswÀhlen.
6. Den kopierten Hash einfĂŒgen.
7. Auf **Download** klicken.

**Schritt 2 â Container erstellen**
1. Im Proxmox-MenĂŒ **Create CT** wĂ€hlen.
2. Als Template das gerade heruntergeladene `openbridgeserver-lxc_âŠ` auswĂ€hlen.
3. Hostname, Passwort, CPU, RAM und Netzwerk nach Bedarf konfigurieren â empfohlen: mindestens 512 MB RAM.
4. Container starten.
**Schritt 3 â Zugriff**
| Dienst | Adresse |
|---|---|
| **open bridge server** WeboberflÀche + API | `http://:8080` |
**Standardzugang:** Benutzername `admin`, Passwort `admin`
â ïž Das Passwort sofort nach der ersten Anmeldung Ă€ndern (Einstellungen â Passwort).
**Sicherheitskonfiguration** (erforderlich):
```bash
# Umgebungsvariablen in /etc/obs.env setzen, z. B.:
OBS_MQTT__HOST=192.168.1.10
# Wird im LXC-Template automatisch beim ersten Start gesetzt (zufÀllig, pro Container).
# Nur bei manuellem Override setzen:
OBS_SECURITY__JWT_SECRET=
# Dienst neu starten
systemctl restart obs
```
---
## Konfiguration
Die Konfiguration wird in dieser Reihenfolge geladen (höher = Vorrang):
1. Umgebungsvariablen (`OBS___`)
2. `config.yaml` (Pfad ĂŒber `OBS_CONFIG`, Standard: `./config.yaml`)
3. Eingebaute Standardwerte
```yaml
server:
host: 0.0.0.0 # Netzwerkschnittstelle
port: 8080 # Port der WeboberflÀche
log_level: INFO # Protokollstufe: DEBUG|INFO|WARNING|ERROR
mqtt:
host: localhost # Interner Mosquitto-Broker
port: 1883
username: null # Zugangsdaten fĂŒr internen Broker
password: null
database:
path: /data/obs.db # Datenbankdatei
ringbuffer:
storage: file # Ănderungsprotokoll: file-only (Datei)
max_entries: 10000 # Maximale Anzahl EintrÀge
max_file_size_bytes: null # Optional: harte Dateigrenze fĂŒr den Ringbuffer
max_age: null # Optional: maximale Eintrags-Alterung in Sekunden
security:
jwt_secret: changeme # SitzungsschlĂŒssel â unbedingt Ă€ndern!
jwt_expire_minutes: 1440 # Sitzungsdauer (Standard: 24 Stunden)
# Optionaler Override fĂŒr die Allowlist privater/interner URL-Ziele.
# Standard: OBS_SECRET_FILE_DIR/url-target-allowlist.yaml, wenn OBS_SECRET_FILE_DIR gesetzt ist,
# sonst secrets/url-target-allowlist.yaml neben der konfigurierten Datenbank.
# url_target_allowlist_path: /data/secrets/url-target-allowlist.yaml
```
> **Hinweis:** Der `mqtt`-Abschnitt betrifft den **internen** Mosquitto-Broker. Externe MQTT-Broker werden als separate Adapter-Instanzen eingerichtet (siehe [MQTT-Adapter](#mqtt-adapter-externer-broker)).
### URL-Ziel-Allowlist fĂŒr interne Dienste
Backend-Abrufe aus Logik-API-Client-Knoten, iCalendar-Knoten, Pushover-`image_url`-AnhĂ€ngen, dem Kamera-Proxy und der Wetter-API blockieren private/lokale Netzwerkziele standardmĂ€Ăig. Admins können bewusst benötigte interne Ziele unter **Einstellungen â Sicherheit â URL-Ziel-Allowlist** freigeben oder die YAML-Datei bearbeiten, die ĂŒber `security.url_target_allowlist_path` konfiguriert ist.
StandardmĂ€Ăig wird die YAML-Datei nach `OBS_SECRET_FILE_DIR/url-target-allowlist.yaml` geschrieben, wenn `OBS_SECRET_FILE_DIR` gesetzt ist. Sonst schreibt OBS nach `secrets/url-target-allowlist.yaml` neben der konfigurierten Datenbankdatei. FĂŒr private Ziele sollte eine IP-Adresse oder ein CIDR-Eintrag verwendet werden, zum Beispiel `192.168.1.23/32` fĂŒr eine einzelne LAN-Kamera oder `10.38.113.0/24` fĂŒr ein internes Netz.
Wenn ein Hostname wie `internal.example` auf eine private IP-Adresse auflöst, muss die aufgelöste IP beziehungsweise das passende CIDR-Netz freigegeben werden. Ein reiner Hostname-Eintrag hebt die private-IP-Sperre nicht auf und umgeht keine DNS-Validierung.
---
## Wie funktioniert open bridge?
```
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â open bridge server â
â â
â âââââââââââââââââââââââ WertĂ€nderung âââââââââââââââââââ â
â â Adapter-Instanzen â ââââââââââââââ¶ â Ereignisbus â â
â â â âââ schreiben â (verteilt an â â
â â KNX, Modbus, â â alle Abnehmer) â â
â â MQTT, 1-Wire ⊠â ââââŹâââââââŹââââââââ â
â âââââââââââââââââââââââ â â â
â ââââââââŒââ ââââŒâââââââ â
â â Werte- â â Verlauf â â
â â Abbild â â RingBuf â â
â â â â MQTT â â
â ââââââââââ â WS â â
â âââââââââââ â
â â
â âââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â Logik-Editor â â
â â WertĂ€nderung â Graph ausfĂŒhren â DataPoint schreiben â â
â âââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â
â âââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â REST-API + WebSocket â â
â âââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
```
**Kernprinzipien:**
- **Adapter** lesen Werte aus dem GebĂ€ude (KNX-Telegramm, Modbus-Register, MQTT-Nachricht, âŠ) und melden sie an den Ereignisbus.
- Der **Ereignisbus** verteilt jeden Wert gleichzeitig an: Werteabbild (aktueller Stand), Verlauf, Ănderungsprotokoll, MQTT-Broker, WebSocket-Clients und den Logik-Editor.
- Der **Logik-Editor** reagiert auf WertĂ€nderungen, fĂŒhrt Automatisierungslogiken aus und schreibt Ergebnisse zurĂŒck in DataPoints.
- **Protokoll-BrĂŒcke:** Wenn ein Wert ĂŒber ein Protokoll empfangen wird, schreibt **open bridge server** ihn automatisch ĂŒber alle anderen verknĂŒpften Protokolle weiter â ohne zusĂ€tzliche Konfiguration.
---
## Datenpunkte
Ein Datenpunkt ist das zentrale Objekt in **open bridge server**. Jeder physische oder virtuelle Wert im System â eine Temperatur, ein Schaltzustand, ein EnergiezĂ€hler â ist ein Datenpunkt.
```
GET /api/v1/datapoints?page=0&size=50 # Liste (seitenweise)
POST /api/v1/datapoints # Neu anlegen
GET /api/v1/datapoints/{id} # Einzelnen laden (inkl. aktueller Wert)
PATCH /api/v1/datapoints/{id} # Ăndern
DELETE /api/v1/datapoints/{id} # Löschen (entfernt auch alle VerknĂŒpfungen)
GET /api/v1/datapoints/{id}/value # Nur den aktuellen Wert
```
**Felder:**
| Feld | Beschreibung |
|---|---|
| `name` | Lesbarer Name, z. B. âWohnzimmer Temperatur" |
| `data_type` | Datentyp: `BOOLEAN`, `INTEGER`, `FLOAT`, `STRING`, `DATE`, `TIME`, `DATETIME` |
| `unit` | Einheit, z. B. `°C`, `%rH`, `kWh`, `lx`, `mm/h`, `nSv/h` |
| `tags` | Schlagwörter zum Gruppieren und Filtern |
| `persist_value` | Letzten Wert beim Neustart wiederherstellen (Standard: `true`) |
| `record_history` | Werteverlauf in der Datenbank speichern (Standard: `true`). Auf `false` setzen um einen Datenpunkt von der History auszuschliessen. |
| `mqtt_topic` | Automatisch vergeben: `dp/{uuid}/value` |
| `mqtt_alias` | Lesbares Alias-Topic, z. B. `alias/klima/wohnzimmer/value` |
```bash
# Temperatur-Datenpunkt anlegen
curl -X POST http://localhost:8080/api/v1/datapoints \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"name": "Wohnzimmer Temperatur",
"data_type": "FLOAT",
"unit": "°C",
"tags": ["klima", "wohnzimmer"]
}'
```
---
## VerknĂŒpfungen (Bindings)
Eine VerknĂŒpfung verbindet einen Datenpunkt mit einer Adapter-Instanz und einer Adresse (z. B. KNX-Gruppenadresse oder Modbus-Register).
```
GET /api/v1/datapoints/{id}/bindings
POST /api/v1/datapoints/{id}/bindings
PATCH /api/v1/datapoints/{id}/bindings/{binding_id}
DELETE /api/v1/datapoints/{id}/bindings/{binding_id}
```
**Richtungen:**
| Richtung | Bedeutung |
|---|---|
| `SOURCE` | Lesen: Adapter empfÀngt Werte und leitet sie an **open bridge server** weiter |
| `DEST` | Schreiben: **open bridge server** sendet Werte an den Adapter |
| `BOTH` | Beides gleichzeitig |
**Wert-Transformation (`value_formula`):**
Optional: eine Formel, die auf den Wert angewendet wird, bevor er ins System eingeht (SOURCE) oder herausgeht (DEST). Die Variable ist immer `x`.
```json
{ "value_formula": "x / 10" }
```
| Formel | Wirkung |
|---|---|
| `x * 3600` | Stunden â Sekunden |
| `x / 10` | Festkomma durch 10 |
| `round(x, 2)` | Auf 2 Dezimalstellen runden |
| `max(0, min(100, x))` | Auf 0â100 begrenzen |
VerfĂŒgbare Funktionen: `abs`, `round`, `min`, `max` und alle `math.*`-Funktionen. Division durch null und ungĂŒltige Ergebnisse werden abgefangen â der ursprĂŒngliche Wert bleibt erhalten.
> **Hinweis:** `round()` verwendet mathematisches Runden (0.5 â aufrunden), nicht das in der Programmierung ĂŒbliche âBankers Rounding".
**Wert-Zuordnung (`value_map`):**
Optional: eine Tabelle, die Rohwerte auf andere Werte abbildet â nĂŒtzlich z. B. bei Enumerationen oder Zustandstexten.
```json
{ "value_map": { "0": "Aus", "1": "Ein", "2": "Standby" } }
```
Der SchlĂŒssel ist immer ein String (der Rohwert wird intern umgewandelt). Gibt es keinen passenden Eintrag, wird der Originalwert unverĂ€ndert weitergegeben. `value_map` wird nach `value_formula` angewendet.
**Sendefilter** (nur fĂŒr DEST/BOTH, werden der Reihe nach geprĂŒft):
| Filter | Beschreibung |
|---|---|
| `send_throttle_ms` | Mindestabstand zwischen zwei SchreibvorgÀngen in Millisekunden |
| `send_on_change` | Nur senden wenn der Wert sich geÀndert hat |
| `send_min_delta` | Nur senden wenn die Abweichung zum letzten Wert mindestens so gross ist (absolut) |
| `send_min_delta_pct` | Nur senden wenn die Abweichung mindestens so gross ist (prozentual) |
**Beispiel: KNX-Temperatur â Modbus-Register**
```bash
# 1. Datenpunkt anlegen
DP_ID=$(curl -s -X POST http://localhost:8080/api/v1/datapoints \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{"name":"Wohnzimmer Temperatur","data_type":"FLOAT","unit":"°C"}' \
| jq -r .id)
# 2. KNX-VerknĂŒpfung (Lesen von GA 1/2/3)
curl -X POST http://localhost:8080/api/v1/datapoints/$DP_ID/bindings \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{"adapter_instance_id": "KNX-UUID", "direction": "SOURCE",
"config": {"group_address": "1/2/3", "dpt_id": "DPT9.001"}}'
# 3. Modbus-VerknĂŒpfung (Schreiben in Register 100)
curl -X POST http://localhost:8080/api/v1/datapoints/$DP_ID/bindings \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{"adapter_instance_id": "MODBUS-UUID", "direction": "DEST",
"config": {"unit_id": 1, "register_type": "holding", "address": 100, "data_format": "float32"}}'
```
---
## Suche
ServergestĂŒtzte Suche ĂŒber alle Datenpunkte. Gibt nie den gesamten Datenbestand zurĂŒck.
```
GET /api/v1/search?q=&tag=&type=&adapter=&page=0&size=50
```
| Parameter | Beschreibung |
|---|---|
| `q` | Suche im Namen |
| `tag` | Nach Schlagwort filtern |
| `type` | Nach Datentyp filtern (z. B. `FLOAT`) |
| `adapter` | Nach Protokoll filtern (z. B. `KNX`) |
---
## Adapter
Jeder Adapter-Typ kann in mehreren unabhĂ€ngigen Instanzen betrieben werden. Alle Instanzen werden ĂŒber die WeboberflĂ€che oder die API verwaltet.
Die **Adapter-Konfiguration erfolgt vollstĂ€ndig ĂŒber die WeboberflĂ€che** â alle Felder werden aus dem JSON-Schema des jeweiligen Adapters dynamisch gerendert. Passwort-Felder erscheinen maskiert. Ănderungen greifen sofort ohne Neustart.
```
GET /api/v1/adapters/instances # Alle Instanzen mit Status
POST /api/v1/adapters/instances # Neue Instanz anlegen
PATCH /api/v1/adapters/instances/{id} # Konfiguration Àndern + neu verbinden
DELETE /api/v1/adapters/instances/{id} # Stoppen + löschen
POST /api/v1/adapters/instances/{id}/restart # Neu verbinden
POST /api/v1/adapters/instances/{id}/test # Verbindung testen
GET /api/v1/adapters/{type}/schema # JSON-Schema der Instanz-Konfiguration
GET /api/v1/adapters/{type}/binding-schema # JSON-Schema der VerknĂŒpfungs-Konfiguration
```
### Anmeldung und Zugangsverwaltung
**open bridge server** unterstĂŒtzt zwei Anmeldemethoden:
| Methode | Verwendung |
|---|---|
| Benutzername + Passwort â JWT-Token | WeboberflĂ€che, Browser |
| API-SchlĂŒssel (`X-API-Key: obs_âŠ`) | Skripte, Automatisierungen |
```
POST /api/v1/auth/login # Anmelden â Token erhalten
POST /api/v1/auth/refresh # Token erneuern
GET /api/v1/auth/users # Alle Benutzer (nur Admin)
POST /api/v1/auth/users # Benutzer anlegen (nur Admin)
DELETE /api/v1/auth/users/{username} # Benutzer löschen (nur Admin)
POST /api/v1/auth/me/change-password # Eigenes Passwort Àndern
POST /api/v1/auth/apikeys # API-SchlĂŒssel anlegen
DELETE /api/v1/auth/apikeys/{id} # API-SchlĂŒssel widerrufen
POST /api/v1/auth/users/{username}/mqtt-password # MQTT-Zugang einrichten
DELETE /api/v1/auth/users/{username}/mqtt-password # MQTT-Zugang entziehen
```
**MQTT-Zugang:** Der interne Mosquitto-Broker ist passwortgeschĂŒtzt. Jeder Benutzer kann einen separaten MQTT-Zugang (unabhĂ€ngig vom Anmeldepasswort) erhalten, um sich direkt mit dem Broker zu verbinden.
---
## Verlauf (History)
Werteverlauf eines Datenpunkts â roh oder als Zusammenfassung.
```
GET /api/v1/history/{id}?from=&to=&limit=
GET /api/v1/history/{id}/aggregate?fn=avg&interval=1h&from=&to=
```
**Zusammenfassungsfunktionen:** `avg` (Durchschnitt), `min`, `max`, `last`
**Zeitintervalle:** `1m`, `5m`, `15m`, `30m`, `1h`, `6h`, `12h`, `1d`
Alle Zeitangaben richten sich nach der in den Einstellungen konfigurierten Zeitzone.
**Aufzeichnung steuern:** Das Feld `record_history` am Datenpunkt kontrolliert, ob Werte in den Verlauf geschrieben werden. Datenpunkte mit `record_history: false` werden vom History-Modul ignoriert. Die Verwaltung erfolgt unter Einstellungen â Verlauf.
---
## Ănderungsprotokoll (RingBuffer)
Der RingBuffer speichert die letzten N WertĂ€nderungen als Protokoll. In der WeboberflĂ€che aktualisiert sich die Liste **sofort** (ohne Neuladen), da neue EintrĂ€ge live ĂŒber die WebSocket-Verbindung ĂŒbertragen werden.
```
GET /api/v1/ringbuffer?q=&adapter=&from=&limit= # EintrÀge abfragen
POST /api/v1/ringbuffer/query # v2 Query-DSL (Filtergruppen + Pagination + Sortierung)
POST /api/v1/ringbuffer/export/csv # CSV-Export der vollstÀndigen gefilterten Ergebnismenge
GET /api/v1/ringbuffer/stats # Anzahl EintrÀge, KapazitÀt
POST /api/v1/ringbuffer/config # file-only + KapazitÀt Àndern
```
Der Parameter `q` durchsucht sowohl den Namen als auch die ID des Datenpunkts.
`POST /api/v1/ringbuffer/query` verwendet eine Filter-DSL mit klarer Semantik:
- `filters.adapters.any_of`: OR innerhalb der Adapterliste.
- `filters.values`: typbewusste Wertfilter (`eq/ne/gt/gte/lt/lte/between/contains/regex`) passend zu `data_type`.
- `filters.metadata`: filterbare Snapshot-Metadaten aus DataPoint/Binding-Kontext (`tags`, `adapter_types`, `group_addresses`, `topics`, `entity_ids`, `register_types`, `register_addresses`).
- Filtergruppen (`time`, `adapters`, `datapoints`, `values`, `metadata`, `q`) werden per AND kombiniert.
- Zeitfilter unterstĂŒtzen offene RĂ€nder (`from` ohne `to`, `to` ohne `from`) und die Kombination aus absoluten Grenzen (`from`/`to`) plus relativen Offsets (`from_relative_seconds`/`to_relative_seconds`).
- Pagination ĂŒber `pagination.limit` + `pagination.offset`, Sortierung ĂŒber `sort.field` (`id|ts`) und `sort.order` (`asc|desc`).
- Das versionierte Metadatenmodell ist dokumentiert in `docs/ringbuffer-metadata-model-v1.md` (`metadata_version: 1`).
`POST /api/v1/ringbuffer/export/csv` nutzt denselben Request-Body wie `/query`, exportiert aber immer die vollstÀndige gefilterte Ergebnismenge (Pagination der UI wird ignoriert).
CSV-Spalten: `id`, `ts`, `datapoint_id`, `name`, `topic`, `old_value_json`, `new_value_json`, `source_adapter`, `quality`, `metadata_version`, `metadata_json`.
---
## Sicherung & Wiederherstellung
VollstÀndige Konfigurationssicherung und -wiederherstellung. Bestehende EintrÀge werden aktualisiert, fehlende neu angelegt.
```
GET /api/v1/config/export # Sicherungsdatei herunterladen (JSON)
POST /api/v1/config/import # Sicherungsdatei einspielen
```
Die Sicherung enthĂ€lt: alle Datenpunkte, VerknĂŒpfungen, Adapter-Instanzen und KNX-Gruppenadressen.
**KNX-Projektdatei importieren:**
```
POST /api/v1/knxproj/import # .knxproj-Datei hochladen (multipart/form-data)
GET /api/v1/knxproj/ga # Importierte Gruppenadressen anzeigen
DELETE /api/v1/knxproj/ga # Alle importierten Adressen löschen
```
Nach dem Import erscheinen die Gruppenadressen als SuchvorschlĂ€ge im VerknĂŒpfungs-Formular.
---
## Systemstatus
```
GET /api/v1/system/health # Erreichbarkeit prĂŒfen (kein Login nötig)
GET /api/v1/system/adapters # Adapter-Status + Anzahl VerknĂŒpfungen
GET /api/v1/system/datatypes # Alle verfĂŒgbaren Datentypen
GET /api/v1/system/settings # Systemeinstellungen lesen (z. B. Zeitzone)
PUT /api/v1/system/settings # Systemeinstellungen Àndern
GET /api/v1/adapters/knx/dpts # Alle registrierten KNX-DPT-Typen auflisten
```
---
## Log-Viewer
Der Log-Viewer zeigt aktuelle Anwendungsmeldungen in Echtzeit. Die Admin-GUI zeigt die letzten 500 EintrÀge und streamt neue EintrÀge live via WebSocket.
```
GET /api/v1/system/logs?limit=N # Aktuelle Log-EintrÀge (neueste zuerst, max. 500)
GET /api/v1/system/log-level # Aktuellen Log-Level lesen (nur Admin)
PUT /api/v1/system/log-level # Log-Level zur Laufzeit Àndern (nur Admin)
```
Log-EintrÀge enthalten folgende Felder:
| Feld | Beschreibung |
|---|---|
| `ts` | Zeitstempel (ISO 8601, UTC) |
| `level` | Log-Level: `DEBUG`, `INFO`, `WARNING`, `ERROR` |
| `logger` | Logger-Name (Modulpfad) |
| `message` | Log-Meldung |
Der Log-Level kann ohne Neustart zur Laufzeit geÀndert werden (nur Admin). Der Puffer hÀlt die letzten 500 EintrÀge und wird beim Neustart nicht gespeichert.
---
## Live-Verbindung (WebSocket)
Ăber die WebSocket-Verbindung werden WertĂ€nderungen und neue RingBuffer-EintrĂ€ge sofort an alle verbundenen Browser ĂŒbertragen â kein manuelles Neuladen nötig.
```
WS /api/v1/ws?token={jwt}
```
**Datenpunkt abonnieren:**
```json
{"action": "subscribe", "datapoint_ids": ["uuid-1", "uuid-2"]}
```
**Eingehende WertÀnderung:**
```json
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"v": 21.4,
"u": "°C",
"t": "2026-03-27T10:23:41.123Z",
"q": "good"
}
```
**Neuer RingBuffer-Eintrag** (an alle Verbindungen, ohne Abo):
```json
{
"action": "ringbuffer_entry",
"entry": {
"ts": "2026-03-27T10:23:41.123Z",
"datapoint_id": "550e8400-...",
"name": "Wohnzimmer Temperatur",
"new_value": 21.4,
"old_value": 21.1,
"quality": "good",
"source_adapter": "KNX"
}
}
```
**DatenqualitÀt (`q`):**
| Wert | Bedeutung |
|---|---|
| `good` | Wert erfolgreich empfangen, Verbindung aktiv |
| `bad` | Adapter getrennt oder Lesefehler |
| `uncertain` | Verbindung wird wiederhergestellt oder Wert möglicherweise veraltet |
---
## Logik-Editor
### Ăbersicht
Der Logik-Editor ermöglicht das visuelle Erstellen von Automatisierungsregeln â ohne Programmierkenntnisse. Blöcke werden per Drag & Drop auf einer ArbeitsflĂ€che platziert und mit Verbindungslinien verknĂŒpft.
**Ablauf:**
1. Ein **DP Lesen**-Block beobachtet einen Datenpunkt.
2. Ăndert sich der Wert, fĂŒhrt **open bridge server** den gesamten Graphen aus.
3. Die Blöcke werden der Reihe nach berechnet.
4. Ein **DP Schreiben**-Block schreibt das Ergebnis zurĂŒck â das löst automatisch alle Adapter, MQTT, den Verlauf und den RingBuffer aus.
5. Der **Trigger**-Block löst den Graphen nach einem Zeitplan aus (z. B. tÀglich um 07:00 Uhr).
Der Graph kann auch manuell ĂŒber den **â¶ AusfĂŒhren**-Button gestartet werden.
**ZustĂ€nde** (Hysterese, Statistik, Betriebsstunden, Min/Max-Tracker, VerbrauchszĂ€hler) werden in der Datenbank gespeichert und ĂŒberleben einen Neustart.
---
### Blocktypen
#### Konstante
| Block | AusgÀnge | Beschreibung |
|---|---|---|
| **Festwert** | Wert | Gibt einen festen Wert aus â Zahl, Ein/Aus oder Text. |
#### Logik
| Block | EingÀnge | AusgÀnge | Beschreibung |
|---|---|---|---|
| **UND** | A, B | Aus | Wahr wenn **alle** EingÀnge wahr sind. |
| **ODER** | A, B | Aus | Wahr wenn **mindestens ein** Eingang wahr ist. |
| **NICHT** | Ein | Aus | Kehrt den Eingang um. |
| **EXKLUSIV-ODER** | A, B | Aus | Wahr wenn **genau ein** Eingang wahr ist. |
| **Vergleich** | A, B | Ergebnis | Vergleicht zwei Werte. Auswahl: `>` `<` `=` `>=` `<=` `â ` |
| **Hysterese** | Wert | Aus | Schaltet ein wenn der Wert ĂŒber âSchwelle EIN" steigt, und erst wieder aus wenn er unter âSchwelle AUS" fĂ€llt. Verhindert schnelles Hin- und Herschalten. |
#### Datenpunkt
| Block | EingÀnge | AusgÀnge | Beschreibung |
|---|---|---|---|
| **DP Lesen** | â | Wert, GeĂ€ndert | Liest einen Datenpunkt. Löst den Graphen bei WertĂ€nderung automatisch aus. Optionale Filter (Mindestabstand, MindestĂ€nderung) und Wert-Transformation. |
| **DP Schreiben** | Wert, Trigger | â | Schreibt einen Wert in einen Datenpunkt. Optionaler Trigger-Eingang: nur schreiben wenn Trigger wahr. Optionale Filter und Wert-Transformation. |
#### Mathematik
| Block | EingÀnge | AusgÀnge | Beschreibung |
|---|---|---|---|
| **Formel** | a, b | Ergebnis | Berechnet einen Ausdruck aus den EingÀngen `a` und `b`. Optional: eine zweite Formel zur Transformation des Ergebnisses (Variable `x`). |
| **Skalieren** | Wert | Ergebnis | Rechnet einen Wert von einem Bereich in einen anderen um, z. B. 0â255 â 0â100 %. |
| **Begrenzer** | Wert | Ergebnis | Begrenzt den Wert auf einen Bereich [Min, Max]. Werte darunter oder darĂŒber werden auf den Grenzwert gesetzt. |
| **Statistik** | Wert, ZurĂŒcksetzen | Min, Max, Mittelwert, Anzahl | FĂŒhrt eine laufende Statistik ĂŒber alle empfangenen Werte. Reset setzt alles zurĂŒck. Ergebnisse werden gespeichert und ĂŒberleben einen Neustart. |
| **Min/Max-Tracker** | Wert | Min tĂ€gl., Max tĂ€gl., Min wöch., Max wöch., Min monatl., Max monatl., Min jĂ€hrl., Max jĂ€hrl., Min abs., Max abs. | Verfolgt Minimal- und Maximalwerte ĂŒber verschiedene ZeitrĂ€ume (tĂ€glich, wöchentlich, monatlich, jĂ€hrlich, absolut). Setzt sich automatisch bei Periodengrenze zurĂŒck. |
| **VerbrauchszĂ€hler** | Wert (ZĂ€hlerstand) | TĂ€glich, Wöchentlich, Monatlich, JĂ€hrlich, Vorheriger Tag, Vorherige Woche, Vorheriger Monat, Vorheriges Jahr | Berechnet Verbrauch aus einem kumulierten ZĂ€hlerstand. Speichert Vorperiodenwerte fĂŒr Vergleiche. |
| **Sommer/Winter (DIN)** | Wert (Aussentemperatur) | Heizungsmodus, Tagesdurchschnitt, Monatsdurchschnitt | Steuert die Heizungsumschaltung nach DIN-Norm anhand von drei Tageswerten (T1 â 07:00, T2 â 14:00, T3 â 22:00). Tagesdurchschnitt = (T1 + T2 + 2ĂT3) / 4. |
#### Text
| Block | EingÀnge | AusgÀnge | Beschreibung |
|---|---|---|---|
| **Text verbinden** | 2â20 EingĂ€nge (konfigurierbar) | Ergebnis | Verbindet mehrere Texte zu einem. Optionales Trennzeichen (z. B. `,` oder ` `). |
#### Timer
| Block | EingÀnge | AusgÀnge | Beschreibung |
|---|---|---|---|
| **Verzögerung** | Trigger | Trigger | Verzögert ein Signal um N Sekunden. |
| **Impuls** | Trigger | Aus | Gibt fĂŒr N Sekunden âWahr" aus, dann âFalsch". |
| **Trigger** | â | Trigger | Löst den Graphen nach einem Zeitplan aus (Cron-Format). Konfigurierbar ĂŒber Vorlagen, einen visuellen Editor (Min/Std/Tag/Mon/Wochentag) oder direkte Eingabe des Ausdrucks. |
| **Betriebsstunden** | Aktiv, ZurĂŒcksetzen | Stunden | ZĂ€hlt Betriebsstunden solange âAktiv" wahr ist. Gespeicherter ZĂ€hlerstand ĂŒberlebt Neustarts. |
#### Skript
| Block | EingÀnge | AusgÀnge | Beschreibung |
|---|---|---|---|
| **Python-Skript** | a, b, c | Ergebnis | FĂŒhrt Python-Code aus. Eingangswerte sind ĂŒber `inputs['a']`, `inputs['b']`, `inputs['c']` verfĂŒgbar. Das Ergebnis wird mit `result = âŠ` gesetzt. Nur mathematische Funktionen erlaubt â kein Dateizugriff, kein Netzwerk. |
#### KI
| Block | EingÀnge | AusgÀnge | Beschreibung |
|---|---|---|---|
| **KI-Logik** | Trigger | Ergebnis | Platzhalter fĂŒr zukĂŒnftige KI-Integration. |
#### MCP
| Block | EingÀnge | AusgÀnge | Beschreibung |
|---|---|---|---|
| **MCP-Werkzeug** | Trigger, Eingabe | Ergebnis, Fertig | Ruft ein Werkzeug auf einem externen MCP-Server auf. |
#### Astro
| Block | AusgÀnge | Beschreibung |
|---|---|---|
| **Astro Sonne** | Sonnenaufgang, Sonnenuntergang, TagsĂŒber | Berechnet Sonnenauf- und -untergang fĂŒr den konfigurierten Standort. Gibt auch aus, ob es gerade hell ist. Konfiguration: Breitengrad, LĂ€ngengrad. BerĂŒcksichtigt die eingestellte Zeitzone. |
#### Benachrichtigung
| Block | EingÀnge | AusgÀnge | Beschreibung |
|---|---|---|---|
| **Pushover** | Trigger, Nachricht | Gesendet | Sendet eine Push-Benachrichtigung auf das Handy via [Pushover](https://pushover.net). Konfiguration: App-Token, User-Key, Titel, PrioritÀt. |
| **SMS (seven.io)** | Trigger, Nachricht | Gesendet | Sendet eine SMS via [seven.io](https://seven.io). Konfiguration: API-SchlĂŒssel, EmpfĂ€nger, Absender. |
#### Integration
| Block | EingÀnge | AusgÀnge | Beschreibung |
|---|---|---|---|
| **API-Abfrage** | Trigger, Inhalt | Antwort, Statuscode, Erfolg | Sendet eine HTTP-Anfrage an eine externe Adresse. Methode wĂ€hlbar (GET/POST/PUT/PATCH/DELETE). Antwortformat: JSON oder Text. SSL-PrĂŒfung konfigurierbar. |
| **JSON-Extraktor** | Daten (JSON-Text) | Wert | Parst einen JSON-String und extrahiert einen Wert anhand eines Pfads mit Punktnotation, z. B. `sensors.temperature`. |
| **XML-Extraktor** | Daten (XML-Text) | Wert | Parst einen XML-String und extrahiert einen Wert per XPath-Ausdruck, z. B. `./sensor/temperature`. |
---
### Filter und Transformation bei DP-Blöcken
Beide DataPoint-Blöcke haben drei Tabs: **Verbindung**, **Transformation** und **Filter**. Ein Punkt (âą) erscheint im Tab wenn etwas aktiv ist.
#### Transformation
Optionale Formel die auf den Wert angewendet wird. Variable: `x`
Vordefinierte Vorlagen (Beispiele):
| Vorlage | Formel |
|---|---|
| Ă 1.000 | `x * 1000` |
| Ă 100 | `x * 100` |
| Ă· 10 | `round(x / 10, 1)` |
| Ă· 100 | `round(x / 100, 2)` |
| Sekunden â Stunden | `x / 3600` |
| Stunden â Sekunden | `x * 3600` |
#### Filter bei DP Lesen
| Filter | Beschreibung |
|---|---|
| Mindestabstand | Wie oft der Graph höchstens ausgelöst wird (z. B. maximal alle 10 Sekunden) |
| Nur bei Ănderung | Graph nur auslösen wenn der Wert sich wirklich geĂ€ndert hat |
| MindestÀnderung (absolut) | Nur auslösen wenn der Wert sich um mindestens N geÀndert hat |
| MindestĂ€nderung (%) | Nur auslösen wenn die Ănderung mindestens N Prozent betrĂ€gt |
#### Filter bei DP Schreiben
| Filter | Beschreibung |
|---|---|
| Mindestabstand | Wie oft höchstens geschrieben wird |
| Nur bei Ănderung | Nicht schreiben wenn der Wert gleich dem zuletzt geschriebenen ist |
| MindestÀnderung (absolut) | Nur schreiben wenn der Wert sich um mindestens N geÀndert hat |
---
### Zeitplan-Konfiguration (Trigger-Block)
Der **Trigger**-Block löst Graphen nach einem Zeitplan aus. Drei Eingabewege, die sich gegenseitig synchronisieren:
**1. Vorlagen** â ĂŒber 30 vordefinierte ZeitplĂ€ne in 4 Gruppen (Minuten-Intervalle, Stunden-Intervalle, TĂ€glich, Wöchentlich/Monatlich)
**2. Visueller Editor** â fĂŒnf Felder: Minute / Stunde / Tag / Monat / Wochentag
**3. Direkteingabe** â Standard Cron-Ausdruck
```
0 7 * * * â tĂ€glich um 07:00
*/15 * * * * â alle 15 Minuten
0 8 * * 1-5 â werktags um 08:00
0 6,18 * * * â tĂ€glich um 06:00 und 18:00
```
Zur ĂberprĂŒfung: [crontab.guru](https://crontab.guru) (Link direkt im Konfigurations-Panel)
---
### Formel-Referenz
In **allen** Formelfeldern (DP Lesen, DP Schreiben, Formel-Block, VerknĂŒpfungs-Transformation) gilt:
- Variable `x` = der eingehende Wert (immer als Zahl ĂŒbergeben)
- Kein Import nötig â alle Funktionen direkt verfĂŒgbar
- `round()` verwendet mathematisches Runden (0.5 â aufrunden)
| Funktion | Beispiel | Beschreibung |
|---|---|---|
| `abs(x)` | `abs(x - 50)` | Absolutbetrag (immer positiv) |
| `round(x, n)` | `round(x, 2)` | Runden auf n Nachkommastellen |
| `min(a, b)` | `min(x, 100)` | Kleinerer der beiden Werte |
| `max(a, b)` | `max(x, 0)` | Grösserer der beiden Werte |
| `sqrt(x)` | `sqrt(x)` | Quadratwurzel |
| `floor(x)` | `floor(x)` | Abrunden auf ganze Zahl |
| `ceil(x)` | `ceil(x)` | Aufrunden auf ganze Zahl |
| `math.log(x)` | `math.log(x)` | NatĂŒrlicher Logarithmus |
| `math.sin(x)` | `math.sin(x)` | Sinus |
| `math.pi` | `x * math.pi / 180` | Kreiszahl Ï |
**Praktische Beispiele:**
| Ziel | Formel |
|---|---|
| Auf 0â100 begrenzen | `max(0, min(100, x))` |
| Fahrenheit â Celsius | `(x - 32) * 5 / 9` |
| Wh â kWh | `x / 1000` |
| Auf halbe Stufen runden | `round(x * 2) / 2` |
| Negativen Wert abschneiden | `max(0, x)` |
**Formel-Block** (EingÀnge `a` und `b`):
```
a * 2 + b # Eingang a verdoppeln, b addieren
max(a, b) # Grösseren der beiden Werte nehmen
round((a + b) / 2, 1) # Mittelwert, 1 Nachkommastelle
abs(a - b) # Absolute Differenz
```
ZusĂ€tzlich kann eine **Ausgangs-Transformation** konfiguriert werden â eine zweite Formel (Variable `x`) die auf das berechnete Ergebnis angewendet wird.
---
### Automatische Typumwandlung
Die Logik-Engine wandelt Werte automatisch um:
| Von | Nach | Regel |
|---|---|---|
| `true`/`false` | Zahl | Wahr â 1.0, Falsch â 0.0 |
| Zahl | Ein/Aus | 0 â Falsch, alles andere â Wahr |
| Text `"123"` | Zahl | 123.0 |
| Text `"true"`, `"on"`, `"1"` | Ein/Aus | Wahr |
| Text `"false"`, `"off"`, `"0"` | Ein/Aus | Falsch |
| Kein Wert | Zahl | 0.0 |
Verbindungen zwischen unterschiedlichen Blocktypen funktionieren damit immer.
---
### Debug-Modus
Zeigt berechnete Zwischenwerte direkt auf den Blöcken an â live und automatisch.
1. Graph öffnen
2. **đ Debug**-Button in der Werkzeugleiste klicken
3. Jeder Block zeigt ein gelbes Band mit seinen aktuellen Ausgangswerten
4. Die Anzeige aktualisiert sich automatisch nach jeder AusfĂŒhrung (WertĂ€nderung, Zeitplan, manueller Start)
| Typ | Darstellung |
|---|---|
| Wahr | `out=â` |
| Falsch | `out=â` |
| Zahl | `value=230.45` |
| DP Schreiben | `â 21.5` |
| Kein Wert | `value=â` |
---
## Adapter-Konfiguration
### KNX-Adapter
**Instanz-Konfiguration â Grundparameter:**
| Feld | Werte | Beschreibung |
|---|---|---|
| `connection_type` | `tunneling` / `tunneling_secure` / `routing` / `routing_secure` | Verbindungstyp (siehe unten) |
| `host` | IP-Adresse | IP der KNX/IP-Zentrale (Tunneling) oder Multicast-Adresse (Routing) |
| `port` | Standard `3671` | Port der KNX/IP-Zentrale |
| `individual_address` | z. B. `1.1.210` | Eigene KNX-Adresse des open bridge Servers |
| `local_ip` | IP-Adresse | Lokale Netzwerkschnittstelle (optional). Bei Routing/Routing Secure: wĂ€hlt die Netzwerkkarte fĂŒr Multicast â bei mehreren Netzwerkkarten **empfohlen**. Bei Tunneling/Tunneling Secure: bindet den Socket an eine bestimmte Schnittstelle â meist nur bei Mehrfach-Netzwerkkarten nötig. Leer lassen = automatische Auswahl. |
**Verbindungstypen:**
| `connection_type` | Beschreibung |
|---|---|
| `tunneling` | UDP-Tunneling zur KNX/IP-Zentrale (Standard) |
| `tunneling_secure` | KNX IP Secure Tunneling (verschlĂŒsselt, TCP) |
| `routing` | IP-Multicast-Routing |
| `routing_secure` | KNX IP Secure Routing (verschlĂŒsselt, Multicast) |
**KNX IP Secure â Keyfile-Modus (empfohlen)**
Der einfachste Weg fĂŒr KNX IP Secure ist der Import der `.knxkeys`-Datei aus ETS:
1. In ETS: **Sicherheit â SchlĂŒsselsicherung exportieren** â `.knxkeys`-Datei speichern
2. In open bridge server: **Einstellungen â Adapter â KNX-Instanz bearbeiten â Keyfile hochladen**
3. Keyfile-Passwort eingeben â open bridge server zeigt alle verfĂŒgbaren Tunnel mit PA, User-ID und Anzahl gesicherter Gruppenadressen
4. GewĂŒnschten Tunnel wĂ€hlen â `individual_address` wird automatisch gesetzt
5. `connection_type` auf `tunneling_secure` (oder `routing_secure`) setzen
| Feld | Beschreibung |
|---|---|
| `knxkeys_file_path` | Wird automatisch gesetzt nach dem Hochladen der Keyfile |
| `knxkeys_password` | Passwort-Feld â Passwort zur `.knxkeys`-Datei |
| `individual_address` | PA des gewÀhlten Tunnels (aus der Tunnel-Liste) |
**KNX IP Secure â Manueller Modus** (nur wenn kein Keyfile vorhanden):
FĂŒr `tunneling_secure`:
| Feld | Werte | Beschreibung |
|---|---|---|
| `user_id` | `1`â`127`, Standard `2` | Benutzer-ID am KNX/IP-Gateway |
| `user_password` | Passwort-Feld | Benutzerpasswort |
| `device_authentication_password` | Passwort-Feld | GerÀte-Authentifizierungspasswort |
FĂŒr `routing_secure`:
| Feld | Werte | Beschreibung |
|---|---|---|
| `backbone_key` | Passwort-Feld | 128-Bit Backbone-SchlĂŒssel als Hex-String (32 Zeichen, z. B. `0102030405060708090a0b0c0d0e0f10`; Trennzeichen `:` und Leerzeichen werden ignoriert) |
> **Hinweis:** Sind `knxkeys_file_path` und `knxkeys_password` gesetzt, haben sie Vorrang vor den manuellen Feldern. Alle Passwort-Felder werden in der WeboberflÀche maskiert dargestellt.
**Keyfile API** (fĂŒr eigene Integrationen):
```
POST /api/v1/knx/keyfile # .knxkeys hochladen, Tunnel-Liste zurĂŒckgeben
DELETE /api/v1/knx/keyfile/{file_id} # Keyfile löschen
```
Antwort des Upload-Endpunkts:
```json
{
"file_id": "uuid",
"file_path": "/data/knxkeys/uuid.knxkeys",
"project_name": "Mein KNX-Projekt",
"tunnels": [
{ "individual_address": "1.1.100", "host": "1.1.50", "user_id": 2, "secure_ga_count": 15 },
{ "individual_address": "1.1.101", "host": "1.1.50", "user_id": 3, "secure_ga_count": 15 }
],
"backbone": null
}
```
**VerknĂŒpfungs-Konfiguration:**
| Feld | Beschreibung |
|---|---|
| `group_address` | KNX-Gruppenadresse (dreiteilig, z. B. `27/6/6`) |
| `dpt_id` | DPT-Kennung â Tabelle unten |
| `state_group_address` | Optionale RĂŒckmelde-Adresse fĂŒr DEST-VerknĂŒpfungen |
| `respond_to_read` | `true`: **open bridge server** beantwortet KNX-Leseanfragen (GroupValueRead) mit dem aktuellen Wert. Standard: `false` |
**UnterstĂŒtzte DPTs:**
**open bridge server** unterstĂŒtzt ĂŒber 85 KNX-Datentypen. Die vollstĂ€ndige Liste ist ĂŒber `GET /api/v1/adapters/knx/dpts` abrufbar.
**DPT 1 â 1-Bit Boolean**
| DPT | Typische Verwendung |
|---|---|
| `DPT1.001` | Schalten (Ein/Aus) |
| `DPT1.002` | Boolean |
| `DPT1.003` | Freigabe (Enable) |
| `DPT1.007` | Schritt/Richtung |
| `DPT1.008` | Auf/Ab |
| `DPT1.009` | Ăffnen/Schliessen |
| `DPT1.010` | Start/Stopp |
| `DPT1.011` | Zustandsanzeige |
| `DPT1.017` | Auslöser (Trigger) |
| `DPT1.018` | Anwesenheit |
| `DPT1.019` | Fenster/TĂŒr |
| `DPT1.021` | Szene A/B |
| `DPT1.022` | Jalousie-Modus |
| `DPT1.023` | Tag/Nacht |
| *(weitere DPT1.x)* | *1-Bit Steuerungen* |
**DPT 2 â 2-Bit Gesteuerter Wert**
| DPT | Typische Verwendung |
|---|---|
| `DPT2.001` | Schaltsteuerung (PrioritÀt + Wert) |
| `DPT2.002` | Boolsche Steuerung |
**DPT 3 â 4-Bit Relativer Steuerwert**
| DPT | Typische Verwendung |
|---|---|
| `DPT3.007` | Dimmen (Richtung + Geschwindigkeit) |
| `DPT3.008` | Jalousie (Richtung + Geschwindigkeit) |
**DPT 4 â 1-Byte Zeichen**
| DPT | Grösse | Typ | Typische Verwendung |
|---|---|---|---|
| `DPT4.001` | 1 Byte | Text | ASCII-Zeichen |
| `DPT4.002` | 1 Byte | Text | ISO-8859-1-Zeichen |
**DPT 5 â 8-Bit Vorzeichenlos**
| DPT | Grösse | Typ | Typische Verwendung |
|---|---|---|---|
| `DPT5.001` | 1 Byte | Zahl (0â100 %) | Dimmen / Jalousie-Position |
| `DPT5.003` | 1 Byte | Zahl (0â360°) | Winkel |
| `DPT5.004` | 1 Byte | Ganzzahl (0â255) | Prozent (unsigned) |
| `DPT5.010` | 1 Byte | Ganzzahl | ZĂ€hlerwert |
**DPT 6 â 8-Bit Vorzeichenbehaftet**
| DPT | Grösse | Typ | Typische Verwendung |
|---|---|---|---|
| `DPT6.001` | 1 Byte | Ganzzahl (â128âŠ127) | Relativer Wert (%) |
| `DPT6.010` | 1 Byte | Ganzzahl | ImpulszÀhler (vorzeichenbehaftet) |
**DPT 7 â 16-Bit Vorzeichenlos**
| DPT | Grösse | Typ | Typische Verwendung |
|---|---|---|---|
| `DPT7.001` | 2 Byte | Ganzzahl (0â65535) | ImpulszĂ€hler |
| `DPT7.002` | 2 Byte | Ganzzahl | Zeitraum (ms) |
| `DPT7.003` | 2 Byte | Ganzzahl | Zeitraum (10 ms) |
| `DPT7.004` | 2 Byte | Ganzzahl | Zeitraum (100 ms) |
| `DPT7.005` | 2 Byte | Ganzzahl | Zeitraum (s) |
| `DPT7.006` | 2 Byte | Ganzzahl | Zeitraum (min) |
| `DPT7.007` | 2 Byte | Ganzzahl | Zeitraum (h) |
| `DPT7.011` | 2 Byte | Ganzzahl | LĂ€nge (mm) |
| `DPT7.012` | 2 Byte | Ganzzahl | StromstÀrke (mA) |
| `DPT7.013` | 2 Byte | Ganzzahl | Helligkeit (lx) |
| `DPT7.600` | 2 Byte | Ganzzahl | Farbtemperatur (K) |
**DPT 8 â 16-Bit Vorzeichenbehaftet**
| DPT | Grösse | Typ | Typische Verwendung |
|---|---|---|---|
| `DPT8.001` | 2 Byte | Ganzzahl | ImpulszÀhler (vorzeichenbehaftet) |
| `DPT8.002` | 2 Byte | Ganzzahl | Zeitraum (ms) |
| `DPT8.005` | 2 Byte | Ganzzahl | Zeitraum (s) |
| `DPT8.010` | 2 Byte | Ganzzahl | Drehzahl-Differenz (1/min) |
| `DPT8.011` | 2 Byte | Ganzzahl | Prozent-Differenz |
| `DPT8.012` | 2 Byte | Ganzzahl | Rotationswinkel (°) |
**DPT 9 â 2-Byte KNX-Gleitkomma (EIS5)**
| DPT | Typische Verwendung |
|---|---|
| `DPT9.001` | Temperatur (°C) |
| `DPT9.002` | Temperaturdifferenz (K) |
| `DPT9.003` | Kelvin/Stunde (K/h) |
| `DPT9.004` | Windgeschwindigkeit (m/s) |
| `DPT9.005` | Luftdruck (Pa) |
| `DPT9.006` | Luftfeuchtigkeit (%) |
| `DPT9.007` | Luftfeuchtigkeit (% rH) |
| `DPT9.008` | COâ-Konzentration (ppm) |
| `DPT9.009` | Spannung (mV) |
| `DPT9.010` | Leistung (W) |
| `DPT9.011` | Zeit (s) |
| `DPT9.020` | Spannung (mV) |
| `DPT9.021` | Strom (mA) |
| `DPT9.024` | Leistung (kW) |
| `DPT9.025` | Volumenfluss (l/h) |
| `DPT9.026` | Niederschlag (l/mÂČ) |
| `DPT9.027` | Luftdruck (Pa) |
| `DPT9.028` | Windgeschwindigkeit (km/h) |
| `DPT9.029` | Absolute Luftfeuchtigkeit (g/mÂł) |
| `DPT9.030` | Einstrahlungsdichte (W/mÂČ) |
**DPT 10, 11 â Uhrzeit und Datum**
| DPT | Grösse | Typ | Typische Verwendung |
|---|---|---|---|
| `DPT10.001` | 3 Byte | Text `HH:MM:SS` | Uhrzeit (inkl. Wochentag) |
| `DPT11.001` | 3 Byte | Text `JJJJ-MM-TT` | Datum |
**DPT 12, 13 â 32-Bit Integer**
| DPT | Grösse | Typ | Typische Verwendung |
|---|---|---|---|
| `DPT12.001` | 4 Byte | Ganzzahl (0â4 Mrd.) | EnergiezĂ€hler (vorzeichenlos) |
| `DPT13.001` | 4 Byte | Ganzzahl (±2 Mrd.) | ImpulszÀhler (vorzeichenbehaftet) |
| `DPT13.010` | 4 Byte | Ganzzahl | Wirkenergie (Wh) |
| `DPT13.013` | 4 Byte | Ganzzahl | Wirkenergie (kWh) |
**DPT 14 â 32-Bit IEEE-754-Gleitkomma (physikalische Grössen)**
| DPT | Typische Verwendung |
|---|---|
| `DPT14.000` | Beschleunigung (m/sÂČ) |
| `DPT14.005` | Winkelgeschwindigkeit (rad/s) |
| `DPT14.007` | FlĂ€che (mÂČ) |
| `DPT14.012` | KapazitÀt (F) |
| `DPT14.017` | Dichte (kg/mÂł) |
| `DPT14.019` | Elektrischer Strom (A) |
| `DPT14.020` | Elektrische FeldstÀrke (V/m) |
| `DPT14.023` | Elektrisches Potential (V) |
| `DPT14.024` | Elektrische Spannung (V) |
| `DPT14.027` | Energie (J) |
| `DPT14.028` | Kraft (N) |
| `DPT14.029` | Frequenz (Hz) |
| `DPT14.033` | WĂ€rmestrom (W) |
| `DPT14.039` | LĂ€nge (m) |
| `DPT14.046` | Lichtstrom (lm) |
| `DPT14.050` | Masse (kg) |
| `DPT14.055` | Leistung (W) |
| `DPT14.056` | Leistungsfaktor |
| `DPT14.058` | Druck (Pa) |
| `DPT14.065` | Widerstand (Ω) |
| `DPT14.066` | Winkelauflösung (°) |
| `DPT14.067` | Drehzahl (1/min) |
| `DPT14.068` | Geschwindigkeit (m/s) |
| `DPT14.069` | Drehmoment (Nm) |
| `DPT14.070` | Volumen (mÂł) |
| `DPT14.071` | Volumenfluss (mÂł/s) |
| `DPT14.075` | Scheinleistung (VA) |
| *(weitere DPT14.x)* | *Physikalische MessÂgrössen* |
**DPT 16, 17, 18, 19 â Text, Szenen, Datum/Zeit**
| DPT | Grösse | Typ | Typische Verwendung |
|---|---|---|---|
| `DPT16.000` | 14 Byte | Text | ASCII-Text (14 Zeichen) |
| `DPT16.001` | 14 Byte | Text | ISO-8859-1-Text (14 Zeichen) |
| `DPT17.001` | 1 Byte | Ganzzahl | Szenennummer (0â63) |
| `DPT18.001` | 1 Byte | Ganzzahl | Szenen-Steuerung (inkl. Lernmodus) |
| `DPT19.001` | 8 Byte | ISO-8601-Text | Datum und Uhrzeit |
**DPT 20 â 1-Byte Enum/Modus**
| DPT | Typische Verwendung |
|---|---|
| `DPT20.001` | HVAC-Modus (Auto/Komfort/Standby/Nacht/Schutz) |
| `DPT20.002` | HVAC-Brennermodus |
| `DPT20.003` | HVAC-GeblÀsemodus |
| `DPT20.004` | HVAC-Mastermodus |
| `DPT20.005` | HVAC-Statusmeldung |
| `DPT20.006` | HVAC-Positionswert |
| `DPT20.007` | DALI-Verblend-Modus |
| `DPT20.008` | Steuerungsverhalten |
| `DPT20.011` | PrioritÀt |
| `DPT20.012` | Lichtsteuermodus |
| `DPT20.013` | Heizungsregelungsmodus |
| `DPT20.017` | BelĂŒftungsmodus |
| `DPT20.020` | Alarmschwere |
| `DPT20.021` | Testmodus |
| `DPT20.100` | GebÀude-Betriebsmodus |
| `DPT20.102` | Aktiver Grundmodus |
| `DPT20.105` | Warmwasser-Modus (DHW) |
| `DPT20.111` | Heizklima-Modus |
| `DPT20.113` | Zeitprogramm |
| `DPT20.600` | Ventilator-Modus |
| `DPT20.601` | Heizungstyp |
| `DPT20.602` | Klappenventil-Modus |
| `DPT20.603` | Heizkreis-Modus |
| `DPT20.604` | Heizkörpermodus |
| *(weitere DPT20.x)* | *1-Byte Enums/Modi* |
**DPT 29 â 64-Bit Integer (Smart Metering)**
| DPT | Grösse | Typ | Typische Verwendung |
|---|---|---|---|
| `DPT29.010` | 8 Byte | Ganzzahl | Wirkenergie (Wh), hochauflösend |
| `DPT29.011` | 8 Byte | Ganzzahl | Scheinenergie (VAh) |
| `DPT29.012` | 8 Byte | Ganzzahl | Blindenergie (VARh) |
**DPT 219, 240 â Spezielle Typen**
| DPT | Grösse | Typ | Typische Verwendung |
|---|---|---|---|
| `DPT219.001` | 2 Byte | Ganzzahl | AlarmInfo (Modus + Statusbits) |
| `DPT240.800` | 3 Byte | JSON-Text | Jalousie-Kombination (Höhe % + Lamellen %) |
> **Hinweis fĂŒr KNX-Dimmer:** Zwei separate VerknĂŒpfungen anlegen â eine DEST fĂŒr die Schreib-Adresse, eine SOURCE fĂŒr die RĂŒckmelde-Adresse.
---
### Modbus-TCP-Adapter
**Instanz-Konfiguration:**
| Feld | Standard | Beschreibung |
|---|---|---|
| `host` | â | IP-Adresse der Modbus-Gegenstelle |
| `port` | `502` | TCP-Port |
| `timeout` | `3.0` | Verbindungs-Timeout in Sekunden |
**VerknĂŒpfungs-Konfiguration:**
| Feld | Werte | Beschreibung |
|---|---|---|
| `unit_id` | `1` | Modbus-Slave-ID (GerÀteadresse) |
| `register_type` | `holding`, `input`, `coil`, `discrete_input` | Registertyp |
| `address` | Ganzzahl | Registeradresse (0-basiert) |
| `count` | `1` | Anzahl zu lesender Register |
| `data_format` | `uint16`, `int16`, `uint32`, `int32`, `float32`, `uint64`, `int64` | Datenformat |
| `scale_factor` | `1.0` | Rohwert Ă Faktor = Messwert |
| `byte_order` | `big` / `little` | Byte-Reihenfolge im Register |
| `word_order` | `big` / `little` | Wort-Reihenfolge bei 32/64-Bit-Werten |
| `poll_interval` | `1.0` | Abfrageintervall in Sekunden (nur SOURCE/BOTH) |
> **Praxistipp:** Die meisten Steuerungen (Siemens, Beckhoff âŠ) verwenden `big`/`big`. Bei offensichtlich falschem Wert zuerst `word_order` auf `little` wechseln.
---
### Modbus-RTU-Adapter
Gleiche VerknĂŒpfungs-Konfiguration wie TCP. ZusĂ€tzliche Instanz-Felder: `port` (z. B. `/dev/ttyUSB0`), `baudrate`, `parity`, `stopbits`, `bytesize`, `timeout`.
---
### 1-Wire-Adapter
Liest Temperatursensoren ĂŒber den Linux-Systemordner (`/sys/bus/w1/âŠ`). Auf Windows funktioniert der Adapter nicht, startet aber ohne Fehlermeldung.
**Instanz-Konfiguration:**
| Feld | Standard | Beschreibung |
|---|---|---|
| `poll_interval` | `30.0` | Abfrageintervall in Sekunden |
| `w1_path` | `/sys/bus/w1/devices` | Pfad zum 1-Wire-Systemordner |
**VerknĂŒpfungs-Konfiguration:**
| Feld | Beschreibung |
|---|---|
| `sensor_id` | Sensor-ID, z. B. `28-0000012345ab` |
| `sensor_type` | Sensortyp, z. B. `DS18B20` (Standard) |
VerfĂŒgbare Sensor-IDs können ĂŒber den Verbindungstest abgerufen werden.
---
### MQTT-Adapter (externer Broker)
Verbindet sich mit einem **externen** MQTT-Broker (getrennt vom internen Mosquitto).
**Instanz-Konfiguration:** `host`, `port`, `username`, `password`
**VerknĂŒpfungs-Konfiguration:**
| Feld | Beschreibung |
|---|---|
| `topic` | Topic zum Empfangen (SOURCE/BOTH) |
| `publish_topic` | Topic zum Senden (DEST/BOTH) â Standard: gleich wie `topic` |
| `retain` | Retain-Flag beim Senden setzen |
---
### Home-Assistant-Adapter
Verbindet **open bridge server** bidirektional mit einer Home-Assistant-Instanz. EmpfĂ€ngt ZustandsĂ€nderungen in Echtzeit ĂŒber WebSocket (`state_changed`-Ereignisse) und schreibt Werte ĂŒber die HA-REST-API (Dienst-Aufrufe).
**Instanz-Konfiguration:**
| Feld | Standard | Beschreibung |
|---|---|---|
| `host` | `homeassistant.local` | Hostname oder IP-Adresse der HA-Instanz |
| `port` | `8123` | Port der HA-WeboberflÀche |
| `token` | â | Long-Lived Access Token (Passwort-Feld) |
| `ssl` | `false` | HTTPS/WSS verwenden |
**VerknĂŒpfungs-Konfiguration:**
| Feld | Beschreibung |
|---|---|
| `entity_id` | Home-Assistant-Entity-ID, z. B. `sensor.wohnzimmer_temperatur` |
| `attribute` | Optionales Attribut statt dem Hauptzustand, z. B. `unit_of_measurement` |
| `service_domain` | Dienst-Domain fĂŒr Schreibbefehle, wird automatisch aus der Entity abgeleitet wenn leer |
| `service_name` | Dienst-Name: Standard `turn_on`/`turn_off` fĂŒr Boolean, `set_value` sonst |
| `service_data_key` | SchlĂŒssel fĂŒr den Wert im Dienst-Aufruf, z. B. `brightness` oder `value` |
TextzustĂ€nde wie `"on"`/`"off"`, `"true"`/`"false"` werden automatisch in Boolean-Werte umgewandelt. Numerische Texte werden als Zahl ĂŒbergeben.
---
### ioBroker-Adapter
Verbindet **open bridge server** bidirektional mit einer ioBroker-Instanz ĂŒber Socket.IO. Werte werden beim VerknĂŒpfen initial gelesen und danach in Echtzeit ĂŒber `stateChange`-Ereignisse aktualisiert; Schreibbefehle werden per `setState` an ioBroker gesendet.
**Instanz-Konfiguration:**
| Feld | Standard | Beschreibung |
|---|---|---|
| `host` | `iobroker.local` | Hostname oder IP-Adresse der ioBroker-Instanz |
| `port` | `8084` | Port des ioBroker Socket.IO/Web-Adapters |
| `username` | â | Optionaler Benutzername |
| `password` | â | Optionales Passwort (Passwort-Feld) |
| `ssl` | `false` | HTTPS verwenden |
| `path` | `/socket.io` | Socket.IO-Pfad |
| `access_token` | â | Optionaler Bearer/OAuth-Token (Passwort-Feld) |
**VerknĂŒpfungs-Konfiguration:**
| Feld | Beschreibung |
|---|---|
| `state_id` | ioBroker-State-ID, z. B. `0_userdata.0.wohnzimmer.temperatur` |
| `command_state_id` | Optional abweichender State fĂŒr Schreibbefehle, z. B. ein `.SET`-State |
| `ack` | Ack-Flag beim Schreiben (`false` = Befehl, `true` = bestÀtigter Status) |
| `source_data_type` | Optionaler Datentyp fĂŒr eingehende Werte: `string`, `int`, `float`, `bool`, `json` |
| `json_key` | Optionaler SchlĂŒssel zum Extrahieren eines Werts aus JSON |
TextzustĂ€nde wie `"on"`/`"off"`, `"true"`/`"false"` werden automatisch in Boolean-Werte umgewandelt. Numerische Texte werden als Zahl ĂŒbergeben. FĂŒr getrennte Status- und Befehlsobjekte kann `state_id` auf den Status und `command_state_id` auf den Befehls-State zeigen.
Entwicklungs- und Review-Notizen zur aktuellen Implementierung stehen in [`docs/iobroker-adapter.md`](docs/iobroker-adapter.md).
---
### SNMP-Adapter
Liest OID-Werte von SNMP-fĂ€higen GerĂ€ten (SNMPv1, v2c, v3) und schreibt Werte per SNMP SET. Jedes Binding konfiguriert seinen eigenen Host und OID â keine persistente TCP-Verbindung, zustandsloses UDP pro Anfrage.
**Instanz-Konfiguration:**
| Feld | Standard | Beschreibung |
|---|---|---|
| `version` | `2c` | SNMP-Version: `1`, `2c` oder `3` |
| `community` | `public` | Community-String (nur v1/v2c) |
| `security_name` | â | Security-Name / Benutzername (nur v3) |
| `security_level` | `noAuthNoPriv` | Sicherheitsstufe (v3): `noAuthNoPriv`, `authNoPriv`, `authPriv` |
| `auth_protocol` | `MD5` | Authentifizierungsprotokoll (v3): `MD5`, `SHA`, `SHA256`, `SHA512` |
| `auth_key` | â | AuthentifizierungsschlĂŒssel (v3, Passwort-Feld) |
| `priv_protocol` | `DES` | Privacy-Protokoll (v3): `DES`, `3DES`, `AES128`, `AES192`, `AES256` |
| `priv_key` | â | Privacy-SchlĂŒssel (v3, Passwort-Feld) |
**VerknĂŒpfungs-Konfiguration:**
| Feld | Standard | Beschreibung |
|---|---|---|
| `host` | `192.168.1.1` | IP-Adresse oder DNS-Name des SNMP-GerÀts |
| `port` | `161` | UDP-Port |
| `oid` | `1.3.6.1.2.1.1.1.0` | Objekt-Identifier, z. B. `1.3.6.1.2.1.1.3.0` |
| `data_type` | `auto` | Werttyp: `auto`, `int`, `float`, `string`, `hex`, `counter`, `gauge`, `timeticks` |
| `poll_interval` | `30.0` | Abfrageintervall in Sekunden (SOURCE/BOTH) |
| `timeout` | `5.0` | Timeout pro Anfrage in Sekunden |
| `retries` | `1` | Wiederholungen bei Fehler |
> **Hinweis:** `pysnmp` muss installiert sein (`pip install pysnmp`). Fehlt die Bibliothek, startet der Adapter ohne Fehlermeldung, kann aber keine Abfragen durchfĂŒhren.
---
### Anwesenheitssimulation-Adapter
Wiederholt historische SchaltzustÀnde wÀhrend der Abwesenheit, damit das GebÀude bewohnt wirkt. Wenn die Simulation aktiv ist, liest der Adapter die Verlaufs-Datenbank der letzten N Tage und löst jeden historischen Schaltvorgang zur gleichen Uhrzeit heute aus.
**Instanz-Konfiguration:**
| Feld | Standard | Beschreibung |
|---|---|---|
| `offset_days` | `7` | Anzahl Tage in der Vergangenheit, deren SchaltzustĂ€nde wiederholt werden (1â30) |
| `control_dp_id` | â | Optionaler Boolean-Datenpunkt: Wert `1` = Anwesend (Simulation aus), Wert `0` = Abwesend (Simulation an) |
| `control_invert` | `false` | Steuerobjekt invertieren |
| `on_presence` | `behalten` | Verhalten bei Anwesenheitserkennung: `behalten` (aktuellen Zustand beibehalten), `zuruecksetzen` (alle auf falsch/0 setzen), `setzen` (auf einen bestimmten Wert setzen) |
| `on_presence_value` | â | Wert der gesetzt wird wenn `on_presence = setzen` |
**VerknĂŒpfungs-Konfiguration:**
| Feld | Standard | Beschreibung |
|---|---|---|
| `offset_override` | â | Ăberschreibt `offset_days` fĂŒr diesen Datenpunkt (1â30) |
| `on_presence_override` | â | Ăberschreibt `on_presence` fĂŒr diesen Datenpunkt |
| `on_presence_value` | â | Ăberschreibt den Wert fĂŒr diesen Datenpunkt wenn `on_presence_override = setzen` |
> **Hinweis:** Nur SOURCE-VerknĂŒpfungen sind gĂŒltig â der Adapter wiederholt historische Werte, akzeptiert aber keine eingehenden Schreibbefehle. DEST/BOTH-VerknĂŒpfungen werden mit einer Warnung ĂŒbersprungen.
---
### Zeitschaltuhr-Adapter
Erzeugt zeitgesteuerte Ereignisse ohne externe Hardware â fĂŒr tageszeit- oder sonnenstandsbasierte Automatisierungen, Feiertags- und Ferienlogik.
**Instanz-Konfiguration:**
| Feld | Standard | Beschreibung |
|---|---|---|
| `latitude` | `47.5` | Breitengrad fĂŒr Sonnenstandsberechnung |
| `longitude` | `8.0` | LĂ€ngengrad fĂŒr Sonnenstandsberechnung |
| `altitude` | `400.0` | Höhe ĂŒber NN in Metern |
| `timezone` | (App-Zeitzone) | IANA-Zeitzone; leer = Systemzeitzone von **open bridge server** verwenden |
| `holiday_country` | `CH` | ISO-3166-LĂ€ndercode fĂŒr Feiertagskalender |
| `holiday_subdivision` | â | Kanton/Bundesland, z. B. `ZH` oder `BY` |
| `holiday_language` | `de` | Sprache fĂŒr Feiertagsnamen |
| `vacation_1_start` ⊠`vacation_6_end` | â | Bis zu 6 Ferienperioden im Format `JJJJ-MM-TT` |
**VerknĂŒpfungs-Konfiguration:**
| Feld | Werte | Beschreibung |
|---|---|---|
| `timer_type` | `daily`, `annual`, `meta` | `daily` = tÀglich wiederkehrend; `annual` = einmaliges Datum; `meta` = Metadaten-Ausgang (Feiertag, Ferien) |
| `meta_type` | `holiday_today`, `holiday_tomorrow`, `holiday_name_today`, `holiday_name_tomorrow`, `vacation_1`âŠ`vacation_6` | FĂŒr `timer_type = meta`: welcher Metadatenwert ausgegeben wird |
| `time_ref` | `absolute`, `sunrise`, `sunset`, `solar_noon`, `solar_altitude` | Zeitreferenz |
| `hour` / `minute` | `0`â`23` / `0`â`59` | Absolute Uhrzeit oder Offset zur Zeitreferenz |
| `offset_minutes` | Ganzzahl | Versatz zur Zeitreferenz in Minuten (positiv = spÀter) |
| `solar_altitude_deg` | `-18`â`90` | Sonnenstand-Schwellwert in Grad (nur `solar_altitude`) |
| `sun_direction` | `rising`, `setting` | Aufsteigende oder absteigende Sonnenbahn (nur `solar_altitude`) |
| `weekdays` | Liste `[0â6]` | Wochentage (0 = Montag). Leer = alle. |
| `months` | Liste `[1â12]` | Monate. Leer = alle. |
| `day_of_month` | `0`â`31` | Tag im Monat; `0` = alle. |
| `every_hour` | `true`/`false` | Jede Stunde zur konfigurierten Minute auslösen |
| `every_minute` | `true`/`false` | Jede Minute auslösen |
| `holiday_mode` | `ignore`, `skip`, `only`, `as_sunday` | Verhalten an Feiertagen |
| `vacation_mode` | `ignore`, `skip`, `only`, `as_sunday` | Verhalten in Ferienperioden |
| `value` | Text | Wert der beim Auslösen geschrieben wird (Standard: `"1"`) |
**Feiertagsmodi:**
| Modus | Verhalten |
|---|---|
| `ignore` | Feiertage/Ferien werden wie normale Tage behandelt |
| `skip` | An diesen Tagen wird nicht ausgelöst |
| `only` | Auslösen nur an Feiertagen/Ferien |
| `as_sunday` | Feiertag/Ferientag wird fĂŒr die WochentagsprĂŒfung als Sonntag (6) behandelt |
---
## MQTT-Topics
**open bridge server** verwendet zwei parallele Topic-Strategien:
| Topic | Beschreibung |
|---|---|
| `dp/{uuid}/value` | Stabil â Ă€ndert sich nie, sicher fĂŒr Automatisierungen. Mit Retain gespeichert. |
| `dp/{uuid}/set` | Auf diesen Topic schreiben um einen Wert zu setzen |
| `dp/{uuid}/status` | Verbindungsstatus des Adapters (mit Retain) |
| `alias/{tag}/{name}/value` | Lesbar und durchsuchbar (nur wenn `mqtt_alias` gesetzt) |
**Nachrichtenformat (`dp/{uuid}/value`):**
```json
{ "v": 21.4, "u": "°C", "t": "2026-03-27T10:23:41.123Z", "q": "good" }
```
| SchlĂŒssel | Bedeutung |
|---|---|
| `v` | Wert |
| `u` | Einheit |
| `t` | Zeitstempel (ISO 8601) |
| `q` | QualitÀt: `good` / `bad` / `uncertain` |
**Wert setzen:**
```bash
mosquitto_pub -t "dp/550e8400-.../set" -m '{"v": 22.5}'
```
---
## Datentypen
| Typ | Beschreibung | MQTT-Format |
|---|---|---|
| `BOOLEAN` | Ein/Aus | `true` / `false` |
| `INTEGER` | Ganze Zahl | Zahl |
| `FLOAT` | Dezimalzahl | Zahl |
| `STRING` | Text | Zeichenkette |
| `DATE` | Datum | `JJJJ-MM-TT` |
| `TIME` | Uhrzeit | `HH:MM:SS` |
| `DATETIME` | Datum und Uhrzeit | ISO 8601 mit Zeitzone |
| `UNKNOWN` | Unbekannt | Hexadezimal-Text |
Typumwandlungen sind verlustfrei wo möglich â bei Verlust wird eine Meldung ins Protokoll geschrieben.
---
## Einstellungen
Die Einstellungen sind ĂŒber die WeboberflĂ€che erreichbar (â in der Seitenleiste).
**Allgemein:**
- **Zeitzone** â alle Zeitangaben in der OberflĂ€che werden in dieser Zeitzone dargestellt (Verlauf, RingBuffer, History-Suche, Astro-Block)
- **KNX-Projektdatei importieren** â ETS-Projektdatei (`.knxproj`) hochladen, um Gruppenadressen als SuchvorschlĂ€ge im VerknĂŒpfungs-Formular zu nutzen
**Verlauf:** Ăbersicht aller Datenpunkte mit History-Aufzeichnung. Datenpunkte mit deaktivierter Aufzeichnung (`record_history: false`) werden zuerst angezeigt. Aufzeichnung per Datenpunkt ein- und ausschalten.
**Passwort:** Eigenes Anmeldepasswort Àndern
**Benutzer** (nur Administratoren): Benutzer anlegen, löschen, MQTT-Zugang verwalten
**API-SchlĂŒssel:** SchlĂŒssel fĂŒr die Anbindung externer Systeme erstellen und widerrufen
**Sicherung:** VollstÀndige Konfiguration herunterladen oder einspielen
---
## Hilfsskripte
### Import-EtsGaCsv.ps1 â ETS-GA-Export importieren
Das Skript `scripts/Import-EtsGaCsv.ps1` liest einen ETS-GA-CSV-Export und legt je Gruppenadresse
automatisch einen DataPoint mit passendem Typ und Einheit an. Anschliessend wird eine
VerknĂŒpfung zur angegebenen KNX-Adapter-Instanz erstellt.
**Voraussetzungen:** PowerShell 5.1 oder neuer, erreichbare **open bridge server**-Instanz, gĂŒltiger API-SchlĂŒssel.
**Parameter:**
| Parameter | Pflicht | Beschreibung |
|---|---|---|
| `-Url` | ja | Basis-URL der **open bridge server**-Instanz, z.B. `http://localhost:8080` |
| `-ApiKey` | ja | API-SchlĂŒssel (`obs_âŠ`) |
| `-File` | ja | Pfad zur ETS-GA-CSV-Datei |
| `-Adapter` | ja | Name der KNX-Adapter-Instanz in **open bridge server** |
| `-LogFile` | nein | Pfad fĂŒr Fehlerprotokoll; ohne Angabe werden Fehler auf der Konsole ausgegeben |
| `-Direction` | nein | VerknĂŒpfungsrichtung: `SOURCE` (Standard), `DEST` oder `BOTH` |
| `-Encoding` | nein | Zeichenkodierung der CSV-Datei: `UTF8` (Standard) oder `Default` (ANSI/Windows-1252). ETS 5 exportiert i.d.R. ANSI, ETS 6 UTF-8. |
**CSV-Format (ETS 5/6 GA-Export):**
Der Export erfolgt in ETS ĂŒber *Gruppenadressliste exportieren â CSV*. Das Skript erkennt Semikolon- und
Komma-Trennzeichen sowie deutschsprachige und englischsprachige Spaltenköpfe automatisch.
```
"Group name";"Address";"Central";"Unfiltered";"Description";"Comment";"DatapointType";"Security"
"Wohnzimmer Temperatur";"1/1/1";"";"";"";"";DPST-9-1;Auto
"Wohnzimmer Helligkeit";"1/1/2";"";"";"";"";DPST-9-2;Auto
"Rolllade EG Auf/Ab";"1/2/1";"";"";"";"";DPST-1-8;Auto
```
DPT-Angaben im Format `DPST-X-Y` (Haupt- und Subtyp) oder `DPT-X` (nur Haupttyp) werden
automatisch in das **open bridge server**-Format (`DPT9.001`) umgewandelt und der passende Datentyp (`FLOAT`,
`INTEGER`, `BOOLEAN`, `STRING`) sowie die Einheit werden gesetzt. Fehlt der DPT, wird `FLOAT`
ohne Einheit verwendet.
**Beispiel:**
```powershell
.\scripts\Import-EtsGaCsv.ps1 `
-Url http://localhost:8080 `
-ApiKey obs_abc123 `
-File C:\Projekte\GA_Export.csv `
-Adapter "KNX/IP"
```
ETS 5 (ANSI-Kodierung):
```powershell
.\scripts\Import-EtsGaCsv.ps1 `
-Url http://localhost:8080 `
-ApiKey obs_abc123 `
-File C:\Projekte\GA_Export.csv `
-Adapter "KNX/IP" `
-Encoding Default
```
Mit Fehlerprotokoll:
```powershell
.\scripts\Import-EtsGaCsv.ps1 `
-Url http://localhost:8080 `
-ApiKey obs_abc123 `
-File C:\Projekte\GA_Export.csv `
-Adapter "KNX/IP" `
-LogFile C:\Projekte\import_errors.log
```
Das Skript lÀuft bei Einzelfehlern durch. Am Ende werden Anzahl der erfolgreich importierten,
ĂŒbersprungenen (Zeilen ohne Adresse) und fehlgeschlagenen GAs ausgegeben.
---
## Visualisierung (Visu)
Die Visu-OberflĂ€che ist eine separate Single-Page-App (erreichbar unter `/visu/`), mit der interaktive BedienoberflĂ€chen â sogenannte **Visu-Seiten** â erstellt und im Vollbildmodus auf Displays oder Tablets angezeigt werden können. Jede Seite besteht aus frei platzierbaren Widgets, die Datenpunkte anzeigen oder steuern.
### Grundriss- und Anlagenschema-Widget
Das **Grundriss-Widget** ermöglicht es, einen GebĂ€udegrundriss oder ein Anlagenschema als interaktiven Hintergrund in eine Visu-Seite einzubinden. Auf dem Bild lassen sich Bereiche (Polygone) definieren, beschriften und mit Aktionen verknĂŒpfen â sowie Mini-Widgets direkt auf dem Plan platzieren.
#### Bild einbinden
Im Konfigurations-Panel des Widgets kann ein Bild hochgeladen werden (SVG, PNG oder JPG). Das Bild wird als Base64-Data-URL direkt im Konfig-JSON gespeichert â kein separater Upload-Endpunkt nötig. Bei Dateien ĂŒber 2 MB erscheint ein Hinweis; fĂŒr Grundrisse wird **SVG empfohlen**, da es verlustfrei skaliert.
Die **Rotation** des Bildes lÀsst sich in 90°-Schritten einstellen (0° / 90° / 180° / 270°), um Landscape-Grafiken direkt im Portrait-Modus verwenden zu können.
#### Bereiche (Polygone) zeichnen
Mit dem Polygon-Werkzeug im Vollbild-Canvas lassen sich Bereiche auf dem Grundriss einzeichnen:
1. Im Konfigurations-Panel auf **Neuer Bereich** klicken â der Fullscreen-Canvas öffnet sich.
2. Durch Klicken auf die ArbeitsflÀche werden Eckpunkte des Polygons gesetzt.
3. Das Polygon wird geschlossen, indem der erste Punkt erneut angeklickt oder **Enter** gedrĂŒckt wird.
Jedem Bereich können folgende Eigenschaften zugewiesen werden:
| Eigenschaft | Beschreibung |
|---|---|
| **Name** | Bezeichnung des Bereichs (z. B. âWohnzimmer") |
| **Beschriftung anzeigen** | Schaltet die Textbeschriftung auf dem Plan ein/aus |
| **Beschriftungsfarbe** | Textfarbe der Bereichsbeschriftung |
| **Beschriftungsposition** | Durch Klick auf den Bereich im Canvas frei positionierbar |
| **Aktion bei Klick** | `Keine` oder `Navigation` â bei Navigation: Ziel-Visu-Seite auswĂ€hlen |
#### Navigation zwischen Seiten
Wenn als Klick-Aktion **Navigation** gewĂ€hlt wird, öffnet sich eine Seitenauswahl. Die gewĂ€hlte Visu-Seite wird beim Klick auf den Bereich im Viewer direkt aufgerufen. So lassen sich z. B. EtagenplĂ€ne miteinander verknĂŒpfen â Klick auf einen Raum öffnet eine Detailansicht.
#### Mini-Widgets platzieren
Auf dem Grundriss können beliebige **Mini-Widgets** (z. B. Schalter, Temperaturanzeige, Dimmregler) direkt auf dem Plan positioniert werden:
1. Im Konfigurations-Panel auf **Mini-Widget hinzufĂŒgen** klicken und den Widget-Typ wĂ€hlen.
2. Auf **Positionieren** klicken â der Fullscreen-Canvas öffnet sich.
3. Das Mini-Widget per **Drag & Drop** an die gewĂŒnschte Stelle auf dem Plan ziehen.
FĂŒr jedes Mini-Widget lassen sich einstellen:
| Eigenschaft | Beschreibung |
|---|---|
| **Widget-Typ** | Beliebiger Visu-Widget-Typ (Schalter, Anzeige, Dimmer, âŠ) |
| **Datenpunkt** | Steuert den Wert des Widgets (Hauptdatenpunkt) |
| **Status-Datenpunkt** | Optionaler zweiter Datenpunkt fĂŒr den Anzeigestatus |
| **Breite / Höhe** | GröĂe des Mini-Widgets in Pixeln |
| **Sichtbar** | Blendet das Widget im Viewer ein oder aus |
Mini-Widgets drehen sich beim Rotieren des Grundrisses nicht mit â sie bleiben immer aufrecht und werden anhand der Bildkoordinaten korrekt ĂŒber dem Grundriss positioniert.
---
## Entwicklung
### Lokale Entwicklung mit PyCharm
Das Repository enthĂ€lt vorkonfigurierte [PyCharm](https://www.jetbrains.com/de-de/pycharm/)-Startkonfigurationen im Verzeichnis `.run/`. Nach dem Ăffnen des Projekts stehen sie direkt in der Run-Auswahl zur VerfĂŒgung.
#### Einmalige Einrichtung
**1. Python-Umgebung anlegen**
```bash
cd openbridgeserver
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt -r requirements_dev.txt
```
In PyCharm unter **Settings â Project â Python Interpreter** den Interpreter `.venv/bin/python` auswĂ€hlen.
**2. Frontend-AbhÀngigkeiten installieren**
```bash
cd gui && npm install
```
**3. Konfigurationsdatei anlegen**
```bash
cp config.example.yaml config.yaml
```
Folgende Werte in `config.yaml` anpassen:
```yaml
mqtt:
username: obs
password: change-this-mqtt-service-password # muss mit .env ĂŒbereinstimmen
database:
path: /absoluter/pfad/zum/projekt/data/obs.db # lokaler Pfad, kein /data
mosquitto:
passwd_file: /absoluter/pfad/zum/projekt/data/mosquitto/passwd
reload_pid: null
reload_command: null
service_username: obs
service_password: change-this-mqtt-service-password
```
**4. Umgebungsvariablen einrichten**
```bash
cp .env.example .env # falls noch nicht vorhanden
```
Die `.env`-Datei enthĂ€lt das MQTT-Passwort, mit dem der Docker-Mosquitto initialisiert wird â dieser Wert muss mit `mqtt.password` in `config.yaml` ĂŒbereinstimmen.
#### Starten
| Run-Konfiguration | Beschreibung |
|---|---|
| **OBS Mosquitto (Docker)** | Startet den MQTT-Broker via Docker |
| **OBS Backend** | Startet den FastAPI-Server auf `localhost:8080` |
| **OBS GUI (Admin)** | Startet den Vite-Dev-Server auf `localhost:5173` |
| **OBS Full Dev Stack** | Startet alle drei gleichzeitig (Compound) |
> **Voraussetzung:** Docker Desktop muss laufen (fĂŒr den Mosquitto-Broker).
#### Erreichbare Dienste im Dev-Modus
| Dienst | Adresse |
|---|---|
| Admin-GUI | http://localhost:5173 |
| API (Swagger) | http://localhost:8080/docs |
| MQTT | localhost:1883 |
**Standardzugang:** `admin` / `admin`
#### Tests ausfĂŒhren
```bash
# Nur Unit- und Adapter-Tests (kein Docker nötig)
pytest tests/unit/ tests/adapters/
# Alle Tests inkl. Integration (Docker muss laufen)
pytest tests/
```
#### Lint lokal (identisch zu GitHub CI)
```bash
# Nur prĂŒfen (gleiches Verhalten wie CI-Job)
./tools/lint.sh --check
# Mit Auto-Fix
./tools/lint.sh --fix
```
#### Lokale Builds (Docker-Image, LXC-Template, App-Bundle)
VollstĂ€ndige Dokumentation zu `build-local.sh` â Befehle, Optionen und das Docker-Image-Namensschema â siehe **[tools/README.de.md](tools/README.de.md)**.
### Lokale Git-Hooks (Pre-Push Gate)
Versionierte Hooks liegen in `.githooks/`. Um sie in einem Klon zu aktivieren, `core.hooksPath` einmalig setzen:
```bash
./tools/setup-git-hooks.sh
```
Bei jedem `git push` fĂŒhrt der Hook aus:
- `./scripts/check-i18n-hardcoded-strings.sh`
- `python3 -m ruff check .`
- `python3 -m ruff format . --check`
- `pytest tests/ -v --cov=obs --cov-report=xml --cov-report=term --junitxml="${TMPDIR:-/tmp}/openbridge-pre-push-junit.xml"`
Einmalig umgehen:
```bash
git push --no-verify
```
---
#### Ăbersetzungen (Weblate / wlc)
Die GUI-Ăbersetzungen werden ĂŒber [hosted.weblate.org](https://hosted.weblate.org/projects/openbridgeserver/) verwaltet. Quellsprache ist Deutsch (`de.json`); die Community ĂŒbersetzt auf Weblate.
**Voraussetzung:** `wlc` ist bereits in `requirements_dev.txt` enthalten und wird bei der normalen Einrichtung mitinstalliert.
Zugangsdaten einrichten â entweder in `~/.config/weblate`:
```ini
[weblate]
url = https://hosted.weblate.org/api/
[keys]
https://hosted.weblate.org/api/ =
```
oder via Umgebungsvariablen: `WLC_URL` / `WLC_KEY`.
**Quell-Strings hochladen** (nach Ănderungen an `de.json`):
```bash
wlc push gui-admin # Admin-GUI (gui/src/locales/de.json)
wlc push frontend-visu # Visu-SPA (frontend/src/locales/de.json)
```
**Ăbersetzungen herunterladen** (nach Community-Ăbersetzungen auf Weblate):
```bash
wlc pull gui-admin
wlc pull frontend-visu
```
Die Weblate-Projektkonfiguration liegt in `.weblate` im Projektwurzelverzeichnis.
---
### Starten ohne Docker
```bash
# Mosquitto (temporÀr)
docker run -d -p 1883:1883 eclipse-mosquitto:2
# Konfiguration
cp config.example.yaml config.yaml
# Server mit automatischem Neustart bei CodeÀnderungen
uvicorn obs.main:create_app --factory --reload --host 0.0.0.0 --port 8080
```
### Datenbankstruktur
Die Datenbank wird automatisch aktualisiert â jede neue Version fĂŒgt fehlende Tabellen und Spalten hinzu, ohne bestehende Daten zu verlieren. Aktuelle Version: **V21**.
| Tabelle | Inhalt |
|---|---|
| `datapoints` | Alle Datenpunkte (inkl. `persist_value`- und `record_history`-Flag) |
| `adapter_bindings` | VerknĂŒpfungen zwischen Datenpunkten und Adaptern (inkl. `value_map`) |
| `adapter_instances` | Adapter-Instanzen |
| `users` | Benutzerkonten |
| `api_keys` | API-SchlĂŒssel (nur als Hashwert gespeichert) |
| `history_values` | Werteverlauf (inkl. `source_adapter`) |
| `logic_graphs` | Logik-Graphen (inkl. gespeichertem Block-Zustand) |
| `app_settings` | Systemeinstellungen (z. B. Zeitzone) |
| `datapoint_last_values` | Letzter bekannter Wert je Datenpunkt â wird beim Start wiederhergestellt |
---
## Ăbersetzungen
ZukĂŒnftig möchten wir [Weblate](https://hosted.weblate.org/projects/open-bridge-server) fĂŒr Community-Ăbersetzungen verwenden. Sobald das möglich ist, sind BeitrĂ€ge sind jederzeit willkommen.
## Lizenz
MIT â kostenlos und quelloffen.
[tests]: https://github.com/abeggled/openbridgeserver/actions/workflows/unittest.yml
[tests-badge]: https://img.shields.io/github/actions/workflow/status/abeggled/openbridgeserver/unittest.yml?style=for-the-badge&logo=github&logoColor=ccc&label=Tests
[coverage]: https://app.codecov.io/github/abeggled/openbridgeserver
[coverage-badge]: https://img.shields.io/codecov/c/github/abeggled/openbridgeserver?style=for-the-badge&logo=codecov&logoColor=ccc&label=Coverage