Neue Version von HTTPMOD mit neuen Features zum Testen

Begonnen von StefanStrobel, 05 Dezember 2015, 08:31:32

Vorheriges Thema - Nächstes Thema

reibuehl

Ich habe etwas Probleme, die richtigen Infos aus einem JSON zu extrahieren...

Ich möchte die ersten vier Gruppen aus der "Departures" Gruppe als readings:

{
  "ms": 140,
  "status": "success",
  "data": {
    "BusGroups": [
      {
        "Type": "Buss",
        "Title": "Bergsunds strand",
        "Departures": [
          {
            "LineNumber": "54",
            "Destination": "Storängsbotten",
            "ExpectedDateTime": "2016-01-20T11:25:36",
            "DisplayTime": "1 min",
            "Deviations": [],
            "StopPointNumber": "10961"
          },
          {
            "LineNumber": "66",
            "Destination": "Reimersholme",
            "ExpectedDateTime": "2016-01-20T11:28:04",
            "DisplayTime": "3 min",
            "Deviations": [],
            "StopPointNumber": "10962"
          },
          {
            "LineNumber": "54",
            "Destination": "Reimersholme",
            "ExpectedDateTime": "2016-01-20T11:29:27",
            "DisplayTime": "5 min",
            "Deviations": [],
            "StopPointNumber": "10962"
          },
          {
            "LineNumber": "66",
            "Destination": "Sofia",
            "ExpectedDateTime": "2016-01-20T11:33:00",
            "DisplayTime": "8 min",
            "Deviations": [],
            "StopPointNumber": "10961"
          },
          {
            "LineNumber": "54",
            "Destination": "Storängsbotten",
            "ExpectedDateTime": "2016-01-20T11:36:53",
            "DisplayTime": "12 min",
            "Deviations": [],
            "StopPointNumber": "10961"
          },
          {
            "LineNumber": "54",
            "Destination": "Reimersholme",
            "ExpectedDateTime": "2016-01-20T11:41:01",
            "DisplayTime": "16 min",
            "Deviations": [],
            "StopPointNumber": "10962"
          },
          {
            "LineNumber": "66",
            "Destination": "Reimersholme",
            "ExpectedDateTime": "2016-01-20T11:45:16",
            "DisplayTime": "21 min",
            "Deviations": [],
            "StopPointNumber": "10962"
          },
          {
            "LineNumber": "54",
            "Destination": "Storängsbotten",
            "ExpectedDateTime": "2016-01-20T11:48:53",
            "DisplayTime": "24 min",
            "Deviations": [],
            "StopPointNumber": "10961"
          },
          {
            "LineNumber": "66",
            "Destination": "Sofia",
            "ExpectedDateTime": "2016-01-20T11:49:28",
            "DisplayTime": "25 min",
            "Deviations": [],
            "StopPointNumber": "10961"
          },
          {
            "LineNumber": "54",
            "Destination": "Reimersholme",
            "ExpectedDateTime": "2016-01-20T11:53:18",
            "DisplayTime": "29 min",
            "Deviations": [],
            "StopPointNumber": "10962"
          },
          {
            "LineNumber": "66",
            "Destination": "Reimersholme",
            "ExpectedDateTime": "2016-01-20T11:56:27",
            "DisplayTime": "11:56",
            "Deviations": [],
            "StopPointNumber": "10962"
          },
          {
            "LineNumber": "54",
            "Destination": "Storängsbotten",
            "ExpectedDateTime": "2016-01-20T12:00:53",
            "DisplayTime": "12:00",
            "Deviations": [],
            "StopPointNumber": "10961"
          },
          {
            "LineNumber": "54",
            "Destination": "Reimersholme",
            "ExpectedDateTime": "2016-01-20T12:03:27",
            "DisplayTime": "12:03",
            "Deviations": [],
            "StopPointNumber": "10962"
          },
          {
            "LineNumber": "66",
            "Destination": "Sofia",
            "ExpectedDateTime": "2016-01-20T12:05:53",
            "DisplayTime": "12:05",
            "Deviations": [],
            "StopPointNumber": "10961"
          },
          {
            "LineNumber": "54",
            "Destination": "Storängsbotten",
            "ExpectedDateTime": "2016-01-20T12:12:53",
            "DisplayTime": "12:12",
            "Deviations": [],
            "StopPointNumber": "10961"
          },
          {
            "LineNumber": "54",
            "Destination": "Reimersholme",
            "ExpectedDateTime": "2016-01-20T12:15:27",
            "DisplayTime": "12:15",
            "Deviations": [],
            "StopPointNumber": "10962"
          },
          {
            "LineNumber": "66",
            "Destination": "Reimersholme",
            "ExpectedDateTime": "2016-01-20T12:16:27",
            "DisplayTime": "12:16",
            "Deviations": [],
            "StopPointNumber": "10962"
          }
        ],
        "CurrentServerTime": "11:24",
        "StopPointDeviations": [],
        "GroupId": "Bergsunds strand#10961",
        "JourneyProduct": 8
      }
    ],
    "TrainGroups": [],
    "TranCityTypes": [],
    "TramTypes": [],
    "MetroRedGroups": [],
    "MetroGreenGroups": [],
    "MetroBlueGroups": [],
    "ShipGroups": [],
    "HasStopPointDeviations": false,
    "LastUpdate": "11:23",
    "Error": null,
    "HasResultData": true
  }
}


