mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-05-01 20:20:10 +00:00
74_Unifi: - Code Cleanup
- Preparing for future functions - Some small bug fixes git-svn-id: https://svn.fhem.de/fhem/trunk@9160 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
14d9008d6d
commit
b6f8484872
@ -1,11 +1,11 @@
|
||||
###############################################################################
|
||||
# $Id: 74_Unifi.pm 2015-08-27 06:00 - rapster - rapster at x0e dot de $
|
||||
# $Id: 74_Unifi.pm 2015-08-29 21:00 - rapster - rapster at x0e dot de $
|
||||
|
||||
package main;
|
||||
use strict;
|
||||
use warnings;
|
||||
use HttpUtils;
|
||||
use POSIX qw(strftime);
|
||||
use POSIX;
|
||||
use JSON qw(decode_json);
|
||||
###############################################################################
|
||||
|
||||
@ -16,7 +16,6 @@ sub Unifi_Initialize($$) {
|
||||
$hash->{SetFn} = "Unifi_Set";
|
||||
$hash->{GetFn} = "Unifi_Get";
|
||||
$hash->{AttrFn} = 'Unifi_Attr';
|
||||
$hash->{NOTIFYDEV} = "global";
|
||||
$hash->{NotifyFn} = "Unifi_Notify";
|
||||
$hash->{AttrList} = "disable:1,0 "
|
||||
."devAlias "
|
||||
@ -34,13 +33,14 @@ sub Unifi_Define($$) {
|
||||
return "Wrong syntax: <version> is not a valid number! Must be 3 or 4." if($a[8] && (!looks_like_number($a[8]) || $a[8] !~ /3|4/));
|
||||
|
||||
my $name = $a[0];
|
||||
my $oldLoginData = ($hash->{loginParams}) ? $hash->{loginParams}->{data}.$hash->{url} : 0;
|
||||
%$hash = ( %$hash,
|
||||
CONNECTED => $hash->{CONNECTED} || 0,
|
||||
url => "https://".$a[2].(($a[3] != 443) ? ':'.$a[3] : '').'/',
|
||||
interval => $a[6] || 30,
|
||||
siteID => $a[7] || 'default',
|
||||
version => $a[8] || 4,
|
||||
NOTIFYDEV => 'global',
|
||||
unifi => {
|
||||
CONNECTED => 0,
|
||||
interval => $a[6] || 30,
|
||||
version => $a[8] || 4,
|
||||
url => "https://".$a[2].(($a[3] == 443) ? '' : ':'.$a[3]).'/api/s/'.(($a[7]) ? $a[7] : 'default').'/',
|
||||
},
|
||||
);
|
||||
$hash->{httpParams} = {
|
||||
hash => $hash,
|
||||
@ -50,28 +50,16 @@ sub Unifi_Define($$) {
|
||||
ignoreredirects => 1,
|
||||
loglevel => 5,
|
||||
sslargs => { SSL_verify_mode => 'SSL_VERIFY_NONE' },
|
||||
header => ($hash->{version} == 3) ? undef : "Content-Type: application/json;charset=UTF-8"
|
||||
};
|
||||
$hash->{loginParams} = {
|
||||
%{$hash->{httpParams}},
|
||||
cookies => ($hash->{loginParams}->{cookies}) ? $hash->{loginParams}->{cookies} : '',
|
||||
callback => \&Unifi_Login_Receive
|
||||
};
|
||||
if($hash->{version} == 3) {
|
||||
$hash->{loginParams}->{url} = $hash->{url}."login";
|
||||
$hash->{loginParams}->{data} = "login=login&username=".Unifi_Urlencode($a[4])."&password=".Unifi_Urlencode($a[5]);
|
||||
if($hash->{unifi}->{version} == 3) {
|
||||
( $hash->{httpParams}->{loginUrl} = $hash->{unifi}->{url} ) =~ s/api\/s.+/login/;
|
||||
$hash->{httpParams}->{loginData} = "login=login&username=".$a[4]."&password=".$a[5];
|
||||
}else {
|
||||
$hash->{loginParams}->{url} = $hash->{url}."api/login";
|
||||
$hash->{loginParams}->{data} = "{'username':'".$a[4]."', 'password':'".$a[5]."'}";
|
||||
( $hash->{httpParams}->{loginUrl} = $hash->{unifi}->{url} ) =~ s/api\/s.+/api\/login/;
|
||||
$hash->{httpParams}->{loginData} = '{"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}) {
|
||||
$hash->{loginParams}->{cookies} = '';
|
||||
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->{unifi}->{url}, interval:$hash->{unifi}->{interval}, version:$hash->{unifi}->{version}";
|
||||
return undef;
|
||||
}
|
||||
###############################################################################
|
||||
@ -149,7 +137,7 @@ sub Unifi_Get($@) {
|
||||
my $clients = '';
|
||||
my $devAliases = AttrVal($name,"devAlias",0);
|
||||
for (keys %{$hash->{clients}}) { # Replace ID's with Aliases
|
||||
if ( $devAliases && $devAliases =~ /$_:(.+?)(\s|$)/
|
||||
if ( ($devAliases && $devAliases =~ /$_:(.+?)(\s|$)/)
|
||||
|| ($devAliases && defined $hash->{clients}->{$_}->{name} && $devAliases =~ /$hash->{clients}->{$_}->{name}:(.+?)(\s|$)/)
|
||||
|| ($devAliases && defined $hash->{clients}->{$_}->{hostname} && $devAliases =~ /$hash->{clients}->{$_}->{hostname}:(.+?)(\s|$)/)
|
||||
|| (defined $hash->{clients}->{$_}->{name} && $hash->{clients}->{$_}->{name} =~ /^([\w\.\-]+)$/)
|
||||
@ -166,7 +154,7 @@ sub Unifi_Get($@) {
|
||||
elsif ($getName eq 'clientData' && $clients) {
|
||||
if($getVal && $getVal ne 'all') { # Make ID from Alias
|
||||
for (keys %{$hash->{clients}}) {
|
||||
if ( $devAliases && $devAliases =~ /$_:$getVal/
|
||||
if ( ($devAliases && $devAliases =~ /$_:$getVal/)
|
||||
|| ($devAliases && defined $hash->{clients}->{$_}->{name} && $devAliases =~ /$hash->{clients}->{$_}->{name}:$getVal/)
|
||||
|| ($devAliases && defined $hash->{clients}->{$_}->{hostname} && $devAliases =~ /$hash->{clients}->{$_}->{hostname}:$getVal/)
|
||||
|| (defined $hash->{clients}->{$_}->{name} && $hash->{clients}->{$_}->{name} eq $getVal)
|
||||
@ -251,13 +239,17 @@ sub Unifi_DoUpdate($@) {
|
||||
}
|
||||
|
||||
if (Unifi_CONNECTED($hash)) {
|
||||
$hash->{unifi}->{updateStartTime} = time();
|
||||
$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_GetAccesspoints_Send => [\&Unifi_GetAccesspoints_Send,'Unifi_GetAccesspoints_Receive',\&Unifi_GetAccesspoints_Receive],
|
||||
Unifi_GetWlans_Send => [\&Unifi_GetWlans_Send,'Unifi_GetWlans_Receive',\&Unifi_GetWlans_Receive],
|
||||
Unifi_GetUnarchivedAlerts_Send => [\&Unifi_GetUnarchivedAlerts_Send,'Unifi_GetUnarchivedAlerts_Receive',\&Unifi_GetUnarchivedAlerts_Receive],
|
||||
Unifi_GetEvents_Send => [\&Unifi_GetEvents_Send,'Unifi_GetEvents_Receive',\&Unifi_GetEvents_Receive],
|
||||
Unifi_GetWlanGroups_Send => [\&Unifi_GetWlanGroups_Send,'Unifi_GetWlanGroups_Receive',\&Unifi_GetWlanGroups_Receive],
|
||||
Unifi_ProcessUpdate => [\&Unifi_ProcessUpdate,''],
|
||||
};
|
||||
Unifi_NextUpdateFn($hash,$self);
|
||||
InternalTimer(time()+$hash->{interval}, 'Unifi_DoUpdate', $hash, 0);
|
||||
}
|
||||
else {
|
||||
Unifi_CONNECTED($hash,'disconnected');
|
||||
@ -272,7 +264,12 @@ sub Unifi_Login_Send($) {
|
||||
my ($name,$self) = ($hash->{NAME},Unifi_Whoami());
|
||||
Log3 $name, 5, "$name ($self) - executed.";
|
||||
|
||||
HttpUtils_NonblockingGet($hash->{loginParams});
|
||||
HttpUtils_NonblockingGet( {
|
||||
%{$hash->{httpParams}},
|
||||
url => $hash->{httpParams}->{loginUrl},
|
||||
data => $hash->{httpParams}->{loginData},
|
||||
callback => \&Unifi_Login_Receive
|
||||
} );
|
||||
return undef;
|
||||
}
|
||||
sub Unifi_Login_Receive($) {
|
||||
@ -283,41 +280,34 @@ sub Unifi_Login_Receive($) {
|
||||
if ($err ne "") {
|
||||
Log3 $name, 5, "$name ($self) - Error while requesting ".$param->{url}." - $err";
|
||||
}
|
||||
elsif ($data ne "" && $hash->{version} == 3) {
|
||||
elsif ($data ne "" && $hash->{unifi}->{version} == 3) {
|
||||
if ($data =~ /Invalid username or password/si) {
|
||||
Log3 $name, 1, "$name ($self) - Login Failed! Invalid username or password!";
|
||||
} else {
|
||||
Log3 $name, 5, "$name ($self) - Login Failed! Version 3 should not deliver data on successfull login.";
|
||||
}
|
||||
}
|
||||
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($data ne "") {
|
||||
eval {
|
||||
$data = decode_json($data);
|
||||
1;
|
||||
} or do {
|
||||
my $e = $@;
|
||||
$data->{meta}->{rc} = 'error';
|
||||
$data->{meta}->{msg} = 'Unifi.FailedToDecodeJSON - $e';
|
||||
};
|
||||
}
|
||||
if ($hash->{version} == 3 || $data->{meta}->{rc} eq "ok") { # v3 has no rc-state
|
||||
elsif ($data ne "" || $hash->{unifi}->{version} == 3) { # v3 Login is empty if login is successfully
|
||||
if ($param->{code} == 200 || $param->{code} == 400 || $param->{code} == 401 || ($hash->{unifi}->{version} == 3 && ($param->{code} == 302 || $param->{code} == 200))) {
|
||||
eval { $data = decode_json($data); 1; } or do { $data = { meta => {rc => 'error.decode_json', msg => $@} }; };
|
||||
|
||||
if ($hash->{unifi}->{version} == 3 || $data->{meta}->{rc} eq "ok") { # v3 has no rc-state
|
||||
Log3 $name, 5, "$name ($self) - state=ok || version=3";
|
||||
$param->{cookies} = '';
|
||||
$hash->{httpParams}->{header} = '';
|
||||
for (split("\r\n",$param->{httpheader})) {
|
||||
if(/^Set-Cookie/) {
|
||||
s/Set-Cookie:\s(.*?);.*/Cookie: $1/;
|
||||
$param->{cookies} .= $_.(($hash->{version} == 3) ? '' : '\r\n'); #v3 has only one cookie and no header at all
|
||||
$hash->{httpParams}->{header} .= $_.'\r\n';
|
||||
}
|
||||
}
|
||||
|
||||
if($param->{cookies} ne '') {
|
||||
Log3 $name, 5, "$name ($self) - Login successfully! $param->{cookies}";
|
||||
if($hash->{httpParams}->{header} ne '') {
|
||||
$hash->{httpParams}->{header} =~ s/\\r\\n$//;
|
||||
Log3 $name, 5, "$name ($self) - Login successfully! $hash->{httpParams}->{header}";
|
||||
Unifi_CONNECTED($hash,'connected');
|
||||
Unifi_DoUpdate($hash);
|
||||
return undef;
|
||||
} else {
|
||||
$hash->{httpParams}->{header} = undef;
|
||||
Log3 $name, 5, "$name ($self) - Something went wrong, login seems ok but no cookies received.";
|
||||
}
|
||||
}
|
||||
@ -336,7 +326,7 @@ sub Unifi_Login_Receive($) {
|
||||
} else {
|
||||
Log3 $name, 5, "$name ($self) - Login Failed (without msg)! - state:'$data->{meta}->{rc}'";
|
||||
}
|
||||
$param->{cookies} = '';
|
||||
$hash->{httpParams}->{header} = undef;
|
||||
}
|
||||
} else {
|
||||
Log3 $name, 5, "$name ($self) - Failed with HTTP Code $param->{code}!";
|
||||
@ -346,7 +336,7 @@ sub Unifi_Login_Receive($) {
|
||||
}
|
||||
Log3 $name, 5, "$name ($self) - Connect/Login to Unifi-Controller failed. Will try again after interval...";
|
||||
Unifi_CONNECTED($hash,'disconnected');
|
||||
InternalTimer(time()+$hash->{interval}, 'Unifi_Login_Send', $hash, 0);
|
||||
InternalTimer(time()+$hash->{unifi}->{interval}, 'Unifi_Login_Send', $hash, 0);
|
||||
return undef;
|
||||
}
|
||||
###############################################################################
|
||||
@ -356,13 +346,11 @@ sub Unifi_GetClients_Send($) {
|
||||
my ($name,$self) = ($hash->{NAME},Unifi_Whoami());
|
||||
Log3 $name, 5, "$name ($self) - executed.";
|
||||
|
||||
my $param = {
|
||||
%{$hash->{httpParams}},
|
||||
url => $hash->{url}."api/s/$hash->{siteID}/stat/sta",
|
||||
header => ($hash->{version} == 3) ? $hash->{loginParams}->{cookies} : $hash->{loginParams}->{cookies}.$hash->{httpParams}->{header},
|
||||
HttpUtils_NonblockingGet( {
|
||||
%{$hash->{httpParams}},
|
||||
url => $hash->{unifi}->{url}."stat/sta",
|
||||
callback => $hash->{updateDispatch}->{$self}[2]
|
||||
};
|
||||
HttpUtils_NonblockingGet($param);
|
||||
} );
|
||||
return undef;
|
||||
}
|
||||
sub Unifi_GetClients_Receive($) {
|
||||
@ -371,118 +359,281 @@ sub Unifi_GetClients_Receive($) {
|
||||
Log3 $name, 5, "$name ($self) - executed.";
|
||||
|
||||
if ($err ne "") {
|
||||
Log3 $name, 5, "$name ($self) - Error while requesting ".$param->{url}." - $err";
|
||||
Unifi_ReceiveFailure($hash,{rc => 'Error while requesting', msg => $param->{url}." - $err"});
|
||||
}
|
||||
elsif ($data ne "") {
|
||||
if ($param->{code} == 200 || $param->{code} == 400 || $param->{code} == 401) {
|
||||
eval {
|
||||
$data = decode_json($data);
|
||||
1;
|
||||
} or do {
|
||||
my $e = $@;
|
||||
$data->{meta}->{rc} = 'error';
|
||||
$data->{meta}->{msg} = 'Unifi.FailedToDecodeJSON - $e';
|
||||
};
|
||||
eval { $data = decode_json($data); 1; } or do { $data = { meta => {rc => 'error.decode_json', msg => $@} }; };
|
||||
|
||||
if ($data->{meta}->{rc} eq "ok") {
|
||||
Log3 $name, 5, "$name ($self) - state:'$data->{meta}->{rc}'";
|
||||
|
||||
readingsBeginUpdate($hash);
|
||||
my $devAliases = AttrVal($name,"devAlias",0);
|
||||
my $connectedClientIDs = {};
|
||||
my $i = 1;
|
||||
my $clientName;
|
||||
$hash->{unifi}->{connectedClients} = undef;
|
||||
for my $h (@{$data->{data}}) {
|
||||
$clientName = $h->{user_id};
|
||||
if ( $devAliases && $devAliases =~ /$clientName:(.+?)(\s|$)/
|
||||
|| ($devAliases && defined $h->{name} && $devAliases =~ /$h->{name}:(.+?)(\s|$)/)
|
||||
|| ($devAliases && defined $h->{hostname} && $devAliases =~ /$h->{hostname}:(.+?)(\s|$)/)
|
||||
|| (defined $h->{name} && $h->{name} =~ /^([\w\.\-]+)$/)
|
||||
|| (defined $h->{hostname} && $h->{hostname} =~ /^([\w\.\-]+)$/)
|
||||
) {
|
||||
$clientName = $1;
|
||||
}
|
||||
|
||||
$hash->{clients}->{$h->{user_id}} = $h;
|
||||
$connectedClientIDs->{$h->{user_id}} = 1;
|
||||
readingsBulkUpdate($hash,$clientName."_hostname",(defined $h->{hostname}) ? $h->{hostname} : (defined $h->{ip}) ? $h->{ip} : 'Unknown');
|
||||
readingsBulkUpdate($hash,$clientName."_last_seen",strftime "%Y-%m-%d %H:%M:%S",localtime($h->{last_seen}));
|
||||
readingsBulkUpdate($hash,$clientName."_uptime",$h->{uptime});
|
||||
readingsBulkUpdate($hash,$clientName,'connected');
|
||||
}
|
||||
for my $clientID (keys %{$hash->{clients}}) {
|
||||
if (!defined($connectedClientIDs->{$clientID}) && $hash->{READINGS}->{$clientID}->{VAL} ne 'disconnected') {
|
||||
Log3 $name, 5, "$name ($self) - Client '$clientID' previously connected is now disconnected.";
|
||||
if ( $devAliases && $devAliases =~ /$clientID:(.+?)(\s|$)/
|
||||
|| ($devAliases && defined $hash->{clients}->{$clientID}->{name} && $devAliases =~ /$hash->{clients}->{$clientID}->{name}:(.+?)(\s|$)/)
|
||||
|| ($devAliases && defined $hash->{clients}->{$clientID}->{hostname} && $devAliases =~ /$hash->{clients}->{$clientID}->{hostname}:(.+?)(\s|$)/)
|
||||
|| (defined $hash->{clients}->{$clientID}->{name} && $hash->{clients}->{$clientID}->{name} =~ /^([\w\.\-]+)$/)
|
||||
|| (defined $hash->{clients}->{$clientID}->{hostname} && $hash->{clients}->{$clientID}->{hostname} =~ /^([\w\.\-]+)$/)
|
||||
) {
|
||||
$clientID = $1;
|
||||
}
|
||||
readingsBulkUpdate($hash,$clientID,'disconnected') if($hash->{READINGS}->{$clientID}->{VAL} ne 'disconnected');
|
||||
}
|
||||
}
|
||||
readingsEndUpdate($hash,1);
|
||||
}
|
||||
else {
|
||||
if (defined($data->{meta}->{msg})) {
|
||||
if ($data->{meta}->{msg} eq 'api.err.LoginRequired') {
|
||||
Log3 $name, 5, "$name ($self) - LoginRequired detected...";
|
||||
if(Unifi_CONNECTED($hash)) {
|
||||
Log3 $name, 5, "$name ($self) - I am the first who detected LoginRequired. Do re-login...";
|
||||
Unifi_CONNECTED($hash,'disconnected');
|
||||
Unifi_DoUpdate($hash);
|
||||
return undef;
|
||||
}
|
||||
}
|
||||
elsif ($data->{meta}->{msg} eq "api.err.NoSiteContext" || ($hash->{version} == 3 && $data->{meta}->{msg} eq "api.err.InvalidObject")) {
|
||||
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."
|
||||
." Try to modify your definition with <sideID> = default.";
|
||||
}
|
||||
else {
|
||||
Log3 $name, 5, "$name ($self) - Failed! - state:'$data->{meta}->{rc}' - msg:'$data->{meta}->{msg}'";
|
||||
}
|
||||
} else {
|
||||
Log3 $name, 5, "$name ($self) - Failed (without message)! - state:'$data->{meta}->{rc}'";
|
||||
$hash->{unifi}->{connectedClients}->{$h->{_id}} = 1;
|
||||
$hash->{clients}->{$h->{_id}} = $h;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
Log3 $name, 5, "$name ($self) - Failed with HTTP Code $param->{code}.";
|
||||
else { Unifi_ReceiveFailure($hash,$data->{meta}); }
|
||||
} else {
|
||||
Unifi_ReceiveFailure($hash,{rc => $param->{code}, msg => "Failed with HTTP Code $param->{code}."});
|
||||
}
|
||||
}
|
||||
Unifi_NextUpdateFn($hash,$self);
|
||||
return undef;
|
||||
}
|
||||
###############################################################################
|
||||
|
||||
sub Unifi_GetAnother_Send($) {
|
||||
sub Unifi_GetWlans_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);
|
||||
HttpUtils_NonblockingGet( {
|
||||
%{$hash->{httpParams}},
|
||||
url => $hash->{unifi}->{url}."list/wlanconf",
|
||||
callback => $hash->{updateDispatch}->{$self}[2],
|
||||
} );
|
||||
return undef;
|
||||
}
|
||||
sub Unifi_GetAnother_Receive($) {
|
||||
sub Unifi_GetWlans_Receive($) {
|
||||
my ($param, $err, $data) = @_;
|
||||
my ($name,$self,$hash) = ($param->{hash}->{NAME},Unifi_Whoami(),$param->{hash});
|
||||
Log3 $hash->{NAME}, 5, "$hash->{NAME} ($self) - executed.";
|
||||
Log3 $name, 5, "$name ($self) - executed.";
|
||||
|
||||
# Do
|
||||
if ($err ne "") {
|
||||
Unifi_ReceiveFailure($hash,{rc => 'Error while requesting', msg => $param->{url}." - $err"});
|
||||
}
|
||||
elsif ($data ne "") {
|
||||
if ($param->{code} == 200 || $param->{code} == 400 || $param->{code} == 401) {
|
||||
eval { $data = decode_json($data); 1; } or do { $data = { meta => {rc => 'error.decode_json', msg => $@} }; };
|
||||
|
||||
if ($data->{meta}->{rc} eq "ok") {
|
||||
Log3 $name, 5, "$name ($self) - state:'$data->{meta}->{rc}'";
|
||||
|
||||
for my $h (@{$data->{data}}) {
|
||||
$hash->{wlans}->{$h->{_id}} = $h;
|
||||
$hash->{wlans}->{$h->{_id}}->{x_passphrase} = '***'; # Don't show passphrase in list
|
||||
}
|
||||
}
|
||||
else { Unifi_ReceiveFailure($hash,$data->{meta}); }
|
||||
} else {
|
||||
Unifi_ReceiveFailure($hash,{rc => $param->{code}, msg => "Failed with HTTP Code $param->{code}."});
|
||||
}
|
||||
}
|
||||
|
||||
Unifi_NextUpdateFn($hash,$self);
|
||||
return undef;
|
||||
}
|
||||
###############################################################################
|
||||
sub Unifi_GetWlanGroups_Send($) {
|
||||
my ($hash) = @_;
|
||||
my ($name,$self) = ($hash->{NAME},Unifi_Whoami());
|
||||
Log3 $name, 5, "$name ($self) - executed.";
|
||||
|
||||
HttpUtils_NonblockingGet( {
|
||||
%{$hash->{httpParams}},
|
||||
url => $hash->{unifi}->{url}."list/wlangroup",
|
||||
callback => $hash->{updateDispatch}->{$self}[2],
|
||||
} );
|
||||
return undef;
|
||||
}
|
||||
sub Unifi_GetWlanGroups_Receive($) {
|
||||
my ($param, $err, $data) = @_;
|
||||
my ($name,$self,$hash) = ($param->{hash}->{NAME},Unifi_Whoami(),$param->{hash});
|
||||
Log3 $name, 5, "$name ($self) - executed.";
|
||||
|
||||
if ($err ne "") {
|
||||
Unifi_ReceiveFailure($hash,{rc => 'Error while requesting', msg => $param->{url}." - $err"});
|
||||
}
|
||||
elsif ($data ne "") {
|
||||
if ($param->{code} == 200 || $param->{code} == 400 || $param->{code} == 401) {
|
||||
eval { $data = decode_json($data); 1; } or do { $data = { meta => {rc => 'error.decode_json', msg => $@} }; };
|
||||
|
||||
if ($data->{meta}->{rc} eq "ok") {
|
||||
Log3 $name, 5, "$name ($self) - state:'$data->{meta}->{rc}'";
|
||||
|
||||
for my $h (@{$data->{data}}) {
|
||||
$hash->{wlangroups}->{$h->{_id}} = $h;
|
||||
}
|
||||
}
|
||||
else { Unifi_ReceiveFailure($hash,$data->{meta}); }
|
||||
} else {
|
||||
Unifi_ReceiveFailure($hash,{rc => $param->{code}, msg => "Failed with HTTP Code $param->{code}."});
|
||||
}
|
||||
}
|
||||
|
||||
Unifi_NextUpdateFn($hash,$self);
|
||||
return undef;
|
||||
}
|
||||
###############################################################################
|
||||
sub Unifi_GetUnarchivedAlerts_Send($) {
|
||||
my ($hash) = @_;
|
||||
my ($name,$self) = ($hash->{NAME},Unifi_Whoami());
|
||||
Log3 $name, 5, "$name ($self) - executed.";
|
||||
|
||||
HttpUtils_NonblockingGet( {
|
||||
%{$hash->{httpParams}},
|
||||
url => $hash->{unifi}->{url}."list/alarm",
|
||||
callback => $hash->{updateDispatch}->{$self}[2],
|
||||
data => "{'_sort': '-time', 'archived': False}",
|
||||
} );
|
||||
return undef;
|
||||
}
|
||||
sub Unifi_GetUnarchivedAlerts_Receive($) {
|
||||
my ($param, $err, $data) = @_;
|
||||
my ($name,$self,$hash) = ($param->{hash}->{NAME},Unifi_Whoami(),$param->{hash});
|
||||
Log3 $name, 5, "$name ($self) - executed.";
|
||||
|
||||
if ($err ne "") {
|
||||
Unifi_ReceiveFailure($hash,{rc => 'Error while requesting', msg => $param->{url}." - $err"});
|
||||
}
|
||||
elsif ($data ne "") {
|
||||
if ($param->{code} == 200 || $param->{code} == 400 || $param->{code} == 401) {
|
||||
eval { $data = decode_json($data); 1; } or do { $data = { meta => {rc => 'error.decode_json', msg => $@} }; };
|
||||
|
||||
if ($data->{meta}->{rc} eq "ok") {
|
||||
Log3 $name, 5, "$name ($self) - state:'$data->{meta}->{rc}'";
|
||||
|
||||
for my $h (@{$data->{data}}) {
|
||||
$hash->{alerts_unarchived}->{$h->{_id}} = $h;
|
||||
}
|
||||
}
|
||||
else { Unifi_ReceiveFailure($hash,$data->{meta}); }
|
||||
} else {
|
||||
Unifi_ReceiveFailure($hash,{rc => $param->{code}, msg => "Failed with HTTP Code $param->{code}."});
|
||||
}
|
||||
}
|
||||
|
||||
Unifi_NextUpdateFn($hash,$self);
|
||||
return undef;
|
||||
}
|
||||
###############################################################################
|
||||
sub Unifi_GetEvents_Send($) {
|
||||
my ($hash) = @_;
|
||||
my ($name,$self) = ($hash->{NAME},Unifi_Whoami());
|
||||
Log3 $name, 5, "$name ($self) - executed.";
|
||||
|
||||
HttpUtils_NonblockingGet( {
|
||||
%{$hash->{httpParams}},
|
||||
url => $hash->{unifi}->{url}."stat/event",
|
||||
callback => $hash->{updateDispatch}->{$self}[2],
|
||||
data => "{'within': 24}", # last 24 hours
|
||||
} );
|
||||
return undef;
|
||||
}
|
||||
sub Unifi_GetEvents_Receive($) {
|
||||
my ($param, $err, $data) = @_;
|
||||
my ($name,$self,$hash) = ($param->{hash}->{NAME},Unifi_Whoami(),$param->{hash});
|
||||
Log3 $name, 5, "$name ($self) - executed.";
|
||||
|
||||
if ($err ne "") {
|
||||
Unifi_ReceiveFailure($hash,{rc => 'Error while requesting', msg => $param->{url}." - $err"});
|
||||
}
|
||||
elsif ($data ne "") {
|
||||
if ($param->{code} == 200 || $param->{code} == 400 || $param->{code} == 401) {
|
||||
eval { $data = decode_json($data); 1; } or do { $data = { meta => {rc => 'error.decode_json', msg => $@} }; };
|
||||
|
||||
if ($data->{meta}->{rc} eq "ok") {
|
||||
Log3 $name, 5, "$name ($self) - state:'$data->{meta}->{rc}'";
|
||||
|
||||
for my $h (@{$data->{data}}) {
|
||||
$hash->{events}->{$h->{_id}} = $h;
|
||||
}
|
||||
}
|
||||
else { Unifi_ReceiveFailure($hash,$data->{meta}); }
|
||||
} else {
|
||||
Unifi_ReceiveFailure($hash,{rc => $param->{code}, msg => "Failed with HTTP Code $param->{code}."});
|
||||
}
|
||||
}
|
||||
|
||||
Unifi_NextUpdateFn($hash,$self);
|
||||
return undef;
|
||||
}
|
||||
###############################################################################
|
||||
sub Unifi_GetAccesspoints_Send($) {
|
||||
my ($hash) = @_;
|
||||
my ($name,$self) = ($hash->{NAME},Unifi_Whoami());
|
||||
Log3 $name, 5, "$name ($self) - executed.";
|
||||
|
||||
HttpUtils_NonblockingGet( {
|
||||
%{$hash->{httpParams}},
|
||||
url => $hash->{unifi}->{url}."stat/device",
|
||||
callback => $hash->{updateDispatch}->{$self}[2],
|
||||
data => "{'_depth': 2, 'test': 0}",
|
||||
} );
|
||||
return undef;
|
||||
}
|
||||
sub Unifi_GetAccesspoints_Receive($) {
|
||||
my ($param, $err, $data) = @_;
|
||||
my ($name,$self,$hash) = ($param->{hash}->{NAME},Unifi_Whoami(),$param->{hash});
|
||||
Log3 $name, 5, "$name ($self) - executed.";
|
||||
|
||||
if ($err ne "") {
|
||||
Unifi_ReceiveFailure($hash,{rc => 'Error while requesting', msg => $param->{url}." - $err"});
|
||||
}
|
||||
elsif ($data ne "") {
|
||||
if ($param->{code} == 200 || $param->{code} == 400 || $param->{code} == 401) {
|
||||
eval { $data = decode_json($data); 1; } or do { $data = { meta => {rc => 'error.decode_json', msg => $@} }; };
|
||||
|
||||
if ($data->{meta}->{rc} eq "ok") {
|
||||
Log3 $name, 5, "$name ($self) - state:'$data->{meta}->{rc}'";
|
||||
|
||||
for my $h (@{$data->{data}}) {
|
||||
$hash->{accespoints}->{$h->{_id}} = $h;
|
||||
}
|
||||
}
|
||||
else { Unifi_ReceiveFailure($hash,$data->{meta}); }
|
||||
} else {
|
||||
Unifi_ReceiveFailure($hash,{rc => $param->{code}, msg => "Failed with HTTP Code $param->{code}."});
|
||||
}
|
||||
}
|
||||
|
||||
Unifi_NextUpdateFn($hash,$self);
|
||||
return undef;
|
||||
}
|
||||
###############################################################################
|
||||
|
||||
sub Unifi_DoAfterUpdate($) {
|
||||
sub Unifi_ProcessUpdate($) {
|
||||
my ($hash) = @_;
|
||||
my ($name,$self) = ($hash->{NAME},Unifi_Whoami());
|
||||
Log3 $name, 5, "$name ($self) - executed.";
|
||||
Log3 $name, 5, "$name ($self) - executed after ".sprintf('%.4f',time() - $hash->{unifi}->{updateStartTime})." seconds.";
|
||||
|
||||
readingsBeginUpdate($hash);
|
||||
#'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''#
|
||||
|
||||
### WLAN Client Readings
|
||||
my ($clientName,$clientRef);
|
||||
my $devAliases = AttrVal($name,"devAlias",0);
|
||||
for my $clientID (keys %{$hash->{clients}}) {
|
||||
$clientRef = $hash->{clients}->{$clientID};
|
||||
|
||||
if ( ($devAliases && $devAliases =~ /$clientID:(.+?)(\s|$)/)
|
||||
|| ($devAliases && defined $clientRef->{name} && $devAliases =~ /$clientRef->{name}:(.+?)(\s|$)/)
|
||||
|| ($devAliases && defined $clientRef->{hostname} && $devAliases =~ /$clientRef->{hostname}:(.+?)(\s|$)/)
|
||||
|| (defined $clientRef->{name} && $clientRef->{name} =~ /^([\w\.\-]+)$/)
|
||||
|| (defined $clientRef->{hostname} && $clientRef->{hostname} =~ /^([\w\.\-]+)$/)
|
||||
) {
|
||||
$clientName = $1;
|
||||
} else { $clientName = $clientID; }
|
||||
|
||||
if (defined $hash->{unifi}->{connectedClients}->{$clientID}) {
|
||||
readingsBulkUpdate($hash,$clientName."_hostname",(defined $clientRef->{hostname}) ? $clientRef->{hostname} : (defined $clientRef->{ip}) ? $clientRef->{ip} : 'Unknown');
|
||||
readingsBulkUpdate($hash,$clientName."_last_seen",strftime "%Y-%m-%d %H:%M:%S",localtime($clientRef->{last_seen}));
|
||||
readingsBulkUpdate($hash,$clientName."_uptime",$clientRef->{uptime});
|
||||
readingsBulkUpdate($hash,$clientName,'connected');
|
||||
}
|
||||
elsif (defined($hash->{READINGS}->{$clientName}) && $hash->{READINGS}->{$clientName}->{VAL} ne 'disconnected') {
|
||||
Log3 $name, 5, "$name ($self) - Client '$clientName' previously connected is now disconnected.";
|
||||
readingsBulkUpdate($hash,$clientName,'disconnected');
|
||||
}
|
||||
}
|
||||
### Other...
|
||||
|
||||
#'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''#
|
||||
readingsEndUpdate($hash,1);
|
||||
|
||||
Log3 $name, 5, "$name ($self) - finished after ".sprintf('%.4f',time() - $hash->{unifi}->{updateStartTime})." seconds.";
|
||||
InternalTimer(time()+$hash->{unifi}->{interval}, 'Unifi_DoUpdate', $hash, 0);
|
||||
|
||||
return undef;
|
||||
}
|
||||
@ -495,36 +646,64 @@ sub Unifi_NextUpdateFn($$) {
|
||||
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') {
|
||||
} elsif(!$NextUpdateFn && $hash->{updateDispatch}->{$_}[0] && $_ ne 'Unifi_ProcessUpdate') {
|
||||
$NextUpdateFn = $hash->{updateDispatch}->{$_}[0];
|
||||
}
|
||||
}
|
||||
if (!$NextUpdateFn && $hash->{updateDispatch}->{Unifi_DoAfterUpdate}[0]) {
|
||||
$NextUpdateFn = $hash->{updateDispatch}->{Unifi_DoAfterUpdate}[0];
|
||||
delete $hash->{updateDispatch}->{Unifi_DoAfterUpdate};
|
||||
if (!$NextUpdateFn && $hash->{updateDispatch}->{Unifi_ProcessUpdate}[0]) {
|
||||
$NextUpdateFn = $hash->{updateDispatch}->{Unifi_ProcessUpdate}[0];
|
||||
delete $hash->{updateDispatch}->{Unifi_ProcessUpdate};
|
||||
}
|
||||
$NextUpdateFn->($hash) if($NextUpdateFn);
|
||||
return undef;
|
||||
}
|
||||
###############################################################################
|
||||
|
||||
sub Unifi_ReceiveFailure($$$) {
|
||||
my ($hash,$meta) = @_;
|
||||
my ($name,$self) = ($hash->{NAME},Unifi_Whowasi());
|
||||
|
||||
if (defined $meta->{msg}) {
|
||||
if ($meta->{msg} eq 'api.err.LoginRequired') {
|
||||
Log3 $name, 5, "$name ($self) - LoginRequired detected...";
|
||||
if(Unifi_CONNECTED($hash)) {
|
||||
Log3 $name, 5, "$name ($self) - I am the first who detected LoginRequired. Do re-login...";
|
||||
Unifi_CONNECTED($hash,'disconnected');
|
||||
Unifi_DoUpdate($hash);
|
||||
return undef;
|
||||
}
|
||||
}
|
||||
elsif ($meta->{msg} eq "api.err.NoSiteContext" || ($hash->{unifi}->{version} == 3 && $meta->{msg} eq "api.err.InvalidObject")) {
|
||||
Log3 $name, 1, "$name ($self) - Failed! - state:'$meta->{rc}' - msg:'$meta->{msg}'"
|
||||
." - This error indicates that the <siteID> in your definition is wrong."
|
||||
." Try to modify your definition with <sideID> = default.";
|
||||
}
|
||||
else {
|
||||
Log3 $name, 5, "$name ($self) - Failed! - state:'$meta->{rc}' - msg:'$meta->{msg}'";
|
||||
}
|
||||
} else {
|
||||
Log3 $name, 5, "$name ($self) - Failed (without message)! - state:'$meta->{rc}'";
|
||||
}
|
||||
}
|
||||
###############################################################################
|
||||
|
||||
sub Unifi_CONNECTED($@) {
|
||||
my ($hash,$set) = @_;
|
||||
|
||||
if ($set) {
|
||||
$hash->{CONNECTED} = $set;
|
||||
$hash->{unifi}->{CONNECTED} = $set;
|
||||
RemoveInternalTimer($hash);
|
||||
%{$hash->{updateDispatch}} = ();
|
||||
if ($hash->{READINGS}->{state}->{VAL} ne $set) {
|
||||
if (!defined($hash->{READINGS}->{state}->{VAL}) || $hash->{READINGS}->{state}->{VAL} ne $set) {
|
||||
readingsSingleUpdate($hash,"state",$set,1);
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
else {
|
||||
if ($hash->{CONNECTED} eq 'disabled') {
|
||||
if ($hash->{unifi}->{CONNECTED} eq 'disabled') {
|
||||
return 'disabled';
|
||||
}
|
||||
elsif ($hash->{CONNECTED} eq 'connected') {
|
||||
elsif ($hash->{unifi}->{CONNECTED} eq 'connected') {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
@ -533,24 +712,15 @@ sub Unifi_CONNECTED($@) {
|
||||
}
|
||||
###############################################################################
|
||||
|
||||
sub Unifi_Urlencode($) {
|
||||
my ($s) = @_;
|
||||
$s =~ s/ /+/g;
|
||||
$s =~ s/([^A-Za-z0-9\+-])/sprintf("%%%02X", ord($1))/seg;
|
||||
return $s;
|
||||
}
|
||||
sub Unifi_Urldecode($) {
|
||||
my ($s) = @_;
|
||||
$s =~ s/\%([A-Fa-f0-9]{2})/pack('C', hex($1))/seg;
|
||||
$s =~ s/\+/ /g;
|
||||
return $s;
|
||||
}
|
||||
sub Unifi_Whoami() { return (split('::',(caller(1))[3]))[1] || ''; }
|
||||
sub Unifi_Whowasi() { return (split('::',(caller(2))[3]))[1] || ''; }
|
||||
###############################################################################
|
||||
|
||||
### KNOWN RESPONSES ###
|
||||
# { "data" : [ ] , "meta" : { "msg" : "api.err.Invalid" , "rc" : "error"}} //Invalid Login credentials in v4, in v3 the login-html-page is returned
|
||||
# { "data" : [ ] , "meta" : { "rc" : "ok"}}
|
||||
# "api.err.NoPermission"
|
||||
# { "data" : [ ] , "meta" : { "msg" : "api.err.InvalidArgs" , "rc" : "error"}} //posted data is not ok
|
||||
# { "data" : [ ] , "meta" : { "msg" : "api.err.InvalidObject" , "rc" : "error"}} //Wrong siteID in v3
|
||||
# { "data" : [ ] , "meta" : { "msg" : "api.err.NoSiteContext" , "rc" : "error"}} //Wrong siteID in v4
|
||||
# { "data" : [ ] , "meta" : { "msg" : "api.err.LoginRequired" , "rc" : "error"}} //Login Required / cookie is invalid / While Login: Unifi v4 is used wiith controller v3
|
||||
@ -648,7 +818,7 @@ The device will be still connected, even it is in PowerSave-Mode. (In this mode
|
||||
|
||||
<h4>Get</h4>
|
||||
<ul>
|
||||
<li><code>get <name> clientData <all|user_id|controllerAlias|hostname|devAlias></code><br>
|
||||
<li><code>get <name> clientData <all|_id|controllerAlias|hostname|devAlias></code><br>
|
||||
Show more details about clients.</li>
|
||||
</ul>
|
||||
|
||||
@ -656,9 +826,9 @@ The device will be still connected, even it is in PowerSave-Mode. (In this mode
|
||||
<h4>Attributes</h4>
|
||||
<ul>
|
||||
<li>attr devAlias<br>
|
||||
Can be used to rename device names in the format <code><user_id|controllerAlias|hostname>:Aliasname.</code><br>
|
||||
Can be used to rename device names in the format <code><_id|controllerAlias|hostname>:Aliasname.</code><br>
|
||||
Separate using blank to rename multiple devices.<br>
|
||||
Example (user_id):<code> attr unifi devAlias 5537d138e4b033c1832c5c84:iPhone-Claudiu</code><br>
|
||||
Example (_id):<code> attr unifi devAlias 5537d138e4b033c1832c5c84:iPhone-Claudiu</code><br>
|
||||
Example (controllerAlias):<code> attr unifi devAlias iPhoneControllerAlias:iPhone-Claudiu</code><br>
|
||||
Example (hostname):<code> attr unifi devAlias iphone:iPhone-Claudiu</code><br></li>
|
||||
<br>
|
||||
|
Loading…
x
Reference in New Issue
Block a user