You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/01_user_guide/mqtt_api.adoc
+49-8Lines changed: 49 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -65,6 +65,47 @@ Eine erfolgreiche Response auf `signalduino/v1/responses` hat folgende Struktur:
65
65
}
66
66
----
67
67
68
+
[[_cli_tool]]
69
+
== CLI Tool zur Steuerung (`tools/sd_mqtt_cli.py`)
70
+
71
+
Das Skript `tools/sd_mqtt_cli.py` dient als einfaches Python-Kommandozeilen-Tool, um Befehle an das PySignalduino MQTT-Gateway zu senden und die Antworten zu empfangen.
72
+
73
+
=== Installation und Ausführung
74
+
75
+
Das Tool benötigt die `paho-mqtt` Abhängigkeit, die in der `requirements-dev.txt` enthalten ist.
76
+
77
+
[source,bash]
78
+
----
79
+
pip install paho-mqtt
80
+
python3 tools/sd_mqtt_cli.py --help
81
+
----
82
+
83
+
=== Verfügbare Kommandos
84
+
85
+
|===
86
+
| Kommando | Beschreibung | Beispiel
87
+
88
+
| `reset`
89
+
| Führt einen Factory Reset durch (`set/factory_reset`).
90
+
| `python3 tools/sd_mqtt_cli.py reset`
91
+
92
+
| `get all-settings`
93
+
| Fragt alle wichtigen CC1101-Einstellungen in einer aggregierten Nachricht ab.
94
+
| `python3 tools/sd_mqtt_cli.py get all-settings`
95
+
96
+
| `get hardware-status --parameter <param>`
97
+
| Fragt einen spezifischen CC1101-Parameter ab. Parameter: `frequency`, `bandwidth`, `rampl`, `sensitivity`, `datarate`.
98
+
| `python3 tools/sd_mqtt_cli.py get hardware-status --parameter frequency`
99
+
100
+
| `get system-status --parameter <param>`
101
+
| **NEU:** Fragt einen spezifischen System-Parameter ab. Parameter: `version`, `freeram`, `uptime`.
102
+
| `python3 tools/sd_mqtt_cli.py get system-status --parameter freeram`
103
+
104
+
| `poll`
105
+
| **NEU:** Fragt nacheinander alle verfügbaren System- und CC1101-Parameter ab. Nützlich zur Diagnose des aktuellen Gerätezustands.
106
+
| `python3 tools/sd_mqtt_cli.py poll`
107
+
|===
108
+
68
109
[[_get_commands]]
69
110
== GET Commands (Status und Konfiguration abrufen)
70
111
@@ -79,20 +120,20 @@ GET-Befehle benötigen eine leere Payload (`{}`) oder nur eine `req_id`.
= ADR-004: Strukturiertes Parsing serieller Antworten für MQTT GET-Befehle
2
+
:revdate: 2026-01-06
3
+
:author: Roo
4
+
5
+
== 1. Kontext
6
+
7
+
Die MQTT-Befehle `get/cc1101/*` (z.B. `get/cc1101/config`) und `get/config/decoder` schlagen mit Timeouts fehl, obwohl die serielle Kommunikation mit der SIGNALDuino-Firmware die Antworten empfängt. Die Ursache liegt darin, dass der `MqttCommandDispatcher` eine strukturierte JSON-Payload (ein Python-Dictionary) als `data`-Feld in der MQTT-Antwort erwartet. Die zugrundeliegenden `SignalduinoCommands` Methoden geben jedoch in diesen Fällen den *rohen* String der seriellen Firmware-Antwort zurück.
8
+
9
+
Der `MqttCommandDispatcher` kann diese String-Antworten nicht direkt in das JSON-Antwortformat umwandeln, was zu einem Abbruch der Verarbeitung und damit zum Timeout führt.
Zusätzlich müssen alle `get` Befehle, die einen rohen String zurückgeben, angepasst werden, um die Konsistenz des MQTT-API zu gewährleisten.
16
+
17
+
== 2. Entscheidung
18
+
19
+
Wir werden die `SignalduinoCommands` Methoden, die serielle GET-Befehle ausführen, so modifizieren, dass sie die rohe Firmware-Antwort parsen und ein konsistentes Python-Dictionary (`Dict[str, Any]`) zurückgeben. Dieses Dictionary wird dann vom `MqttCommandDispatcher` als JSON-Payload im `data`-Feld der MQTT-Antwort verwendet.
20
+
21
+
Dies stellt sicher, dass alle erfolgreichen `GET` Anfragen über MQTT eine strukturierte und maschinenlesbare JSON-Antwort erhalten und die Timeouts vermieden werden.
22
+
23
+
=== Detaillierte Logik-Anpassungen
24
+
25
+
1. **`get_config` (CG):**
26
+
* Wird eine private Hilfsfunktion `_parse_decoder_config(response: str) -> Dict[str, int]` in [`signalduino/commands.py`](signalduino/commands.py) implementiert.
27
+
* Diese Funktion parst den `key=value;` String in ein Dictionary (z.B. `{'MS': 1, 'MU': 1, 'MC': 1, 'Mred': 1}`).
28
+
* Der Rückgabetyp von `get_config` wird von `str` auf `Dict[str, int]` geändert.
29
+
30
+
2. **`get_ccconf` (C0DnF):**
31
+
* Diese Methode gibt einen String wie `C0Dn11=<Hex-Wert>` zurück.
32
+
* Die Methode wird angepasst, um die rohe String-Antwort in ein Dictionary zu kapseln, z.B. `{'cc1101_config_string': response_string}`.
33
+
* Der Rückgabetyp von `get_ccconf` wird von `str` auf `Dict[str, str]` geändert.
34
+
35
+
3. **Weitere einfache GET-Befehle:**
36
+
* Methoden wie `get_version`, `get_free_ram`, `get_uptime` geben bereits einen geparsten Wert zurück (String oder Int), der korrekt gekapselt wird. Diese Methoden bleiben unverändert, da sie bereits einen strukturierten Wert zurückgeben, der indirekt im `data`-Feld des MQTT-Payloads landet.
37
+
38
+
== 3. Konsequenzen
39
+
40
+
=== Positive
41
+
* **Behebung der Timeouts:** Die MQTT GET-Befehle für Konfigurationen werden korrekt beantwortet und die Timeouts behoben.
42
+
* **API-Konsistenz:** Alle MQTT `GET` Antworten liefern nun eine konsistente, JSON-serialisierbare Struktur.
43
+
* **Wartbarkeit:** Der Code wird robuster, da das Parsing der seriellen Antwort in der `commands.py`-Schicht zentralisiert ist.
44
+
45
+
=== Negative
46
+
* **Refactoring:** Es müssen kleinere Refactorings in [`signalduino/commands.py`](signalduino/commands.py) durchgeführt werden, um die Rückgabetypen der Methoden anzupassen.
47
+
* **Tests/Dokumentation:** Die zugehörigen Unittests in [`tests/test_mqtt_commands.py`](tests/test_mqtt_commands.py) und die MQTT API Dokumentation in [`docs/01_user_guide/mqtt_api.adoc`](docs/01_user_guide/mqtt_api.adoc) müssen aktualisiert werden.
48
+
49
+
== 4. Alternativen
50
+
51
+
1. **Alternative 1: Parsing im `MqttCommandDispatcher`:** Die Rohergebnisse als `str` beibehalten und das Parsen spezifischer Befehlsantworten direkt im `MqttCommandDispatcher` durchführen.
52
+
* *Nachteil:* Vermischt die Zuständigkeiten. Der Dispatcher sollte nur das Routing und die Validierung übernehmen, während die `SignalduinoCommands` die Logik für die Kommunikation und das Parsen der Firmware-spezifischen Antworten enthalten sollten.
53
+
* *Abgelehnt* wegen schlechter Architektur und Verstoß gegen das Single Responsibility Principle.
54
+
55
+
2. **Alternative 2: Globaler, einfacher String-Wrapper im Dispatcher:** Jede String-Antwort global in ein einfaches Dictionary wie `{'response': <String>}` verpacken.
56
+
* *Nachteil:* Führt zu einer inkonsistenten API, da einige Befehle (wie `get/config/decoder`) semantisch reiche, parsbare Daten liefern, die als roher String versteckt wären.
57
+
* *Abgelehnt* zugunsten einer semantisch korrekten, strukturierten Antwort.
0 commit comments