Geht das mit dem Modul?
Reiner.

StefanStrobel

Hallo Reiner,

Das sollte gehen.
Gib einfach mal das Attribut extractAllJSON an.
Dann werden alle Daten in Readings geholt.
Die Namen der Readings entsprechen dabei den Strings, die Du bei den readingXJSON oder getXJSON Attributen angeben kannst, um später nur noch die gewünschten Readings zu speichern.

Gruß
   Stefan

StefanStrobel

Hallo Tim,

Probleme mit Umlauten etc. solltest Du mit den encode und decode Attributen lösen können.

Gruß
   Stefan

reibuehl

Hallo Stefan,

ich hatte es mit dem Attribut extractAllJSON versucht, das hat auch soweit funktioniert, ich hatte dann keine Möglichkeit gefunden, die Umlaute korrekt einzustellen.
Ich habe verschiedene Kombinationen von readingEncode und readingDecode versucht, die schienen aber keinen Einfluss auf die Umlaute zu haben.
Außerdem ist es mir nicht gelungen, veraltete readings zu löschen bzw. zu überschreiben, obwohl ich diese Parameter gesetzt habe:


attr BusInfo readingMaxAge 300
attr BusInfo readingMaxAgeReplacement offline
attr BusInfo readingMaxAgeReplacementMode text


Gibt es eine Möglichkeit, vielleicht in Zukunft einen readingMaxAgeReplacementMode delete zu implementieren?

Gruß,
Reiner

Reiner.

Cruiser79

Zitat von: StefanStrobel am 20 Januar 2016, 12:04:00
Hallo Tim,

Probleme mit Umlauten etc. solltest Du mit den encode und decode Attributen lösen können.

Gruß
   Stefan

Hi Stefan,

im Request der Anfrage steht eigentlich, das es schon als UTF-8 ankommt "Content-Type: text/html;charset=UTF-8 "
FHEM und somit auch das HTTPMOD Modul arbeiten doch schon in UTF-8? Frage mich nun also, was ich da wie encoden oder decoden soll? Kannst du mir mal sagen, welches encode/decode Attribute fehlt?

Gruß,
Tim
FHEM auf Raspberry Pi
HM-CFG-LAN mit HM-TC-IT-WM-W-EU, HM-CC-RT-DN, HM-WDS10-TH-O, HM-LC-SW1-FM, HM-LC-Bl1-FM
Signalduino mit Elro AB440, LOGILINK WS0002, IT CMR-1000

reibuehl

