HTTPMOD

Aus FHEMWiki
Version vom 24. März 2015, 21:15 Uhr von StefanStrobel (Diskussion | Beiträge) (Doku für neue HTTPMOD Version mit GET Optionen erweitert)
HTTPMOD
Zweck / Funktion
Extract information from devices with an HTTP interface (or, more generic, from any URL) or send information to such devices
Allgemein
Typ Gerätemodul
Details
Dokumentation EN / DE
Support (Forum) Sonstiges
Modulname 98_HTTPMOD.pm
Ersteller StefanStrobel (Forum / Wiki)
Wichtig: sofern vorhanden, gilt im Zweifel immer die (englische) Beschreibung in der commandref!


HTTPMOD provides a generic way to retrieve information from devices with an HTTP Interface and store them in Readings or send information to such devices. It queries a given URL with Headers and data defined by attributes.

From the HTTP response it extracts readings named in attributes using Regexes also defined by attributes.

In an advanced configuration the module can also send information to devices. To do this, a generic set option can be configured using attributes.

Availability

The module has been checked in

Prerequisites

This module uses the non blocking HTTP function HttpUtils_NonblockingGet provided by FHEM's HttpUtils in a new version published in December 2013. If not already installed in your environment, please update FHEM or install it manually using appropriate commands from your environment.

Define

define <name> HTTPMOD <URL> <Interval>

The module connects to the given URL every Interval seconds, sends optional headers and data and then parses the response with regular expressions to set readings.

Example:

define PM HTTPMOD http://MyPoolManager/cgi-bin/webgui.fcgi 60

Set-Commands

can be defined using attributes, see advanced configuration

Get-Commands

can be defined using attributes, see advanced configuration

simple Attributes

do_not_notify
readingFnAttributes
requestHeader.*
Define an additional HTTP Header to set in the HTTP request
requestData
POST Data to be sent in the request. If not defined, it will be a GET request as defined in HttpUtils used by this module
reading[0-9]+Name
the name of a reading to extract with the corresponding readingRegex
reading[0-9]+Regex
defines the regex to be used for extracting the reading. The value to extract should be in a sub expression e.g. ([\d\.]+) in the above example
reading[0-9]*Expr
defines an expression that is used in an eval to compute the readings value. The raw value will be in the variable $val.
reading[0-9]*Map
defines a mapping from raw to visible values like "0:mittig, 1:oberhalb, 2:unterhalb". If specified as readingMap then the attribute value is a default for all other readings that don't specify an explicit reading[0-9]*Map.
reading[0-9]*Format
Defines a format string that will be used in sprintf to format a reading value. If specified as readingFormat then the attribute value is a default for all other readings that don't specify an explicit reading[0-9]*Format.
noShutdown
pass the noshutdown flag to HTTPUtils for webservers that need it (some embedded webservers only deliver empty pages otherwise)
disable
stop doing automatic HTTP requests while this attribute is set to 1
timeout
time in seconds to wait for an answer. Default value is 2


simple Configuration of HTTP Devices

