+ Antworten
Seite 1 von 7 1 2 3 ... LetzteLetzte
Ergebnis 1 bis 10 von 70
  1. #1
    Registriert seit
    Oct 2010
    Beiträge
    50

    Standard JSON-RPC über Python

    Hallo Leute

    Ich kämpfe mit der JSON-RPC-Schnittstelle. Genauer mit der Formatierung des "Param"-Feldes.

    Ausgangslage:
    Ein Raspberry-Pi hat ein 4x4 Keypad an einen I2C-Keyboard-controller angeschlossen und soll die gedrückte Taste via JSON-RPC an IPS übermitteln. Die gedrückte Taste ist eine 3-stellige Ziffer.

    Auf dem Raspberry läuft ein Python-Script. Der JSON-RPC-Teil sieht so aus:

    Code:
    # JSON-RPS zu IPS definieren
    def IpsRpc(methodIps, paramIps):
        url = "http://<username>:<password>@<IPS-IP>:82/api/"
        headers = {'content-type': 'application/json'}
    
        payload = {
            "method": methodIps,
            "params": paramIps,
            "jsonrpc": "2.0",
            "id": 0,
        }
        print json.dumps(payload)
    
        response = requests.post(url, data=json.dumps(payload), headers=headers).json
    
        print(response)
    Der Aufruf geschieht mittels dem Befehl:
    Code:
    IpsRpc("SetValue", '[10900, '+str(key) +']')
    und generiert folgenden JSON-String:
    Code:
    {"jsonrpc": "2.0", "params": "[10900, 183]", "method": "SetValue", "id": 0}
    10900 ist dabei die zu aktualisierende Variablen-ID von IPS. 183 ist die 3-stellige Ziffer der gedrückten Taste. Soweit sogut, nur antwortet mir IPS mit folgender Fehlermeldung:
    Code:
    {u'jsonrpc': u'2.0', u'id': None, u'error': {u'message': u'Invalid request (params field invalid)', u'code': u'-32600'}}
    Der Fehler liegt offensichtlich beim "Params" -Feld.

    Wenn ich stattdessen folgenden CURL-Aufruf mache, funktioniert alles bestens:
    Code:
     curl -i -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0", "id": "0", "method": "SetValue", "params": [10900, 183]}' http://<username>:<password>@<IPS-IP>:82/api/
    Mittels Wireshark sehe ich den Unterschied, dass der CURL-Aufruf die Daten des "Param"-Feldes als Array verschickt, der Python Aufruf als String.

    Nun meine Fragen an euch:
    Wie müssen die Daten des Param-Feldes genau übermittelt werden ? Als String oder als Array ? Wenn als String mit den eckigen Klammer oder ohne ? Ich habe diverse Beispiele gefunden, allerdings immer nur mit der Methode "IPS_RunScript". Hat mir vielleicht jemand ein funktionierendes Beispiel mit "SetValue" oder sieht wo ich mich vertan habe ?

    Auf die Idee den JSON-RPC-Aufruf via dem Shell-Befehl CURL zu machen, kam ich natürlich auch schon. Nur habe ich mich da mit den doppelten und einfachen Hochkommas ziemlich vertan ... Eleganter wäre es natürlich schon alles in einem Python-Script zu haben.

    Danke und Gruss
    Letraz
    IPS 4.4 Unlimited auf Win7 (ESXi) (~ 2000 Variablen) / Raspberry Pi3 an EloTouch-Panel / CCU3 Charly mit 43 HM-Aktoren Funk, 24 HM-Aktoren Wired, 7x HM-Aktoren IP / 4x IPS-RGBW / 1x IPS Lüftgüte / 6x Squeezebox / 2x Reinhardt-Wetterstation / 1x Netatmo / 2x Landis + Gyr E230 / 3x Fronius Wechselrichter / TOA-Blitzortung / CTA-Wärmepumpe / Sony-TV / ... und noch vieles mehr, welches auf die Einbindung in wartet...

  2. #2
    Registriert seit
    Oct 2010
    Beiträge
    50

    ... ich habe mich in der Zwischenzeit etwas Schlau gemacht. Gemäss der "JSON-RPC 2.0 Spezifikation" --> http://www.jsonrpc.org/specification MUSS das Feld "params" ein Array sein.

    Ich hatte einen Fehler in der Parameterübergabe meines Funktionsaufrufs. Korrekt muss der Aufruf lauten:
    Code:
    IpsRpc("SetValue", [10900, +(key)])
    Dann ergibt sich folgender JSON-String:
    Code:
    {"jsonrpc": "2.0", "params": [10900, 183], "method": "SetValue", "id": "0"}
    Der Output sieht fast identisch aus wie vorher, nur der Unterschied ist jetzt das Array beim Feld "params".
    Geändert von Letraz (27.12.14 um 16:05 Uhr) Grund: Rechtschreibefehler korrigiert
    IPS 4.4 Unlimited auf Win7 (ESXi) (~ 2000 Variablen) / Raspberry Pi3 an EloTouch-Panel / CCU3 Charly mit 43 HM-Aktoren Funk, 24 HM-Aktoren Wired, 7x HM-Aktoren IP / 4x IPS-RGBW / 1x IPS Lüftgüte / 6x Squeezebox / 2x Reinhardt-Wetterstation / 1x Netatmo / 2x Landis + Gyr E230 / 3x Fronius Wechselrichter / TOA-Blitzortung / CTA-Wärmepumpe / Sony-TV / ... und noch vieles mehr, welches auf die Einbindung in wartet...

  3. #3
    Registriert seit
    Oct 2010
    Beiträge
    50

    Standard Erledigt

    ... ich nochmals.

    Es trat noch das Problem auf, dass mit dem Python-modul "python-requests" Version 0.12.1-1 (Python Version 2.7.3) kein Authentication-header an IPS gesendet wurde und daher immer eine "Invalid Username/Password for remote access" - Fehlermeldung zurückgeliefert wurde. (Wie ich Wireshark zum debuggen liebe )
    Dazu muss noch "HTTPBasicAuth" importiert werden.

    Mein Erster und jetzt zu meiner vollsten Zufriedenheit funktionierende Python-Script (der JSON-RPC relevante Teil) sieht wie folgt aus:

    Code:
    # notwendige Module importieren
    import requests, json
    from requests.auth import HTTPBasicAuth
    ...
    # JSON-RPS zu IPS definieren
    def IpsRpc(methodIps, paramIps):
        url = "http://<IPS-IP>:82>/api/"
        auth=HTTPBasicAuth('<username>', '<passwort>')   # username nicht codiert, bsp. johndoe@unknown.net 
        headers = {'content-type': 'application/json'}
    
        payload = {
            "method": methodIps,
            "params": paramIps,
            "jsonrpc": "2.0",
            "id": "0",
        }
        response = requests.post(url, auth=auth, data=json.dumps(payload), headers=headers).json
    ...
    IpsRpc("SetValue", [10900, +(key)])  # 10900 = zu aktualisierende IPS-Variablen-ID, key = zu sendender Wert
    IPS 4.4 Unlimited auf Win7 (ESXi) (~ 2000 Variablen) / Raspberry Pi3 an EloTouch-Panel / CCU3 Charly mit 43 HM-Aktoren Funk, 24 HM-Aktoren Wired, 7x HM-Aktoren IP / 4x IPS-RGBW / 1x IPS Lüftgüte / 6x Squeezebox / 2x Reinhardt-Wetterstation / 1x Netatmo / 2x Landis + Gyr E230 / 3x Fronius Wechselrichter / TOA-Blitzortung / CTA-Wärmepumpe / Sony-TV / ... und noch vieles mehr, welches auf die Einbindung in wartet...

  4. #4
    Registriert seit
    Aug 2013
    Beiträge
    117

    Code:
    # JSON-RPS zu IPS definieren
    def IpsRpc(methodIps, paramIps):
        url = "http://<username>:<password>@<IPS-IP>:82/api/"
        headers = {'content-type': 'application/json'}
    
        payload = {
            "method": methodIps,
            "params": paramIps,
            "jsonrpc": "2.0",
            "id": 0,
        }
        print json.dumps(payload)
    
        response = requests.post(url, data=json.dumps(payload), headers=headers).json
    
        print(response)

    Code:
    IpsRpc("SetValue", [10900, +(key)])
    Kannst du mir mal erklären was dieser Teil macht? Irgendwie steig ich da nicht ganz durch.
    Ergeben all diese CODE-schnipsel ein komplettes Python-Script?

    Code:
    {"jsonrpc": "2.0", "params": [10900, 183], "method": "SetValue", "id": "0"}
    OK hierbei wird der Wert 183 in die IPS Variable 10900 geschrieben. Richtig?
    Geändert von Stefan W (29.12.14 um 23:55 Uhr)
    IPS 4.3 Professional | Siemens S7-300 | IBH-Link | RaspberryPi | Arduino Mega 2560 | Arduino Nano

  5. #5
    Registriert seit
    Feb 2005
    Ort
    Lübeck
    Beiträge
    21,258

    Danke für dein Beispiel

    Habe das Thema mal ein wenig umbenannt und nach oben gehängt!

    paresy

  6. #6
    Registriert seit
    Oct 2010
    Beiträge
    50

    Hallo Stefan

    Bitte entschuldige die späte Antwort.

    Code:
    IpsRpc("SetValue", [10900, +(key)])
    Diese Zeile ruft die Funktion "IpsRpc" auf und übergibt ihr ein Array mit zwei Werten. 10900 ist die zu aktualisierende Variable in IPS und die Python-Variable (key) beinhaltet den Tastencode der gedrückten Taste (den Wert "183" im Beispiel).

    Diese Zeilen sind zwar schon ein komplettes Python-Script, allerdings macht das so noch nicht viel. Die Funktion IpsRpc (also die Zeile "def IpsRpc(methodIps, paramIps):" bis "print(response)") definiert eine Funktion namens IpsRpc und sendet beim Aufruf die erhaltenen Daten an IPS. Die zitierte Zeile oben ruft eben diese Funktion "IpsRpc" auf (= führt sie aus) und übergibt ihr Daten, welche dann an IPS gesendet werden.

    Der Rest meines Python-Scriptes habe ich nicht gepostet, da es lediglich für meinen Anwendungsfall passt. Wie eingangs erwähnt frage ich via I2C einen 4x4 Keyboard-controller ab und übermittle die gedrückte Taste.
    IPS 4.4 Unlimited auf Win7 (ESXi) (~ 2000 Variablen) / Raspberry Pi3 an EloTouch-Panel / CCU3 Charly mit 43 HM-Aktoren Funk, 24 HM-Aktoren Wired, 7x HM-Aktoren IP / 4x IPS-RGBW / 1x IPS Lüftgüte / 6x Squeezebox / 2x Reinhardt-Wetterstation / 1x Netatmo / 2x Landis + Gyr E230 / 3x Fronius Wechselrichter / TOA-Blitzortung / CTA-Wärmepumpe / Sony-TV / ... und noch vieles mehr, welches auf die Einbindung in wartet...

  7. #7
    Registriert seit
    Dec 2010
    Beiträge
    48

    hi,

    danke fuer deine Berichte zum posten der Variablen aus Python. Ich wuerde das gerne ein etwas erweitern, allerdings kaempfe ich ein bisschen mit den Funktionen zum Zusammenbauen der Variablenwerte/Strings/Nicht-Strings.

    --EDIT--

    Noch 5 Versuche mehr und jetzt hab ich's auch geschafft, hier die Aenderung um beliebige Typen schreiben zu koennen:

    Boolean:
    Code:
    variable=44718
    value=True
    IpsRpc("SetValue", [variable,value])
    String:
    Code:
    variable=44713
    value="abc"
    IpsRpc("SetValue", [variable,value])
    Int/Float:
    Code:
    variable=44711
    value=123
    IpsRpc("SetValue", [variable,value])
    Geändert von obstler42 (09.01.15 um 22:12 Uhr)

  8. #8
    Registriert seit
    Dec 2009
    Ort
    Ruhrgebiet
    Beiträge
    49

    Hallo Letraz,

    ja, auch ich muss mich bei Dir bedanken, für Dein tolles Konzept.

    Obwohl ich JSON-RPC schon "lange" benutze, um z.B. aus eigenen WEB-Seiten mittels JSON-RPC Werte aus IPS abzufragen, oder zu ändern (alles mittels PHP), war es mir bislang nicht möglich etwas ähnliches unter Python zu erledigen. (btw: ich bin blutiger Anfänger was Python betrifft.)

    Ich suchte eine Möglichkeit, meinen Raspberry Pi dazu zu bringen irgendwelche Werte oder Ereignisse mittels Python an meine normale IPS Installation (Windows Home Server) zu übertragen. Jetzt geht das !

    Vielleicht noch eine Anmerkung dazu:
    Ich hatte mir vorher schon - speziell für JSON-RPC - eine separate WebServer Instanz eingerichtet. (s.Bild)
    Damit wird die Verbindung und Authentifizierung zu IPS vielleicht etwas übersichtlicher:

    url = "http://192.168.xxx.xxx:8088/api/"
    auth=HTTPBasicAuth('nnn','ppp')


    Gruß
    mareng

    Name:  WebServer_JSON_RPC.JPG