Hi Stefan,

ich habe jetzt mal wie von Dir angeregt die mit extractAllJSON ermittelten Namen/Pfade von Hand eingetragen und extractAllJSON aus der Konfiguration gelöscht. Jetzt bekomme ich aber gar keine Updates mehr. Im Logfile steht:

2016.01.20 14:31:12 3: BusInfo: Read response to update didn't match any Reading

Das ist die aktuelle Konfiguration:

define BusInfo HTTPMOD http://sl.se/api/sv/RealTime/GetDepartures/1388 60
attr BusInfo userattr 1 enableCookies reading01JSON reading01Name reading02JSON reading03JSON reading04JSON reading05JSON reading06JSON reading07JSON reading08JSON reading09JSON reading10JSON reading11JSON reading12JSON readingDecode readingEncode readingMaxAge readingMaxAgeReplacement readingMaxAgeReplacementMode
attr BusInfo enableCookies 1
attr BusInfo reading01JSON data_BusGroups_01_Departures_01_Destination
attr BusInfo reading02JSON data_BusGroups_01_Departures_01_DisplayTime
attr BusInfo reading03JSON data_BusGroups_01_Departures_01_LineNumber
attr BusInfo reading04JSON data_BusGroups_01_Departures_02_Destination
attr BusInfo reading05JSON data_BusGroups_01_Departures_02_DisplayTime
attr BusInfo reading06JSON data_BusGroups_01_Departures_02_LineNumber
attr BusInfo reading07JSON data_BusGroups_01_Departures_03_Destination
attr BusInfo reading08JSON data_BusGroups_01_Departures_03_DisplayTime
attr BusInfo reading09JSON data_BusGroups_01_Departures_03_LineNumber
attr BusInfo reading10JSON data_BusGroups_01_Departures_04_Destination
attr BusInfo reading11JSON data_BusGroups_01_Departures_04_DisplayTime
attr BusInfo reading12JSON data_BusGroups_01_Departures_04_LineNumber
attr BusInfo readingMaxAge 300
attr BusInfo readingMaxAgeReplacement offline
attr BusInfo readingMaxAgeReplacementMode text
attr BusInfo room Devices
Reiner.

Cruiser79

Zitat von: Reiner am 20 Januar 2016, 14:32:16
Hi Stefan,

ich habe jetzt mal wie von Dir angeregt die mit extractAllJSON ermittelten Namen/Pfade von Hand eingetragen und extractAllJSON aus der Konfiguration gelöscht. Jetzt bekomme ich aber gar keine Updates mehr. Im Logfile steht:

2016.01.20 14:31:12 3: BusInfo: Read response to update didn't match any Reading

Das ist die aktuelle Konfiguration:

define BusInfo HTTPMOD http://sl.se/api/sv/RealTime/GetDepartures/1388 60
attr BusInfo userattr 1 enableCookies reading01JSON reading01Name reading02JSON reading03JSON reading04JSON reading05JSON reading06JSON reading07JSON reading08JSON reading09JSON reading10JSON reading11JSON reading12JSON readingDecode readingEncode readingMaxAge readingMaxAgeReplacement readingMaxAgeReplacementMode
attr BusInfo enableCookies 1
attr BusInfo reading01JSON data_BusGroups_01_Departures_01_Destination
attr BusInfo reading02JSON data_BusGroups_01_Departures_01_DisplayTime
attr BusInfo reading03JSON data_BusGroups_01_Departures_01_LineNumber
attr BusInfo reading04JSON data_BusGroups_01_Departures_02_Destination
attr BusInfo reading05JSON data_BusGroups_01_Departures_02_DisplayTime
attr BusInfo reading06JSON data_BusGroups_01_Departures_02_LineNumber
attr BusInfo reading07JSON data_BusGroups_01_Departures_03_Destination
attr BusInfo reading08JSON data_BusGroups_01_Departures_03_DisplayTime
attr BusInfo reading09JSON data_BusGroups_01_Departures_03_LineNumber
attr BusInfo reading10JSON data_BusGroups_01_Departures_04_Destination
attr BusInfo reading11JSON data_BusGroups_01_Departures_04_DisplayTime
attr BusInfo reading12JSON data_BusGroups_01_Departures_04_LineNumber
attr BusInfo readingMaxAge 300
attr BusInfo readingMaxAgeReplacement offline
attr BusInfo readingMaxAgeReplacementMode text
attr BusInfo room Devices


