mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-04-08 07:24:21 +00:00
HUEbridge: added group handling
added pollDevices attribute added httpUtils for nonblocking mode HUEDevice: added group handling added renaming of devices and groups in the bridge git-svn-id: https://svn.fhem.de/fhem/trunk@7314 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
1e67bc9ce4
commit
effe1db3dc
@ -1,5 +1,10 @@
|
||||
# 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.
|
||||
- feature: HUEbridge: added group handling
|
||||
added pollDevices attribute
|
||||
added httpUtils for nonblocking mode
|
||||
- feature: HUEDevice: added group handling
|
||||
added renaming of devices and groups in the bridge
|
||||
- added: 30_MilightBridge / 31_MilightDevice: Support Milight
|
||||
(Applamp/LimitlessLED/EasyBulb) LED lights/strips/controllers.
|
||||
- feature: HUEDevice: allow ct presets in webCmd
|
||||
|
@ -11,9 +11,10 @@ use strict;
|
||||
use warnings;
|
||||
use POSIX;
|
||||
use JSON;
|
||||
#use Try::Tiny;
|
||||
use Data::Dumper;
|
||||
|
||||
use HttpUtils;
|
||||
|
||||
my $HUEBridge_isFritzBox = undef;
|
||||
sub
|
||||
HUEBridge_isFritzBox()
|
||||
@ -23,7 +24,6 @@ HUEBridge_isFritzBox()
|
||||
return $HUEBridge_isFritzBox;
|
||||
}
|
||||
|
||||
|
||||
sub HUEBridge_Initialize($)
|
||||
{
|
||||
my ($hash) = @_;
|
||||
@ -40,18 +40,18 @@ sub HUEBridge_Initialize($)
|
||||
$hash->{SetFn} = "HUEBridge_Set";
|
||||
$hash->{GetFn} = "HUEBridge_Get";
|
||||
$hash->{UndefFn} = "HUEBridge_Undefine";
|
||||
$hash->{AttrList}= "key disable:1";
|
||||
$hash->{AttrList}= "key disable:1 httpUtils:1,0 pollDevices:1";
|
||||
}
|
||||
|
||||
sub
|
||||
HUEBridge_Read($@)
|
||||
{
|
||||
my ($hash,$name,$id,$obj)= @_;
|
||||
my ($hash,$chash,$name,$id,$obj)= @_;
|
||||
|
||||
if( $id =~ m/^G(\d.*)/ ) {
|
||||
return HUEBridge_Call($hash, 'groups/' . $1, $obj);
|
||||
return HUEBridge_Call($hash, $chash, 'groups/' . $1, $obj);
|
||||
}
|
||||
return HUEBridge_Call($hash, 'lights/' . $id, $obj);
|
||||
return HUEBridge_Call($hash, $chash, 'lights/' . $id, $obj);
|
||||
}
|
||||
|
||||
sub
|
||||
@ -86,7 +86,7 @@ HUEBridge_Define($$)
|
||||
}
|
||||
|
||||
$interval= 300 unless defined($interval);
|
||||
if( $interval < 60 ) { $interval = 60; }
|
||||
if( $interval < 10 ) { $interval = 10; }
|
||||
|
||||
$hash->{STATE} = 'Initialized';
|
||||
|
||||
@ -95,6 +95,8 @@ HUEBridge_Define($$)
|
||||
|
||||
$attr{$name}{"key"} = join "",map { unpack "H*", chr(rand(256)) } 1..16 unless defined( AttrVal($name, "key", undef) );
|
||||
|
||||
$hash->{helper}{last_config_timestamp} = 0;
|
||||
|
||||
if( !defined($hash->{helper}{count}) ) {
|
||||
$modules{$hash->{TYPE}}{helper}{count} = 0 if( !defined($modules{$hash->{TYPE}}{helper}{count}) );
|
||||
$hash->{helper}{count} = $modules{$hash->{TYPE}}{helper}{count}++;
|
||||
@ -135,7 +137,7 @@ sub HUEBridge_OpenDev($)
|
||||
{
|
||||
my ($hash) = @_;
|
||||
|
||||
my $result = HUEBridge_Call($hash, 'config', undef);
|
||||
my $result = HUEBridge_Call($hash, undef, 'config', undef);
|
||||
if( !defined($result) ) {
|
||||
return undef;
|
||||
}
|
||||
@ -181,18 +183,21 @@ sub HUEBridge_Pair($)
|
||||
sub
|
||||
HUEBridge_Set($@)
|
||||
{
|
||||
my ($hash, $name, $cmd) = @_;
|
||||
my ($hash, $name, $cmd, $arg, @params) = @_;
|
||||
|
||||
# usage check
|
||||
if($cmd eq 'statusRequest') {
|
||||
RemoveInternalTimer($hash);
|
||||
$hash->{LOCAL} = 1;
|
||||
#RemoveInternalTimer($hash);
|
||||
HUEBridge_GetUpdate($hash);
|
||||
delete $hash->{LOCAL};
|
||||
return undef;
|
||||
|
||||
} elsif($cmd eq 'swupdate') {
|
||||
my $obj = {
|
||||
'swupdate' => { 'updatestate' => 3, },
|
||||
};
|
||||
my $result = HUEBridge_Call($hash, 'config', $obj);
|
||||
my $result = HUEBridge_Call($hash, undef, 'config', $obj);
|
||||
|
||||
if( !defined($result) || $result->{'error'} ) {
|
||||
return $result->{'error'}->{'description'};
|
||||
@ -201,11 +206,53 @@ HUEBridge_Set($@)
|
||||
$hash->{updatestate} = 3;
|
||||
$hash->{STATE} = "updating";
|
||||
return "starting update";
|
||||
|
||||
} elsif($cmd eq 'autocreate') {
|
||||
HUEBridge_Autocreate($hash,1);
|
||||
return HUEBridge_Autocreate($hash,1);
|
||||
|
||||
} elsif($cmd eq 'creategroup') {
|
||||
|
||||
my @lights = ();
|
||||
for my $param (@params) {
|
||||
$param = $defs{$param}{ID} if( defined $defs{$param} && $defs{$param}{TYPE} eq 'HUEDevice' );
|
||||
push( @lights, $param );
|
||||
}
|
||||
|
||||
my $obj = { 'name' => $arg,
|
||||
'lights' => \@lights,
|
||||
};
|
||||
|
||||
my $result = HUEBridge_Call($hash, undef, 'groups', $obj, 'POST');
|
||||
|
||||
if( $result->{success} ) {
|
||||
HUEBridge_Autocreate($hash);
|
||||
|
||||
my $code = $name ."-G". $result->{success}{id};
|
||||
return "created $modules{HUEDevice}{defptr}{$code}->{NAME}" if( defined($modules{HUEDevice}{defptr}{$code}) );
|
||||
}
|
||||
|
||||
return $result->{error}{description} if( $result->{error} );
|
||||
return undef;
|
||||
|
||||
} elsif($cmd eq 'deletegroup') {
|
||||
if( defined $defs{$arg} && $defs{$arg}{TYPE} eq 'HUEDevice' ) {
|
||||
$defs{$arg}{ID} =~ m/G(.*)/;
|
||||
$arg = $1;
|
||||
}
|
||||
|
||||
my $code = $name ."-G". $arg;
|
||||
if( defined($modules{HUEDevice}{defptr}{$code}) ) {
|
||||
CommandDelete( undef, "$modules{HUEDevice}{defptr}{$code}{NAME}" );
|
||||
CommandSave(undef,undef) if( AttrVal( "autocreate", "autosave", 1 ) );
|
||||
}
|
||||
|
||||
my $result = HUEBridge_Call($hash, undef, "groups/$arg", undef, 'DELETE');
|
||||
return $result->{error}{description} if( $result->{error} );
|
||||
|
||||
return undef;
|
||||
|
||||
} else {
|
||||
my $list = "autocreate:noArg statusRequest:noArg";
|
||||
my $list = "creategroup deletegroup autocreate:noArg statusRequest:noArg";
|
||||
$list .= " swupdate:noArg" if( defined($hash->{updatestate}) && $hash->{updatestate} == 2 );
|
||||
return "Unknown argument $cmd, choose one of $list";
|
||||
}
|
||||
@ -220,20 +267,30 @@ HUEBridge_Get($@)
|
||||
|
||||
# usage check
|
||||
if($cmd eq 'devices') {
|
||||
my $result = HUEBridge_Call($hash, 'lights', undef);
|
||||
my $result = HUEBridge_Call($hash, undef, 'lights', undef);
|
||||
my $ret = "";
|
||||
foreach my $key ( sort keys %$result ) {
|
||||
$ret .= $key .": ". $result->{$key}{name} ."\n";
|
||||
foreach my $key ( sort {$a<=>$b} keys %$result ) {
|
||||
my $code = $name ."-". $key;
|
||||
my $fhem_name ="";
|
||||
$fhem_name = $modules{HUEDevice}{defptr}{$code}->{NAME} if( defined($modules{HUEDevice}{defptr}{$code}) );
|
||||
$ret .= sprintf( "%2i: %-25s %-15s %s\n", $key, $result->{$key}{name}, $fhem_name, $result->{$key}{type} );
|
||||
}
|
||||
$ret = sprintf( "%2s %-25s %-15s %s\n", "ID", "NAME", "FHEM", "TYPE" ) .$ret if( $ret );
|
||||
return $ret;
|
||||
|
||||
} elsif($cmd eq 'groups') {
|
||||
my $result = HUEBridge_Call($hash, 'groups', undef);
|
||||
$result->{0} = { name => "Lightset 0", };
|
||||
my $result = HUEBridge_Call($hash, undef, 'groups', undef);
|
||||
$result->{0} = { name => 'Lightset 0', type => 'LightGroup', lights => ["ALL"] };
|
||||
my $ret = "";
|
||||
foreach my $key ( sort keys %$result ) {
|
||||
$ret .= $key .": ". $result->{$key}{name} ."\n";
|
||||
foreach my $key ( sort {$a<=>$b} keys %$result ) {
|
||||
my $code = $name ."-G". $key;
|
||||
my $fhem_name ="";
|
||||
$fhem_name = $modules{HUEDevice}{defptr}{$code}->{NAME} if( defined($modules{HUEDevice}{defptr}{$code}) );
|
||||
$ret .= sprintf( "%2i: %-15s %-15s %-15s %s\n", $key, $result->{$key}{name}, $fhem_name, $result->{$key}{type}, join( ",", @{$result->{$key}{lights}} ) );
|
||||
}
|
||||
$ret = sprintf( "%2s %-15s %-15s %-15s %s\n", "ID", "NAME", "FHEM", "TYPE", "LIGHTS" ) .$ret if( $ret );
|
||||
return $ret;
|
||||
|
||||
} else {
|
||||
return "Unknown argument $cmd, choose one of devices:noArg groups:noArg";
|
||||
}
|
||||
@ -250,16 +307,49 @@ HUEBridge_GetUpdate($)
|
||||
InternalTimer(gettimeofday()+$hash->{INTERVAL}, "HUEBridge_GetUpdate", $hash, 0);
|
||||
}
|
||||
|
||||
my $result = HUEBridge_Call($hash, 'config', undef);
|
||||
#my $result = HUEBridge_Call($hash, undef, undef);
|
||||
my $type;
|
||||
my $result;
|
||||
if( AttrVal($name,"pollDevices",0) ) {
|
||||
my ($now) = gettimeofday();
|
||||
if( $hash->{LOCAL} || $now - $hash->{helper}{last_config_timestamp} > 300 ) {
|
||||
$result = HUEBridge_Call($hash, $hash, undef, undef);
|
||||
$hash->{helper}{last_config_timestamp} = $now;
|
||||
} else {
|
||||
$type = 'lights';
|
||||
$result = HUEBridge_Call($hash, $hash, 'lights', undef);
|
||||
}
|
||||
} else {
|
||||
$type = 'config';
|
||||
$result = HUEBridge_Call($hash, $hash, 'config', undef);
|
||||
}
|
||||
|
||||
return undef if( !defined($result) );
|
||||
|
||||
HUEBridge_dispatch( {hash=>$hash,chash=>$hash,type=>$type}, undef, undef, $result );
|
||||
|
||||
#HUEBridge_Parse($hash, $result);
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub
|
||||
HUEBridge_Parse($$)
|
||||
{
|
||||
my($hash,$result) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
Log3 $name, 4, "parse status message for $name";
|
||||
#Log3 $name, 5, Dumper $result;
|
||||
|
||||
#Log 3, Dumper $result;
|
||||
#$result = $result->{config};
|
||||
$result = $result->{config} if( defined($result->{config}) );
|
||||
|
||||
$hash->{name} = $result->{name};
|
||||
$hash->{swversion} = $result->{swversion};
|
||||
|
||||
if( defined( $result->{swupdate} ) ) {
|
||||
my $txt = $result->{swupdate}->{text};
|
||||
readingsSingleUpdate($hash, "swupdate", $txt, defined($hash->{LOCAL} ? 0 : 1)) if( $txt && $txt ne ReadingsVal($name,"swupdate","") );
|
||||
readingsSingleUpdate($hash, "swupdate", $txt, 1) if( $txt && $txt ne ReadingsVal($name,"swupdate","") );
|
||||
if( defined($hash->{updatestate}) ){
|
||||
$hash->{STATE} = "update done" if( $result->{swupdate}->{updatestate} == 0 && $hash->{updatestate} >= 2 );
|
||||
$hash->{STATE} = "update failed" if( $result->{swupdate}->{updatestate} == 2 && $hash->{updatestate} == 3 );
|
||||
@ -284,13 +374,14 @@ HUEBridge_Autocreate($;$)
|
||||
}
|
||||
}
|
||||
|
||||
my $result = HUEBridge_Call($hash, 'lights', undef);
|
||||
my $autocreated = 0;
|
||||
my $result = HUEBridge_Call($hash,undef, 'lights', undef);
|
||||
foreach my $key ( keys %$result ) {
|
||||
my $id= $key;
|
||||
|
||||
my $code = $name ."-". $id;
|
||||
if( defined($modules{HUEDevice}{defptr}{$code}) ) {
|
||||
Log3 $name, 4, "$name: id '$id' already defined as '$modules{HUEDevice}{defptr}{$code}->{NAME}'";
|
||||
Log3 $name, 5, "$name: id '$id' already defined as '$modules{HUEDevice}{defptr}{$code}->{NAME}'";
|
||||
next;
|
||||
}
|
||||
|
||||
@ -307,17 +398,19 @@ HUEBridge_Autocreate($;$)
|
||||
$cmdret= CommandAttr(undef,"$devname alias ".$result->{$id}{name});
|
||||
$cmdret= CommandAttr(undef,"$devname room HUEDevice");
|
||||
$cmdret= CommandAttr(undef,"$devname IODev $name");
|
||||
|
||||
$autocreated++;
|
||||
}
|
||||
}
|
||||
|
||||
$result = HUEBridge_Call($hash, 'groups', undef);
|
||||
$result = HUEBridge_Call($hash,undef, 'groups', undef);
|
||||
$result->{0} = { name => "Lightset 0", };
|
||||
foreach my $key ( keys %$result ) {
|
||||
my $id= $key;
|
||||
|
||||
my $code = $name ."-G". $id;
|
||||
if( defined($modules{HUEDevice}{defptr}{$code}) ) {
|
||||
Log3 $name, 4, "$name: id '$id' already defined as '$modules{HUEDevice}{defptr}{$code}->{NAME}'";
|
||||
Log3 $name, 5, "$name: id '$id' already defined as '$modules{HUEDevice}{defptr}{$code}->{NAME}'";
|
||||
next;
|
||||
}
|
||||
|
||||
@ -334,10 +427,14 @@ HUEBridge_Autocreate($;$)
|
||||
$cmdret= CommandAttr(undef,"$devname alias ".$result->{$id}{name});
|
||||
$cmdret= CommandAttr(undef,"$devname room HUEDevice");
|
||||
$cmdret= CommandAttr(undef,"$devname IODev $name");
|
||||
|
||||
$autocreated++;
|
||||
}
|
||||
}
|
||||
|
||||
return undef;
|
||||
CommandSave(undef,undef) if( $autocreated && AttrVal( "autocreate", "autosave", 1 ) );
|
||||
|
||||
return "created $autocreated devices";
|
||||
}
|
||||
|
||||
sub HUEBridge_ProcessResponse($$)
|
||||
@ -378,49 +475,56 @@ sub HUEBridge_Register($)
|
||||
'devicetype' => 'fhem',
|
||||
};
|
||||
|
||||
return HUEBridge_Call($hash, undef, $obj);
|
||||
return HUEBridge_Call($hash, undef, undef, $obj);
|
||||
}
|
||||
|
||||
#Executes a JSON RPC
|
||||
sub
|
||||
HUEBridge_Call($$$)
|
||||
HUEBridge_Call($$$$;$)
|
||||
{
|
||||
my ($hash,$path,$obj) = @_;
|
||||
my ($hash,$chash,$path,$obj,$method) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
#Log3 $name, 3, "Sending: " . Dumper $obj;
|
||||
#Log3 $hash->{NAME}, 5, "Sending: " . Dumper $obj;
|
||||
|
||||
my $json = undef;
|
||||
$json = encode_json($obj) if $obj;
|
||||
|
||||
return HUEBridge_HTTP_Call($hash,$path,$json);
|
||||
if( !defined($attr{$name}{httpUtils}) ) {
|
||||
return HUEBridge_HTTP_Call($hash,$path,$json,$method);
|
||||
} else {
|
||||
return HUEBridge_HTTP_Call2($hash,$chash,$path,$json,$method);
|
||||
}
|
||||
}
|
||||
|
||||
#JSON RPC over HTTP
|
||||
sub HUEBridge_HTTP_Call($$$)
|
||||
sub
|
||||
HUEBridge_HTTP_Call($$$;$)
|
||||
{
|
||||
my ($hash,$path,$obj) = @_;
|
||||
my ($hash,$path,$obj,$method) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
return undef if($attr{$name} && $attr{$name}{disable});
|
||||
#return { state => {reachable => 0 } } if($attr{$name} && $attr{$name}{disable});
|
||||
|
||||
my $uri = "http://" . $hash->{Host} . "/api";
|
||||
my $method = 'GET';
|
||||
if( defined($obj) ) {
|
||||
$method = 'PUT';
|
||||
$method = 'PUT' if( !$method );
|
||||
|
||||
if( $hash->{STATE} eq 'Pairing' ) {
|
||||
$method = 'POST';
|
||||
} else {
|
||||
$uri .= "/" . AttrVal($name, "key", "");
|
||||
}
|
||||
if( $hash->{STATE} eq 'Pairing' ) {
|
||||
$method = 'POST';
|
||||
} else {
|
||||
$uri .= "/" . AttrVal($name, "key", "");
|
||||
}
|
||||
} else {
|
||||
$uri .= "/" . AttrVal($name, "key", "");
|
||||
}
|
||||
$method = 'GET' if( !$method );
|
||||
if( defined $path) {
|
||||
$uri .= "/" . $path;
|
||||
}
|
||||
#Log3 $name, 3, "Url: " . $uri;
|
||||
Log3 $name, 4, "using HUEBridge_HTTP_Request: $method ". ($path?$path:'');
|
||||
my $ret = HUEBridge_HTTP_Request(0,$uri,$method,undef,$obj,undef);
|
||||
#Log3 $name, 3, Dumper $ret;
|
||||
if( !defined($ret) ) {
|
||||
@ -442,6 +546,186 @@ sub HUEBridge_HTTP_Call($$$)
|
||||
return HUEBridge_ProcessResponse($hash,from_json($ret));
|
||||
}
|
||||
|
||||
sub
|
||||
HUEBridge_HTTP_Call2($$$$;$)
|
||||
{
|
||||
my ($hash,$chash,$path,$obj,$method) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
return undef if($attr{$name} && $attr{$name}{disable});
|
||||
#return { state => {reachable => 0 } } if($attr{$name} && $attr{$name}{disable});
|
||||
|
||||
my $url = "http://" . $hash->{Host} . "/api";
|
||||
my $blocking = $attr{$name}{httpUtils} < 1;
|
||||
$blocking = 1 if( !defined($chash) );
|
||||
if( defined($obj) ) {
|
||||
$method = 'PUT' if( !$method );
|
||||
|
||||
if( $hash->{STATE} eq 'Pairing' ) {
|
||||
$method = 'POST';
|
||||
$blocking = 1;
|
||||
} else {
|
||||
$url .= "/" . AttrVal($name, "key", "");
|
||||
}
|
||||
} else {
|
||||
$url .= "/" . AttrVal($name, "key", "");
|
||||
}
|
||||
$method = 'GET' if( !$method );
|
||||
|
||||
if( defined $path) {
|
||||
$url .= "/" . $path;
|
||||
}
|
||||
#Log3 $name, 3, "Url: " . $url;
|
||||
|
||||
#Log 2, $path;
|
||||
if( $blocking ) {
|
||||
Log3 $name, 4, "using HttpUtils_BlockingGet: $method ". ($path?$path:'');
|
||||
|
||||
my($err,$data) = HttpUtils_BlockingGet({
|
||||
url => $url,
|
||||
timeout => 4,
|
||||
method => $method,
|
||||
noshutdown => 1,
|
||||
header => "Content-Type: application/json",
|
||||
data => $obj,
|
||||
});
|
||||
|
||||
return HUEBridge_ProcessResponse($hash,from_json($data));
|
||||
|
||||
HUEBridge_dispatch( {hash=>$hash,chash=>$chash,type=>$path},$err,$data );
|
||||
} else {
|
||||
Log3 $name, 4, "using HttpUtils_NonblockingGet: $method ". ($path?$path:'');
|
||||
|
||||
my($err,$data) = HttpUtils_NonblockingGet({
|
||||
url => $url,
|
||||
timeout => 10,
|
||||
method => $method,
|
||||
noshutdown => 1,
|
||||
header => "Content-Type: application/json",
|
||||
data => $obj,
|
||||
hash => $hash,
|
||||
chash => $chash,
|
||||
type => $path,
|
||||
callback => \&HUEBridge_dispatch,
|
||||
});
|
||||
|
||||
return undef;
|
||||
}
|
||||
}
|
||||
|
||||
sub
|
||||
HUEBridge_dispatch($$$;$)
|
||||
{
|
||||
my ($param, $err, $data,$json) = @_;
|
||||
my $hash = $param->{hash};
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
#Log3 $name, 5, "HUEBridge_dispatch";
|
||||
|
||||
if( $err ) {
|
||||
Log3 $name, 2, "$name: http request failed: $err";
|
||||
} elsif( $data || $json ) {
|
||||
if( $data && $data !~ m/^[\[{].*[\]}]$/ ) {
|
||||
Log3 $name, 2, "$name: invalid json detected: $data";
|
||||
return undef;
|
||||
}
|
||||
|
||||
$json = from_json($data) if( !$json );
|
||||
my $type = $param->{type};
|
||||
|
||||
if( ref($json) eq 'ARRAY' )
|
||||
{
|
||||
if( defined($json->[0]->{error}))
|
||||
{
|
||||
my $error = $json->[0]->{error}->{'description'};
|
||||
|
||||
$hash->{STATE} = $error;
|
||||
|
||||
Log3 $name, 3, $error;
|
||||
}
|
||||
|
||||
#return ($json->[0]);
|
||||
}
|
||||
|
||||
if( $hash == $param->{chash} ) {
|
||||
if( !defined($type) ) {
|
||||
HUEBridge_Parse($hash,$json->{config});
|
||||
|
||||
if( defined($json->{groups}) ) {
|
||||
my $groups = $json->{groups};
|
||||
foreach my $id ( keys %{$groups} ) {
|
||||
my $code = $name ."-G". $id;
|
||||
my $chash = $modules{HUEDevice}{defptr}{$code};
|
||||
|
||||
if( defined($chash) ) {
|
||||
HUEDevice_Parse($chash,$groups->{$id});
|
||||
} else {
|
||||
Log3 $name, 2, "$name: message for unknow group received: $code";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$type = 'lights';
|
||||
$json = $json->{lights};
|
||||
|
||||
}
|
||||
|
||||
if( $type eq 'lights' ) {
|
||||
my $lights = $json;
|
||||
foreach my $id ( keys %{$lights} ) {
|
||||
my $code = $name ."-". $id;
|
||||
my $chash = $modules{HUEDevice}{defptr}{$code};
|
||||
|
||||
if( defined($chash) ) {
|
||||
HUEDevice_Parse($chash,$lights->{$id});
|
||||
} else {
|
||||
Log3 $name, 2, "$name: message for unknow device received: $code";
|
||||
}
|
||||
}
|
||||
|
||||
} elsif( $type =~ m/^config$/ ) {
|
||||
HUEBridge_Parse($hash,$json);
|
||||
|
||||
} else {
|
||||
Log3 $name, 2, "$name: message for unknow type received: $type";
|
||||
Log3 $name, 4, Dumper $json;
|
||||
|
||||
}
|
||||
|
||||
} elsif( $type =~ m/^lights\/(\d*)$/ ) {
|
||||
HUEDevice_Parse($param->{chash},$json);
|
||||
|
||||
} elsif( $type =~ m/^groups\/(\d*)$/ ) {
|
||||
HUEDevice_Parse($param->{chash},$json);
|
||||
|
||||
} elsif( $type =~ m/^lights\/(\d*)\/state$/ ) {
|
||||
my $chash = $param->{chash};
|
||||
if( $chash->{helper}->{update_timeout} ) {
|
||||
RemoveInternalTimer($chash);
|
||||
InternalTimer(gettimeofday()+1, "HUEDevice_GetUpdate", $chash, 0);
|
||||
} else {
|
||||
RemoveInternalTimer($chash);
|
||||
HUEDevice_GetUpdate( $chash );
|
||||
}
|
||||
|
||||
} elsif( $type =~ m/^groups\/(\d*)\/action$/ ) {
|
||||
my $chash = $param->{chash};
|
||||
if( $chash->{helper}->{update_timeout} ) {
|
||||
RemoveInternalTimer($chash);
|
||||
InternalTimer(gettimeofday()+1, "HUEDevice_GetUpdate", $chash, 0);
|
||||
} else {
|
||||
RemoveInternalTimer($chash);
|
||||
HUEDevice_GetUpdate( $chash );
|
||||
}
|
||||
|
||||
} else {
|
||||
Log3 $name, 2, "$name: message for unknow type received: $type";
|
||||
Log3 $name, 4, Dumper $json;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#adapted version of the CustomGetFileFromURL subroutine from HttpUtils.pm
|
||||
sub
|
||||
HUEBridge_HTTP_Request($$$@)
|
||||
@ -587,6 +871,11 @@ HUEBridge_HTTP_Request($$$@)
|
||||
<ul>
|
||||
<li>autocreate<br>
|
||||
Create fhem devices for all bridge devices.</li>
|
||||
<li>creategroup <name> <light-1>[ <light-2>..<lignt-n>]<br>
|
||||
Create a group out of <light-1>-<light-n> in the bridge.
|
||||
The lights can be given as fhem device names or bridge device numbers.</li>
|
||||
<li>deletegroup <name>|<id><br>
|
||||
Deletes the given group in the bridge and deletes the associated fhem device.</li>
|
||||
<li>statusRequest<br>
|
||||
Update bridge status.</li>
|
||||
<li>swupdate<br>
|
||||
|
@ -156,9 +156,6 @@ sub HUEDevice_Define($$)
|
||||
|
||||
my ($name, $type, $id, $interval) = @args;
|
||||
|
||||
$interval= 60 unless defined($interval);
|
||||
if( $interval < 10 ) { $interval = 60; }
|
||||
|
||||
$hash->{STATE} = 'Initialized';
|
||||
$hash->{helper}{interfaces}= "dimmer";
|
||||
|
||||
@ -181,6 +178,14 @@ sub HUEDevice_Define($$)
|
||||
|
||||
$modules{HUEDevice}{defptr}{$code} = $hash;
|
||||
|
||||
if( AttrVal($hash->{IODev}->{NAME}, "pollDevices", undef) ) {
|
||||
$interval = 0 unless defined($interval);
|
||||
} else {
|
||||
$interval = 60 unless defined($interval);
|
||||
}
|
||||
|
||||
$interval = 60 if( $interval && $interval < 10 );
|
||||
|
||||
$args[3] = "" if( !defined( $args[3] ) );
|
||||
if( !$hash->{helper}->{group} ) {
|
||||
$hash->{DEF} = "$id $args[3]";
|
||||
@ -214,7 +219,11 @@ sub HUEDevice_Define($$)
|
||||
}
|
||||
|
||||
RemoveInternalTimer($hash);
|
||||
InternalTimer(gettimeofday()+10, "HUEDevice_GetUpdate", $hash, 0) if( !$hash->{helper}->{group} );
|
||||
if( $init_done ) {
|
||||
HUEDevice_GetUpdate($hash);
|
||||
} else {
|
||||
InternalTimer(gettimeofday()+10, "HUEDevice_GetUpdate", $hash, 0);
|
||||
}
|
||||
|
||||
return undef;
|
||||
}
|
||||
@ -402,6 +411,43 @@ HUEDevice_Set($@)
|
||||
|
||||
$hash->{helper}->{update_timeout} = AttrVal($name, "delayedUpdate", 0);
|
||||
|
||||
if( $hash->{helper}->{group} ) {
|
||||
if( $aa[0] eq 'lights' ) {
|
||||
my @lights = ();
|
||||
for my $param (@aa[1..@aa-1]) {
|
||||
$param = $defs{$param}{ID} if( defined $defs{$param} && $defs{$param}{TYPE} eq 'HUEDevice' );
|
||||
push( @lights, $param );
|
||||
}
|
||||
|
||||
my $obj = { 'lights' => \@lights, };
|
||||
|
||||
my $result = HUEDevice_ReadFromServer($hash,$hash->{ID},$obj);
|
||||
if( $result->{success} ) {
|
||||
RemoveInternalTimer($hash);
|
||||
HUEDevice_GetUpdate($hash);
|
||||
}
|
||||
|
||||
return $result->{error}{description} if( $result->{error} );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if( $aa[0] eq 'rename' ) {
|
||||
my $new_name = join( ' ', @aa[1..@aa-1]);
|
||||
my $obj = { 'name' => $new_name, };
|
||||
|
||||
my $result = HUEDevice_ReadFromServer($hash,$hash->{ID},$obj);
|
||||
if( $result->{success} ) {
|
||||
RemoveInternalTimer($hash);
|
||||
HUEDevice_GetUpdate($hash);
|
||||
CommandAttr(undef,"$name alias $new_name");
|
||||
CommandSave(undef,undef) if( AttrVal( "autocreate", "autosave", 1 ) );
|
||||
}
|
||||
|
||||
return $result->{error}{description} if( $result->{error} );
|
||||
return undef;
|
||||
}
|
||||
|
||||
if( (my $joined = join(" ", @aa)) =~ /:/ ) {
|
||||
my @cmds = split(":", $joined);
|
||||
for( my $i = 0; $i <= $#cmds; ++$i ) {
|
||||
@ -476,6 +522,9 @@ HUEDevice_Set($@)
|
||||
|
||||
#$list .= " dim06% dim12% dim18% dim25% dim31% dim37% dim43% dim50% dim56% dim62% dim68% dim75% dim81% dim87% dim93% dim100%" if( $subtype =~ m/dimmer/ );
|
||||
|
||||
$list .= " lights" if( $hash->{helper}->{group} );
|
||||
$list .= " rename";
|
||||
|
||||
return SetExtensions($hash, $list, $name, @aa);
|
||||
}
|
||||
|
||||
@ -646,8 +695,8 @@ HUEDevice_ReadFromServer($@)
|
||||
no strict "refs";
|
||||
my $ret;
|
||||
unshift(@a,$name);
|
||||
$ret = IOWrite($hash, @a);
|
||||
#$ret = IOWrite($hash,$hash,@a);
|
||||
#$ret = IOWrite($hash, @a);
|
||||
$ret = IOWrite($hash,$hash,@a);
|
||||
use strict "refs";
|
||||
return $ret;
|
||||
return if(IsDummy($name) || IsIgnored($name));
|
||||
@ -717,6 +766,9 @@ HUEDevice_Parse($$)
|
||||
|
||||
Log3 $name, 4, "parse status message for $name";
|
||||
|
||||
$hash->{name} = $result->{'name'};
|
||||
$hash->{type} = $result->{'type'};
|
||||
|
||||
if( $hash->{helper}->{group} ) {
|
||||
$hash->{lights} = join( ",", @{$result->{lights}} );
|
||||
|
||||
@ -724,17 +776,16 @@ HUEDevice_Parse($$)
|
||||
my $code = $hash->{IODev}->{NAME} ."-". $id;
|
||||
my $chash = $modules{HUEDevice}{defptr}{$code};
|
||||
|
||||
HUEDevice_GetUpdate($chash) if( defined($chash) );
|
||||
#HUEDevice_GetUpdate($chash) if( defined($chash) );
|
||||
}
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
$hash->{modelid} = $result->{'modelid'};
|
||||
$hash->{name} = $result->{'name'};
|
||||
$hash->{type} = $result->{'type'};
|
||||
$hash->{swversion} = $result->{'swversion'};
|
||||
|
||||
|
||||
$attr{$name}{model} = $result->{'modelid'} unless( defined($attr{$name}{model}) || $result->{'modelid'} eq '' );
|
||||
$attr{$name}{subType} = $hueModels{$attr{$name}{model}}{subType} unless( defined($attr{$name}{subType})
|
||||
|| !defined($attr{$name}{model})
|
||||
@ -857,7 +908,10 @@ HUEDevice_Parse($$)
|
||||
|
||||
This can be a hue bulb, a living colors light or a living whites bulb or dimmer plug.<br><br>
|
||||
|
||||
The device status will be updated every <interval> seconds. The default and minimum is 60. Groups are updated only on definition and statusRequest<br><br>
|
||||
The device status will be updated every <interval> seconds. 0 means no updates.
|
||||
The default and minimum is 60 if the IODev has not set pollDevices to 1.
|
||||
The default ist 0 if the IODev has set pollDevices to 1.
|
||||
Groups are updated only on definition and statusRequest<br><br>
|
||||
|
||||
Examples:
|
||||
<ul>
|
||||
@ -927,9 +981,18 @@ HUEDevice_Parse($$)
|
||||
<li>effect [none|colorloop]</li>
|
||||
<li>transitiontime <time><br>
|
||||
set the transitiontime to <time> 1/10s</li>
|
||||
<li>rgb <rrggbb></li>
|
||||
<li>rgb <rrggbb><br>
|
||||
set the color to (the nearest equivalent of) <rrggbb></li>
|
||||
<br>
|
||||
<li>delayedUpdate</li>
|
||||
<li>immediateUpdate</li>
|
||||
<br>
|
||||
<li>lights <light-1>[ <light-2>..<light-n>]<br>
|
||||
Only valid for groups. Changes the list of lights in this group.
|
||||
The lights can be given as fhem device names or bridge device numbers.</li>
|
||||
<li>rename <new name><br>
|
||||
Renames the device in the bridge and changes the fhem alias.</li>
|
||||
<br>
|
||||
<li><a href="#setExtensions"> set extensions</a> are supported.</li>
|
||||
<br>
|
||||
Note:
|
||||
|
Loading…
x
Reference in New Issue
Block a user