mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-04-07 06:48:43 +00:00
74_Unifi: - Added Attribute 'devAlias' to rename device names (ID).
- Bugfix: Module not started without restart after first definition. - Cleaned up a lot of code. - Added some code for internal use. - Removed use of hash->{STATE}. git-svn-id: https://svn.fhem.de/fhem/trunk@9132 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
a75c03970e
commit
c3076d5e15
@ -1,5 +1,7 @@
|
|||||||
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
|
# 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.
|
# Do not insert empty lines here, update check depends on it.
|
||||||
|
- feature: 74_Unifi: - Added Attribute 'devAlias' to rename device names (ID)
|
||||||
|
- bugfix: Module not started without restart after def
|
||||||
- feature: 74_Unifi: - Added support for Controller v3 (v4 already supported)
|
- feature: 74_Unifi: - Added support for Controller v3 (v4 already supported)
|
||||||
- change: 74_Unifi: - changed get-Name from 'clientDetails' to 'clientData'
|
- change: 74_Unifi: - changed get-Name from 'clientDetails' to 'clientData'
|
||||||
- changed start from defFn to NotifyFn
|
- changed start from defFn to NotifyFn
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
# $Id: 74_Unifi.pm 2015-08-24 23:00 - rapster - rapster at x0e dot de $
|
# $Id: 74_Unifi.pm 2015-08-25 20:00 - rapster - rapster at x0e dot de $
|
||||||
|
|
||||||
package main;
|
package main;
|
||||||
use strict;
|
use strict;
|
||||||
@ -19,6 +19,7 @@ sub Unifi_Initialize($$) {
|
|||||||
$hash->{NOTIFYDEV} = "global";
|
$hash->{NOTIFYDEV} = "global";
|
||||||
$hash->{NotifyFn} = "Unifi_Notify";
|
$hash->{NotifyFn} = "Unifi_Notify";
|
||||||
$hash->{AttrList} = "disable:1,0 "
|
$hash->{AttrList} = "disable:1,0 "
|
||||||
|
."devAlias "
|
||||||
.$readingFnAttributes;
|
.$readingFnAttributes;
|
||||||
}
|
}
|
||||||
###############################################################################
|
###############################################################################
|
||||||
@ -35,14 +36,15 @@ sub Unifi_Define($$) {
|
|||||||
my $name = $a[0];
|
my $name = $a[0];
|
||||||
my $oldLoginData = ($hash->{loginParams}) ? $hash->{loginParams}->{data}.$hash->{url} : 0;
|
my $oldLoginData = ($hash->{loginParams}) ? $hash->{loginParams}->{data}.$hash->{url} : 0;
|
||||||
%$hash = ( %$hash,
|
%$hash = ( %$hash,
|
||||||
url => "https://".$a[2].(($a[3] != 443) ? ':'.$a[3] : '').'/',
|
CONNECTED => $hash->{CONNECTED} || 0,
|
||||||
interval => $a[6] || 30,
|
url => "https://".$a[2].(($a[3] != 443) ? ':'.$a[3] : '').'/',
|
||||||
siteID => $a[7] || 'default',
|
interval => $a[6] || 30,
|
||||||
version => $a[8] || 4,
|
siteID => $a[7] || 'default',
|
||||||
|
version => $a[8] || 4,
|
||||||
);
|
);
|
||||||
$hash->{httpParams} = {
|
$hash->{httpParams} = {
|
||||||
hash => $hash,
|
hash => $hash,
|
||||||
timeout => 8,
|
timeout => 5,
|
||||||
method => "POST",
|
method => "POST",
|
||||||
noshutdown => 0,
|
noshutdown => 0,
|
||||||
ignoreredirects => 1,
|
ignoreredirects => 1,
|
||||||
@ -63,9 +65,10 @@ sub Unifi_Define($$) {
|
|||||||
$hash->{loginParams}->{data} = "{'username':'".$a[4]."', 'password':'".$a[5]."'}";
|
$hash->{loginParams}->{data} = "{'username':'".$a[4]."', 'password':'".$a[5]."'}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Don't use old cookies when user, pw or url changed
|
||||||
if($oldLoginData && $oldLoginData ne $hash->{loginParams}->{data}.$hash->{url}) {
|
if($oldLoginData && $oldLoginData ne $hash->{loginParams}->{data}.$hash->{url}) {
|
||||||
$hash->{loginParams}->{cookies} = '';
|
$hash->{loginParams}->{cookies} = '';
|
||||||
readingsSingleUpdate($hash,"state","disconnected",1);
|
Unifi_CONNECTED($hash,'disconnected');
|
||||||
}
|
}
|
||||||
|
|
||||||
Log3 $name, 5, "$name: Defined with url:$hash->{url}, interval:$hash->{interval}, siteID:$hash->{siteID}, version:$hash->{version}";
|
Log3 $name, 5, "$name: Defined with url:$hash->{url}, interval:$hash->{interval}, siteID:$hash->{siteID}, version:$hash->{version}";
|
||||||
@ -83,18 +86,17 @@ sub Unifi_Undef($$) {
|
|||||||
|
|
||||||
sub Unifi_Notify($$) {
|
sub Unifi_Notify($$) {
|
||||||
my ($hash,$dev) = @_;
|
my ($hash,$dev) = @_;
|
||||||
my $name = $hash->{NAME};
|
my ($name,$self) = ($hash->{NAME},Unifi_Whoami());
|
||||||
|
|
||||||
return if($dev->{NAME} ne "global");
|
return if($dev->{NAME} ne "global");
|
||||||
return if(!grep(m/^INITIALIZED|REREADCFG$/, @{$dev->{CHANGED}}));
|
return if(!grep(m/^DEFINED|MODIFIED|INITIALIZED|REREADCFG$/, @{$dev->{CHANGED}}));
|
||||||
|
|
||||||
if(AttrVal($name, "disable", 0)) {
|
if(AttrVal($name, "disable", 0)) {
|
||||||
Log3 $name, 5, "$name: Notify - Detect disabled state, do nothing...";
|
Log3 $name, 5, "$name ($self) - DEFINED|MODIFIED|INITIALIZED|REREADCFG - Device '$name' is disabled, do nothing...";
|
||||||
readingsSingleUpdate($hash,"state","disabled",0) if($hash->{STATE} ne "disabled");
|
Unifi_CONNECTED($hash,'disabled');
|
||||||
} else {
|
} else {
|
||||||
Log3 $name, 5, "$name: Notify - Call DoUpdate...";
|
Log3 $name, 5, "$name ($self) - DEFINED|MODIFIED|INITIALIZED|REREADCFG - Remove all Timers & Call DoUpdate...";
|
||||||
RemoveInternalTimer($hash);
|
Unifi_CONNECTED($hash,'initialized');
|
||||||
readingsSingleUpdate($hash,"state","initialized",0);
|
|
||||||
Unifi_DoUpdate($hash);
|
Unifi_DoUpdate($hash);
|
||||||
}
|
}
|
||||||
return undef;
|
return undef;
|
||||||
@ -117,7 +119,7 @@ sub Unifi_Set($@) {
|
|||||||
}
|
}
|
||||||
Log3 $name, 5, "$name: set called with $setName " . ($setVal ? $setVal : "") if ($setName ne "?");
|
Log3 $name, 5, "$name: set called with $setName " . ($setVal ? $setVal : "") if ($setName ne "?");
|
||||||
|
|
||||||
if($hash->{STATE} ne 'connected' && $setName !~ /clear/) {
|
if(!Unifi_CONNECTED($hash) && $setName !~ /clear/) {
|
||||||
return "Unknown argument $setName, choose one of clear:all,readings,clientData";
|
return "Unknown argument $setName, choose one of clear:all,readings,clientData";
|
||||||
}
|
}
|
||||||
elsif($setName !~ /update|clear/) {
|
elsif($setName !~ /update|clear/) {
|
||||||
@ -127,6 +129,7 @@ sub Unifi_Set($@) {
|
|||||||
Log3 $name, 4, "$name: set $setName";
|
Log3 $name, 4, "$name: set $setName";
|
||||||
|
|
||||||
if ($setName eq 'update') {
|
if ($setName eq 'update') {
|
||||||
|
RemoveInternalTimer($hash);
|
||||||
Unifi_DoUpdate($hash,1);
|
Unifi_DoUpdate($hash,1);
|
||||||
}
|
}
|
||||||
elsif ($setName eq 'clear') {
|
elsif ($setName eq 'clear') {
|
||||||
@ -136,9 +139,7 @@ sub Unifi_Set($@) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($setVal eq 'clientData' || $setVal eq 'all') {
|
if ($setVal eq 'clientData' || $setVal eq 'all') {
|
||||||
for (keys %{$hash->{clients}}) {
|
%{$hash->{clients}} = ();
|
||||||
delete $hash->{clients}->{$_};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -150,18 +151,31 @@ sub Unifi_Get($@) {
|
|||||||
my ($hash,@a) = @_;
|
my ($hash,@a) = @_;
|
||||||
return "\"get $hash->{NAME}\" needs at least one argument" if ( @a < 2 );
|
return "\"get $hash->{NAME}\" needs at least one argument" if ( @a < 2 );
|
||||||
my ($name,$getName,$getVal) = @a;
|
my ($name,$getName,$getVal) = @a;
|
||||||
my $clients = join(',',keys(%{$hash->{clients}}));
|
|
||||||
|
my $clients = '';
|
||||||
|
my $devAliases = AttrVal($name,"devAlias",0);
|
||||||
|
if($devAliases) { # Replace ID's with Aliases
|
||||||
|
for (keys %{$hash->{clients}}) {
|
||||||
|
$_ = $1 if($devAliases && $devAliases =~ /$_:(.+?)(\s|$)/);
|
||||||
|
$clients .= ','.$_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if($getName !~ /clientData/) {
|
if($getName !~ /clientData/) {
|
||||||
return "Unknown argument $getName, choose one of ".(($clients) ? "clientData:all,$clients" : "");
|
return "Unknown argument $getName, choose one of ".(($clients) ? "clientData:all$clients" : "");
|
||||||
}
|
}
|
||||||
elsif ($getName eq 'clientData' && $clients) {
|
elsif ($getName eq 'clientData' && $clients) {
|
||||||
|
if($getVal && $devAliases) { # Make ID from Alias
|
||||||
|
for (keys %{$hash->{clients}}) {
|
||||||
|
$getVal = $_ if($devAliases =~ /$_:$getVal/);
|
||||||
|
}
|
||||||
|
}
|
||||||
my $clientData = '';
|
my $clientData = '';
|
||||||
if(!$getVal || $getVal eq 'all') {
|
if(!$getVal || $getVal eq 'all') {
|
||||||
$clientData .= "======================================\n";
|
$clientData .= "======================================\n";
|
||||||
for my $client (sort keys %{$hash->{clients}}) {
|
for my $client (sort keys %{$hash->{clients}}) {
|
||||||
for (sort keys %{$hash->{clients}->{$client}}) {
|
for (sort keys %{$hash->{clients}->{$client}}) {
|
||||||
$clientData .= "$_ = $hash->{clients}->{$client}->{$_}\n";
|
$clientData .= "$_ = ".((defined($hash->{clients}->{$client}->{$_})) ? $hash->{clients}->{$client}->{$_} : '')."\n";
|
||||||
}
|
}
|
||||||
$clientData .= "======================================\n";
|
$clientData .= "======================================\n";
|
||||||
}
|
}
|
||||||
@ -170,7 +184,7 @@ sub Unifi_Get($@) {
|
|||||||
elsif(defined($hash->{clients}->{$getVal})) {
|
elsif(defined($hash->{clients}->{$getVal})) {
|
||||||
$clientData .= "======================================\n";
|
$clientData .= "======================================\n";
|
||||||
for (sort keys %{$hash->{clients}->{$getVal}}) {
|
for (sort keys %{$hash->{clients}->{$getVal}}) {
|
||||||
$clientData .= "$_ = $hash->{clients}->{$getVal}->{$_}\n";
|
$clientData .= "$_ = ".((defined($hash->{clients}->{$getVal}->{$_})) ? $hash->{clients}->{$getVal}->{$_} : '')."\n";
|
||||||
}
|
}
|
||||||
$clientData .= "======================================\n";
|
$clientData .= "======================================\n";
|
||||||
return $clientData;
|
return $clientData;
|
||||||
@ -190,18 +204,17 @@ sub Unifi_Attr(@) {
|
|||||||
if($cmd eq "set") {
|
if($cmd eq "set") {
|
||||||
if($attr_name eq "disable") {
|
if($attr_name eq "disable") {
|
||||||
if($attr_value == 1) {
|
if($attr_value == 1) {
|
||||||
readingsSingleUpdate($hash,"state","disabled",1);
|
Unifi_CONNECTED($hash,'disabled');
|
||||||
RemoveInternalTimer($hash);
|
|
||||||
}
|
}
|
||||||
elsif($attr_value == 0 && $hash->{STATE} eq "disabled") {
|
elsif($attr_value == 0 && Unifi_CONNECTED($hash) eq "disabled") {
|
||||||
readingsSingleUpdate($hash,"state","initialized",1);
|
Unifi_CONNECTED($hash,'initialized');
|
||||||
Unifi_DoUpdate($hash);
|
Unifi_DoUpdate($hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elsif($cmd eq "del") {
|
elsif($cmd eq "del") {
|
||||||
if($attr_name eq "disable" && $hash->{STATE} eq "disabled") {
|
if($attr_name eq "disable" && Unifi_CONNECTED($hash) eq "disabled") {
|
||||||
readingsSingleUpdate($hash,"state","initialized",1);
|
Unifi_CONNECTED($hash,'initialized');
|
||||||
Unifi_DoUpdate($hash);
|
Unifi_DoUpdate($hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -211,25 +224,26 @@ sub Unifi_Attr(@) {
|
|||||||
|
|
||||||
sub Unifi_DoUpdate($@) {
|
sub Unifi_DoUpdate($@) {
|
||||||
my ($hash,$manual) = @_;
|
my ($hash,$manual) = @_;
|
||||||
my $name = $hash->{NAME};
|
my ($name,$self) = ($hash->{NAME},Unifi_Whoami());
|
||||||
Log3 $name, 5, "$name: DoUpdate - executed.";
|
Log3 $name, 5, "$name ($self) - executed.";
|
||||||
|
|
||||||
if($hash->{STATE} eq "disabled") {
|
if (Unifi_CONNECTED($hash) eq "disabled") {
|
||||||
Log3 $name, 5, "$name: DoUpdate - Detect disabled state, End now...";
|
Log3 $name, 5, "$name ($self) - Device '$name' is disabled, End now...";
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($hash->{STATE} ne 'connected') {
|
if (Unifi_CONNECTED($hash)) {
|
||||||
readingsSingleUpdate($hash,"state","disconnected",1) if($hash->{STATE} ne 'disconnected');
|
$hash->{updateDispatch} = { # {updateDispatch}->{callFn}[callFnRef,'receiveFn',receiveFnRef]
|
||||||
|
Unifi_GetClients_Send => [\&Unifi_GetClients_Send,'Unifi_GetClients_Receive',\&Unifi_GetClients_Receive],
|
||||||
|
Unifi_GetAnother_Send => [\&Unifi_GetAnother_Send,'Unifi_GetAnother_Receive',\&Unifi_GetAnother_Receive],
|
||||||
|
Unifi_DoAfterUpdate => [\&Unifi_DoAfterUpdate,''],
|
||||||
|
};
|
||||||
|
Unifi_NextUpdateFn($hash,$self);
|
||||||
|
InternalTimer(time()+$hash->{interval}, 'Unifi_DoUpdate', $hash, 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Unifi_CONNECTED($hash,'disconnected');
|
||||||
Unifi_Login_Send($hash)
|
Unifi_Login_Send($hash)
|
||||||
} else {
|
|
||||||
Unifi_GetClients_Send($hash);
|
|
||||||
# Do more...
|
|
||||||
if($manual) {
|
|
||||||
Log3 $name, 5, "$name: DoUpdate - This was a manual-updated.";
|
|
||||||
} else {
|
|
||||||
InternalTimer(time()+$hash->{interval}, 'Unifi_DoUpdate', $hash, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
@ -237,51 +251,41 @@ sub Unifi_DoUpdate($@) {
|
|||||||
|
|
||||||
sub Unifi_Login_Send($) {
|
sub Unifi_Login_Send($) {
|
||||||
my ($hash) = @_;
|
my ($hash) = @_;
|
||||||
my $name = $hash->{NAME};
|
my ($name,$self) = ($hash->{NAME},Unifi_Whoami());
|
||||||
Log3 $name, 5, "$name: Login_Send - executed.";
|
Log3 $name, 5, "$name ($self) - executed.";
|
||||||
|
|
||||||
if($hash->{STATE} eq "disabled") {
|
|
||||||
Log3 $name, 5, "$name: Login_Receive - Detect disabled state, End now...";
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
HttpUtils_NonblockingGet($hash->{loginParams});
|
HttpUtils_NonblockingGet($hash->{loginParams});
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
sub Unifi_Login_Receive($) {
|
sub Unifi_Login_Receive($) {
|
||||||
my ($param, $err, $data) = @_;
|
my ($param, $err, $data) = @_;
|
||||||
my $hash = $param->{hash};
|
my ($name,$self,$hash) = ($param->{hash}->{NAME},Unifi_Whoami(),$param->{hash});
|
||||||
my $name = $hash->{NAME};
|
Log3 $name, 5, "$name ($self) - executed.";
|
||||||
Log3 $name, 5, "$name: Login_Receive - executed.";
|
|
||||||
|
|
||||||
if ($err ne "") {
|
if ($err ne "") {
|
||||||
Log3 $name, 5, "$name: Login_Receive - Error while requesting ".$param->{url}." - $err";
|
Log3 $name, 5, "$name ($self) - Error while requesting ".$param->{url}." - $err";
|
||||||
}
|
}
|
||||||
elsif ($data ne "" && $hash->{version} == 3) {
|
elsif ($data ne "" && $hash->{version} == 3) {
|
||||||
if ($data =~ /Invalid username or password/si) {
|
if ($data =~ /Invalid username or password/si) {
|
||||||
Log3 $name, 1, "$name: Login_Receive - Login Failed! Invalid username or password! Will try again after interval... ";
|
Log3 $name, 1, "$name ($self) - Login Failed! Invalid username or password!";
|
||||||
} else {
|
} else {
|
||||||
Log3 $name, 5, "$name: Login_Receive - Login Failed! Version 3 should not deliver data on successfull login. Will try again after interval... ";
|
Log3 $name, 5, "$name ($self) - Login Failed! Version 3 should not deliver data on successfull login.";
|
||||||
}
|
}
|
||||||
readingsSingleUpdate($hash,"state","disconnected",1) if($hash->{STATE} ne "disconnected");
|
|
||||||
InternalTimer(time()+$hash->{interval}, 'Unifi_Login_Send', $hash, 0);
|
|
||||||
return undef;
|
|
||||||
}
|
}
|
||||||
elsif ($data ne "" || $hash->{version} == 3) { # v3 Login is empty if login is successfully
|
elsif ($data ne "" || $hash->{version} == 3) { # v3 Login is empty if login is successfully
|
||||||
if ($param->{code} == 200 || $param->{code} == 400 || $param->{code} == 401 || ($hash->{version} == 3 && ($param->{code} == 302 || $param->{code} == 200))) {
|
if ($param->{code} == 200 || $param->{code} == 400 || $param->{code} == 401 || ($hash->{version} == 3 && ($param->{code} == 302 || $param->{code} == 200))) {
|
||||||
if($hash->{version} != 3) {
|
if($data ne "") {
|
||||||
eval {
|
eval {
|
||||||
$data = decode_json($data);
|
$data = decode_json($data);
|
||||||
1;
|
1;
|
||||||
} or do {
|
} or do {
|
||||||
my $e = $@;
|
my $e = $@;
|
||||||
Log3 $name, 5, "$name: Login_Receive - Failed to decode returned json object! Will try again after interval... - error:$e";
|
$data->{meta}->{rc} = 'error';
|
||||||
readingsSingleUpdate($hash,"state","disconnected",1) if($hash->{STATE} ne "disconnected");
|
$data->{meta}->{msg} = 'Unifi.FailedToDecodeJSON - $e';
|
||||||
InternalTimer(time()+$hash->{interval}, 'Unifi_Login_Send', $hash, 0);
|
|
||||||
return undef;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if ($hash->{version} == 3 || $data->{meta}->{rc} eq "ok") { # v3 has no rc-state
|
if ($hash->{version} == 3 || $data->{meta}->{rc} eq "ok") { # v3 has no rc-state
|
||||||
Log3 $name, 5, "$name: Login_Receive - state=ok || version=3";
|
Log3 $name, 5, "$name ($self) - state=ok || version=3";
|
||||||
$param->{cookies} = '';
|
$param->{cookies} = '';
|
||||||
for (split("\r\n",$param->{httpheader})) {
|
for (split("\r\n",$param->{httpheader})) {
|
||||||
if(/^Set-Cookie/) {
|
if(/^Set-Cookie/) {
|
||||||
@ -291,41 +295,39 @@ sub Unifi_Login_Receive($) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if($param->{cookies} ne '') {
|
if($param->{cookies} ne '') {
|
||||||
Log3 $name, 5, "$name: Login_Receive - Login successfully! $param->{cookies}";
|
Log3 $name, 5, "$name ($self) - Login successfully! $param->{cookies}";
|
||||||
readingsSingleUpdate($hash,"state","connected",1);
|
Unifi_CONNECTED($hash,'connected');
|
||||||
RemoveInternalTimer($hash);
|
|
||||||
Unifi_DoUpdate($hash);
|
Unifi_DoUpdate($hash);
|
||||||
}else {
|
return undef;
|
||||||
Log3 $name, 5, "$name: Login_Receive - Something went wrong, login seems ok but no cookies received. Will try again after interval...";
|
} else {
|
||||||
readingsSingleUpdate($hash,"state","disconnected",1) if($hash->{STATE} ne "disconnected");
|
Log3 $name, 5, "$name ($self) - Something went wrong, login seems ok but no cookies received.";
|
||||||
InternalTimer(time()+$hash->{interval}, 'Unifi_Login_Send', $hash, 0);
|
|
||||||
}
|
}
|
||||||
return undef;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (defined($data->{meta}->{msg})) {
|
if (defined($data->{meta}->{msg})) {
|
||||||
if ($data->{meta}->{msg} eq 'api.err.Invalid') {
|
if ($data->{meta}->{msg} eq 'api.err.Invalid') {
|
||||||
Log3 $name, 1, "$name: Login_Receive - Login Failed! Invalid username or password!"
|
Log3 $name, 1, "$name ($self) - Login Failed! Invalid username or password!"
|
||||||
." - state:'$data->{meta}->{rc}' - msg:'$data->{meta}->{msg}' - Will try again after interval...";
|
." - state:'$data->{meta}->{rc}' - msg:'$data->{meta}->{msg}'";
|
||||||
} elsif ($data->{meta}->{msg} eq 'api.err.LoginRequired') {
|
} elsif ($data->{meta}->{msg} eq 'api.err.LoginRequired') {
|
||||||
Log3 $name, 1, "$name: Login_Receive - Login Failed! This error while login indicates that you use wrong <version> or"
|
Log3 $name, 1, "$name ($self) - Login Failed! - state:'$data->{meta}->{rc}' - msg:'$data->{meta}->{msg}' -"
|
||||||
." have to define <version> in your fhem definition. - Will try again after interval...";
|
." This error while login indicates that you use wrong <version> or"
|
||||||
}else {
|
." have to define <version> in your fhem definition.";
|
||||||
Log3 $name, 5, "$name: Login_Receive - Login Failed! - state:'$data->{meta}->{rc}' - msg:'$data->{meta}->{msg}'";
|
} else {
|
||||||
|
Log3 $name, 5, "$name ($self) - Login Failed! - state:'$data->{meta}->{rc}' - msg:'$data->{meta}->{msg}'";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log3 $name, 5, "$name: Login_Receive - Login Failed (without message)! - state:'$data->{meta}->{rc}'";
|
Log3 $name, 5, "$name ($self) - Login Failed (without message)! - state:'$data->{meta}->{rc}'";
|
||||||
}
|
}
|
||||||
$param->{cookies} = '';
|
$param->{cookies} = '';
|
||||||
readingsSingleUpdate($hash,"state","disconnected",1) if($hash->{READINGS}->{state}->{VAL} ne "disconnected");
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log3 $name, 5, "$name: Login_Receive - Failed with HTTP Code $param->{code}!";
|
Log3 $name, 5, "$name ($self) - Failed with HTTP Code $param->{code}!";
|
||||||
readingsSingleUpdate($hash,"state","disconnected",1) if($hash->{READINGS}->{state}->{VAL} ne "disconnected");
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Log3 $name, 5, "$name ($self) - Failed because no data was received!";
|
||||||
}
|
}
|
||||||
Log3 $name, 5, "$name: Login_Receive - Connect/Login to Unifi-Controller failed! Will try again after interval...";
|
Log3 $name, 5, "$name ($self) - Connect/Login to Unifi-Controller failed. Will try again after interval...";
|
||||||
readingsSingleUpdate($hash,"state","disconnected",1) if($hash->{STATE} ne "disconnected");
|
Unifi_CONNECTED($hash,'disconnected');
|
||||||
InternalTimer(time()+$hash->{interval}, 'Unifi_Login_Send', $hash, 0);
|
InternalTimer(time()+$hash->{interval}, 'Unifi_Login_Send', $hash, 0);
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
@ -333,25 +335,25 @@ sub Unifi_Login_Receive($) {
|
|||||||
|
|
||||||
sub Unifi_GetClients_Send($) {
|
sub Unifi_GetClients_Send($) {
|
||||||
my ($hash) = @_;
|
my ($hash) = @_;
|
||||||
Log3 $hash->{NAME}, 5, "$hash->{NAME}: GetClients_Send - executed.";
|
my ($name,$self) = ($hash->{NAME},Unifi_Whoami());
|
||||||
|
Log3 $name, 5, "$name ($self) - executed.";
|
||||||
|
|
||||||
my $param = {
|
my $param = {
|
||||||
%{$hash->{httpParams}},
|
%{$hash->{httpParams}},
|
||||||
url => $hash->{url}."api/s/$hash->{siteID}/stat/sta",
|
url => $hash->{url}."api/s/$hash->{siteID}/stat/sta",
|
||||||
header => ($hash->{version} == 3) ? $hash->{loginParams}->{cookies} : $hash->{loginParams}->{cookies}.$hash->{httpParams}->{header},
|
header => ($hash->{version} == 3) ? $hash->{loginParams}->{cookies} : $hash->{loginParams}->{cookies}.$hash->{httpParams}->{header},
|
||||||
callback => \&Unifi_GetClients_Receive
|
callback => $hash->{updateDispatch}->{$self}[2]
|
||||||
};
|
};
|
||||||
HttpUtils_NonblockingGet($param);
|
HttpUtils_NonblockingGet($param);
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
sub Unifi_GetClients_Receive($) {
|
sub Unifi_GetClients_Receive($) {
|
||||||
my ($param, $err, $data) = @_;
|
my ($param, $err, $data) = @_;
|
||||||
my $hash = $param->{hash};
|
my ($name,$self,$hash) = ($param->{hash}->{NAME},Unifi_Whoami(),$param->{hash});
|
||||||
my $name = $hash->{NAME};
|
Log3 $name, 5, "$name ($self) - executed.";
|
||||||
Log3 $name, 5, "$name: GetClients_Receive - executed.";
|
|
||||||
|
|
||||||
if ($err ne "") {
|
if ($err ne "") {
|
||||||
Log3 $name, 5, "$name: GetClients_Receive - Error while requesting ".$param->{url}." - $err";
|
Log3 $name, 5, "$name ($self) - Error while requesting ".$param->{url}." - $err";
|
||||||
}
|
}
|
||||||
elsif ($data ne "") {
|
elsif ($data ne "") {
|
||||||
if ($param->{code} == 200 || $param->{code} == 400 || $param->{code} == 401) {
|
if ($param->{code} == 200 || $param->{code} == 400 || $param->{code} == 401) {
|
||||||
@ -360,27 +362,32 @@ sub Unifi_GetClients_Receive($) {
|
|||||||
1;
|
1;
|
||||||
} or do {
|
} or do {
|
||||||
my $e = $@;
|
my $e = $@;
|
||||||
Log3 $name, 5, "$name: GetClients_Receive - Failed to decode returned json object! - error:$e";
|
$data->{meta}->{rc} = 'error';
|
||||||
return undef;
|
$data->{meta}->{msg} = 'Unifi.FailedToDecodeJSON - $e';
|
||||||
};
|
};
|
||||||
if ($data->{meta}->{rc} eq "ok") {
|
if ($data->{meta}->{rc} eq "ok") {
|
||||||
Log3 $name, 5, "$name: GetClients_Receive - Data received successfully! - state:'$data->{meta}->{rc}'";
|
Log3 $name, 5, "$name ($self) - state:'$data->{meta}->{rc}'";
|
||||||
|
|
||||||
readingsBeginUpdate($hash);
|
readingsBeginUpdate($hash);
|
||||||
|
my $devAliases = AttrVal($name,"devAlias",0);
|
||||||
my $connectedClientIDs = {};
|
my $connectedClientIDs = {};
|
||||||
my $i = 1;
|
my $i = 1;
|
||||||
|
my $clientName;
|
||||||
for my $h (@{$data->{data}}) {
|
for my $h (@{$data->{data}}) {
|
||||||
|
$clientName = $h->{user_id};
|
||||||
|
$clientName = $1 if $devAliases =~ /$clientName:(.+?)(\s|$)/;
|
||||||
$hash->{clients}->{$h->{user_id}} = $h;
|
$hash->{clients}->{$h->{user_id}} = $h;
|
||||||
$connectedClientIDs->{$h->{user_id}} = 1;
|
$connectedClientIDs->{$h->{user_id}} = 1;
|
||||||
readingsBulkUpdate($hash,$h->{user_id}."_hostname",($h->{hostname}) ? $h->{hostname} : ($h->{ip}) ? $h->{ip} : 'Unknown');
|
readingsBulkUpdate($hash,$clientName."_hostname",($h->{hostname}) ? $h->{hostname} : ($h->{ip}) ? $h->{ip} : 'Unknown');
|
||||||
readingsBulkUpdate($hash,$h->{user_id}."_last_seen",strftime "%Y-%m-%d %H:%M:%S",localtime($h->{last_seen}));
|
readingsBulkUpdate($hash,$clientName."_last_seen",strftime "%Y-%m-%d %H:%M:%S",localtime($h->{last_seen}));
|
||||||
readingsBulkUpdate($hash,$h->{user_id}."_uptime",$h->{uptime});
|
readingsBulkUpdate($hash,$clientName."_uptime",$h->{uptime});
|
||||||
readingsBulkUpdate($hash,$h->{user_id},'connected');
|
readingsBulkUpdate($hash,$clientName,'connected');
|
||||||
}
|
}
|
||||||
for my $clientID (keys %{$hash->{clients}}) {
|
for my $clientID (keys %{$hash->{clients}}) {
|
||||||
if (!defined($connectedClientIDs->{$clientID}) && $hash->{READINGS}->{$clientID}->{VAL} ne 'disconnected') {
|
if (!defined($connectedClientIDs->{$clientID}) && $hash->{READINGS}->{$clientID}->{VAL} ne 'disconnected') {
|
||||||
Log3 $name, 5, "$name: GetClients_Receive - Client '$clientID' previously connected is now disconnected.";
|
Log3 $name, 5, "$name ($self) - Client '$clientID' previously connected is now disconnected.";
|
||||||
readingsBulkUpdate($hash,$clientID,'disconnected');
|
$clientID = $1 if $devAliases =~ /$clientID:(.+?)(\s|$)/;
|
||||||
|
readingsBulkUpdate($hash,$clientID,'disconnected') if($hash->{READINGS}->{$clientID}->{VAL} ne 'disconnected');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
readingsEndUpdate($hash,1);
|
readingsEndUpdate($hash,1);
|
||||||
@ -388,35 +395,111 @@ sub Unifi_GetClients_Receive($) {
|
|||||||
else {
|
else {
|
||||||
if (defined($data->{meta}->{msg})) {
|
if (defined($data->{meta}->{msg})) {
|
||||||
if ($data->{meta}->{msg} eq 'api.err.LoginRequired') {
|
if ($data->{meta}->{msg} eq 'api.err.LoginRequired') {
|
||||||
Log3 $name, 5, "$name: GetClients_Receive - LoginRequired detected...";
|
Log3 $name, 5, "$name ($self) - LoginRequired detected...";
|
||||||
if($hash->{STATE} ne 'disconnected') {
|
if(Unifi_CONNECTED($hash)) {
|
||||||
Log3 $name, 5, "$name: GetClients_Receive - I am the first who detected LoginRequired. Do re-login...";
|
Log3 $name, 5, "$name ($self) - I am the first who detected LoginRequired. Do re-login...";
|
||||||
readingsSingleUpdate($hash,"state","disconnected",1);
|
Unifi_CONNECTED($hash,'disconnected');
|
||||||
RemoveInternalTimer($hash);
|
|
||||||
Unifi_DoUpdate($hash);
|
Unifi_DoUpdate($hash);
|
||||||
|
return undef;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elsif ($data->{meta}->{msg} eq "api.err.NoSiteContext" || ($hash->{version} == 3 && $data->{meta}->{msg} eq "api.err.InvalidObject")) {
|
elsif ($data->{meta}->{msg} eq "api.err.NoSiteContext" || ($hash->{version} == 3 && $data->{meta}->{msg} eq "api.err.InvalidObject")) {
|
||||||
Log3 $name, 1, "$name: GetClients_Receive - Failed! - state:'$data->{meta}->{rc}' - msg:'$data->{meta}->{msg}'"
|
Log3 $name, 1, "$name ($self) - Failed! - state:'$data->{meta}->{rc}' - msg:'$data->{meta}->{msg}'"
|
||||||
." - This error indicates that the <siteID> in your definition is wrong."
|
." - This error indicates that the <siteID> in your definition is wrong."
|
||||||
." Try to modify your definition with <sideID> = default. Will try again after interval...";
|
." Try to modify your definition with <sideID> = default.";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Log3 $name, 5, "$name: GetClients_Receive - Failed! - state:'$data->{meta}->{rc}' - msg:'$data->{meta}->{msg}'";
|
Log3 $name, 5, "$name ($self) - Failed! - state:'$data->{meta}->{rc}' - msg:'$data->{meta}->{msg}'";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log3 $name, 5, "$name: GetClients_Receive - Failed (without message)! - state:'$data->{meta}->{rc}'";
|
Log3 $name, 5, "$name ($self) - Failed (without message)! - state:'$data->{meta}->{rc}'";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Log3 $name, 5, "$name: GetClients_Receive - Failed with HTTP Code $param->{code}!";
|
Log3 $name, 5, "$name ($self) - Failed with HTTP Code $param->{code}.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Unifi_NextUpdateFn($hash,$self);
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
sub Unifi_GetAnother_Send($) {
|
||||||
|
my ($hash) = @_;
|
||||||
|
my ($name,$self) = ($hash->{NAME},Unifi_Whoami());
|
||||||
|
Log3 $name, 5, "$name ($self) - executed.";
|
||||||
|
|
||||||
|
$hash->{updateDispatch}->{$self}[2]->( {hash => $hash} ); # DUMMY
|
||||||
|
#HttpUtils_NonblockingGet($param);
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
sub Unifi_GetAnother_Receive($) {
|
||||||
|
my ($param, $err, $data) = @_;
|
||||||
|
my ($name,$self,$hash) = ($param->{hash}->{NAME},Unifi_Whoami(),$param->{hash});
|
||||||
|
Log3 $hash->{NAME}, 5, "$hash->{NAME} ($self) - executed.";
|
||||||
|
|
||||||
|
# Do
|
||||||
|
|
||||||
|
Unifi_NextUpdateFn($hash,$self);
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
sub Unifi_DoAfterUpdate($) {
|
||||||
|
my ($hash) = @_;
|
||||||
|
my ($name,$self) = ($hash->{NAME},Unifi_Whoami());
|
||||||
|
Log3 $name, 5, "$name ($self) - executed.";
|
||||||
|
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
sub Unifi_NextUpdateFn($$) {
|
||||||
|
my ($hash,$fn) = @_;
|
||||||
|
|
||||||
|
my $NextUpdateFn = 0;
|
||||||
|
for (keys %{$hash->{updateDispatch}}) { # {updateDispatch}->{callFn}[callFnRef,'receiveFn',receiveFnRef]
|
||||||
|
if($hash->{updateDispatch}->{$_}[1] && $hash->{updateDispatch}->{$_}[1] eq $fn) {
|
||||||
|
delete $hash->{updateDispatch}->{$_};
|
||||||
|
} elsif(!$NextUpdateFn && $hash->{updateDispatch}->{$_}[0] && $_ ne 'Unifi_DoAfterUpdate') {
|
||||||
|
$NextUpdateFn = $hash->{updateDispatch}->{$_}[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!$NextUpdateFn && $hash->{updateDispatch}->{Unifi_DoAfterUpdate}[0]) {
|
||||||
|
$NextUpdateFn = $hash->{updateDispatch}->{Unifi_DoAfterUpdate}[0];
|
||||||
|
delete $hash->{updateDispatch}->{Unifi_DoAfterUpdate};
|
||||||
|
}
|
||||||
|
$NextUpdateFn->($hash) if($NextUpdateFn);
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
sub Unifi_CONNECTED($@) {
|
||||||
|
my ($hash,$set) = @_;
|
||||||
|
|
||||||
|
if ($set) {
|
||||||
|
$hash->{CONNECTED} = $set;
|
||||||
|
RemoveInternalTimer($hash);
|
||||||
|
%{$hash->{updateDispatch}} = ();
|
||||||
|
if ($hash->{READINGS}->{state}->{VAL} ne $set) {
|
||||||
|
readingsSingleUpdate($hash,"state",$set,1);
|
||||||
|
}
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ($hash->{CONNECTED} eq 'disabled') {
|
||||||
|
return 'disabled';
|
||||||
|
}
|
||||||
|
elsif ($hash->{CONNECTED} eq 'connected') {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
sub Unifi_Urlencode($) {
|
sub Unifi_Urlencode($) {
|
||||||
my ($s) = @_;
|
my ($s) = @_;
|
||||||
$s =~ s/ /+/g;
|
$s =~ s/ /+/g;
|
||||||
@ -429,6 +512,7 @@ sub Unifi_Urldecode($) {
|
|||||||
$s =~ s/\+/ /g;
|
$s =~ s/\+/ /g;
|
||||||
return $s;
|
return $s;
|
||||||
}
|
}
|
||||||
|
sub Unifi_Whoami() { return (split('::',(caller(1))[3]))[1] || ''; }
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
### KNOWN RESPONSES ###
|
### KNOWN RESPONSES ###
|
||||||
@ -508,15 +592,14 @@ The device will be still connected, even it is in PowerSave-Mode. (In this mode
|
|||||||
Version must be specified if version is not 4. At the moment version 3 and 4 are supported.<br>
|
Version must be specified if version is not 4. At the moment version 3 and 4 are supported.<br>
|
||||||
default: 4</code><br>
|
default: 4</code><br>
|
||||||
</ul> <br>
|
</ul> <br>
|
||||||
<br>
|
|
||||||
Notes:<br>
|
|
||||||
<li>If you change <interval> while Unifi is running, the interval is changed only after the next automatic-update. <br>
|
|
||||||
To change it immediately, disable Unifi with "attr disable 1" and enable it again.</li>
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
<h4>Example</h4>
|
<h4>Examples</h4>
|
||||||
<ul>
|
<ul>
|
||||||
<code>define my_unifi_controller Unifi 192.168.1.15 443 user password</code><br>
|
<code>define my_unifi_controller Unifi 192.168.1.15 443 admin secret</code><br>
|
||||||
|
<br>
|
||||||
|
Or with optional parameters <interval>, <siteID> and <version>:<br>
|
||||||
|
<code>define my_unifi_controller Unifi 192.168.1.15 443 admin secret 30 default 3</code><br>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h4>Set</h4>
|
<h4>Set</h4>
|
||||||
@ -532,19 +615,26 @@ The device will be still connected, even it is in PowerSave-Mode. (In this mode
|
|||||||
|
|
||||||
<h4>Get</h4>
|
<h4>Get</h4>
|
||||||
<ul>
|
<ul>
|
||||||
<li><code>get <name> clientData <all|clientID></code><br>
|
<li><code>get <name> clientData <all|devAlias|clientID></code><br>
|
||||||
Show more details about clients.</li>
|
Show more details about clients.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
<h4>Attributes</h4>
|
<h4>Attributes</h4>
|
||||||
<ul>
|
<ul>
|
||||||
|
<li>attr devAlias<br>
|
||||||
|
Can be used to rename device names in the format DEVICEUUID:Aliasname.<br>
|
||||||
|
Separate using blank to rename multiple devices.<br>
|
||||||
|
Example:<code> attr unifi devAlias 5537d138e4b033c1832c5c84:iPhone-Claudiu</code></li>
|
||||||
|
<br>
|
||||||
<li>attr disable <1|0><br>
|
<li>attr disable <1|0><br>
|
||||||
With this attribute you can disable the whole module. <br>
|
With this attribute you can disable the whole module. <br>
|
||||||
If set to 1 the module will be stopped and no updates are performed.<br>
|
If set to 1 the module will be stopped and no updates are performed.<br>
|
||||||
If set to 0 the automatic updating will performed.</li>
|
If set to 0 the automatic updating will performed.</li>
|
||||||
|
<br>
|
||||||
<li>attr <a href="#verbose">verbose</a> 5<br>
|
<li>attr <a href="#verbose">verbose</a> 5<br>
|
||||||
This attribute will help you if something does not work as espected.</li>
|
This attribute will help you if something does not work as espected.</li>
|
||||||
|
<br>
|
||||||
<li><a href="#readingFnAttributes">readingFnAttributes</a></li>
|
<li><a href="#readingFnAttributes">readingFnAttributes</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user