Wenn ich mich nicht irre, fehlt doch bei jedem readingXXJSON das dazugehörige readingXXName. Du musst dem Modul doch noch sagen, in welches Reading er die per readingXXJSON aus dem Request herausextrahierten Daten packen soll.

Gruß,
Tim
FHEM auf Raspberry Pi
HM-CFG-LAN mit HM-TC-IT-WM-W-EU, HM-CC-RT-DN, HM-WDS10-TH-O, HM-LC-SW1-FM, HM-LC-Bl1-FM
Signalduino mit Elro AB440, LOGILINK WS0002, IT CMR-1000

StefanStrobel

Hallo Reiner und Tim,

Für jedes Reading wird immer ein Name benötigt. Die Parse-Anweisung kann dann zwischen Regex, XPath oder JSON variieren. ohne readingXXName läuft ein readingXXJSON daher ins Leere.

Was Umlaute etc. angeht, so gibt es leider kein Patentrezept. Auch wenn der Server "behauptet" UTF-8 zu liefern, kommt es bei Haustechnik-Geräten o.ä. immer wieder vor, dass der Entwickler gar nicht wusste was er tut und die Texte dann doch in irgendeiner DOS-Codepage oder ähnlichen Kodierungen geliefert werden.
Da hilft nur genau  hinsehen, wie die Zeichen tatsächlich geliefert werden und dann passend hin- und her wandeln.

Ein ReplacementMode delete wäre eine unkomplizierte Erweiterung. Das bau ich demnächst mal ein.

Gruss
    Stefan

StefanStrobel

Hallo Oliver und Frank,

mit den Zyklischen Abfragen bei HTTPMOD ist das folgendermassen:
Ursprünglich war die Grundidee von HTTPMOD dass man über eine einzige URL regelmäßig Daten abfragen kann, und das in der einen Antwort mehrere interessante Werte stehen können. Daher kommt die URL und das Intervall beim Define. HTTPMOD ruft die URL dann in einer GetUpdate-Funktion automatische regelmäßig auf und mit den reading... Attributen wird diese eine Antwort geparsed und die Werte werden in meist mehreren Readings gespeichert.

In einer späteren Erweiterung habe ich die get... Attribute eingebaut, damit man mit einem Get-Kommando explizit / bei Bedarf Daten abrufen kann. Dabei kann man für jedes Get eine abweichende URL und optional alternative Parse-Optionen angeben (muss man aber nicht, dann greifen auch hier die reading... Attribute).

Damit Werte mit eigener URL dann auch automatisch zyklisch abgefragt werden können, kann man mit dem getXXPoll Attribut das Get quasi an die GetUpdate-Funktion anhängen und mit dem PollDelay eine seltenere Abfrage umsetzen.
Die Gets mit automatischer Abfrage braucht man eigntlich nur dann, wenn mehrere Werte wirklich über unterschiedliche URLs abgefragt werden müssen.

Unterm Strich bedeutet das dass man für zyklische Abfragen meistens besser mit reading... Attributen und einer URL + Intervall-Angabe beim Define fährt. Insbesondere wenn man mehrere Werte aus einer Antwort auslesen möchte.
Wenn man das mit einzelnen Gets realisiert, geht das zwar auch, aber dann wird für jedes Get ein separater HTTP-Request erzeugt. Wenn dabei die URL eigentlich die gleiche ist, ist das überflüssig und das abgefragte Gerät wird mehrfach hintereinander nach den gleichen Daten gefragt.