If your device expects special HTTP-headers then specify them as attr requestHeader1 to attr requestHeaderX. If your Device expects an HTTP POST instead of HTTP GET then the POST-data can be specified as attr requestData. To get the readings, specify pairs of attr readingXName and attr readingXRegex to define which readings you want to extract from the HTTP response and how to extract them. (The old syntax attr readingsNameX and attr readingsRegexX is still supported but the new one with attr readingXName and attr readingXRegex should be preferred. The actual values to be extracted have to be sub expressions within () in the regex (see example below)

Example for a PoolManager 5:

The PoolManager Web GUI can be queried with HTTP POST Requests like this one:

POST /cgi-bin/webgui.fcgi HTTP/1.1
Host: 192.168.70.90
Accept: */*
Content-Type: application/json;charset=UTF-8
Content-Length: 60

{"get" :["34.4001.value" ,"34.4008.value" ,"34.4033.value"]}

The resulting HTTP Response would look like this:

HTTP/1.1 200 OK
Content-type: application/json; charset=UTF-8
Expires: 0
Cache-Control: no-cache
Date: Sun, 12 Jan 2014 12:23:11 GMT
Server: lighttpd/1.4.26
Content-Length: 179

{
	"data":	{
		"34.4001.value":	"7.00",
		"34.4008.value":	"0.52",
		"34.4033.value":	"24.8"
	},
	"status":	{
		"code":	0
	},
	"event":	{
		"type":	1,
		"data":	"48.30000.0"
	}
}

To configure HTTPMOD for a PoolManager one would first define a PoolManager device with e.g. the name PM, the URL and an interval of e.g. 60 seconds.

Then the data to be sent in the request needs to be defined because in this example the device expects a POST request so the query is not contained in the URL but in the request data.

Also as seen above the device expects special HTTP headers in the request so these headers also need to be defined as attr PM requestHeader1 and attr PM requestHeader2

Then the names of the readings to be extracted would be set with attributes

Then for each reading value to be extracted a regular expression needs to be set that will match the value in question within ().

Example:

define PM HTTPMOD http://MyPoolManager/cgi-bin/webgui.fcgi 60
attr PM reading01Name PH
attr PM reading01Regex 34.4001.value":[ \t]+"([\d\.]+)"

attr PM reading02Name CL
attr PM reading02Regex 34.4008.value":[ \t]+"([\d\.]+)"

attr PM reading03Name3TEMP
attr PM reading03Regex 34.4033.value":[ \t]+"([\d\.]+)"

attr PM requestData {"get" :["34.4001.value" ,"34.4008.value" ,"34.4033.value", "14.16601.value", "14.16602.value"]}
attr PM requestHeader1 Content-Type: application/json
attr PM requestHeader2 Accept: */*
attr PM stateFormat {sprintf("%.1f Grad, PH %.1f, %.1f mg/l Chlor", ReadingsVal($name,"TEMP",0), ReadingsVal($name,"PH",0), ReadingsVal($name,"CL",0))}

If you need to do some calculation on a raw value before it is used as a reading, you can define the attribute readingXExpr which can use the raw value from the variable $val

Example:

attr PM reading03Expr $val * 10


Example for AmbientMonitor

AmbientMonitor is a webbased visualisation for sensors connected to an Arduino device. Its web interface can also be queried with HTTMOD to grab the data into readings.

This example was provided by locutus. The hardware configuration is an Arduino + Ethercard with ENC28J60 Controller + DHT22 Sensor and software can be downloaded from https://github.com/lucadentella/AmbientMonitor

In this example an HTTP GET is sufficent, so no requestData is needed. The device provides temperature and humidity readings in an HTTP response that looks like:

HTTP/1.0 200 OK 
Content-Type: text/html 

myCB({'temperature':22.00,'humidity':46.00})

the definition could be:

define AmbientMonitor HTTPMOD http://192.168.1.221/?callback=? 300
attr AmbientMonitor requestHeader Content-Type: application/json
attr AmbientMonitor reading1Name Temperatur
attr AmbientMonitor reading1Regex temperature':([\d\.]+)
attr AmbientMonitor reading2Name Feuchtigkeit
attr AmbientMonitor reading2Regex humidity':([\d\.]+)
attr AmbientMonitor stateFormat {sprintf("Temperatur %.1f C, Feuchtigkeit %.1f %", ReadingsVal($name,"Temperatur",0), ReadingsVal($name,"Feuchtigkeit",0))}


Some help with Regular Expressions

If HTTPMOD seems not to work and the FHEM Logfile contains a message like

HTTPMOD: Response didn't match Reading ...

then you should check if the value you want to extract is read into the internal with the name buf. Internals are visible when you click on the defined HTTPMOD Device. buf is an internal variable that contains the HTTP Response read. If the value is there and you get the mentioned message then probably something is wrong with your regular expression. If you are new to regular expressions then the introduction at http://perldoc.perl.org/perlretut.html might be helpful.

For a typical HTTPMOD use case where you want to extract a number out of a HTTP-Response you can use something like [\d\.]+ to match the number itself. The expression matches the number characters (\d) or a . if one of these characters occurs at least once.

To tell HTTPMOD that the number is what you want to use for the reading, you have to put the expression in between (). A ([\d\.]+) alone would match the longest number in the HTTP Response which is very likely not the number you are looking for so you need to add something to the expression to give it a context and define how to find the number that you are looking for. if there is a title text before the number or a special text after the number you can put this in the regex. In one of the examples above humidity':([\d\.]+) is looking for the number that immediately follows the text humidity': without any blanks in between.

Additional notes

If you don't know which URLs, headers or POST data your web GUI uses, you might try a local proxy like BurpSuite BurpSuite to track requests and responses

Advanced configuration to define a set and send data to a device

When a set option is defined by attributes, the module will use the value given to the set command and translate it into an HTTP-Request that sends the value to the device.

Extension to the above example for a PoolManager 5:

attr PM set01Name HeizungSoll
attr PM set01URL http://MyPoolManager/cgi-bin/webgui.fcgi?sid=$sid
attr PM set01Hint 6,10,20,30
attr PM set01Min 6
attr PM set01Max 30
attr PM setHeader1 Content-Type: application/json
attr PM set01Data {"set" :{"34.3118.value" :"$val" }}

This example defines a set option with the name HeizungSoll. By issuing set PM HeizungSoll 10 in FHEM, the value 10 will be sent in the defined HTTP Post to URL http://MyPoolManager/cgi-bin/webgui.fcgi in the Post Data as

{"set" :{"34.3118.value" :"10" }}

The optional attributes set01Min and set01Max define input validations that will be checked in the set function. The optional attribute set01Hint will define a selection list for the Fhemweb GUI.

Advanced configuration to create a valid session id that might be necessary in set options

when sending data to an HTTP-Device in a set, HTTPMOD will replace any $sid in the URL, Headers and Post data with the internal $hash->{sid}. To authenticate towards the device and give this internal a value, you can use an optional multi step login procedure defined by the following attributes:

sid[0-9]*URL
sid[0-9]*IDRegex
sid[0-9]*Data.*
sid[0-9]*Header.*
sid[0-9]*IgnoreRedirects

Each step can have a URL, Headers, Post Data pieces and a Regex to extract a resulting Session ID into $hash->{sid}. HTTPMOD will create a sorted list of steps (the numbers between sid and URL / Data / Header) and the loop through these steps and send the corresponding requests to the device. For each step a $sid in a Header or Post Data will be replaced with the current content of $hash->{sid}.

Using this feature, HTTPMOD can perform a forms based authentication and send user name, password or other necessary data to the device and save the session id for further requests.

To determine when this login procedure is necessary, HTTPMOD will first try to do a set without doing the login procedure. If the Attribute ReAuthRegex is defined, it will then compare the HTTP Response to the set request with the regular expression from ReAuthRegex. If it matches, then a login is performed. The ReAuthRegex is meant to match the error page a device returns if authentication or reauthentication is required e.g. because a session timeout has expired.

If for one step not all of the URL, Data or Header Attributes are set, then HTTPMOD tries to use a sidURL, sidData.* or sidHeader.* Attribue (without the step number after sid). This way parts that are the same for all steps don't need to be defined redundantly.

Example for a multi step login procedure:

attr PM sidURL http://192.168.70.90/cgi-bin/webgui.fcgi?sid=$sid
attr PM sidHeader1 Content-Type: application/json
attr PM sid1IDRegex wui.init\('([^']+)'
attr PM sid2Data {"set" :{"9.17401.user" :"fhem" ,"9.17401.pass" :"password" }}
attr PM sid3Data {"set" :{"35.5062.value" :"128" }}
attr PM sid4Data {"set" :{"42.8026.code" :"pincode" }}


