Skip to content

Commit e24d668

Browse files
committed
feat: Implement MQTT command interface for various commands with tests
1 parent c28f2db commit e24d668

19 files changed

+1719
-1797
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# ADR 001: MQTT Topic Struktur und Versionierung
2+
3+
## Kontext
4+
5+
Die vorhandene MQTT-Integration in PySignalduino verfügt über eine minimale Topic-Struktur für Telemetrie, aber keine konsistente, versionierte Befehlsschnittstelle. Für die Implementierung einer konsistenten API für alle Firmware-Parameter ist eine klare Struktur und Versionierung erforderlich, um Zukunftsfähigkeit und Wartbarkeit zu gewährleisten.
6+
7+
## Entscheidung
8+
9+
Wir führen eine hierarchische und versionierte Topic-Struktur für Befehle, Antworten und Statusmeldungen ein.
10+
11+
**Struktur:** `signalduino/<version>/<type>/<target>/<parameter>`
12+
13+
**Beispiele:**
14+
* **Befehle (Commands):** `signalduino/v1/commands/set/cc1101/frequency`
15+
* **Antworten (Responses):** `signalduino/v1/responses/get/system/version`
16+
* **Fehler (Errors):** `signalduino/v1/errors/set/cc1101/frequency`
17+
* **Status (State):** `signalduino/v1/state/device/uptime`
18+
19+
## Begründung
20+
21+
1. **Versionierung (`v1`):** Durch die Topic-Versionierung können wir später Breaking Changes einführen (z.B. `v2`) und ältere Clients über einen längeren Zeitraum unterstützen, ohne die gesamte Infrastruktur sofort anpassen zu müssen.
22+
2. **Hierarchie (`commands`/`responses`/`errors`):** Die klare Trennung von Request- und Response-Topics vereinfacht die clientseitige Implementierung und ermöglicht eine präzise Konfiguration von MQTT-ACLs (Access Control Lists). Clients müssen nur Topics abonnieren, die für ihre Rolle relevant sind (z.B. nur `responses` und `errors`).
23+
3. **Konsistenz (`get`/`set`/`command`):** Das Paradigma spiegelt die gängige Praxis in modernen APIs (REST, IoT) wider und bietet eine intuitive Steuerung für alle Firmware-Parameter.
24+
25+
## Konsequenzen
26+
27+
* **Code-Änderungen:** Der MQTT-Client in PySignalduino muss so erweitert werden, dass er Befehle auf diesen spezifischen Topics abonniert und eingehende Payloads entsprechend dem `type` (`get`/`set`/`command`) an einen Command Dispatcher weiterleitet.
28+
* **Kompatibilität:** Es besteht keine Abwärtskompatibilität zur bisherigen minimalen MQTT-Integration. Da diese jedoch ohnehin unstrukturiert und unvollständig war, wird dies als akzeptabler Breaking Change im Zuge der Implementierung der V1-API angesehen.
29+
* **Dokumentation:** Alle Clients und die Benutzerdokumentation müssen auf diese neue Topic-Struktur umgestellt werden.
30+
31+
---
32+
[Fortsetzung in ADR-002]
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# ADR 002: Command Dispatcher Pattern und JSON-Schema-Validierung
2+
3+
## Kontext
4+
5+
Die Verarbeitung eingehender MQTT-Befehle erfordert Robustheit, Skalierbarkeit und strenge Eingabeverifizierung, insbesondere da die Befehle direkt in serielle Kommandos für die Firmware übersetzt werden, was kritische Hardware-Einstellungen beeinflussen kann (z.B. CC1101-Register). Ein direktes Mapping von Topic zu Funktion ist unflexibel und anfällig für ungültige Eingaben.
6+
7+
## Entscheidung
8+
9+
Wir implementieren einen dedizierten **Command Dispatcher** als zentrale Komponente zwischen der MQTT-Schnittstelle und dem `SignalduinoController`. Jeder eingehende Befehl wird vor der Ausführung einer strikten **JSON-Schema-Validierung** unterzogen.
10+
11+
**Workflow des Dispatchers:**
12+
1. MQTT-Interface empfängt Payload.
13+
2. Dispatcher extrahiert `command_name`, `target`, `type` und `req_id`.
14+
3. Dispatcher übergibt Payload an den **Input Validator**.
15+
4. Der Validator verwendet ein dem `command_name` zugeordnetes JSON-Schema, um die `value` und `parameters` zu prüfen.
16+
5. Nur bei erfolgreicher Validierung wird der Befehl an den **Command Executor** weitergeleitet.
17+
18+
## Begründung
19+
20+
1. **Sicherheit und Stabilität:** Die JSON-Schema-Validierung garantiert, dass nur erwartete Datenformate und Wertebereiche an den Core-Controller und letztlich an die serielle Schnittstelle gelangen. Dies verhindert Pufferüberläufe oder die Einstellung illegaler Hardware-Werte.
21+
2. **Entkopplung:** Der Command Dispatcher entkoppelt die MQTT-Topics von den internen Python-Methoden. Topic-Änderungen erfordern keine Anpassung der Business-Logik.
22+
3. **Flexibilität:** Das Muster ermöglicht eine einfache Erweiterung um neue Befehle und Befehls-Typen (z.B. zukünftige `batch`-Befehle) ohne Modifikation der Kernlogik.
23+
4. **Strukturierte Fehlerbehandlung:** Validierungsfehler können sofort mit einem HTTP 400-ähnlichen Status (Bad Request) beantwortet werden, bevor Ressourcen für die serielle Kommunikation verschwendet werden.
24+
25+
## Konsequenzen
26+
27+
* **Neue Komponenten:** Es müssen die Komponenten `Command Dispatcher` und `Input Validator` (mit Integration einer JSON-Schema-Bibliothek wie `jsonschema`) implementiert werden.
28+
* **Wartungsaufwand:** Für jeden neuen Befehl muss ein entsprechendes JSON-Schema definiert und gewartet werden. Dies ist ein akzeptabler Aufwand im Austausch für erhöhte Robustheit und Sicherheit.
29+
* **Abhängigkeiten:** Die externe Abhängigkeit zu einer JSON-Schema-Validierungsbibliothek wird hinzugefügt.
30+
31+
---
32+
[Ende der ADRs für diese Architekturphase]
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
= Architekturproposal: Erweiterung der MQTT-Schnittstelle um Firmware-Befehle
2+
:revdate: 2025-12-21
3+
:page-layout: proposal
4+
:sectnums:
5+
:toc: left
6+
:toc-title: Inhalt
7+
8+
<<<
9+
10+
== 1. Einleitung und Zielsetzung
11+
12+
Dieses Architekturproposal definiert die Integration von direkten Firmware-Steuerungsbefehlen (`set raw`, `set cc1101_reg`) in die `PySignalduino` MQTT-API (V1), basierend auf den etablierten Architekturentscheidungen in ADR-001 und ADR-002. Ziel ist es, die volle Funktionalität der seriellen Schnittstelle über MQTT verfügbar zu machen.
13+
14+
== 2. Betroffene Komponenten
15+
16+
* `signalduino/mqtt.py`: Muss Abonnements für die neuen Command-Topics registrieren.
17+
* `signalduino/controller.py`: Muss um die Logik zur Ausführung dieser Befehle erweitert werden.
18+
* `Command Dispatcher` (gemäß ADR-002): Neue Routen und JSON-Schemas für die Validierung müssen hinzugefügt werden.
19+
20+
== 3. Definition der MQTT-Kommandos
21+
22+
Die neuen Befehle folgen der in ADR-001 definierten Struktur: `signalduino/v1/commands/set/<target>/<parameter>`. Das Payload-Format ist strikt JSON und wird durch den Command Dispatcher validiert.
23+
24+
=== 3.1. `set raw` (Senden von rohen Firmware-Befehlen)
25+
26+
|===
27+
| Thema | `signalduino/v1/commands/set/firmware/raw`
28+
| Payload-Format | JSON
29+
| Payload-Schema (Teilauszug) | Objekt mit `value` (String, z.B. C11)
30+
| Beispiel Payload | `{"value": "C11"}`
31+
| Beschreibung | Leitet den String im Feld `value` direkt als seriellen Befehl an die Firmware weiter.
32+
|===
33+
34+
=== 3.2. `set cc1101_reg` (Setzen eines CC1101-Registers)
35+
36+
Dieser Befehl ermöglicht das Setzen eines spezifischen CC1101-Registers.
37+
38+
|===
39+
| Thema | `signalduino/v1/commands/set/cc1101/register`
40+
| Payload-Format | JSON
41+
| Payload-Schema (Teilauszug) | Objekt mit `address` (Hex-String, 2 Zeichen) und `value` (Hex-String, 2 Zeichen)
42+
| Beispiel Payload | `{"address": "0D", "value": "2E"}`
43+
| Beschreibung | Setzt das CC1101-Register an der Adresse `address` auf den Wert `value`. Alle Werte müssen als Hex-Strings (z.B. "0D") übergeben werden.
44+
|===
45+
46+
== 4. Architekturentscheidung und Begründung
47+
48+
Basierend auf den Anforderungen wird die folgende Entscheidung getroffen und in das Projekt-ADR-System integriert:
49+
50+
[IMPORTANT]
51+
====
52+
**Titel:** Integration der Firmware-Steuerbefehle (`raw`, `cc1101_reg`) in die V1 MQTT-API
53+
54+
**Kontext:** Um PySignalduino zu einem vollständigen Backend für Steuerungs-Frontends (wie FHEM) zu machen, ist es erforderlich, die direkten Steuerungsmöglichkeiten der seriellen Schnittstelle (z.B. Frequenz- und Registermanipulation) über die standardisierte MQTT-API anzubieten.
55+
56+
**Entscheidung:**
57+
Die Befehle `set raw` und `set cc1101_reg` werden unter den in Abschnitt 3.1 und 3.2 definierten Topics und Payloads in die MQTT-Schnittstelle integriert. Die strikte **JSON-Schema-Validierung** wird für beide Befehle implementiert.
58+
59+
**Begründung:**
60+
* **Vollständigkeit:** Diese Befehle schließen eine kritische Lücke im Funktionsumfang der MQTT-API im Vergleich zur seriellen Schnittstelle.
61+
* **Sicherheit:** Die direkte Manipulation der CC1101-Hardware erfordert höchste Sorgfalt. Die in ADR-002 beschlossene **JSON-Schema-Validierung** ist für diese Befehle zwingend erforderlich, um sicherzustellen, dass nur gültige Adressen und Werte an die Firmware gesendet werden.
62+
* **Konsistenz:** Durch die Verwendung der `signalduino/v1/commands/set` Topic-Hierarchie wird die Konsistenz mit dem Rest der API gewahrt.
63+
64+
**Konsequenzen:**
65+
* Es müssen zwei neue JSON-Schemas für die Validierung erstellt werden.
66+
* Der `Command Dispatcher` muss erweitert werden, um diese Befehle zu routen.
67+
* Die Kernfunktionalität muss in `signalduino/controller.py` implementiert werden.
68+
====
69+
70+
== 5. Compliance-Checks (Mermaid)
71+
72+
Der erweiterte Workflow visualisiert die Verarbeitung eines CC1101-Registersatzbefehls:
73+
74+
[mermaid, flowchart, "CC1101 Register Set Workflow"]
75+
----
76+
flowchart TD
77+
A[MQTT Client sendet set cc1101_reg] --> B{Topic: signalduino/v1/commands/set/cc1101/register}
78+
B --> C[MQTT Interface empfängt Payload]
79+
C --> D[Command Dispatcher]
80+
D --> E{Input Validator (JSON Schema)}
81+
E -- Validierung fehlgeschlagen --> F[Error Response Topic publish]
82+
E -- Validierung erfolgreich --> G[SignalduinoController.execute_command]
83+
G --> H[Controller generiert serielle Raw-Befehle]
84+
H --> I[Transport Layer sendet an Hardware]
85+
I --> J{Hardware (SIGNALduino)}
86+
J --> K[Hardware setzt CC1101 Register]
87+
----
88+
89+
== 6. Nächste Schritte (Phase 2)
90+
91+
Nach Genehmigung dieses Proposals folgt die Implementierungsplanung (Phase 2) mit der Erstellung der JSON-Schemas und der genauen Definition der `Controller`-Methoden.
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Architekturproposal: Erweiterung der MQTT-Schnittstelle um Firmware-Befehle
2+
3+
**Datum:** 2025-12-21
4+
**Basis:** ADR-001 (Topic-Struktur), ADR-002 (Command Dispatcher)
5+
6+
## 1. Einleitung und Zielsetzung
7+
8+
Dieses Architekturproposal definiert die Integration von direkten Firmware-Steuerungsbefehlen (`set raw`, `set cc1101_reg`) in die `PySignalduino` MQTT-API (V1). Ziel ist es, die volle Funktionalität der seriellen Schnittstelle über MQTT verfügbar zu machen.
9+
10+
## 2. Definition der MQTT-Kommandos
11+
12+
Die neuen Befehle folgen der in ADR-001 definierten Struktur: `signalduino/v1/commands/set/<target>/<parameter>`. Das Payload-Format ist strikt JSON und wird durch den Command Dispatcher validiert.
13+
14+
### 2.1. `set raw` (Senden von rohen Firmware-Befehlen)
15+
16+
| Schlüssel | Wert |
17+
| :--- | :--- |
18+
| **Topic** | `signalduino/v1/commands/set/firmware/raw` |
19+
| **Payload-Format** | JSON |
20+
| **Payload-Schema (Teilauszug)** | Objekt mit `value` (String, z.B. C11) |
21+
| **Beispiel Payload** | `{"value": "C11"}` |
22+
| **Beschreibung** | Leitet den String im Feld `value` direkt als seriellen Befehl an die Firmware weiter. |
23+
24+
### 2.2. `set cc1101_reg` (Setzen eines CC1101-Registers)
25+
26+
| Schlüssel | Wert |
27+
| :--- | :--- |
28+
| **Topic** | `signalduino/v1/commands/set/cc1101/register` |
29+
| **Payload-Format** | JSON |
30+
| **Payload-Schema (Teilauszug)** | Objekt mit `address` (Hex-String, 2 Zeichen) und `value` (Hex-String, 2 Zeichen) |
31+
| **Beispiel Payload** | `{"address": "0D", "value": "2E"}` |
32+
| **Beschreibung** | Setzt das CC1101-Register an der Adresse `address` auf den Wert `value`. Alle Werte müssen als Hex-Strings (z.B. "0D") übergeben werden. |
33+
34+
## 3. Architekturentscheidung (ADR-Auszug)
35+
36+
> **Titel:** Integration der Firmware-Steuerbefehle (`raw`, `cc1101_reg`) in die V1 MQTT-API
37+
>
38+
> **Kontext:** Um PySignalduino zu einem vollständigen Backend für Steuerungs-Frontends (wie FHEM) zu machen, ist es erforderlich, die direkten Steuerungsmöglichkeiten der seriellen Schnittstelle (z.B. Frequenz- und Registermanipulation) über die standardisierte MQTT-API anzubieten.
39+
>
40+
> **Entscheidung:**
41+
> Die Befehle `set raw` und `set cc1101_reg` werden unter den in Abschnitt 2.1 und 2.2 definierten Topics und Payloads in die MQTT-Schnittstelle integriert. Die strikte **JSON-Schema-Validierung** wird für beide Befehle implementiert.
42+
>
43+
> **Begründung:**
44+
> 1. **Vollständigkeit:** Diese Befehle schließen eine kritische Lücke im Funktionsumfang der MQTT-API im Vergleich zur seriellen Schnittstelle.
45+
> 2. **Sicherheit:** Die direkte Manipulation der CC1101-Hardware erfordert höchste Sorgfalt. Die in ADR-002 beschlossene JSON-Schema-Validierung ist für diese Befehle zwingend erforderlich, um sicherzustellen, dass nur gültige Adressen und Werte an die Firmware gesendet werden.
46+
> 3. **Konsistenz:** Durch die Verwendung der `signalduino/v1/commands/set` Topic-Hierarchie wird die Konsistenz mit dem Rest der API gewahrt.
47+
48+
## 4. Compliance-Checks (Mermaid)
49+
50+
Der erweiterte Workflow visualisiert die Verarbeitung eines CC1101-Registersatzbefehls.
51+
52+
```mermaid
53+
flowchart TD
54+
A[MQTT Client sendet set cc1101_reg] --> B{Topic: signalduino/v1/commands/set/cc1101/register}
55+
B --> C[MQTT Interface empfängt Payload]
56+
C --> D[Command Dispatcher]
57+
D --> E{Input Validator (JSON Schema)}
58+
E -- Validierung fehlgeschlagen --> F[Error Response Topic publish]
59+
E -- Validierung erfolgreich --> G[SignalduinoController.execute_command]
60+
G --> H[Controller generiert serielle Raw-Befehle]
61+
H --> I[Transport Layer sendet an Hardware]
62+
I --> J{Hardware (SIGNALduino)}
63+
J --> K[Hardware setzt CC1101 Register]
64+
```

0 commit comments

Comments
 (0)