mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-02-25 16:05:19 +00:00
02_HTTPAPI: contrib version
git-svn-id: https://svn.fhem.de/fhem/trunk@28901 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
ce1521fdba
commit
55c0f59756
507
fhem/contrib/DS_Starter/02_HTTPAPI.pm
Normal file
507
fhem/contrib/DS_Starter/02_HTTPAPI.pm
Normal file
@ -0,0 +1,507 @@
|
|||||||
|
# $Id: 02_HTTPAPI.pm 26361 2022-08-30 09:21:46Z klaus.schauer $
|
||||||
|
# HTTP API commands
|
||||||
|
# set command: http://<ip-addr>:<ip-port>/<apiName>/set?device=<devname>&action=<cmd>
|
||||||
|
# get command: http://<ip-addr>:<ip-port>/<apiName>/get?device=<devname>&action=<cmd>
|
||||||
|
# read reading: http://<ip-addr>:<ip-port>/<apiName>/read?device=<devname>&reading=<name>
|
||||||
|
# write reading: http://<ip-addr><ip-port>/<apiName>/write?device=<devname>&reading=<name>&value=<val>
|
||||||
|
|
||||||
|
package main;
|
||||||
|
use Encode qw(decode encode);
|
||||||
|
use SetExtensions;
|
||||||
|
use strict;
|
||||||
|
use TcpServerUtils;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
my $gPath = '';
|
||||||
|
BEGIN {
|
||||||
|
$gPath = substr($0, 0, rindex($0, '/'));
|
||||||
|
}
|
||||||
|
if (lc(substr($0, -7)) eq 'fhem.pl') {
|
||||||
|
$gPath = $attr{global}{modpath}.'/FHEM';
|
||||||
|
}
|
||||||
|
use lib ($gPath.'/lib', $gPath.'/FHEM/lib', './FHEM/lib', './lib', './FHEM', './', '/usr/local/FHEM/share/fhem/FHEM/lib');
|
||||||
|
|
||||||
|
my $encoding = 'UTF-8';
|
||||||
|
my $infix = 'api';
|
||||||
|
my $linkPattern = "^\/?(([^\/]*(\/[^\/]+)*)\/?)\$";
|
||||||
|
my $tcpServAdr = 'global';
|
||||||
|
my $tcpServPort = 8087;
|
||||||
|
|
||||||
|
sub HTTPAPI_Initialize {
|
||||||
|
my ($hash) = @_;
|
||||||
|
$hash->{AttrFn} = "HTTPAPI_Attr";
|
||||||
|
$hash->{DefFn} = "HTTPAPI_Define";
|
||||||
|
$hash->{ReadFn} = "HTTPAPI_Read";
|
||||||
|
$hash->{UndefFn} = "HTTPAPI_Undef";
|
||||||
|
$hash->{AttrList} = "disable:0,1 devicesCtrl " . $readingFnAttributes;
|
||||||
|
$hash->{parseParams} = 1;
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub HTTPAPI_Define {
|
||||||
|
my ($hash, $a, $h) = @_;
|
||||||
|
my $name = $a->[0];
|
||||||
|
if (defined $a->[2]) {
|
||||||
|
$hash->{INFIX} = $a->[2];
|
||||||
|
$infix = $a->[2];
|
||||||
|
} elsif (exists $h->{infix}) {
|
||||||
|
$hash->{INFIX} = $h->{infix};
|
||||||
|
$infix = $h->{infix};
|
||||||
|
} else {
|
||||||
|
$hash->{INFIX} = $infix;
|
||||||
|
}
|
||||||
|
# check if valid folder name
|
||||||
|
if ($hash->{INFIX} !~ /^[^\\\/\?\*\"\'\>\<\:\|]*$/) {
|
||||||
|
return "HTTPAPI: wrong syntax, correct is: define <name> HTTPAPI [infix=]<infix> [port=][[IPV6:]<port>] [global=][global|local|<hostname>]";
|
||||||
|
}
|
||||||
|
my ($pport, $port);
|
||||||
|
if (defined $a->[3]) {
|
||||||
|
$pport = $a->[3];
|
||||||
|
} elsif (exists $h->{port}) {
|
||||||
|
$pport = $h->{port};
|
||||||
|
} else {
|
||||||
|
$pport = $tcpServPort;
|
||||||
|
}
|
||||||
|
$port = $pport;
|
||||||
|
$port =~ s/^IPV6://;
|
||||||
|
return "HTTPAPI: wrong syntax, correct is: define <name> HTTPAPI [infix=]<infix> [port=][[IPV6:]<port>] [global=][global|local|<hostname>]" if ($port !~ m/^\d+$/);
|
||||||
|
if (defined $a->[4]) {
|
||||||
|
$hash->{GLOBAL} = $a->[4];
|
||||||
|
} elsif (exists $h->{global}) {
|
||||||
|
$hash->{GLOBAL} = $h->{global};
|
||||||
|
} else {
|
||||||
|
$hash->{GLOBAL} = $tcpServAdr;
|
||||||
|
}
|
||||||
|
|
||||||
|
# open TCP server for HTTP API service
|
||||||
|
my $ret = TcpServer_Open($hash, $pport, (($hash->{GLOBAL} eq 'local') ? undef : $hash->{GLOBAL}));
|
||||||
|
if($ret && !$init_done) {
|
||||||
|
Log3 $name, 1, "HTTPAPI $ret already exists";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
readingsSingleUpdate($hash, "state", "initialized", 1);
|
||||||
|
Log3 $name, 2, "HTTPAPI $name initialized";
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub HTTPAPI_Attr {
|
||||||
|
my ($cmd, $name, $aName, $aVal) = @_;
|
||||||
|
if ($cmd eq "set") {
|
||||||
|
if ($aName =~ "devicesCtrl") {
|
||||||
|
if ($aVal !~ /^[A-Z_a-z0-9\,]+$/) {
|
||||||
|
Log3 $name, 2, "HTTPAPI $name invalid reading list in attr $name $aName $aVal (only A-Z, a-z, 0-9, _ and , allowed)";
|
||||||
|
return "Invalid reading name $aVal (only A-Z, a-z, 0-9, _ and , allowed)";
|
||||||
|
}
|
||||||
|
#addToDevAttrList($name, $aName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub HTTPAPI_CGI {
|
||||||
|
# execute request to http://<host>:<port>/$infix?<cmd string>
|
||||||
|
my ($hash, $name, $request) = @_;
|
||||||
|
my $apiCmd;
|
||||||
|
my $apiCmdString;
|
||||||
|
my $fhemDevName;
|
||||||
|
my $link;
|
||||||
|
return($hash, 503, 'close', "text/plain; charset=utf-8", encode($encoding, "error=503 Service Unavailable")) if(IsDisabled($name));
|
||||||
|
|
||||||
|
if($request =~ m/^(\/$infix)\/(set|get|read|readtimestamp|readinternal|write)\?(.*)$/) {
|
||||||
|
$link = $1;
|
||||||
|
$apiCmd = $2;
|
||||||
|
$apiCmdString = $3;
|
||||||
|
|
||||||
|
# url decoding
|
||||||
|
$request =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
|
||||||
|
readingsSingleUpdate($defs{$name}, 'request', $request, 0);
|
||||||
|
|
||||||
|
if ($apiCmdString =~ /&device(\=[^&]*)?(?=&|$)|^device(\=[^&]*)?(&|$)/) {
|
||||||
|
$fhemDevName = substr(($1 // $2), 1);
|
||||||
|
# url decoding
|
||||||
|
$fhemDevName =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
|
||||||
|
if (IsDevice($fhemDevName) && !IsDisabled($fhemDevName) && !IsIgnored($fhemDevName)) {
|
||||||
|
# Control of the device allowed?
|
||||||
|
my $devicesCtrl = AttrVal($name, 'devicesCtrl', undef);
|
||||||
|
my $allowedDev;
|
||||||
|
if (defined $devicesCtrl) {
|
||||||
|
my @devicesCtrl = split(',', $devicesCtrl);
|
||||||
|
foreach (@devicesCtrl) {
|
||||||
|
next if($_ ne $fhemDevName);
|
||||||
|
$allowedDev = $fhemDevName;
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
return($hash, 403, 'close', "text/plain; charset=utf-8", encode($encoding, "error=403 Forbidden, $request > control of the device $fhemDevName not allowed")) if (!defined($allowedDev))
|
||||||
|
}
|
||||||
|
if ($apiCmd eq 'get') {
|
||||||
|
my $getCmd;
|
||||||
|
if ($apiCmdString =~ /&action(\=[^&]*)?(?=&|$)|^action(\=[^&]*)?(&|$)/) {
|
||||||
|
$getCmd = substr(($1 // $2), 1);
|
||||||
|
# url decoding
|
||||||
|
$getCmd =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
|
||||||
|
my $ret = CommandGet(undef, "$fhemDevName $getCmd");
|
||||||
|
if ($ret) {
|
||||||
|
return($hash, 200, 'close', "text/plain; charset=utf-8", encode($encoding, "$getCmd=$ret"))
|
||||||
|
} else {
|
||||||
|
return($hash, 400, 'close', "text/plain; charset=utf-8", encode($encoding, "error=400 Bad Request, $request > get $fhemDevName $getCmd"))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return($hash, 400, 'close', "text/plain; charset=utf-8", encode($encoding, "error=400 Bad Request, $request > attribute action is missing"))
|
||||||
|
}
|
||||||
|
} elsif ($apiCmd =~ /^read|readtimestamp|readinternal$/) {
|
||||||
|
my $valName;
|
||||||
|
if ($apiCmdString =~ /&reading(\=[^&]*)?(?=&|$)|^reading(\=[^&]*)?(&|$)|&internal(\=[^&]*)?(&|$)/) {
|
||||||
|
$valName = substr(($1 // $2 // $3 // $4), 1);
|
||||||
|
# url decoding
|
||||||
|
$valName =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
|
||||||
|
my $val = $apiCmd eq 'readtimestamp' ? ReadingsTimestamp($fhemDevName, $valName, undef) :
|
||||||
|
$apiCmd eq 'readinternal' ? InternalVal($fhemDevName, $valName, undef) :
|
||||||
|
ReadingsVal($fhemDevName, $valName, undef);
|
||||||
|
#readingsSingleUpdate($defs{$name}, 'reponse', "$valName=$val", 1);
|
||||||
|
if (defined $val) {
|
||||||
|
return($hash, 200, 'close', "text/plain; charset=utf-8", encode($encoding, "$valName=$val"));
|
||||||
|
} else {
|
||||||
|
return($hash, 400, 'close', "text/plain; charset=utf-8", encode($encoding, "error=400 Bad Request, $request > reading $valName unknown"))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return($hash, 400, 'close', "text/plain; charset=utf-8", encode($encoding, "error=400 Bad Request, $request > attribute reading/internal is missing"))
|
||||||
|
}
|
||||||
|
} elsif ($apiCmd eq 'set') {
|
||||||
|
my $setCmd;
|
||||||
|
if ($apiCmdString =~ /&action(\=[^&]*)?(?=&|$)|^action(\=[^&]*)?(&|$)/) {
|
||||||
|
$setCmd = substr(($1 // $2), 1);
|
||||||
|
# url decoding
|
||||||
|
$setCmd =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
|
||||||
|
#my $ret = CommandSet(undef, "$fhemDevName $setCmd");
|
||||||
|
#my $ret = AnalyzeCommand($defs{$hash->{SNAME}}, "set $fhemDevName $setCmd");
|
||||||
|
my $ret = AnalyzeCommand($defs{$name}, "set $fhemDevName $setCmd");
|
||||||
|
if ($ret) {
|
||||||
|
return($hash, 400, 'close', "text/plain; charset=utf-8", encode($encoding, "error=400 Bad Request, $request > $ret"))
|
||||||
|
} else {
|
||||||
|
return($hash, 200, 'close', "text/plain; charset=utf-8", encode($encoding, "$fhemDevName=$setCmd"))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return($hash, 400, 'close', "text/plain; charset=utf-8", encode($encoding, "error=400 Bad Request, $request > attribute action is missing"))
|
||||||
|
}
|
||||||
|
|
||||||
|
} elsif ($apiCmd eq 'write') {
|
||||||
|
my $readingName;
|
||||||
|
if ($apiCmdString =~ /&reading(\=[^&]*)?(?=&|$)|^reading(\=[^&]*)?(&|$)/) {
|
||||||
|
$readingName = substr(($1 // $2), 1);
|
||||||
|
# url decoding
|
||||||
|
$readingName =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
|
||||||
|
my $readingVal;
|
||||||
|
|
||||||
|
if ($apiCmdString =~ /&value(\=[^&]*)?(?=&|$)|^value(\=[^&]*)?(&|$)/) {
|
||||||
|
$readingVal = substr(($1 // $2), 1);
|
||||||
|
# url decoding
|
||||||
|
$readingVal =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
|
||||||
|
if ($readingVal ne '') {
|
||||||
|
my $result = readingsSingleUpdate($defs{$fhemDevName}, $readingName, $readingVal, 1);
|
||||||
|
if ($readingName eq 'state') {
|
||||||
|
$readingVal = $result;
|
||||||
|
} else {
|
||||||
|
($readingName, $readingVal) = split(/:\s?/, $result);
|
||||||
|
}
|
||||||
|
return($hash, 200, 'close', "text/plain; charset=utf-8", encode($encoding, "$readingName=$readingVal"))
|
||||||
|
} else {
|
||||||
|
readingsDelete($defs{$fhemDevName}, $readingName);
|
||||||
|
return($hash, 200, 'close', "text/plain; charset=utf-8", encode($encoding, "$readingName="))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
# delete reading if value is not found
|
||||||
|
readingsDelete($defs{$fhemDevName}, $readingName);
|
||||||
|
return($hash, 200, 'close', "text/plain; charset=utf-8", encode($encoding, "$readingName="))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return($hash, 400, 'close', "text/plain; charset=utf-8", encode($encoding, "error=400 Bad Request, $request > attribute reading is missing"))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return($hash, 400, 'close', "text/plain; charset=utf-8", encode($encoding, "error=400 Bad Request, $request > action $apiCmd unknown"))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return($hash, 400, 'close', "text/plain; charset=utf-8", encode($encoding, "error=400 Bad Request, $request > device $fhemDevName unknown, disabled or ignored by the user"))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return($hash, 400, 'close', "text/plain; charset=utf-8", encode($encoding, "error=400 Bad Request, $request > attribute device missing"))
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return HTTPAPI_CommandRef($hash);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub HTTPAPI_CommandRef {
|
||||||
|
my ($hash) = @_;
|
||||||
|
my $fileName = $gPath . '/02_HTTPAPI.pm';
|
||||||
|
my ($err, @contents) = FileRead({FileName => $fileName, ForceType => 'file'});
|
||||||
|
return ($hash, 404, 'close', "text/plain; charset=utf-8", encode($encoding, "error=404 Not Found, file $fileName not found")) if ($err);
|
||||||
|
my $contents = join("\n", @contents);
|
||||||
|
$contents =~ /\n=begin.html([\s\S]*)\n=end.html/gs;
|
||||||
|
return ($hash, 200, 'close', "text/html; charset=utf-8", encode($encoding, $1));
|
||||||
|
}
|
||||||
|
|
||||||
|
sub HTTPAPI_Read {
|
||||||
|
my ($hash) = @_;
|
||||||
|
my $name = $hash->{NAME};
|
||||||
|
|
||||||
|
# accept request and create a child
|
||||||
|
if ($hash->{SERVERSOCKET}) {
|
||||||
|
my $chash = TcpServer_Accept($hash, "HTTPAPI");
|
||||||
|
return if (!$chash);
|
||||||
|
$chash->{encoding} = $encoding;
|
||||||
|
$chash->{cname} = $name;
|
||||||
|
$chash->{CD}->blocking(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
# read data
|
||||||
|
my $buf;
|
||||||
|
my $ret = sysread($hash->{CD}, $buf, 2048);
|
||||||
|
|
||||||
|
# connection error, 0=EOF, undef=error
|
||||||
|
if (!defined($ret) || $ret <= 0) {
|
||||||
|
TcpServer_Close($hash, 1);
|
||||||
|
delete $hash->{BUF};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$hash->{BUF} .= $buf;
|
||||||
|
my $content = '';
|
||||||
|
my $contentType = '';
|
||||||
|
|
||||||
|
while(exists($hash->{BUF}) && length($hash->{BUF}) > 0) {
|
||||||
|
if (!$hash->{HDR}) {
|
||||||
|
last if ($hash->{BUF} !~ m/^(.*?)(\n\n|\r\n\r\n)(.*)$/s);
|
||||||
|
$hash->{HDR} = $1;
|
||||||
|
$hash->{BUF} = $3;
|
||||||
|
if ($hash->{HDR} =~ m/Content-Length:\s*([^\r\n]*)/si) {
|
||||||
|
$hash->{CONTENT_LENGTH} = $1;
|
||||||
|
}
|
||||||
|
if ($hash->{HDR} =~ m/Content-Type:\s*([^\r\n]*)/si) {
|
||||||
|
$contentType = $1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($hash->{CONTENT_LENGTH}) {
|
||||||
|
return if (length($hash->{BUF}) < $hash->{CONTENT_LENGTH});
|
||||||
|
$content = substr($hash->{BUF}, 0, $hash->{CONTENT_LENGTH});
|
||||||
|
$hash->{BUF} = substr($hash->{BUF}, $hash->{CONTENT_LENGTH});
|
||||||
|
}
|
||||||
|
my @httpheader = split(/[\r\n]+/, $hash->{HDR});
|
||||||
|
my ($method, $url, $httpvers) = split(" ", $httpheader[0], 3) if ($httpheader[0]);
|
||||||
|
$method = "" if (!$method);
|
||||||
|
delete ($hash->{HDR});
|
||||||
|
|
||||||
|
if ($method !~ m/^(GET|POST)$/i) {
|
||||||
|
$ret = HTTPAPI_TcpServerWrite($hash, 405, 'close', "text/plain; charset=utf-8", "error=405 Method Not Allowed");
|
||||||
|
delete $hash->{CONTENT_LENGTH};
|
||||||
|
next;
|
||||||
|
} elsif ($method eq 'POST' && $contentType ne 'application/xml') {
|
||||||
|
$ret = HTTPAPI_TcpServerWrite($hash, 400, 'close', "text/plain; charset=utf-8", "error=400 Bad Request");
|
||||||
|
delete $hash->{CONTENT_LENGTH};
|
||||||
|
next;
|
||||||
|
} elsif ($url eq "/favicon.ico") {
|
||||||
|
$ret = HTTPAPI_TcpServerWrite($hash, 404, 'close', "text/plain; charset=utf-8", "error=404 Not Found");
|
||||||
|
delete $hash->{CONTENT_LENGTH};
|
||||||
|
next;
|
||||||
|
} elsif ($url !~ m/\/$infix\//i) {
|
||||||
|
$ret = HTTPAPI_TcpServerWrite($hash, 400, 'close', "text/plain; charset=utf-8", "error=400 Bad Request - wrong infix");
|
||||||
|
delete $hash->{CONTENT_LENGTH};
|
||||||
|
next;
|
||||||
|
} else {
|
||||||
|
$url =~ m/\/$infix\/(.*)\?(.*)$/i;
|
||||||
|
my ($requestCmd, $cmdString) = ($1, $2);
|
||||||
|
# CGI Aufruf
|
||||||
|
$ret = HTTPAPI_TcpServerWrite(HTTPAPI_CGI($hash, $hash->{cname}, $url));
|
||||||
|
delete $hash->{CONTENT_LENGTH};
|
||||||
|
next:
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
TcpServer_Close($hash, 1);
|
||||||
|
delete $hash->{BUF};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub HTTPAPI_TcpServerWrite {
|
||||||
|
my ($hash, $httpState, $connection, $contentType, $content) = @_;
|
||||||
|
my ($contentLength, $header) = (0, "HTTP/1.1 ");
|
||||||
|
my %httpState = (
|
||||||
|
200 => '200 OK',
|
||||||
|
400 => '400 Bad Request',
|
||||||
|
403 => '403 Forbidden',
|
||||||
|
404 => '404 Not Found',
|
||||||
|
405 => '405 Method Not Allowed',
|
||||||
|
503 => '503 Service Unavailable'
|
||||||
|
);
|
||||||
|
$content = $content // '';
|
||||||
|
$contentLength = length($content);
|
||||||
|
$header .= "$httpState{$httpState}\r\nContent-Length: $contentLength\r\n";
|
||||||
|
$header .= "Allow: GET, POST\r\n" if ($httpState == 405);
|
||||||
|
$header .= "Connection: $connection\r\n" if (defined $connection);
|
||||||
|
$header .= "Content-Type: $contentType\r\n" if (defined $contentType);
|
||||||
|
$header .= "\r\n";
|
||||||
|
return TcpServer_WriteBlocking($hash, $header . $content);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub HTTPAPI_Undef {
|
||||||
|
my ($hash) = @_;
|
||||||
|
return TcpServer_Close($hash, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
||||||
|
|
||||||
|
=pod
|
||||||
|
=item device
|
||||||
|
=item summary HTTP API server that executes set/get commands and sets/reads readings
|
||||||
|
=item summary_DE HTTP API-Server, der set-/get-Befehle ausführt und Readings setzt/liest
|
||||||
|
=begin html
|
||||||
|
|
||||||
|
<a id="HTTPAPI"></a>
|
||||||
|
<h3>HTTPAPI</h3>
|
||||||
|
<ul>
|
||||||
|
HTTPAPI is a compact HTML API server that performs http requests to execute set and get commands
|
||||||
|
and reads and writes readings.<br><br>
|
||||||
|
|
||||||
|
<a id="HTTPAPI-define"></a>
|
||||||
|
<b>Define</b>
|
||||||
|
<ul>
|
||||||
|
<code>define <name> HTTPAPI [infix=][<apiName>] [port=][[IPV6:]<port>] [global=][global|local|<hostname>]</code><br><br>
|
||||||
|
|
||||||
|
Defines the HTTP API server.<br>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<code><apiName></code> is the portion behind the base URL (usually <code>http://<hostname>:<port>/<apiName></code>).<br>
|
||||||
|
<code>[<apiName>] = api</code> is default.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<code>[[IPV6:]<port>] = 8087</code> is default.<br>
|
||||||
|
To use IPV6, specify the portNumber as <code>IPV6:<number></code>, in this case the perl module IO::Socket:INET6 will be requested.
|
||||||
|
On Linux you may have to install it with <code>cpan -i IO::Socket::INET6</code> or <code>apt-get libio-socket-inet6-perl</code>.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<code>[global|local|<hostname>] = global</code> is default.<br>
|
||||||
|
If the parameter is set to local, the server will only listen to localhost connections. If is set to global, the server
|
||||||
|
will listen on all interfaces, else it wil try to resolve the parameter as a hostname, and listen only on this interface.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
Example:
|
||||||
|
<ul>
|
||||||
|
<code>define httpapi HTTPAPI</code> (Configuration with default values)<br>
|
||||||
|
or<br>
|
||||||
|
<code>define httpapi HTTPAPI api 8087 global</code><br>
|
||||||
|
or<br>
|
||||||
|
<code>define httpapi HTTPAPI infix=api1 port=8089 global=local</code><br>
|
||||||
|
</ul>
|
||||||
|
</ul>
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
<a id="HTTPAPI-get"></a>
|
||||||
|
<b>Get</b>
|
||||||
|
<ul>
|
||||||
|
<li>API command line for executing a get command<br>
|
||||||
|
Request:
|
||||||
|
<ul>
|
||||||
|
<code>http://<ip-addr>:<port>/<apiName>/get?device=<devname>&action=<cmd></code><br>
|
||||||
|
</ul>
|
||||||
|
Response:
|
||||||
|
<ul>
|
||||||
|
<code><action>=<response>|error=<error message></code><br>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
<a id="HTTPAPI-set"></a>
|
||||||
|
<b>Set</b>
|
||||||
|
<ul>
|
||||||
|
<li>API command line for executing a set command<br>
|
||||||
|
Request:
|
||||||
|
<ul>
|
||||||
|
<code>http://<ip-addr>:<port>/<apiName>/set?device=<devname>&action=<cmd></code><br>
|
||||||
|
</ul>
|
||||||
|
Response:
|
||||||
|
<ul>
|
||||||
|
<code><device>=<cmd>|error=<error message></code><br>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
<a id="HTTPAPI-events"></a>
|
||||||
|
<b>Generated events</b>
|
||||||
|
<ul>
|
||||||
|
<li>API command line for setting a reading<br>
|
||||||
|
Request:
|
||||||
|
<ul>
|
||||||
|
<code>http://<ip-addr>:<port>/<apiName>/write?device=<devname>&reading=<name>&value=<val></code><br>
|
||||||
|
</ul>
|
||||||
|
Response:
|
||||||
|
<ul>
|
||||||
|
<code><reading name>=<val>|error=<error message></code><br>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>API command line for querying a reading<br>
|
||||||
|
Request:
|
||||||
|
<ul>
|
||||||
|
<code>http://<ip-addr>:<port>/<apiName>/read?device=<devname>&reading=<name></code><br>
|
||||||
|
</ul>
|
||||||
|
Response:
|
||||||
|
<ul>
|
||||||
|
<code><reading name>=<val>|error=<error message></code><br>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>API command line for querying the timestamp of a reading<br>
|
||||||
|
Request:
|
||||||
|
<ul>
|
||||||
|
<code>http://<ip-addr>:<port>/<apiName>/readtimestamp?device=<devname>&reading=<name></code><br>
|
||||||
|
</ul>
|
||||||
|
Response:
|
||||||
|
<ul>
|
||||||
|
<code><reading name>=<timestamp>|error=<error message></code><br>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>API command line for deleting a reading<br>
|
||||||
|
Request:
|
||||||
|
<ul>
|
||||||
|
<code>http://<ip-addr>:<port>/<apiName>/write?device=<devname>&reading=<name>&value=</code><br>
|
||||||
|
<code>http://<ip-addr>:<port>/<apiName>/write?device=<devname>&reading=<name></code><br>
|
||||||
|
</ul>
|
||||||
|
Response:
|
||||||
|
<ul>
|
||||||
|
<code><reading name>=|error=<error message></code><br>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
<b>Usage information</b>
|
||||||
|
<ul>
|
||||||
|
<li>All links are relative to <code>http://<ip-addr>:<port>/</code>.</li>
|
||||||
|
<li>Commands are not executed if the disable or ignore attribute of the device is set. See also <a href="#HTTPAPI-attr-devicesCtrl">devicesCtrl</a>.</li>
|
||||||
|
<li>The <code>http://<ip-addr>:<port>/<apiName>/</code> command displays the module-specific commandref.</li>
|
||||||
|
<li>The response message is encoded to UTF-8.</li>
|
||||||
|
</ul>
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
<a id="HTTPAPI-attr"></a>
|
||||||
|
<b>Attributes</b>
|
||||||
|
<ul>
|
||||||
|
<li><a id="HTTPAPI-attr-devicesCtrl">devicesCtrl</a> <device_1>,...,<device_n>,
|
||||||
|
A comma separated list all devices to be controlled.<br>
|
||||||
|
[devicesCtrl] = < > is default, all devices can be controlled.
|
||||||
|
</li>
|
||||||
|
<li><a href="#disable">disable</a> 0|1<br>
|
||||||
|
If applied commands will not be executed.
|
||||||
|
</li>
|
||||||
|
<li><a href="#verbose">verbose</a> 0...5
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
=end html
|
||||||
|
=cut
|
Loading…
x
Reference in New Issue
Block a user