Forum: Mikrocontroller und Digitale Elektronik Arduino Bibliothek für JSON Handling


von Michael S. (rbs_phoenix)


Lesenswert?

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:
1
// JSON-String, value_type, function_pointer
2
JSON_Command_Struct = commands[6] = {
3
{ "{\"settings\":{\"led_brightness\":?}}", "int", exec_Settings_LedBrightness },
4
{ "{\"settings\":{\"close_time_ms\":?}}", "int", exec_Settings_CloseTimeMs },
5
{ "{\"info\":{\"temp\":?}}", "null", exec_Info_Temp },
6
{ "{\"info\":{\"supply_voltage\":?}}", "null", exec_Info_SupplyVoltage },
7
{ "{\"action\":{\"led_state\":?}}", "bool", exec_Action_LedState },
8
{ "{\"action\":{\"toggle_relay\":?}}", "bool", exec_Action_ToggleRelay }
9
}

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

von Codeklopfer (Gast)


Lesenswert?

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!

von Stefan F. (Gast)


Lesenswert?

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.

von Michael S. (rbs_phoenix)


Lesenswert?

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?

von Christoph M. (mchris)


Lesenswert?

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.

von Stefan F. (Gast)


Lesenswert?

Michael S. schrieb:
> Welches Forum wäre denn genehm?

Lass dich nicht ärgern, der will nur ablenken.

von Hannes J. (Firma: _⌨_) (pnuebergang)


Lesenswert?

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

von Ben B. (Firma: Funkenflug Industries) (stromkraft)


Lesenswert?

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.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

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.

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

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.

von Michael S. (rbs_phoenix)


Lesenswert?

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.

von Johannes S. (Gast)


Lesenswert?

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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.