Advanced configuration to define a get and request additional data with its own request from a device

The normal automatic HTTP request that is done repeatedly after the defined interval has elapsed works well in cases where all required readings can be requested in one common HTTP request. If however a device needs individual requests with different URLs or different POST data for each value, then another method is necessary. For such cases a get option can be defined and the user can either issue Fhem get commands each time he needs the reading or the user can set an attribute to request the reading automatically together with the normal iteration. For each get option attributes define an individual URL, optional headers, and post data as well as individual regular expressions and formatting options.

Example for a Siemens webserver provided by Lanhydrock:

define ozw672 HTTPMOD https://192.168.178.8/api/auth/login.json?user=test&pwd=test 300

attr ozw672 get1Name tempAussen
attr ozw672 get1URL https://192.168.178.8/api/menutree/read_datapoint.json?SessionId=$sid&Id=1960
attr ozw672 get1Poll 1
attr ozw672 get1PollDelay 1800

attr ozw672 get2Name tempAussenGemischt
attr ozw672 get2URL https://192.168.178.8/api/menutree/read_datapoint.json?SessionId=$sid&Id=1964
attr ozw672 get2Poll 1
attr ozw672 get2PollDelay 1800

attr ozw672 get3Name tempTWW
attr ozw672 get3URL https://192.168.178.8/api/menutree/read_datapoint.json?SessionId=$sid&Id=1996
attr ozw672 get3Poll 1