Die requestData bzw. getXXData Attribute sorgen dafür dass kein HTTP-GET sondern ein HTTP-POST gesendet wird. Dabei landen die Daten nicht wie bei einem Get als Query-String (nach ?) in der URL sondern als mehrzeiliger Daten-Anteil nach den HTTP-Headern. Hier kommt es darauf an, was das Gerät haben will. Manche verstehen die Abfragen sowohl als HTTP-GET mit Daten als Query-String nach einem ? in der URL, als auch per HTTP-POST, andere erwarten einen HTTP-POST.

Die getXXURL ist wie oben schon geschrieben dafür da dass man bei jedem Get eine eigene URL angeben kann. Wenn die URL nicht angegeben wird, verwendet HTTPMOD automatisch die URL aus dem Define.

Ich hoffe die Erläuterung hilft Euch weiter :-)

Gruss
    Stefan

reibuehl

Hallo Stefan,

vielen Dank für die Klarstellung mit dem readingXXName. Ich war davon ausgegangen, dass dies ein optionales Setting ist und der "Pfad" aus dem readingXXJSON genommen wird, wenn es nicht angegeben ist.

Nach der Umstellung auf einzelne Readings und hinzufügen von readingXXEncode utf-8 funktionieren bei mir nun auch die Umlaute. Nur zu meinem Verständnis: Wie hätte man das bei extractAllJSON für alle readings definieren müssen?

Bin mal gespannt, ob das readingMaxAgeReplacement heute nacht funktioniert wenn der letzte Bus durch ist :)

Vielen Dank für die tolle Arbeit!

Gruß,
Reiner
Reiner.

reibuehl

Noch eine kleine Frage... :)

Bei HTTPMOD Devices steht im Internals Feld STATE bei mir immer "???". Wäre es möglich, da einen Wert - z.B. die Text-Form des letzten HTTP Status Codes - einzutragen? Der Status-Code wird ja im Internal "code" abgelegt.

Gruß,
Reiner
Reiner.

frank

ZitatIch hoffe die Erläuterung hilft Euch weiter :-)
sicherlich, danke.   :)
FHEM: 6.0(SVN) => Pi3(buster)
IO: CUL433|CUL868|HMLAN|HMUSB2|HMUART
CUL_HM: CC-TC|CC-VD|SEC-SD|SEC-SC|SEC-RHS|Sw1PBU-FM|Sw1-FM|Dim1TPBU-FM|Dim1T-FM|ES-PMSw1-Pl
IT: ITZ500|ITT1500|ITR1500|GRR3500
WebUI [HMdeviceTools.js (hm.js)]: https://forum.fhem.de/index.php/topic,106959.0.html

Bootscreen

Zitat von: Reiner am 20 Januar 2016, 21:35:26
Noch eine kleine Frage... :)

Bei HTTPMOD Devices steht im Internals Feld STATE bei mir immer "???". Wäre es möglich, da einen Wert - z.B. die Text-Form des letzten HTTP Status Codes - einzutragen? Der Status-Code wird ja im Internal "code" abgelegt.

Gruß,
Reiner
teste mal stateFormat: {sprintf("%s",InternalVal("<device>","code",""))}

weiß jemand wie ich die meldung wegbekomme? "Read response to update didn't match any Reading"

