mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-01-31 06:39:11 +00:00
83_IOhomecontrol: control IOhomecontrol devices via REST API
git-svn-id: https://svn.fhem.de/fhem/trunk@15075 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
7b5b638935
commit
fc6c242556
@ -1,5 +1,6 @@
|
||||
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
|
||||
# Do not insert empty lines here, update check depends on it.
|
||||
- new: 83_IOhomecontrol: control IOhomecontrol devices via REST API
|
||||
- feature: 31_PLAYBULB: add support for Candle S Firmware 1.4
|
||||
- feature: 73_GardenaSmartBridge: add attribut disabledForInterval
|
||||
- new: 73_WaterCalculator.pm: New module for water consumption and cost
|
||||
|
412
fhem/FHEM/83_IOhomecontrol.pm
Normal file
412
fhem/FHEM/83_IOhomecontrol.pm
Normal file
@ -0,0 +1,412 @@
|
||||
# $Id$
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# 83_IOhomecontrol.pm
|
||||
# Copyright by Dr. Boris Neubert
|
||||
# e-mail: omega at online dot de
|
||||
#
|
||||
# This file is part of fhem.
|
||||
#
|
||||
# Fhem is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Fhem is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with fhem. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
package main;
|
||||
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use HttpUtils;
|
||||
use JSON;
|
||||
#use Data::Dumper;
|
||||
|
||||
#####################################
|
||||
sub IOhomecontrol_Initialize($) {
|
||||
my ($hash) = @_;
|
||||
|
||||
$hash->{DefFn} = "IOhomecontrol_Define";
|
||||
$hash->{UndefFn} = "IOhomecontrol_Undef";
|
||||
$hash->{GetFn} = "IOhomecontrol_Get";
|
||||
$hash->{SetFn} = "IOhomecontrol_Set";
|
||||
$hash->{parseParams} = 1;
|
||||
#$hash->{AttrFn} = "IOhomecontrol_Attr";
|
||||
#$hash->{AttrList}= "";
|
||||
}
|
||||
|
||||
#####################################
|
||||
sub IOhomecontrol_Define($$) {
|
||||
|
||||
# define <name> IOhomecontrol <model> <host> <pwfile>
|
||||
my ($hash, $argref, undef) = @_;
|
||||
|
||||
my @def= @{$argref};
|
||||
if($#def != 4) {
|
||||
my $msg = "wrong syntax: define <name> IOhomecontrol <model> <host> <pwfile>";
|
||||
Log 2, $msg;
|
||||
return $msg;
|
||||
}
|
||||
|
||||
my $name = $def[0];
|
||||
my $unused = $def[2];
|
||||
my $host = $def[3];
|
||||
my $pwfile = $def[4];
|
||||
|
||||
$hash->{"host"}= $host;
|
||||
$hash->{"pwfile"}= $pwfile;
|
||||
$hash->{fhem}{".token"}= undef;
|
||||
$hash->{fhem}{".scenes"}= undef;
|
||||
|
||||
$hash->{STATE} = "Initialized";
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
||||
#####################################
|
||||
sub IOhomecontrol_Undef($$) {
|
||||
return undef;
|
||||
}
|
||||
|
||||
#####################################
|
||||
# Internals
|
||||
#####################################
|
||||
|
||||
sub IOhomecontrol_Exec($$$$) {
|
||||
|
||||
my ($hash, $api, $action, $params) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
my $host = $hash->{"host"};
|
||||
my $token = $hash->{fhem}{".token"};
|
||||
|
||||
# build header
|
||||
my $header = {
|
||||
"Accept" => "application/json",
|
||||
"Content-Type" => "application/json;charset=utf-8",
|
||||
};
|
||||
if(defined($token)) {
|
||||
$header->{"Authorization"} = "Bearer $token";
|
||||
};
|
||||
|
||||
# build payload
|
||||
my $payload = {
|
||||
"action" => $action,
|
||||
"params" => $params,
|
||||
};
|
||||
my $json = encode_json $payload;
|
||||
#Debug "IOhomecontrol $name: sending $json";
|
||||
|
||||
# build HTTP request
|
||||
my $httpParams = {
|
||||
url => "http://$host/api/v1/$api",
|
||||
timeout => 2,
|
||||
method => "POST",
|
||||
noshutdown => 1,
|
||||
keepalive => 0,
|
||||
httpversion => "1.1",
|
||||
header => $header,
|
||||
data => $json,
|
||||
};
|
||||
|
||||
my ($err, $data)= HttpUtils_BlockingGet($httpParams);
|
||||
|
||||
if(defined($err) && $err) {
|
||||
Log3 $hash, 2, "IOhomecontrol $name returned error: $err";
|
||||
return undef;
|
||||
} else {
|
||||
if(defined($data) && $data) {
|
||||
# strip junk from the beginning
|
||||
$data =~ s/^\)\]\}\',//;
|
||||
#Debug "IOhomecontrol $name: data $data";
|
||||
my $result = decode_json $data;
|
||||
#Debug Dumper $result;
|
||||
my $errorsref= $result->{errors};
|
||||
my @errors= @{$errorsref};
|
||||
$err= "";
|
||||
if(@errors) {
|
||||
$err= join(" ", @errors);
|
||||
Log3 $hash, 2, "IOhomecontrol $name: API $api, action $action returned errors ($err).";
|
||||
};
|
||||
readingsBeginUpdate($hash);
|
||||
readingsBulkUpdate($hash, "deviceStatus", $result->{deviceStatus});
|
||||
readingsBulkUpdate($hash, "errors", $err);
|
||||
readingsEndUpdate($hash, 1);
|
||||
return undef if(@errors);
|
||||
return $result; # this is a hash reference
|
||||
} else {
|
||||
Log3 $hash, 2, "IOhomecontrol $name returned no data.";
|
||||
return undef;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#####################################
|
||||
|
||||
sub IOhomecontrol_getPassword($) {
|
||||
my $hash = shift;
|
||||
|
||||
my $pwfile= $hash->{"pwfile"};
|
||||
if(open(PWFILE, $pwfile)) {
|
||||
my @contents= <PWFILE>;
|
||||
close(PWFILE);
|
||||
return undef unless @contents;
|
||||
my $password = $contents[0];
|
||||
chomp $password;
|
||||
return $password;
|
||||
} else {
|
||||
return undef;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sub IOhomecontrol_Login($) {
|
||||
my $hash = shift;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
Log3 $hash, 4, "IOhomecontrol $name: Logging in...";
|
||||
my $password = IOhomecontrol_getPassword($hash);
|
||||
if(!defined($password)) {
|
||||
Log3 $hash, 2, "IOhomecontrol $name: No password.";
|
||||
return 0;
|
||||
}
|
||||
my $params = { "password" => $password };
|
||||
my $result= IOhomecontrol_Exec($hash, "auth", "login", $params);
|
||||
if(defined($result)) {
|
||||
my $token= $result->{token};
|
||||
Log3 $hash, 4, "IOhomecontrol $name got token: $token";
|
||||
$hash->{fhem}{".token"}= $token;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub IOhomecontrol_Logout($) {
|
||||
my $hash = shift;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
Log3 $hash, 4, "IOhomecontrol $name: Logging out...";
|
||||
my $params = { };
|
||||
my $result= IOhomecontrol_Exec($hash, "auth", "logout", $params);
|
||||
if(defined($result)) {
|
||||
Log3 $hash, 4, "IOhomecontrol $name logged out.";
|
||||
$hash->{fhem}{".token"}= undef;
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub IOhomecontrol_Action($$$$) {
|
||||
my ($hash, $api, $action, $params) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
Log3 $hash, 4, "IOhomecontrol $name: API $api, action $action";
|
||||
if(IOhomecontrol_Login($hash)) {
|
||||
my $result= IOhomecontrol_Exec($hash, $api, $action, $params);
|
||||
IOhomecontrol_Logout($hash);
|
||||
return $result;
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
||||
#####################################
|
||||
sub IOhomecontrol_makeScenes($) {
|
||||
my $hash= shift;
|
||||
|
||||
my $scenes= $hash->{fhem}{".scenes"};
|
||||
if(!defined($scenes)) {
|
||||
$scenes= IOhomecontrol_getScenes($hash);
|
||||
$hash->{fhem}{".scenes"} = $scenes;
|
||||
}
|
||||
my $sc= {};
|
||||
if(defined($scenes)) {
|
||||
my $data= $scenes->{data};
|
||||
#Debug "data: " . Dumper $data;
|
||||
foreach my $item (@{$data}) {
|
||||
#Debug "data item: " . Dumper $item;
|
||||
my $name= $item->{name};
|
||||
my $id= $item->{id};
|
||||
#Debug "$id: $name";
|
||||
$sc->{$id}= $name;
|
||||
}
|
||||
my $sns= "";
|
||||
foreach my $id (sort keys %{$sc}) {
|
||||
$sns.="," if($sns);
|
||||
$sns.= sprintf("%d: %s", $id, $sc->{$id});
|
||||
}
|
||||
readingsSingleUpdate($hash, "scenes", $sns, 1);
|
||||
}
|
||||
return $sc; # a hash id => name
|
||||
}
|
||||
|
||||
sub IOhomecontrol_getScenes($) {
|
||||
my $hash= shift;
|
||||
my $scenes= IOhomecontrol_Action($hash, "scenes", "get", {});
|
||||
#Debug Dumper $scenes;
|
||||
return $scenes;
|
||||
}
|
||||
|
||||
sub IOhomecontrol_runSceneById($$$) {
|
||||
my ($hash, $id, $name)= @_;
|
||||
IOhomecontrol_Action($hash, "scenes", "run", { id => $id });
|
||||
readingsSingleUpdate($hash, "lastScene", $name, 1);
|
||||
}
|
||||
|
||||
#####################################
|
||||
sub IOhomecontrol_Get($@) {
|
||||
my ($hash, $argsref, undef) = @_;
|
||||
|
||||
my @a= @{$argsref};
|
||||
return "get needs at least one parameter" if(@a < 2);
|
||||
|
||||
my $name = $a[0];
|
||||
my $cmd= $a[1];
|
||||
my $arg = ($a[2] ? $a[2] : "");
|
||||
my @args= @a; shift @args; shift @args;
|
||||
|
||||
my $answer= "";
|
||||
if($cmd eq "scenes") {
|
||||
$hash->{fhem}{".scenes"}= undef; # forget scenes forces get from device
|
||||
my $sc= IOhomecontrol_makeScenes($hash);
|
||||
foreach my $id (sort keys %{$sc}) {
|
||||
$answer.="\n" if($answer);
|
||||
$answer.= sprintf("%2d: %s", $id, $sc->{$id});
|
||||
}
|
||||
} else {
|
||||
return "Unknown argument $cmd, choose one of scenes:noArg";
|
||||
}
|
||||
|
||||
return $answer;
|
||||
}
|
||||
|
||||
|
||||
#####################################
|
||||
|
||||
# sub IOhomecontrol_Attr($@) {
|
||||
#
|
||||
# my @a = @_;
|
||||
# my $hash= $defs{$a[1]};
|
||||
# my $name= $hash->{NAME};
|
||||
#
|
||||
# if($a[0] eq "set") {
|
||||
# if($a[2] eq "") {
|
||||
# }
|
||||
# }
|
||||
#
|
||||
# return undef;
|
||||
# }
|
||||
|
||||
|
||||
#####################################
|
||||
sub IOhomecontrol_Set($@) {
|
||||
my ($hash, $argsref, undef) = @_;
|
||||
|
||||
my @a= @{$argsref};
|
||||
return "set needs at least one parameter" if(@a < 2);
|
||||
|
||||
my $name = shift @a;
|
||||
my $cmd= shift @a;
|
||||
|
||||
my $usage= "Unknown argument $cmd, choose one of scene";
|
||||
if($cmd eq "scene") {
|
||||
if($#a) {
|
||||
return "Command scene needs exactly one argument.";
|
||||
} else {
|
||||
my $sc= IOhomecontrol_makeScenes($hash);
|
||||
my $id= $a[0];
|
||||
if($id !~ /^\d+$/) {
|
||||
#Debug "IOhomecontrol $name: looking up scene $id by name...";
|
||||
my %cs= reverse %{$sc};
|
||||
$id= $cs{$id};
|
||||
}
|
||||
my $sn= $sc->{$id};
|
||||
if(defined($sn)) {
|
||||
Log3 $hash, 4, "IOhomecontrol $name: running scene id $id, name $sn";
|
||||
IOhomecontrol_runSceneById($hash, $id, $sn);
|
||||
} else {
|
||||
return "No such scene $id";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return $usage
|
||||
}
|
||||
|
||||
return undef;
|
||||
|
||||
}
|
||||
|
||||
#####################################
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
=item device
|
||||
=item summary control IOhomecontrol devices via REST API
|
||||
=item summary_DE IOhomecontrol-Geräte mittels REST-API steuern
|
||||
=begin html
|
||||
|
||||
<a name="IOhomecontrol"></a>
|
||||
<h3>IOhomecontrol</h3>
|
||||
<ul>
|
||||
|
||||
<a name="IOhomecontroldefine"></a>
|
||||
<b>Define</b><br><br>
|
||||
<ul>
|
||||
<code>define <name> IOhomecontrol <model> <host> <pwfile> </code><br><br>
|
||||
|
||||
Defines a IOhomecontrol device. <code><model></code> is a placeholder for future amendments. <code><host></code> is the IP address or hostname of the IOhomecontrol device. <code><pwfile></code> is a file that contains the password to log into the device.<br><br>
|
||||
|
||||
Example:
|
||||
<ul>
|
||||
<code>define velux IOhomecontrol KLF200 192.168.0.91 /opt/fhem/etc/veluxpw.txt</code><br>
|
||||
</ul>
|
||||
<br><br>
|
||||
</ul>
|
||||
|
||||
<a name="IOhomecontrolset"></a>
|
||||
<b>Set</b><br><br>
|
||||
<ul>
|
||||
<code>set <name> scene <id></code>
|
||||
<br><br>
|
||||
Runs the scene identified by <code><id></code> which can be either the numeric id of the scene or the scene's name.
|
||||
<br><br>
|
||||
Examples:
|
||||
<ul>
|
||||
<code>set velux scene 1</code><br>
|
||||
<code>set velux scene "all shutters down"</code><br>
|
||||
</ul>
|
||||
<br>
|
||||
Scene names with blanks must be enclosed in double quotes.
|
||||
<br><br>
|
||||
</ul>
|
||||
|
||||
|
||||
<a name="IOhomecontrolget"></a>
|
||||
<b>Get</b><br><br>
|
||||
<ul>
|
||||
<code>get <name> scenes</code>
|
||||
<br><br>
|
||||
Retrieves the ids and names of the scenes from the device.
|
||||
<br><br>
|
||||
Example:
|
||||
<ul>
|
||||
<code>get velux scenes</code><br>
|
||||
</ul>
|
||||
</ul>
|
||||
<br><br>
|
||||
|
||||
</ul>
|
||||
|
||||
=end html
|
||||
=cut
|
@ -341,6 +341,7 @@ FHEM/82_LGTV.pm markusbloch Multimedia
|
||||
FHEM/82_LGTV_IP12.pm markusbloch Multimedia
|
||||
FHEM/82_LGTV_WebOS.pm CoolTux Multimedia
|
||||
FHEM/82_M232Voltage.pm neubert Sonstige Systeme
|
||||
FHEM/83_IOhomecontrol.pm neubert Sonstige Systeme
|
||||
FHEM/87_WS2000.pm tdressler Sonstiges
|
||||
FHEM/86_Robonect.pm andi291 Sonstige Systeme
|
||||
FHEM/88_ALL4000T.pm sachag Sonstiges
|
||||
|
Loading…
Reference in New Issue
Block a user