attr ozw672 get4Name tempKesselSoll
attr ozw672 get4URL https://192.168.178.8/api/menutree/read_datapoint.json?SessionId=$sid&Id=1910
attr ozw672 get4Poll 1

attr ozw672 get5Name tempKesselRuecklauf
attr ozw672 get5URL https://192.168.178.8/api/menutree/read_datapoint.json?SessionId=$sid&Id=1915
attr ozw672 get5Poll 1

attr ozw672 get6Name tempKesselRuecklaufSoll
attr ozw672 get6URL https://192.168.178.8/api/menutree/read_datapoint.json?SessionId=$sid&Id=1916
attr ozw672 get6Poll 1

attr ozw672 get7Name anzahlStartsBrenner
attr ozw672 get7URL https://192.168.178.8/api/menutree/read_datapoint.json?SessionId=$sid&Id=1927
attr ozw672 get7PollDelay 1800
attr ozw672 get7Poll 1

attr ozw672 get8Name statusKessel
attr ozw672 get8URL https://192.168.178.8/api/menutree/read_datapoint.json?SessionId=$sid&Id=1898
attr ozw672 get8Poll 1
attr ozw672 get8Regex Value": "([a-zA-Zü ]*)"
attr ozw672 get8Map Aus:0, Nachlauf aktiv:5, Freigegeben für TWW:10, Freigegeben für HK:20, In Teillastbetrieb für TWW:40, In Teillastbetrieb für HK:50, In Betrieb für Trinkwasser:90, In Betrieb für Heizkreis:100

attr ozw672 getRegex Value": "[ ]*([-.0-9]*)"

attr ozw672 reAuthRegex .*session not valid.*
attr ozw672 sid1IDRegex .*"(.*-.*-.*-[0-9a-z]*).*
attr ozw672 sid1URL https://192.168.178.8/api/auth/login.json?user=test&pwd=test


Advanced attributes

ReAuthRegex
regular Expression to match an error page indicating that a session has expired and a new authentication for read access needs to be done. This attribute only makes sense if you need a forms based authentication for reading data and if you specify a multi step login procedure based on the sid.. attributes.
sid[0-9]*URL
different URLs or one common URL to be used for each step of an optional login procedure.
sid[0-9]*IDRegex
different Regexes per login procedure step or one common Regex for all steps to extract the session ID from the HTTP response
sid[0-9]*Data.*
data part for each step to be sent as POST data to the corresponding URL
sid[0-9]*Header.*
HTTP Headers to be sent to the URL for the corresponding step
sid[0-9]*IgnoreRedirects
Tells the HttpUtils to not follow HTTP Redirects for this Request. Might be needed for some devices that set a session cookie within a 303 Redirect.


