Hallo zusammen.
Ich wollte für mein nächstes (Arduino basiertes) Projekt für die UART
Kommunikation JSON verwenden. Dies habe ich auch bereits bei einem nicht
von mir entwickelten Gerät genutzt. Diese Art der Kommunikation gefällt
mir ganz gut, weshalb ich so ein ähnliches Handling mit dem JSON Format
auch umsetzen will.
Ich habe bereits ArduinoJSON getestet und das mit dem Beispielstring und
das anzeigen eines Values zu einem Tag/Key funktioniert. Dazu muss man
aber den Key wissen und dieser muss auch wirklich im String stehen. Für
das Handling steht da aber nichts weiter, doch bevor ich mir da ein
großes Stück Software selber schreibe (was ich zur Not eben auch machen
würde/könnte), wollte ich fragen, ob es da nicht eine fertige Lösung
gibt oder ob es, ich nenne es mal "JSON-Standard-Strukturen" gibt.
Hier mal ein Beispiel, was mir im Idealfall vorschwebt:
Ich habe ein "JSON-Baum", der so aussieht:
1
settings
2
-> led_brightness
3
-> close_time_ms
4
info
5
-> temp
6
-> supply_voltage
7
action
8
-> led_state
9
-> toggle_relay
Dies soll dann zu folgenden "Befehlen" führen:
1
{"settings":{"led_brightness":255}}// Legt die Helligkeit einer LED am Ausgang fest, wenn an ist
2
{"settings":{"close_time_ms":1000}}// Legt die Zeit fest, wie lange beim Toggle-Befehl (siehe unten) das Relais geschlossen bleiben soll
3
{"info":{"temp":null}}// Auslesen der Temperatur auf der PCB
4
{"info":{"supply_voltage":null}}// Auslesen der Betriebsspannung
5
{"action":{"led_state":true}}// Schaltet die LED an
6
{"action":{"led_state":false}}// Schaltet die LED aus
7
{"action":{"led_state":null}}// Gibt den aktuellen Zustand der LED wieder
8
{"action":{"toggle_relay":true}}// Schaltet ein Relais für x Millisekunden an und danach wieder aus
Es ist quasi ein Strukturbaum, der dann zu einem Wert/Value führt. Ist
dieser "null", soll der Wert zurückgegeben werden, wenn ein Value
übergeben wird, soll dies eine schreibende/ausführende Funktion haben.
Zuzüglich würde ich den Zugriff definieren, ob es read-only oder
read-write ist. Im oben genannten Falle würde ich dann info/temp und
info/supply_voltage als read-only definieren.
Den Handler, den ich mir vorstelle, soll dann mehrere Dinge übernehmen:
- Prüfen, ob der "Pfad" gültig ist (dann käme bei
{"settings":{"supply_voltage":null}} ein Fehler)
- Prüfen, ob ein read-only Befehl schreibend aufgerufen wird ( z.B.
{"info":{"temp":30}} führt zum Fehler)
- Prüfen, ob das Value dem geforderten Typen entspricht ( z.B.
{"action":{"led_state":"AN"}} führt zum Fehler)
- Wenn alles korrekt abgeschickt wurde, soll die entsprechende
Funktion/Action ausgeführt werden, z.B. durch einen Funktionszeiger.
Dies alles kann man z.B. auch direkt durch if-elseif-else Klötze
abarbeiten, aber das ist ziemlich unflexibel und unkonfortabel.
Am besten fände ich eine header-Datei oder ähnliches, die z.B. so
aussehen könnte:
Der Handler würde dann oben stehende Funktionen (Error-Handling)
übernehmen, sodass man als "Nutzer" des Handlers nur noch diese
Befehlsliste pflegen müsste und natürlich die angegebenen Funktionen
erstellen müsste, die dann letztendlich das Ausführen, was ausgeführt
werden soll (LED anschalten usw).
Ich kann mir vorstellen, dass es dort einen Standard und dazu auch schon
fertige Handler gibt. Wenn ich danach bei Google suche, kommen aber nur
verschiedene Bibliotheken, wie z.B. ArduinoJSON, die aus einem JSON
String die entsprechenden Values zugreifbar macht. Das, was mir
vorschwebt, treibt das ganze ja schon noch eine ganze Ecke weiter.
Vielleicht sieht ein existierender Standard ja auch etwas anders aus,
z.B. dass es nicht verschachtelt ist. Das ist mir erstmal nicht wichtig.
Wenn so etwas fertig existiert, würde ich mir einiges an Aufwand sparen
können, zudem das Ganze vermutlich auch deutlich eleganter programmiert
wäre, als ich es würde oder noch mehr Funktionalität beinhaltet, die ich
momentan zwar nicht brauche, aber vielleicht später ganz nützlich wäre
(z.B. das Sperren gewisser Zweige, das man erstmal durch ein Login
entsperren muss).
Gibt es so ein Handler oder eine JSON Standard Struktur, die sowas
ähnliches tut?
Grüße
Michael
Schön, bist ein Codeklopper und ich ein Hardwarefreak, der gerade noch
den Unterschied zwischen java und js kennt - Da Du keine Antworten hast,
ists entweder das fall-sche Unter- oder Oberforum -
viel Glück beim nächsten Fall!
Immerhin ist JSON primitiver als XML. Aber noch viel einfacher ist das
Properties Format (wie *.ini nur ohne Abschnitte).
info.temp=21
info.supply_voltage=3.3
action.led_state=1
usw.
Dafür brauchst du gar keine Bibliothek, ausser den C Standard.
Stefan ⛄ F. schrieb:> Immerhin ist JSON primitiver als XML. Aber noch viel einfacher ist> das Properties Format (wie *.ini nur ohne Abschnitte).> info.temp=21> info.supply_voltage=3.3> action.led_state=1>> usw.>> Dafür brauchst du gar keine Bibliothek, ausser den C Standard.
Naja, klar. Letztendlich muss irgendein String interpretiert werden, um
da den Befehl und die ggf. vorhandenen Parameter zu extrahieren.
Genaugenommen ist das JSON Format auch kein muss. Aber da es ja keine
seltene Anforderung an ein Gerät ist, Befehle zu empfangen, validieren
und auszuführen, dachte ich, dass es dafür eine einfach
anpassbare/erweiterbare Lösung gibt. Diese
Bibliothek/Klasse/Engine/Parser/Interpreter, oder wie man es auch immer
nennen mag, sollte also idealerweise ein Fehler zurück geben, wenn man
in deinem Beispiel "action.ledstate=1" oder "action.led_state=an"
schickt.
Codeklopfer schrieb:> Schön, bist ein Codeklopper und ich ein Hardwarefreak, der gerade> noch den Unterschied zwischen java und js kennt - Da Du keine Antworten> hast, ists entweder das fall-sche Unter- oder Oberforum ->> viel Glück beim nächsten Fall!
Genaugenommen bin ich kein Codeklopper, sonst hätte ich sowas bestimmt
schon lange fertig, bevor ich diese Beiträge hier geschrieben hätte.
Welches Forum wäre denn genehm? Ich bin wohl fälschlicherweise davon
ausgegangen, dass das Unterforum "Mikrocontroller und Elektronik" sich
mit Mikrocontrollern beschäftigt. Dann lieber "PC-Programmierung",
obwohl es kein PC ist?
Michael S. schrieb:> oder ob es, ich nenne es mal "JSON-Standard-Strukturen" gibt.
Kurze Antwort: Smart Objects + TLV + SLIP
Lange Antwort:
Wenn ich von dem Beispiel mal auf die Anwendung schließe, dann würde ich
mir aus dem Katalog von IPSO Smart Objects
http://openmobilealliance.org/wp/OMNA/LwM2M/LwM2MRegistry.html die
passenden nehmen (die Objekte ab 3200), statt mir die Datenstrukturen
selber auszudenken.
Als Encoding würde ich das dafür standardisierte Type-Lenght-Value
(TLV), nehmen, weil es recht kompakt ist wenn man es mit einem µC machen
muss. Ein standardisiertes JSON-Encoding gibt es auch, wenn man denn
unbedingt JSON haben möchte.
Den Rest von LwM2M oder MQTT? Na ja, kommt auf die Anwendung an. Für
irgendwas, was über UART läuft, würde ich mir den Rest erst einmal
schenken. Wichtig wäre mir nur, dass ich Frames/Messages auf der
seriellen Verbindung eindeutig erkennen kann, und zwar nicht daran, dass
ich einen TLV- oder JSON-Datenstrom durchparsen muss, in der Hoffnung
irgendwann was Komplettes bekommen zu haben, sondern dass ich einen
Datensatz bekomme.
Da ich ein alter Sack bin würde ich ein Protokoll nehmen mit dem ich
über Jahrzehnte gut gefahren bin. Es kommt zwar aus einer ganz anderen
Welt, aber ist passt gut und ist in 50 Zeilen C implementiert, RFC 1055
SLIP https://tools.ietf.org/html/rfc1055
Wenn ich diese JSON Scheiße so lese bin ich echt froh, daß so ein UART
volle 8 Bit kann... Ansonsten viel Spaß beim Schreiben des Interpreters.
Kein Wundern wenn man bald einen 64 Bit Prozessor braucht, um eine
einzelne LED blinken zu lassen.
Ben B. schrieb:> Kein Wundern wenn man bald einen 64 Bit Prozessor braucht, um eine> einzelne LED blinken zu lassen.
Natürlich mit FPU und mind. 1.5GHz.
Wenn man JSON richtig implementieren will, muss man auch UTF-8 können.
Nur mal so zur Info.
Wenn man einen Standard nur zum Teil umsetzt, geht sein größter Vorteil
verloren: Dass es ein Standard ist.
Früher oder später will da jemand Umlaute übertragen und fängt das
Fluchen an, weil sein Framework auf den Gegenseite nur UTF-8 kann, was
ja auch im Sinne der Erfindung von JSON ist.
Christoph M. schrieb:> Für so eine Sache würde ich fertige Kommunikationsprotokolle wie> OSC>> https://de.wikipedia.org/wiki/Open_Sound_Control>> oder MQTT>> https://de.wikipedia.org/wiki/MQTT>> empfehlen.> Die sind einfach und es gibt schon Haufenwweise Smartphone Apps zum> steuern.
OSC scheint sowas ähnliches zu sein. Das könnte ich mir nochmal genauer
angucken.
MQTT braucht einen Broker, oder? Man muss ja irgendwas subscriben. Das
wäre für eine mehr oder weniger komplexe, direkte Verbindung ungünstig.
Hannes J. schrieb:> Wenn ich von dem Beispiel mal auf die Anwendung schließe, dann würde ich> mir aus dem Katalog von IPSO Smart Objects> http://openmobilealliance.org/wp/OMNA/LwM2M/LwM2MRegistry.html die> passenden nehmen (die Objekte ab 3200), statt mir die Datenstrukturen> selber auszudenken.>> Als Encoding würde ich das dafür standardisierte Type-Lenght-Value> (TLV), nehmen, weil es recht kompakt ist wenn man es mit einem µC machen> muss. Ein standardisiertes JSON-Encoding gibt es auch, wenn man denn> unbedingt JSON haben möchte.
Wäre auch eine Überlegung Wert. Legt mich aber nicht auf mein Beispiel
fest. Wenn sowas gut und relativ platzsparend implementiert werden kann,
würde ich das dann auch in Zukunft einsetzen wollen. Ob es eine
Relaiskarte, Labornetzteil oder Wetterstation ist (wieder: nur
Beispiele), ich hätte dann immer den u.U. etwas oversized interpreter
fertig und brauch mich um das ganze Handling nicht kümmern. Wenn ich mit
Strings arbeite, dann kann dieser auch über UART, iR, Bluetooth oder was
auch immer kommen. So die Idee.
Ben B. schrieb:> Wenn ich diese JSON Scheiße so lese bin ich echt froh, daß so ein> UART volle 8 Bit kann... Ansonsten viel Spaß beim Schreiben des> Interpreters. Kein Wundern wenn man bald einen 64 Bit Prozessor braucht,> um eine einzelne LED blinken zu lassen.
JSON ist ja nur die Formatierung. Aber dass man über Strings ein Gerät
steuert gibt es ja schon ein paar Jährchen.
JSON finde ich auch gut und zumindest auf den Cortex-M kann man das
schon gut gebrauchen. Es hat natürlich mehr Overhead weil erstmal die
Token erkannt werden müssen und dann sind noch String Vergleiche nötig
um die gewünschten Keys zu finden. Binär ist das zwar schneller, hat
dafür ein Kompatibilitätsproblem. Wenn Daten hochfrequent zyklisch
gefeuert werden würde ich auch eher binär nehmen, für z.B. Setupdaten
die an mehrere Geräte gehen und sich in der Struktur ändern können kann
JSON mehr Vorteile haben.
Eine Lib die ich mal verwendet habe ist JSMN,
https://github.com/zserge/jsmn.
Das ist aber auch low level parsing, ein übergeordnetes Schema das einen
KV Storage implementiert habe ich noch nicht generisch gebaut. Aber KV
Storage mit JSON liefert als Suchbegriff vielleicht ein paar Treffer.