FHEM > Sonstiges

Neue Version von HTTPMOD mit neuen Features zum Testen

(1/246) > >>

StefanStrobel:
Hier eine neue Version von HTTPMOD zum Testen.

Bitte gebt mir Feedback wenn Ihr Bugs findet.

Folgendes ist neu:
- direktes Parsen von JSON inkl. automatischer Erzeugung von Readings für jedes Objekt
- Parsen von HTML-Daten und XML-Daten per XPath ist besser integriert und kann mit einem XPath mehrere Readings setzen
- Parsen von Regexes mit mehreren capture Groups kann mehrere Readings setzen
- dynamische Ersetzungen für URL, Header und Post Daten
- Reaktion auf Readings, die nicht aktualisiert wurden
- Erweiterte Dokumentation
- Maps können auch Leerzeichen im Text enthalten
- ParseFunction zum Einklinken eigener Parse-Funktionen
- diverse Bug Fixes und Kleinigkeiten

HTTPMOD hat sich intern an vielen Stellen geändert, so dass eine Parsing-Anweisung (Regex oder auch XPath) mehrere Readings erzeugen kann.
Beispiel:


--- Code: --- attr myDevice reading02Regex something[ \t]+([\d\.]+)[ \t]+([\d\.]+)
attr myDevice reading02Name Temp

--- Ende Code ---
   
hier enthält die Regex zwei capture groups, die jeweils auf eine Zahl matchen.
Dabei werden zwei Readings erzeugt:


--- Code: --- Temp-1
Temp-2

--- Ende Code ---
man kann diesen Readings auch eigene Namen geben. Dazu kann man die Attribute reading02-1Name, reading02-2Name etc. angeben. z.B.:

--- Code: --- attr myDevice reading02-1Name AussenTemp
attr myDevice reading02-2Name InnenTemp

--- Ende Code ---
   
Entsprechend kann man alle anderen Attribute für die Aufbereitung und Formattierung der Readings auch mit Nummer-Nummer spezifizieren.

In den meisten Fällen wird jedoch der bisherige Weg, bei dem für jedes Reading eine eigene Regex angegeben wird, der einfachste bleiben.
   
   
aus der Doku zu JSON:
Wenn ein Webservice Daten im JSON-Format schickt, kann HTTPMOD diese jetzt direkt parsen und aus den Objekten Readings erzeugen.
Das folgende Beispiel fragt Daten von einem Poolmanager ab (noch ohne Readings):

