Daten per JSON aus FHEM lesen

Begonnen von AndreM, 01 Mai 2020, 23:27:09

Vorheriges Thema - Nächstes Thema

AndreM

Guten Abend Forum,
bin mir nicht ganz sicher ob ich hier ind er richtigen Abteilung bin.. Es geht um Json und wie ich die daten mit Retrofit/Gson (Android) aus FHEM auslesen kann.

Ich habe brereits die cmd=jsonlist2 gefunden, ganz weiter komme ich leider noich nicht.
Wie kann ich daraus einzelen Devices filtern... Ich frage Json mit diesem Befehl ab:

<IP-FHEM>/fhem?cmd=jsonlist2&Name=SZ_Wand_Climate&XHR=1

Soweit ich mich eingelesen habe, muss auch zwischen dem jsonlist2 und Name= ein UND (&) Zeichen stehen.
Das Ergebnis daraus sind alle Devices die ich FHEM angelegt habe.
{
  "Arg":"",
  "Results": [
  { ALLE DEVICES AUS FHEM



Gebe ich die Abfrage wie folgt ein bekomme ich zumidest das einzelne Gerät. Nur das "&" gegen "%20" getauscht und "Name" entfernt

<IP-FHEM>/fhem?cmd=jsonlist2%20SZ_Wand_Climate&XHR=1

Ergebnis:
{
  "Arg":"SZ_Wand_Climate",
  "Results": [
  {
    "Name":"SZ_Wand_Climate",
    "PossibleSets":
    "Internals": {
      "NAME": "SZ_Wand_Climate",
      "NOTIFYDEV": "global",
      "NR": "106",
      "NTFY_ORDER": "50-SZ_Wand_Climate",
      "STATE": "T: 18.7 desired: 17.0",
      "TYPE": "CUL_HM",
      "chanNo": "02",
      "device": "SZ_Wand",
      "peerList": "SZ_HK_Climate,"
    },
    "Readings": {
      "boostTime": { "Value":"-", "Time":"2020-04-28 14:39:15" },
      "commReporting": { "Value":"on", "Time":"2020-04-28 14:39:15" },
      "controlMode": { "Value":"auto", "Time":"2020-04-28 14:39:15" },
      "desired-temp": { "Value":"17.0", "Time":"2020-05-01 23:17:01" },
      "dewpoint": { "Value":"7.9", "Time":"2020-05-01 23:17:01" },
      "humidity": { "Value":"55", "Time":"2020-05-01 23:17:01" },



Mich stört irgendwie der Eintrag "Arg" und das man ihn nur gefüllt bekommt wenn man "%20" anstatt "&" eingibt.

Ich bin mir nicht klar wie ich die %20 in zwischen jsonlist2 und SZ_Wand_CLimate in Retrofit programmieren muss..


Ich hoffe ich treffe auf jemanden der sich mit Retrofit oder Gson auskennt!!!!!

Danke!!

Schönen Gruß
Andre



rudolfkoenig

ZitatIch hoffe ich treffe auf jemanden der sich mit Retrofit oder Gson auskennt!!!!!
Ich durfte mich vor Jahren mit dieser Kombo quaelen, und mein Eindruck war, dass jemand eine JSON-Bibliothek implementierte, ohne das Wesen von JSON zu begreifen, dazu kam eine umstaendliche und unflexible HTTP-Bibliothek.  Ich qualifiziere mich damit nicht als Kenner dieser Bibliotheken, und nein, ich habe keine Alternativen.

Zu den Beobachtungen:
- JsonList2 ist ein normales FHEM Befehl (siehe Doku), den man in der Kommandozeile ausfuehren kann. Die Argumente werden FHEM-ueblich per Leerzeichen getrennt, und man findet sie in der Antwort im Arg wieder.
- FHEMWEB kann alles ausfuehren, was in der Kommandozeile akzeptiert wird.
- Die Argumente kann man im URL auch anders spezifizieren: wenn man cmd.XXX statt cmd verwendet, dann werden die URL Parameter dev.XXX, arg.XXX und val.XXX an das Befehl mit Leerzeichen angehaengt. D.h.:
http://localhost:8083/fhem?cmd.json=JsonList2&dev.json=global&fwcsrf=csrf_389277372435138&XHR=1
liefert das Ergebnis von "JsonList2 global" zurueck.

Ich meine mit dem zweiten Syntax kann man eine passenden Retrofit-Klasse bauen, in der Art
@GET("fhem")
Observable<Response<String>> fhem(@Query("cmd.retrofit") String cmd, @Query("dev.retrofit") String dev);

(ungetestet!)

AndreM

#2
Hallo Rudolf Danke für deine ausführliche Antwort. Ich werde das aufjedenfall ausprobieren.

Mich wundert es, das sowas keiner braucht :o
Mein aktuelles Projekt ist es, eine AndroidApp auf mein Smarthome zugeschnitten zu programmieren.

Ich habe gerade noch das Problem, dass ich die "Test App" (einen JSON Abfrage Button  ;D ;D) auf meinem Smartphon installiere und dann die Fehlermeldung bekomme -> Cleartext HTTP traffic to <IP-FHEM> not permitted.

Ich habe im lokalen Netzwerk aber garkein Password definiert.

EDIT:

Sorry war ich wohl zu schnell.. Ist kein Problem in FHEM sondern in Android... Behoben mit:
https://stackoverflow.com/questions/39933345/no-network-security-config-specified-using-platform-default-android-log

rudolfkoenig

Falls openssl auf dem FHEM-Rechner installiert ist, dann duerfte das Aktivieren von HTTPS einfach aus Setzen des Attributes bestehen.
Man kriegt zwar nur ein self-signed Zertifikat, aber immerhin.

AndreM

#4
Hallo Rudolf,
kurz nachdem ich auf deine erste Antwort gestoßen bin hat mir eine Kollege "Volley" für Android empfohlen. Das habe ich gerade als erstes ausprobiert und bin schwer begeistert, dass es funktioniert.

Hier mal ein Java-Code-Schnipsel:


private void jsonParse(String device, String reading, String value) {

        String url = "http://<IP-FHEM>/fhem?cmd=jsonlist2%20" + device +"&" + reading +"&XHR=1";

        JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, null,

                new com.android.volley.Response.Listener<JSONObject>() {
                    @Override
                    public void onResponse(JSONObject response) {
                        try {
                            //Level0 Abfrage
                            JSONArray jsonArray = response.getJSONArray("Results");
                            //Level1 Abfrage
                            JSONObject jsonObjectLevel1 = jsonArray.getJSONObject(0);
                            //Level2 Abfrage
                            JSONObject jsonObjectLevel2 = jsonObjectLevel1.getJSONObject("Readings");
                            //Level3 Abfrage
                            JSONObject jsonObjectLevel3 = jsonObjectLevel2.getJSONObject(reading);
                            //Output aus 1.Abfrage Result
                            String nameOfDevice = jsonObjectLevel1.getString("Name");
                            //Output aus 2.Abfrage Results.Readings
                            String nameOfReading = jsonObjectLevel2.getString(reading);
                            //Output aus 3.Abfrage Results.Readings
                            String ValueOfReading = jsonObjectLevel3.getString(value);
                                    mTextViewResult.append("Name: " + nameOfDevice + "\n\n" + "Reading: " + nameOfReading + "\n\n"  + "Value: " + ValueOfReading  + "\n\n");

                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                mTextViewResult.setText(error.getMessage());
            }
        });

        mQueue.add(request);
    }


Ich rufe die Methode jsonParse() auf und übergebe die Werte, die ich aus der FHEM-Json lesen möchte in die URL und die Abfragen (hier device, reading, value). Diese hole ich mir dann Objectlevel für Objectlevel ab und schreibe es mir in die Ausgabe (siehe Bild).

Mal sehen wie Volley mit "Posts" umgeht.

EDIT:
Funktionert auch wunderbar!!
Java-Code-Schnipsel:
private void jsonPost(String device, String command, String value) {

        String url = "http://<IP-FHEM>/fhem?cmd=set%20" + device +"%20" + command +"%20" + value;

        StringRequest postRequest = new StringRequest(Request.Method.POST, url,
                new Response.Listener<String>()
                {
                    @Override
                    public void onResponse(String response) {
                        // response
                        Log.d("Response", response);
                    }
                },
                new Response.ErrorListener()
                {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        // error
                        Log.d("Error.Response", String.valueOf(error));
                    }
                }
        );

        mQueue.add(postRequest);
    }


Die URL einfach an den POST angepasst und die POST-Methode von Volley eingesetzt.