- git rm --cached odoo: Gitlink-Eintrag entfernt, odoo/ wird jetzt korrekt versioniert - odoo/src/odoo-dev.conf: db_name = odoo gesetzt (behebt 404 bei mehreren DBs) - docs/FEATURE_REQUEST_DYNAMIC_PARSER_REGISTRY.md: Feature Request inkl. ADR - docs/IMPLEMENTATION_PLAN_DYNAMIC_PARSER_REGISTRY.md: 3-Phasen-Implementierungsplan - iot_bridge/README.md: Doku aktualisiert
6.2 KiB
Feature Request: Dynamic Parser Registry
Stand: 2026-03-10
Status: Architektur entschieden
Umsetzungs-Plan: docs/IMPLEMENTATION_PLAN_DYNAMIC_PARSER_REGISTRY.md
Motivation
Der parser_type ist derzeit an zwei Stellen hartcodiert:
- IoT Bridge (
core/device_manager.py): Es gibt einen einzigen globalenShellyParser().
Derparser_type-String aus der Konfiguration wird zwar transportiert, aber vollständig ignoriert. - Odoo (
models/mqtt_device.py): Das Feldparser_typeist ein statischesfields.Selection
mit fest eingetragenen Werten (shelly_pm,tasmota,generic).
Es gibt keinen API-Call zur Bridge, um verfügbare Parser dynamisch zu ermitteln.
Das Ergebnis: Neue Parser können nicht hinzugefügt werden, ohne Code an mehreren Stellen
manuell anzupassen – und die Odoo-Konfiguration bleibt inkonsistent mit dem, was die Bridge
tatsächlich unterstützt.
Ziele
1. Erweiterbare Parser-Registry in der IoT Bridge
Die Bridge soll eine Registry führen, die parser_type-Strings auf Parser-Klassen abbildet.
Neue Parser können registriert werden, ohne den DeviceManager oder andere Kern-Komponenten
zu ändern.
Aktueller Zustand:
self.parser = parser or ShellyParser() # global, für alle Geräte
Ziel:
- Pro-Gerät-Parser statt einem globalen Parser
- Registry-lookup beim Anlegen eines Geräts:
parser_type → ParserClass - Unbekannte
parser_type-Strings erzeugen einen klar verständlichen Fehler (kein Silent-Fallback)
Die Registry soll außerdem einen API-Endpunkt (GET /parsers o. ä.) bereitstellen,
der die aktuell verfügbaren Parser-Typen auflistet.
2. Automatische Erkennung verfügbarer Parser in Odoo
Das parser_type-Feld in ows.mqtt.device soll nicht mehr hartcodiert sein.
Stattdessen ruft Odoo zur Laufzeit die Liste der verfügbaren Parser von der Bridge ab
(GET /parsers o. ä.) und befüllt die Auswahl dynamisch.
Mögliche Mechanismen:
fields.Selectionmit dynamischerselection-Methode, die die Bridge befragt- Alternativer Ansatz: separates Modell
ows.mqtt.parser.typemit Sync-Button / Cron
Welcher Mechanismus gewählt wird, ist Teil der Implementierungsplanung.
3. Parser-typ-abhängige Konfigurationsparameter in Odoo
Verschiedene Parser benötigen unterschiedliche Konfigurationsparameter.
Die aktuellen Felder (Leistungs-Schwellenwerte, Debounce-Zeiten usw.) sind spezifisch
für den Shelly-PM-Parser und ergeben für andere Gerätetypen keinen Sinn.
Ziel: Die Odoo-Oberfläche zeigt nur die Parameter an, die für den gewählten parser_type
relevant sind. Die Bridge kennt pro Parser-Typ das zugehörige Konfigurations-Schema
(JSON Schema o. ä.) und stellt dieses ebenfalls über die API bereit.
Damit kann Odoo:
- Irrelevante Felder ausblenden (
attrs/invisiblein der View) - Validierung parser-spezifisch durchführen
- Das korrekte Konfigurations-JSON für die Bridge generieren
Abgrenzung
- Die konkrete Implementierung eines zweiten Parsers (z. B. Laser-Cutter On/Off) ist
nicht Teil dieses Feature Requests. Sie setzt aber diese Architektur voraus. - Die Frage, welche Felder ein neuer Parser benötigt, wird im jeweiligen Parser-spezifischen
Issue/Plan geklärt.
Architektur-Entscheidung (ADR)
Datum: 2026-03-10
Entscheidung: Bridge als Single Source of Truth, Odoo bleibt statisch
Kontext
IoT Bridge und Odoo-Modul sind fest gekoppelt – sie werden gemeinsam deployed.
Ein neuer Parser erfordert immer eine Änderung an beiden Komponenten.
Entscheidung
Die Bridge ist die einzige Stelle, an der ein Parser definiert wird.
Das Odoo-Modul ist das statisch abgeleitete Ergebnis dieser Definition.
GET /parsers (JSON-Schema, definiert in der Bridge)
│
▼
Ableitung (bei jedem neuen Parser, manuell oder per Script)
│
├──▶ Python-Felder im Odoo-Modell (fields.Integer, fields.Float, …)
├──▶ XML-View mit invisible-Logik (attrs invisible="parser_type != 'x'")
└──▶ Selection-Eintrag ('shelly_pm', 'Shelly PM Mini G3')
Schema-Format (Bridge → Ableitungsgrundlage)
Die Bridge liefert pro Parser-Typ ein maschinenlesbares Parameter-Schema:
{
"shelly_pm": {
"display_name": "Shelly PM Mini G3",
"parameters": [
{
"key": "power_on_threshold_w",
"odoo_field": "power_on_threshold_w",
"type": "integer",
"unit": "W",
"label": "Einschalt-Schwelle",
"default": 20,
"required": true,
"group": "session_detection",
"help": "Ab welcher Leistung gilt das Gerät als eingeschaltet?"
}
]
}
}
Aus jedem Parameter-Eintrag lässt sich eindeutig ableiten:
| Schema-Feld | Odoo-Artefakt |
|---|---|
odoo_field + type |
Feldname und Feldtyp im Python-Modell |
label |
string= im Feldaufruf |
help |
help= im Feldaufruf |
default |
default= im Feldaufruf |
required |
required=True (optional: nur pro Parser-Typ) |
parser_types (Liste) |
invisible-Bedingung in der XML-View |
Konsequenzen
Gewinn:
- Kein EAV, kein Runtime-Rendering, kein Verbiegen des Odoo-Frameworks
- Odoo bleibt wartbar und testbar wie bisher
- Neue Parser = kleiner, mechanischer Änderungsaufwand in Odoo
Akzeptierter Kompromiss:
- Ein neuer Parser erfordert ein neues Odoo-Modul-Deployment
- Die
GET /parsers-Antwort der Bridge und das Odoo-Modell können theoretisch
aus dem Sync geraten – wird durch Tests/CI abgesichert
Betroffene Komponenten (erster Überblick)
| Komponente | Datei(en) | Art der Änderung |
|---|---|---|
| IoT Bridge – Parser-Registry | parsers/__init__.py, neu: parsers/registry.py |
Neu |
| IoT Bridge – DeviceManager | core/device_manager.py |
Umbau: pro-Gerät-Parser |
| IoT Bridge – API | api/models.py, api/server.py |
Erweiterung: GET /parsers |
| Odoo – mqtt_device | models/mqtt_device.py |
Umbau: dynamisches Selection-Feld |
| Odoo – Views | views/mqtt_device_views.xml |
Umbau: bedingte Sichtbarkeit |
| Odoo – API-Client | (neu oder bestehend) | Neu: Fetch verfügbarer Parser |