--- Code: ---define test2 HTTPMOD none 0
attr test2 get01Name Chlor
attr test2 getURL http://192.168.70.90/cgi-bin/webgui.fcgi
attr test2 getHeader1 Content-Type: application/json
attr test2 getHeader2 Accept: */*
attr test2 getData {"get" :["34.4008.value"]}

--- Ende Code ---
Die HTTP-Response enthält dann folgende Daten:

--- Code: ---{
"data": {
"34.4008.value": "0.25"
},
"status":       {
"code": 0
},
"event":        {
"type": 1,
"data": "48.30000.0"
}
}

--- Ende Code ---
Um bisher den Wert 0.25 in das Reading Chlor zu bekommen, musste man eine Regex wie folgt definieren:


--- Code: --- attr test2 get01Regex 34.4008.value":[ \t]+"([\d\.]+)"

--- Ende Code ---
Mit dem neuen JSON-Parsing könnte man statt dessen das Objekt in seiner Hierarchie adressieren:


--- Code: --- attr test2 get01JSON data_34.4008.value

--- Ende Code ---
oder - wenn die Benennung der Reading keine Rolle spielt, kann man auch automatisch aus allen Objekten ein Reading erzeugen und den Pfad in der Hierarchie als Namen verwenden. (Ich habe mich hier an einem Code-Beispiel von Andre orientiert)
Dafür gibt es das folgende Attribut:


--- Code: --- attr test2 extractAllJSON

--- Ende Code ---
Das gilt dann für alle gelesenen Daten in dieser Modul-Instanz und erzeigt aus obigen Daten die folgenden Readings:


--- Code: --- data_34.4008.value 0.25
event_data 48.30000.0
event_type 1
status_code 0

--- Ende Code ---
Alternativ kann man auch schreiben:


--- Code: --- attr test2 get01ExtractAllJSON

--- Ende Code ---
dann werden nur beim get Kommando get01 alle Objekte extrahiert.

aus der Doku zu XPath:

Eine andere Alternative zum Parsen von HTTP-Responses ist die Verwendung von XPath.
In der bisherigen Erweiterung von HTTPMOD für XPath hatte man einen XPath mit "xpath:" in Regexes angegeben.
Die neue Integration hat dafür ein eigenes Attribut. Wenn man HTML-Daten mit XPath parsen möchte, ist es:


--- Code: ---(reading|get)[0-9]+XPath
--- Ende Code ---

und für echte XML-Daten:


--- Code: ---(reading|get)[0-9]+XPath-Strict
--- Ende Code ---

Im Beispiel enthält eine HTTP-Response die folgenden XML-Daten:

--- Code: ---<root xmlns:foo="http://www.foo.org/" xmlns:bar="http://www.bar.org">
<actors>
<actor id=&quot;1&quot;>Peter X</actor>
<actor id=&quot;2&quot;>Charles Y</actor>
<actor id=&quot;3&quot;>John Doe</actor>
</actors>
</root>

--- Ende Code ---
Mit der XPath-Syntax könnte man schreiben:


--- Code: --- attr myDevice reading01Name Actor
attr myDevice reading01XPath-Strict //actor[2]/text()

--- Ende Code ---
Das erzeugt ein Reading mit dem Namen "Actor" und dem Wert "Charles Y".

Da XPath-Angaben wie Regexes mit mehreren capture groups auch zu mehreren Treffern führen können, greift auch hier die Neuerung von HTTPMOD, bei der mit einer Anweisung mehrere Readings erzeugt werden :


--- Code: --- attr myDevice reading01Name Actor
attr myDevice reading01XPath-Strict //actor/text()

--- Ende Code ---
Hier würden folgende Readings erzeugt:   


--- Code: --- Actor-1 Peter X
Actor-2 Charles Y
Actor-3 John Doe

--- Ende Code ---
      

Für HTML-Daten funktioniert das entsprechend, jedoch statt mit XPath-Strict einfach mit XPath.

Zu Replacements:

Manchmal möchte man einzelne Teile einer URL, eines Headers oder der Post-Daten dynamisch ersetzen um z.B. das aktuelle Datum darin einzubauen oder weitere Daten an den Server zu senden. Mit den neuen Replacements kann man dafür beliebige Teile dieser Daten durch Text, den Inhalt von Readings oder Internals oder sogar mit Perl-Expressions ersetzen. Die Attribute dafür lauten:


--- Code: ---  replacement[0-9]*Regex
  replacement[0-9]*Mode
  replacement[0-9]*Value
  [gs]et[0-9]*Replacement[0-9]*Value

--- Ende Code ---

Für eine Ersetzung definiert man immer einen regulären Ausdruck, der dann direkt vor dem Absenden des Requests gegen URL, Header und Post-Daten gematcht wird.
Die Art, wie dann ersetzt wird, gibt man mit dem Mode an. Wenn mode "reading" enthält, dann wird Value als Name eines Readings oder als Device:Reading interpretiert und der Wert des Readings wird an die Stelle des Matches gesetzt. der Mode "internal" funktioniert entsprechend mit Internals.
Für Profis gibt es den Mode "expression", bei dem der Wert von Value als Perl-Expression ausgewertet wird.

Beispiel:


--- Code: --- attr mydevice getData {"get" :["%%value%%.value"]}
attr mydevice replacement01Mode text
attr mydevice replacement01Regex %%value%%

attr mydevice get01Name Chlor
attr mydevice get01Replacement01Value 34.4008

attr mydevice get02Name Something
attr mydevice get02Replacement01Value 31.4024

--- Ende Code ---
Hier wird %%value%% als Platzhalter fpr die Ersetzung fediniert.
Für alle Get-Kommandos gibt es ähnliche HTTP-Post Daten, die sich nur an einer Zahl unterscheiden. Deshalb sind die Post-Daten als "getData" definiert und gelten so für alle Get-Befehle. Auf Ebene der individuellen Get-Befehle wird dann nur noch ein Name und der zu ersetzende Wert angegeben.

Mit dem Mode "expression" kann man noch flexiblere Ersetzungen definieren:
         

--- Code: --- attr mydevice replacement01Mode expression
attr mydevice replacement01Regex {{([^}]+)}}
attr mydevice replacement01Value ReadingsVal("mydevice", $1, "")
attr mydevice getData {"get" :["{{temp}}.value"]}

--- Ende Code ---
In diesem Beispiel alles innerhalb von doppelten geschweiften Klammern wird als Ersetzung erkannt und der Text dazwischen steht in der Ersetzungs-Expression als $1 zur Verfügung. Im Beispiel wird es als Parameter an ReadingsVal übergeben.

Zu MaxAge:

Bisher bleiben einmal gesetzte Readings bei HTTPMOD bestehen, auch wenn das abgefragte Gerät nicht mehr antwortet.
Am Timestamp der Readings kann man erkennen, dass sie veraltet sind und man konnte mit anderen Modulen wie Watchdog reagieren wenn ein bestimmtes Alter überschritten wurde.
Auf häufige Nachfrage von Anwendern ist nun ein Feature in HTTPMOD gelandet, mit dem man direkt in HTTPMOD bei jedem Reading angeben kann, wie lange das Reading gültig bleibt, falls es nicht mehr aktualisiert wird. Dazu kann man ein maximales Alter in Sekunden und eine Ersetzung mit den folgenden Attributen definieren:


--- Code: ---  (reading|get)[0-9]*(-[0-9]+)?MaxAge
  (reading|get)[0-9]*(-[0-9]+)?MaxAgeReplacementMode
  (reading|get)[0-9]*(-[0-9]+)?MaxAgeReplacement

--- Ende Code ---
Falls ein solches Attribut definiert wird, prüft HTTPMOD bei jedem Aufruf der internen Lese-Funktion, welche Readings zu alt sind und wendet auf diese dann die Ersetzung an. Als Mode für die Ersetzung steht dabei nur "text" und "expression" zur Verfügung.
MaxAge wird in Sekunden angegeben und innerhalb einer Ersetzungs-Expression kann mit $val der frühere Wert verwendet werden.

Beispiel:

--- Code: --- attr PM readingMaxAge 300<br>
attr PM readingMaxAgeReplacement "outdated - was " . $val <br>
attr PM readingMaxAgeReplacementMode expression

--- Ende Code ---
In diesem Beispiel wird MaxAge generisch für alle Readings angebenen, die mit einem reading-Attribut definiert wurden. Entsprechend könnte man es auch für ein einzelnes Reading oder einen Get-Befehl angeben (wie oben bei Format, Expr etc.)

Weitere Details stehen in der Doku bzw. im Code :-). Das Wiki muss erst noch aktualisiert werden.

EDIT:
7.12.15: neue Version angehängt
10.12.15 nochmal neue Version angehängt (Fehler im JSON parsing korrigiert und Attribut extractAllJSON auf Start mit kleinem "e" geändert damit es konsistent zum Rest ist.
22.12.15: neues Modul angehängt - Fehler beseitigt
28.12.15: neues Modul angehängt - setParseResponse Attribut
12.1.16: neues Modul angehängt - einfaches Cookie-Handling, Sid Extraktion und ReAuth Erkennung auch per JSON und XPath, Verbesserung bei den Replacements etc. (siehe späterer Post)
16.1.16: neue Version angehängt. Jetzt kann man auch bei get einen optionalen Wert mitgeben, der dann per Replacement in den HTTP-Request eingebaut werden kann. (siehe post vom 16.1.)
23.1.16 neue Version: Attribut RegOpt für Regex-Options wie g, AutoNumLen um Zahlen, die beim Reading-Namen automatusch angehängt werden wenn es mehrere Matches gibt, mit führenden Nullen zu formatieren, diverse Verbesserungen an der Doku, MATCHED_READINGS korrigiert
25.1.16: neue Version: das Verhalten beim Zufügen von Attributen zu userattr für fhemweb optimiert.
1.2.16: neue Version: ein Löschen von enableCookies löscht nun auch den Cookie-Speicher.
2.2.16: neue Version: Warnung gefixt, neue Attribute authRetries und clearSIdBeforeAuth, Auth wird nicht mehr gequeued sondern vorgezogen wenn nötig
4.2.16: kleine Änderung: bei fehlendem readingXXName wird unnamed-XX als Name verwendet oder falls readingXXJSON angegeben wurde der Wert dieses Attributs.
5.2.16: Warnung gefixt.
13.2.16: Neue Zwischenversion, IMap und OMap teilweise implementiert, httpVersion und sslVersion Attribute hinzugefügt.
14.2.16: Nochmal eine Zwischenversion: sslArgs können spezifiziert werden, z.B. attr myDevice sslArgs SSL_verify_mode,SSL_VERIFY_NONE
15.2.16: Neue Version: set storeKeyValue verwendet setKeyValue zum speichern z.B. von Passwörtern ausserhalb der Konfiguration. Ein neuer replacement mode "key" kann auf getKeyValue zugreifen. Map und Expr Attribute wurden zu IMap für Eingaben und OMap für Ausgaben, entsprechend IExpr und OExpr für Ein- bzw. Ausgaben. set upgradeAttributes zum automatischen anpassen der Attribute auf die neue Syntax.
20.2.16: Neue Version, $XML::XPath::SafeMode = 1 für XML Parser gesetzt um Memory Leak zu vermeiden

Gruss
    Stefan

BKSolo:
Hallo Stefan, vielen Dank für die Bereitstellung. Meine ersten Erfahrungen auf dem Raspberry 2 sind.

Habe das Modul ausgetauscht und beim Restart im Logfile den Fehler " Can't locate JSON.pm in...." erhalten. Habe dieses mit

--- Code: ---sudo apt-get install libjson-perl
--- Ende Code ---
behoben.

Erneuter Restart ergab im Logfile den Fehler " Can't locate HTML/TreeBuilder/XPath.pm in....". Vorgängig hatte ich mit

--- Code: ---sudo apt-get install libxml-parser-perl libxml-xpath-perl libxml-TreeBuilder-perl
--- Ende Code ---
die Libraries installiert.
Bis jetzt konnte ich noch nichts finden was zusätzlich installiert werden müsste.
Ein "find" über die Installation zeigt mir das ich auf "/usr/share/perl5/XML/XPath.pm" das XPath.pm vorhanden ist.

Was mach ich falsch?
Danke, Bruno


justme1968:
kurzer vorschlag vor dem testen: wie wäre es json und xpath nur dann anzubieten wenn die module auch installiert sind?

ich glaube das würde vielen problemen vorbeugen wenn die neue version eingecheckt wird und es hilft auch anwendern auf plattformen auf denen nicht so einfach ein perl modul nach zu installieren ist.

gruss
  andre

BKSolo:
Hallo Andre, es wäre schade wenn wir die Module erst bekommen wenn diese "Fertig" und voll "Integriert" sind.
Ich war mit Alpha2 auf das XML angewiesen und sehr froh dass es diese ersten Versionen des Moduls gab. Es ist jedem freigestellt ob er es in einer frühen Version testen und einsetzen will.

Hallo Stefan, ich konnte in der Zwischenzeit den Fehler beheben mit

--- Code: ---sudo cpan install HTML::TreeBuilder::XPath
--- Ende Code ---
und werde meine laufende Installation Alpha2 mit dem neuen Modul auf meinem Test-Raspberry testen.

Danke und Gruss, Bruno

justme1968:
ich glaube du hast mich falsch verstanden ...

es ging darum features im fhem modul nur dann zu aktivieren wenn die benötigten Perl module auch vorhanden sind.

dann muss man nicht perl module installieren die man für sich selber nicht braucht, und es wird später wenn die neue version eingecheckt wird keinen aufschrei geben weil die hälfte der bestehenden defines plötzlich weg ist.

es ging nicht darum den funktionsumfang einzuschränken oder keine vor vorversionen mehr herauszugeben. ganz im gegenteil.

Navigation

[0] Themen-Index

[#] Nächste Seite

Zur normalen Ansicht wechseln