set[0-9]+Name
Name of a set option
set[0-9]*URL
URL to be requested for the set option
set[0-9]*Data
Data to be sent to the device as POST data when the set is executed
set[0-9]*Header
HTTP Headers to be sent to the device when the set is executed
set[0-9]+Min
Minimum value for input validation.
set[0-9]+Max
Maximum value for input validation.
set[0-9]+Expr
Perl Expression to compute the raw value to be sent to the device from the input value passed to the set.
set[0-9]+Map
Map that defines a mapping from raw to visible values like "0:mittig, 1:oberhalb, 2:unterhalb". This attribute atomatically creates a hint for FhemWEB so the user can choose one of the visible values or select a value with a slider.
set[0-9]+Hint
Explicit hint for fhemWEB that will be returned when set ? is seen. Can be used to get a slider or a list of values to choose from.
set[0-9]*ReAuthRegex
Regex that will detect when a session has expired an a new login needs to be performed.
get[0-9]+Name
Name of a get option and Reading to be retrieved / extracted
get[0-9]*URL
URL to be requested for the get option. If this option is missing, the URL specified during define will be used.
get[0-9]*Data
optional data to be sent to the device as POST data when the get is executed. if this attribute is not specified, an HTTP GET method will be used instead of an HTTP POST
get[0-9]*Header
optional HTTP Headers to be sent to the device when the get is executed
get[0-9]+Poll
if set to 1 the get is executed automatically during the normal update cycle (after the interval provided in the define command has elapsed)
get[0-9]+PollDelay
if the value should not be read in each iteration (after the interval given to the define command), then a minimum delay can be specified with this attribute. This has only an effect if the above Poll attribute has also been set. Every time the update function is called, it checks if since this get has been read the last time, the defined delay has elapsed. If not, then it is skipped this time.
PollDelay can be specified as seconds or as x[0-9]+ which means a multiple of the interval in the define command.
get[0-9]*Regex
If this attribute is specified, the Regex defined here is used to extract the value from the HTTP Response and assign it to a Reading with the name defined in the get[0-9]+Name attribute.
If this attribute is not specified for an individual Reading but as getRegex, then it applies to all get options where no specific Regex is defined.
If neither a generic getRegex attribute nor a specific get[0-9]+Regex attribute is specified, then HTTPMOD tries all Regex / Reading pairs defined in Reading[0-9]+Name and Reading[0-9]+Regex attributes and assigns the Readings that match.
get[0-9]*Expr
this attribute behaves just like Reading[0-9]*Expr but is applied to a get value.
get[0-9]*Map
this attribute behaves just like Reading[0-9]*Map but is applied to a get value.
get[0-9]*Format
this attribute behaves just like Reading[0-9]*Format but is applied to a get value.
get[0-9]*CheckAllReadings
this attribute modifies the behavior of HTTPMOD when the HTTP Response of a get command is parsed.
If this attribute is set to 1, then additionally to any matching of get specific regexes (get[0-9]*Regex), also all the Regex / Reading pairs defined in Reading[0-9]+Name and Reading[0-9]+Regex attributes are checked and if they match, the coresponding Readings are assigned as well.


queueDelay
HTTP Requests will be sent from a queue in order to avoid blocking when several Requests have to be sent in sequence. This attribute defines the delay between calls to the function that handles the send queue. It defaults to one second.
queueMax
Defines the maximum size of the send queue. If it is reached then further HTTP Requests will be dropped and not be added to the queue
minSendDelay
Defines the minimum time between two HTTP Requests.

Links