Hits: 2525
Größe:  39.1 KB
    einige Raspi's - 1wire - FHZ1000PC - FHT80b - FS20 diverse Komponenten - Homematic - Arduinos

  9. #9
    Registriert seit
    Dec 2009
    Ort
    Ruhrgebiet
    Beiträge
    49

    Standard Wie erhalte ich in Python Ergebnisse aus IPS mittels JSON-RPC ..?

    Hallo,

    jetzt muss ich doch nochmal auf das Thema zurückkommen.

    Die Übertragung von Werten von einem Raspi aus in IPS-Variablen funktioniert nach den zuvor beschriebenen Beispielen problemlos.

    Nun möchte ich gerne auf diese Weise Variableninhalte aus IPS in Python verwenden. Alle verzweifelten Versuche haben bisher keinen Erfolg gebracht. Vielleicht kann mir jemand ein Beispiel dazu nennen ? (Ich bin kein Python Experte !!)

    Ich verwende die selbe Funktion "IpsRpc" nur mit den angepassten Parametern
    >>>>> IpsRpc("GetValueFormatted", "18447") # 18447 ist die Variablen ID

    und versuche mit
    >>>> response = requests.post(url, auth=auth, data=json.dumps(payload), headers=headers).json
    und
    >>>> print response
    auf das Ergebnis zuzugreifen.

    Als Ergebnis erhalte ich:
    <bound method Response.json of <Response [200]>>

    Das ist sicherlich zu kurz gedacht, das mit dem "print", aber wie gesagt ich bin leider kein Python Experte.

    Kann mir trotzdem jemand sagen wie es richtig geht ?

    Besten Dank im vorraus.

    Gruß
    mareng
    einige Raspi's - 1wire - FHZ1000PC - FHT80b - FS20 diverse Komponenten - Homematic - Arduinos

  10. #10
    Registriert seit
    Dec 2009
    Ort
    Ruhrgebiet
    Beiträge
    49

    Standard In eigener Sache: "Problem" gelöst ...

    So, nach vielen Recherchen im Netz habe ich eine Antwort auf die (meine) Frage erhalten. Ich möchte mein Ergebnis niemandem vorenthalten, weil ich inzwischen weiss, wie mühseelig eine solche Suche sein kann.

    Zuerst der Hinweis auf die Webseite, die mich mich wirklich entscheidend weitergebracht hat:
    http://www.python-requests.org/en/la...sponse-content

    Die ganze Problematik hing demnach nicht an einer fehlerhaften Verwendung der "json"-Library, sondern an der richtigen Nutzung von "requests".

    Ich habe mal die Einzelschritte in Python aufgeführt:
    Code:
    >>> import requests
    >>> from requests.auth import HTTPBasicAuth
    >>> import json
    >>> url = "http://192.168.0.nnn:8088/api/"
    >>> auth=HTTPBasicAuth('uuuu','pppp')
    >>> headers = {'content-type': 'application/json'}
    >>> payload = {"method": "GetValueFloat", "params": [18447], "jsonrpc": "2.0", "id": "0"}    # 18447 ist ID im IPS
    >>> r = requests.post(url, auth=auth, data=json.dumps(payload), headers=headers, stream=True)  # Achtung ! kein ".json" am Ende
    >>> r.text
    u'{"result":6597.34000000006,"id":"0","jsonrpc":"2.0"}'
    >>> s = r.text    # s:   nur zum Test ... !
    >>> print s
    {"result":6597.34000000006,"id":"0","jsonrpc":"2.0"}
    >>> r.json()["result"]
    6597.34000000006
    >>> gc = r.json()["result"]    # gc ist eine gas_counter Variable 
    >>> print gc
    6597.34
    >>>
    Der entscheidende Punkt war die - offensichtlich unzulässige - Verwendung von .json am Ende des request Statements.

    Ich habe die Einzelschritte selbstverständlich in eine Funktion integriert, so wie bereits oben beschrieben.

    Damit kann ich nun meine Anforderung an die Kopplung raspberry <--> IPS erfüllen.

    viele Grüße
    mareng
    einige Raspi's - 1wire - FHZ1000PC - FHT80b - FS20 diverse Komponenten - Homematic - Arduinos

Ähnliche Themen

  1. JSON-RPC über C#/VB.NET Step by Step
    Von Schablone im Forum Entwicklung mit PHP-SDK/Delphi-SDK
    Antworten: 20
    Letzter Beitrag: 11.09.16, 14:13
  2. Json rpc
    Von wango im Forum Skripte, PHP, SQL
    Antworten: 3
    Letzter Beitrag: 20.08.14, 20:13
  3. JSON-RPC interface
    Von barcaj im Forum General Discussion
    Antworten: 4
    Letzter Beitrag: 10.03.14, 21:19
  4. JSON-RPC über VB.NET Step by Step - Diskussionsthread
    Von Schablone im Forum Entwicklung mit PHP-SDK/Delphi-SDK
    Antworten: 8
    Letzter Beitrag: 24.02.14, 19:39
  5. JSON-RPC Version?
    Von axbigo im Forum Allgemeine Diskussion (2.x/3.x)
    Antworten: 1
    Letzter Beitrag: 14.10.13, 17:01

Stichworte