JSON decode

Hallo zusammen,

ich versuche mich gerade das erste mal mit JSON.
leider habe ich davon noch nicht so wirklich Ahnung.

ich habe mit folgendem Skript Daten empfangen:

$content = Sys_GetURLContent("http://192.168.0.149/get/json/test");
//print $content;
$json=json_decode($content);
print_r ($json);

als Ergebnis bekomme ich folgendes:

Array
(
[0] => stdClass Object
(
[UG] => Array
(
[0] => Array
(
[0] => Büro
[1] => 21
[2] => 0
[3] =>
)

                [1] => Array
                    (
                        [0] => Hobby
                        [1] => 21
                        [2] => 0
                        [3] => 
                    )

            )

    )

[1] => stdClass Object
    (
        [EG] => Array
            (
                [0] => Array
                    (
                        [0] => Wohnzimmer
                        [1] => 21
                        [2] => 0
                        [3] => 
                    )

Wenn ich es richtig verstanden habe soll das auch so aussehen.

Jetzt fehlt mir aber der Ansatz wie ich die Werte ausgewertet bekomme.
Ich möchte gerne auswerten wie viele Stockwerke und Räume es gibt.
Dann möchte ich die Variablen anlegen und mit den Werten befüllen.

Könnte mir bitte jemand auf die Sprünge helfen.
Danke
Isi

Hi!

Ein Blick in diesen schönen Thread liefert einige Beispiele :slight_smile:
IP-Symcon - Wie kann ich… 2.0

stdClassObjekt „spricht man an“ mit „->“ und Array „Blöcke“ ganz normal mit z.B. [0]

Grüße,
Chris

Und zählen kann man beides mit count.
Außer du willst eh alles auslesen, dann bietet sich foreach an.
Michael

…das müsst ihr mir bitte genauer erklären.

echo „Hobby Soll: „.$json->UG[1].“ °C“."
";

Ergebnis:

<br />
<b>Notice</b>: Trying to get property of non-object in <b>/mnt/data/symcon/scripts/40459.ips.php</b> on line <b>7</b><br />
Hobby Soll: °C
Array
(
[0] => stdClass Object
(
[UG] => Array
(
[0] => Array
(
[0] => Büro
[1] => 21
[2] => 0
[3] =>
)

                [1] =&gt; Array
                    (
                        [0] =&gt; Hobby
                        [1] =&gt; 21
                        [2] =&gt; 0
                        [3] =&gt; 
                    )

            )

    )

Kann mir bitte jemand ein Bsp. erstellen?
Ich stehe glaube ich auf dem Schlauch.

so,
ich konnte jetzt mit

$test= "Hobby Solltemp.= ".$json [0]->UG[1][1]." °C"."
";

folgendes Ergebnis erhalten:
Hobby Solltemp.= 21 °C

Aber ist das Protokoll nicht etwas unlogisch aufgebaut?

Es sollte eigentlich folgende Struktur übertragen:

UG
Raum1
Name
Sollwert
Offset
Istwert
Raum2
Name
Sollwert
Offset
OG
Raum1
Name
Sollwert
Offset
Istwert
Raum2
Name
Sollwert
Offset
Ostwert

Wobei sich die Anzahl der Geschosse und Räume ändern können.
Die Daten in den Räumen sind immer gleich (Reihenfolge und Anzahl)

Das derzeit verwendete JSON ist da glaube ich nicht richtig aufgebaut oder ich verstehe es nicht richtig…


Array
(
    [0] => stdClass Object
        (
            [UG] => Array
                (
                    [0] => Array
                        (
                            [0] => Büro
                            [1] => 21
                            [2] => 0
                            [3] => 
                        )

                    [1] => Array
                        (
                            [0] => Hobby
                            [1] => 21
                            [2] => 0
                            [3] => 
                        )

                )

        )

    [1] => stdClass Object
        (
            [EG] => Array
                (
                    [0] => Array
                        (
                            [0] => Wohnzimmer
                            [1] => 21
                            [2] => 0
                            [3] => 
                        )

                    [1] => Array
                        (
                            [0] => Esszimmer
                            [1] => 21
                            [2] => 0
                            [3] => 
                        )

                    [2] => Array
                        (
                            [0] => Küche
                            [1] => 21
                            [2] => 0
                            [3] => 
                        )

                    [3] => Array
                        (
                            [0] => WC
                            [1] => 21
                            [2] => 0
                            [3] => 
                        )

                )

        )

    [2] => stdClass Object
        (
            [OG] => Array
                (
                    [0] => Array
                        (
                            [0] => Bad
                            [1] => 21
                            [2] => 0
                            [3] => 
                        )

                    [1] => Array
                        (
                            [0] => Mario
                            [1] => 21
                            [2] => 0
                            [3] => 
                        )

                    [2] => Array
                        (
                            [0] => Felix
                            [1] => 21
                            [2] => 0
                            [3] => 
                        )

                    [3] => Array
                        (
                            [0] => Schlafzimmer
                            [1] => 21
                            [2] => 0
                            [3] => 
                        )

                )

        )

)

Kann mir das jemand erklären?

Kaum probiert man es selbst, bekommt man es hin :wink: :smiley:

Wie die JSON aufgebaut ist, dafür ist nur das Gerät (oder was du da hast) verantwortlich und nicht IPS.

Die Daten auswerten liegt dann wiederum bei dir. Du kannst ja Abfragen, ob Wert X = „UG“ ist und dann darunter die Daten entsprechend in Variablen stecken oder was auch immer.

>> Außerdem wäre die Verwendung von CODE/PHP-Tags schön, sieht dann nicht so „wild“ aus in deinem Post :wink:

Grüße,
Chris

Hallo Bayaro,
Danke für diene Tips.
Ich hatte den Beitrag schon gelesen, konnte aber nichts mit den Arrays ohne Benennung anfangen.
Jetzt kann ich’s ja :smiley:

Dass der Inhalt des JSON vom Gerät abhängig ist ist mir schon klar.
Da es sich hier um einen ersten Versuch handelt und die api noch nicht erstellt ist, kann ich noch Einfluss auf den Afbau nehmen.
Daher wollte ich mehrere Meinungen zum Aufbau einholen.
Ich kenne mich ja nicht so wirklich damit aus…
Aber wann hat man schon mal die Möglichkeit seine Wünsche bei einem Hersteller einfließen zu lassen.
Das möchte ich natürlich so nutzen, dass das Gerät nachher optimal (über ein Modul) an IPS angebunden werden kann.
Daher ist es mir wichtig, dass die Struktur vom Gerät übernommen werden kann.
Nur so ist es möglich das Modul später allen Usern zur Verfügung zu stellen.

Ich brauche also Input!

Gruß
Jens

Hey Jens :slight_smile:

…sag das doch gleich…meine Glaskugel ist momentan verliehen an den Weihnachtsmann :smiley:

Also, wenn du dem Hersteller sagen kannst, wie er die JSON aufbauen soll, dann sag ihm doch einfach, wie er es besser/anders machen kann. Wenn du das von uns wissen willst, dann brauchen wir VIEL MEHR Informationen wie wo was du da treibst oder treiben willst :slight_smile:

Und, ohne viel darüber zu wissen, finde ich den Aufbau eigentlich ok. Die 1. „Ebene“ sind Zahlen von 0 bis X. Und danach kommen die Bezeichnungen, welche man einfach abfragen kann. Und darunter dann die Infos. Also fragt man einfach ab, if EintragX == Stockwerk, dann hau alles darunter in Variablen mit Prefix „StockwerkXY_“.

Man kann aber auch die 1. Ebene direkt mit Stockwerksnamen machen und dann lässt man sich darunter einfach alle Details ausgeben, spart eine Abfrage :smiley:

Falls nicht zutreffend…wie gesagt…mehr Infos bitte :wink:

Grüße,
Chris

Also,
Dann fange ich mal an

Es geht um eine FBH-Steuerung die selbstlernend ist und auf die Wettervorhersage reagiert.
An die Steuerung sind Raumregler angebunden die die Raumtemperatur messen und an denen man die Solltemperatur einstellen kann.
D.h. Die Steuerung läuft autark.

Die Etagen und Räume werden händisch angelegt.
Den Räumen werden Icons und Ausgänge für die Ventilsteller zugeteilt.

Folgende Daten gibt es zu einem Raum:
GET:
Ist Temp.
Soll Temp.
Steller an/ aus
Icon (1,2,3…)
Offset ( das ist die Korrektur des Sollwerts anhand der Wetterdaten)

SET:
Soll Temp.

Folgende Daten gibt es Übergreifend:

GET:
A-Temp
Anwesend (ja/nein)
Wärmebedarf (ja/nein) (zum Pumpe oder Kessel schalten)

SET:
Anwesenheit

Meine Ideen dazu:
-Automatisches Anlegen der Variablen und Struktur in IPS durch hinzufügen einer Instanz
-Automatisches aktualisieren der Werte

Vorteile der Anbindung an IPS:
-Sollwertvorgabe Raumtemp. durch Wochentimer
-Sollwertvorgabe RAUMTEMP. durch Anwesenheitsstatus in IPS
-loggen der Raumtemperaturen
-Verwenden der A-Temp.
-grafische Darstellung der Temperaturverläufe

Das Tema FBH kommt hier jeden Winter neu und es sieht so aus als hätten einige User da bedarf einer „sauberen“ Lösung.
Durch den Autarken Betrieb läuft das Gerät auch ohne IPS und kann über die Raumtermostate gesteuert werden.
Somit ist sichergestellt, dass die Bude nie kalt ist.
Durch die Anbindung über LAN ist diese Lösung auch mit der Symbox einsetzbar und es muss nichts gebastelt werden.
Durch die lernenden Regler im Gerät wird die Temperatur oft auf 0,1 Grad genau erreicht.

Hallo ,
ich versuche mich gerade an der Verarbeitung des JSON.

Leider funktioniert meine Abfrage nicht wie ich möchte.
Ich komme einfach nicht hinter die Syntax

################################################################################
$anz_eta = (count ($json));									//Anzahl der Etagen geht
for ($e=0;$e<$anz_eta;$e++)
{
	$name_eta=(key($json[$e]));                     	//Namen der Etagen geht


	// hier die Etagen anlegen
	echo $name_eta;
	
	$anz_raum = (count ($json[$e]->$name_eta));        //Anzahl der Räume je Etage
	
		for ($r=0;$r<$anz_raum;$r++)
		{
		$name_raum=($json[$e]->$name_eta[$r][0]);       //Namen der Etagen get nicht!!!
		
		//hier die Räume anlegen
		echo $name_raum;
		
		}
}
################################################################################

Fehlermeldung:

UG
Notice:  Undefined property: stdClass::$U in /mnt/data/symcon/scripts/40459.ips.php on line 26

Notice:  Undefined property: stdClass::$G in /mnt/data/symcon/scripts/40459.ips.php on line 26
EG
Notice:  Undefined property: stdClass::$E in /mnt/data/symcon/scripts/40459.ips.php on line 26

Notice:  Undefined property: stdClass::$G in /mnt/data/symcon/scripts/40459.ips.php on line 26

Notice:  Uninitialized string offset: 2 in /mnt/data/symcon/scripts/40459.ips.php on line 26

Der Fehler liegt in Zeile:

$name_raum=($json[$e]->$name_eta[$r][0]);       //Namen der Etagen get nicht!!!

Wenn ich $name_eta durch UG oder EG oder OG ersetzte geht es.
Kann mir bitte jemand helfen.

Danke
Jens

Ich könnte jetzt mehrere Zeilen über den Unsinn schreiben was es bringt als Identifier ein Geschoss und Raumnamen zu nutzen.
Aber damit du erstmal weiterkommst.
Versuch einfach mal json_decode($data,true) dann wird dir kein Objekt sondern ein Array erzeugt.
Vielleicht klappt es damit besser.
Michael

Hallo Michael,

danke für dienen Tipp.
Das hatte ich aber schon.
Ich hätte sehr großes Interesse an den Zeilen die den optimalen und sinnvollen Aufbau des JSON beschreiben!
Wie im 7. Beitrag schon beschrieben, möchte ich gerne die Gelegenheit nicht ungenutzt lassen.

Eine Lösung meines Problems habe ich leider immer noch nicht, weshalb ich einfach mal meinen derzeitigen Stand anhänge:

<?

 //JSON einlesen
$content = Sys_GetURLContent("http://192.168.0.149/get/json/v1/1/temps/");
//print $content."
"."
";

//JSON als Array ausgeben
$json=json_decode($content);
//print_r ($json);

//Test zum Auslesen der Temp in Hobbyraum
$hobbytemp= "Hobby Solltemp.= ".$json [0]->UG[1][1]." °C"."
";
//echo $hobbytemp;

################################################################################
$anz_eta = (count ($json));									//Anzahl der Etagen geht
for ($e=0;$e<$anz_eta;$e++)
{
	$name_eta=(key($json[$e]));                     	//Namen der Etagen geht
   

	// hier die Etagen anlegen
	echo "Schleife 1 (Etagen) --> Durchlauf ".$e." Etage = ".$name_eta."
";
	
	$anz_raum = (count ($json[$e]->$name_eta));        //Anzahl der Räume je Etage
	
		for ($r=0;$r<$anz_raum;$r++)
		{
		$name_raum=($json[$e]->$name_eta[$r][0]);       //Namen der Etagen get nicht!!!
		
		//hier die Räume anlegen
		echo "Schleife 2 (Räume) --> Durchlauf ".$e." Raum = ".$name_raum."
";
		}
}
################################################################################


?>

$content =

[{"UG": [["B\u00fcro", 21.0, 0.0, null], ["Hobby", 21.0, 0.0, null]]}, {"EG": [["Wohnzimmer", 21.0, 0.0, null], ["Esszimmer", 21.0, 0.0, null], ["K\u00fcche", 21.0, 0.0, null], ["WC", 21.0, 0.0, null]]}, {"OG": [["Bad", 21.0, 0.0, null], ["Mario", 21.0, 0.0, null], ["Felix", 21.0, 0.0, null], ["Schlafzimmer", 21.0, 0.0, null]]}]

$json =

Array
(
    [0] => stdClass Object
        (
            [UG] => Array
                (
                    [0] => Array
                        (
                            [0] => Büro
                            [1] => 21
                            [2] => 0
                            [3] => 
                        )

                    [1] => Array
                        (
                            [0] => Hobby
                            [1] => 21
                            [2] => 0
                            [3] => 
                        )

                )

        )

    [1] => stdClass Object
        (
            [EG] => Array
                (
                    [0] => Array
                        (
                            [0] => Wohnzimmer
                            [1] => 21
                            [2] => 0
                            [3] => 
                        )

                    [1] => Array
                        (
                            [0] => Esszimmer
                            [1] => 21
                            [2] => 0
                            [3] => 
                        )

                    [2] => Array
                        (
                            [0] => Küche
                            [1] => 21
                            [2] => 0
                            [3] => 
                        )

                    [3] => Array
                        (
                            [0] => WC
                            [1] => 21
                            [2] => 0
                            [3] => 
                        )

                )

        )

    [2] => stdClass Object
        (
            [OG] => Array
                (
                    [0] => Array
                        (
                            [0] => Bad
                            [1] => 21
                            [2] => 0
                            [3] => 
                        )

                    [1] => Array
                        (
                            [0] => Mario
                            [1] => 21
                            [2] => 0
                            [3] => 
                        )

                    [2] => Array
                        (
                            [0] => Felix
                            [1] => 21
                            [2] => 0
                            [3] => 
                        )

                    [3] => Array
                        (
                            [0] => Schlafzimmer
                            [1] => 21
                            [2] => 0
                            [3] => 
                        )

                )

        )

)

Wenn ich das Skript ausführe erhalte ich folgende Ausgabe:

Schleife 1 (Etagen) --> Durchlauf 0 Etage = UG

Notice:  Undefined property: stdClass::$U in /mnt/data/symcon/scripts/40459.ips.php on line 29
Schleife 2 (Räume) --> Durchlauf 0 Raum = 

Notice:  Undefined property: stdClass::$G in /mnt/data/symcon/scripts/40459.ips.php on line 29
Schleife 2 (Räume) --> Durchlauf 0 Raum = 
Schleife 1 (Etagen) --> Durchlauf 1 Etage = EG

Notice:  Undefined property: stdClass::$E in /mnt/data/symcon/scripts/40459.ips.php on line 29
Schleife 2 (Räume) --> Durchlauf 1 Raum = 

Notice:  Undefined property: stdClass::$G in /mnt/data/symcon/scripts/40459.ips.php on line 29
Schleife 2 (Räume) --> Durchlauf 1 Raum = 

Notice:  Uninitialized string offset: 2 in /mnt/data/symcon/scripts/40459.ips.php on line 29

Notice:  Uninitialized string offset: 0 in /mnt/data/symcon/scripts/40459.ips.php on line 29

Fatal error:  Cannot access empty property in /mnt/data/symcon/scripts/40459.ips.php on line 29

Das sieht für mich so aus als würde es die Variable $name_eta

$name_raum=($json[$e]->$name_eta[$r][0]);

Buchstaben für Buchstaben verarbeitet und nicht als String.
Aber nur wenn das [$r] dahinter steht, da es ja in der ersten Schleife mit

$anz_raum = (count ($json[$e]->$name_eta));        //Anzahl der Räume je Etage

funktioniert.

Moin!

Wenn Michael einen „Plan“ hat, dann wird da was dran sein :smiley:

Also versuchen wir es mal zu eruieren… Will man alle Temperaturen haben, dann wäre ein JSON gut, welches den „Zweig“ Temperaturen hat und darunter alle Stockwerke + Räume mit jeweiliger Temperatur.

Will man z.B. Temperaturen und Luftfeuchte von allen Räumen eines Stockwerk haben, dann durchwühlt man einmal alle Temperaturen und alle Luftfeuchten und schreibt alle mit z.B. Stockwerk = OG in ein Array und gibt es am Ende aus.

Hmmm…also wenn man das so aufschreibt, dann wird es einem klar, wieso es besser ist nach Temperatur, Luftfeuchte, … den Aufbau zu machen und darunter dann Stockwerke und Räume :smiley: Die Muddi weiß halt einfach was gut für einen ist :wink: :smiley:

Als Fazit wäre damit so ein Aufbau wohl gut:

Temperaturen 
 > Raumname1
   > Temperatur vom Raum1
   > Stockwerk in dem der Raum1 ist
 > Raumname2
   > Temperatur vom Raum2
   > Stockwerk in dem der Raum2 ist
Luftfeuchtigkeiten
 > Raumname1
   > Luftfeuchte vom Raum2
   > Stockwerk in dem der Raum2 ist
 > Raumname2
   > Luftfeuchte vom Raum2
   > Stockwerk in dem der Raum2 ist

Da könnte man dann sagen „alle Temperaturen“ und danach eingrenzen mit „if Stockwerk == OG“ oder „if Raum == Raum1“ usw…

Grüße,
Chris

Ich habe gerade keinen Plan, liege noch immer flach :wink:
Aber normalerweise nimmt man keine logische Struktur um Daten einer Hardware eindeutig zuzuordnen.
Ich würde sogar noch weiter davor anfangen…
Sollen die Daten nur per Pull geholt werden ?
Oder wäre es nicht besser das die Hardware Änderungen automatisch per Event überträgt?
Wenn ich mal wider fit bin, und am Rechner Sitze, kann ich ja mal mehr schreiben.
Michael

Danke euch,

Ich wünsche dir erst mal gute Besserung und freu mich auf deinen Ansatz.

Frohe Weihnachten noch an alle

So basierend hierauf:

Zuerst solltest du dich von den Gedanken ‚trennen‘ dass du die Struktur direkt in IPS per Modul nachbauen kannst.
Der logische Baum unterliegt den Nutzer, somit ist es komplett sinnfrei hier die logische Struktur der Hardware nachzubauen.

Sinnvoller ist es da, z.B. beim erstellen der Instanzen in IPS die Namen auszulesen und dem User diese Arbeit beim Einrichten abzunehmen.

Die Struktur ist für IPS selbst komplett egal. Der Austausch von Daten zwischen Instanzen ist die ‚physikalische‘ Anbindung, welche völlig losgelöst von der logischen Struktur ist.

Um jetzt die einzelnen Räume (=Hardware in den Räumen) eindeutig zu identifizieren würde ich einfach irgendeine feste / unveränderbare Kennung nutzen. Auf jeden Fall nicht den Namen, weil was passiert wenn aus Mario mal Lisa wird ?
Die Hardware schraubst du ja nicht um, du änderst nur den Namen.

Ich für meinen Teil würde die Anbindung auch nicht über HTTP machen, sondern lieber direkt mit einem TCP-ServerSocket auf der Hardware sprechen.
Bei HTTP mußt du (aktuell, WebSockets mal außen vor) pollen, und das ist immer ‚blöd‘.
Besser wäre es, wenn die Hardware automatisch die Daten (zyklisch oder bei Änderung) an die verbundenen TCP-Clients sendet (= IPS).

Da ist JSON zwar seht praktisch, aber wie willst du denn nachher aus IPS steuern ?
JSON-RPC wäre die Variante, welche Funktionen und auch Events implementiert.

Es braucht ja nicht viele Funktionen auf beiden Seiten.
Einmal z.B. OnChange von Hardware zu IPS, wenn es ‚neue‘ Daten gibt.
Und dann noch z.B. SetTemp von IPS zur Hardware, sowie ein Befehl um einmal alle Daten anzufordern.

Beispiele wie das dann nachher aussehen könnte:
Objekt eines ‚Raum‘

{
    "id": 1,
    "room": "Hobby",
    "target": 21.0,
    "temp": 0.0,
    "offset": null
}

Datenempfang von Werten:

{
    "jsonrpc": "2.0",
    "method": "OnChange",
    "params": {
        "data": {
            "result": [
                {
                    "id": 0,
                    "room": "B\u00fcro",
                    "target": 21.0,
                    "temp": 0.0,
                    "offset": null
                },
                {
                    "id": 1,
                    "room": "Hobby",
                    "target": 21.0,
                    "temp": 0.0,
                    "offset": null
                },
                {
                    "id": 2,
                    "room": "Wohnzimmer",
                    "target": 21.0,
                    "temp": 0.0,
                    "offset": null
                }
            ]
        }
    },
    "sender": "Vendor"
}

Wobei das Objekt ‚result‘ ein Array von Objekt des Typ ‚Raum‘ enthält.

Sollwerte setzen könnte so gehen:

{
    "jsonrpc": "2.0",
    "method": "SetTemp",
    "params": {
        "item": [{
                "id": 0,
                "target": 21.0
            }]
    },
    "id": 4639
}

Wobei Item auch mehrere Objekte enthalten könnte.

Üblicherweise werden Funktionen auch mit einer Rückmeldung quittiert:

{
    "jsonrpc": "2.0",
    "result": true,
    "id": 4639
}

Um nachher das in ein Modul zu packen, ist es praktisch hier einen Splitter und eine Geräte-Instanz zu schreiben.
Der Splitter nimmt die Daten vom ClientSocket entgegen und zerlegt jedes JSON-Objekt in einzelne ‚Räume‘.
Diese Daten werden an die Geräte-Instanzen weitergereicht, welche dann prüfen ob diese Daten für ‚ihre‘ Raum-ID sind und dann ggfls. Variablen updaten.

Beim Ändern von der SollTemp aus dem WebFront bzw. per PHP-Script, wird diese Funktion über die Geräte-Instanzen ausgelöst.
Die Geräte-Instanzen senden die gewünschte Solltemp an den Splitter, welcher das in einen JSON-RPC-Request verpackt an den ClientSocket sendet.

Soweit zur ‚Theorie‘ :smiley:

Wobei eine JSON-RPC-Anbindung habe ich gerade mit Kodi in Arbeit.
Sieht dann z.B. so aus:

Michael

Hallo Michael,

Besten Dank für deine ausführliche Beschreibung!
Das mit den Raum-ID’s ist ne gute Sache.
Die Struktur soll sich jeder anlegen wie er möchte, das ist auch mein Ziel.
Ich möchte nur wie du es beschreibst die Daten aus der Regelung auslesen und die Instanzen anlegen.
Ich werde mal einen Vorschlag des Aufbaus und der Inhalte erarbeiten und an die Firma senden.
Mal schauen was daraus wird.
Auch der Weg über den ClientSocket gefällt mir sehr gut…
Werde ich mir anschauen.

Wünsche noch einen schönen Sonntag.

Isi