Internals:
   BUSY       0
   CHANGED
   DEF        https://creativecommons.tankerkoenig.de/json/detail.php?id=005056ba-7cb6-1ed2-bceb-7c4d1b36ed27&apikey= 60
   Interval   60
   JSONEnabled 1
   LASTSEND   1453380210.95255
   MainURL    https://creativecommons.tankerkoenig.de/json/detail.php?id=005056ba-7cb6-1ed2-bceb-7c4d1b36ed27&apikey=
   NAME       Sprit.Star_BadSachsa.SuperE5
   NR         38
   STATE      1.219
   TRIGGERTIME 1453380270.94978
   TRIGGERTIME_FMT 2016-01-21 13:44:30
   TYPE       HTTPMOD
   addr       https://creativecommons.tankerkoenig.de:443
   buf        HTTP/1.1 200 OKcode       200
   conn
   data
   displayurl https://creativecommons.tankerkoenig.de/json/detail.php?id=005056ba-7cb6-1ed2-bceb-7c4d1b36ed27&apikey=
   header
   host       creativecommons.tankerkoenig.de
   httpheader HTTP/1.1 200 OK
   hu_blocking 0
   hu_filecount 255
   ignoreredirects 0
   loglevel   4
   path       /json/detail.php?id=005056ba-7cb6-1ed2-bceb-7c4d1b36ed27&apikey=
   protocol   https
   redirects  0
   timeout    2
   url        https://creativecommons.tankerkoenig.de/json/detail.php?id=005056ba-7cb6-1ed2-bceb-7c4d1b36ed27&apikey=
   value      0
   QUEUE:
   Readings:
     2016-01-21 13:31:31   Status          true
     2016-01-21 13:31:31   SuperE5         1.219
   Request:
     data
     header
     ignoreredirects 0
     retryCount 0
     type       update
     url        https://creativecommons.tankerkoenig.de/json/detail.php?id=005056ba-7cb6-1ed2-bceb-7c4d1b36ed27&apikey=
     value      0
   Defptr:
     Readingbase:
       Status     get
       SuperE5    get
     Readingnum:
       Status     02
       SuperE5    01
     Readingoutdated:
     Readingsubnum:
       Status
       SuperE5
   Lastpoll:
     Status     1453379490.88667
     SuperE5    1453379490.88667
   Sslargs:
Attributes:
   alias      Star - Bad Sachsa - Super - (06:00-21:00 | WE 8:30-20:00)
   get01JSON  station_e5
   get01Name  SuperE5
   get01Poll  1
   get01PollDelay 900
   get02JSON  station_isOpen
   get02Name  Status
   get02Poll  1
   get02PollDelay 900
   group      Spritpreise
   room       Spritpreise
   stateFormat SuperE5
   userattr   extractAllJSON get01JSON get01Name get01Poll get01PollDelay get02JSON get02Name get02Poll get02PollDelay getData getHeader1 getHeader2 getURL stateFormat
Gruß
Oliver

FHEM 5.7 Hardware:
Raspberry PI B+ | HomeMatic USB 2 | 433Mhz Sender (pilight) | nanoCUL (433Mhz)

reibuehl

Zitat von: Bootscreen am 21 Januar 2016, 13:45:37
teste mal stateFormat: {sprintf("%s",InternalVal("<device>","code",""))}

Danke! Das sieht schon viel besser aus :)
Reiner.

StefanStrobel

Hallo Oliver,

hast Du schon von get... auf reading... umgestellt?
Die Meldung, die Dich stört, kommt dann wenn die Antwort auf einen Request nicht geparsed werden konnte bzw. keine Readings belegt werden konnten. Probiers doch mal ungefähr so:


define Sprit.Jet_Goettingen.SuperE5 HTTPMOD https://creativecommons.tankerkoenig.de/json/detail.php?id=51d4b46c-a095-1aa0-e100-80009459e03a&apikey= 900
attr Sprit.Jet_Goettingen.SuperE5 reading01JSON station_e5
attr Sprit.Jet_Goettingen.SuperE5 reading01Name SuperE5
attr Sprit.Jet_Goettingen.SuperE5 reading02JSON station_isOpen
attr Sprit.Jet_Goettingen.SuperE5 reading02Name Status
attr Sprit.Jet_Goettingen.SuperE5 requestHeader1 Content-Type: application/json
attr Sprit.Jet_Goettingen.SuperE5 requestHeader2 Accept: */*
attr Sprit.Jet_Goettingen.SuperE5 enableControlSet 1
attr Sprit.Jet_Goettingen.SuperE5 showMatched 1


Gruss
    Stefan