2018-06-10 15:42:35 +00:00
##############################################################################
2015-09-01 20:57:16 +00:00
# $Id$
2015-08-23 00:13:22 +00:00
2018-01-17 22:38:27 +00:00
# CHANGED
##############################################################################
2018-02-05 20:45:17 +00:00
# V 2.0
2018-01-17 22:38:27 +00:00
# - feature: 74_Unifi: add new set commands to block/unblock clients,
# enable/disable WLAN, new client-Reading essid
2018-02-05 20:45:17 +00:00
# V 2.1
2018-01-17 22:38:27 +00:00
# - feature: 74_Unifi: add new set command to en-/disable Site Status-LEDs
2018-02-05 20:45:17 +00:00
# V 2.1.1
2018-01-19 21:11:09 +00:00
# - bugfix: 74_Unifi: fixed blockClient
2018-02-05 20:45:17 +00:00
# V 2.1.2
2018-01-21 19:51:41 +00:00
# - feature: 74_Unifi: new Readings for WLAN-states, fixed Warning
2018-02-05 20:45:17 +00:00
# V 2.1.3
2018-01-27 12:27:57 +00:00
# - change: 74_Unifi: SSIDs-Readings and drop-downs use goodReadingName()
2018-02-05 20:45:17 +00:00
# V 2.1.4
# - feature: 74_Unifi: added voucher-functions
2018-03-11 14:54:39 +00:00
# V 2.2
# - feature: 74_Unifi: added set updateClien, encrypt user and password
2018-04-15 18:33:31 +00:00
# V 2.2.1
# - feature: 74_Unifi: update VC-readings immediately when getting voucher
2018-04-20 19:15:38 +00:00
# V 2.2.2
# - fixed: 74_Unifi: restart-typo in poe
2018-05-10 14:43:22 +00:00
# V 2.2.3
# - fixed: 74_Unifi: Cookies for UnifiController 5.9.4
2018-05-27 10:45:08 +00:00
# V 2.2.4
# - fixed: 74_Unifi: import encode_json for newest libs
2018-06-10 15:42:35 +00:00
# V 3.0
# - feature: 74_Unifi: new child-Module UnifiSwitch
# V 3.0.1
# - feature: 74_Unifi: new reading UC_newClients for new clients
# - feature: 74_Unifi: block clients by mac-address
2018-06-23 11:22:34 +00:00
# V 3.0.2
# - fixed: 74_Unifi: Minor bugfix in notify-function
2018-07-18 10:48:39 +00:00
# V 3.0.3
# - fixed: 74_Unifi: Minor loglevel-bugfix
2018-07-22 15:16:09 +00:00
# V 3.0.4
# - fixed: 74_Unifi: Readingname -UC_newClients with leading -
# - changed: 74_Unifi: Reading(name) for Utilization of APs with UC V 5.7/8.x
2018-10-31 10:53:51 +00:00
# V 3.0.5
# - feature: 74_Unifi: Added readings for wan_ip and results of speedtest
2019-02-24 17:53:04 +00:00
# V 3.1.0
# - changed: 74_Unifi: removed deprecated UnifiSwitch-functions!
2019-03-16 13:16:35 +00:00
# V 3.2.0
# - changed: 74_Unifi: removed UCv3 support
2019-03-20 19:15:01 +00:00
# V 3.2.1
# - feature: 74_Unifi: new attribute customClientReadings
2019-03-24 07:37:28 +00:00
# V 3.2.2
# - feature: 74_Unifi: textField-long support for customClientReadings
2019-03-24 09:59:38 +00:00
# V 3.2.3
# - feature: 74_Unifi: new customClientReading _f_last_seen_duration
2019-03-25 20:02:14 +00:00
# V 3.2.4
2019-05-19 06:19:20 +00:00
# - feature: 74_Unifi: new attribute customClientNames
2019-03-27 22:12:52 +00:00
# V 3.2.5
# - fixed: 74_Unifi: fixed createVoucher and (un-)blockClient for UC-V5.10
2019-03-28 17:30:26 +00:00
# V 3.2.6
# - fixed: 74_Unifi: fixed locate/restartAP and disconnectClient for UC-V5.10
2019-04-15 20:14:18 +00:00
# V 3.2.7
# - fixed: 74_Unifi: fixed reading-Update for disconnected clients
2019-05-19 06:19:20 +00:00
# V 3.2.8
# - feature: 74_Unifi: read the client insights to update blocked reading
# V 3.3.0
# - feature: 74_Unifi: supports new module UnifiClient
# - feature: 74_Unifi: read usergroups at define-module, new setter "refreshUsergroups"
# - feature: 74_Unifi: new setter "removeClientReadings"
# - feature: 74_Unifi: persist disconnected clients and rebuild them after fhem-restart
2019-05-22 20:13:24 +00:00
# V 3.3.1
# - fixed: 74_Unifi: fixed Loglevel
2019-05-25 16:19:00 +00:00
# V 3.3.2
# - fixed: 74_Unifi: fixed restore clients at fhem restart
2019-06-24 19:07:58 +00:00
# V 3.3.3
# - fixed: 74_Unifi: fixed (un)blockClient for UC Version 5.10.24
2019-05-22 20:13:24 +00:00
2018-01-17 22:38:27 +00:00
2015-08-23 00:13:22 +00:00
package main ;
2019-06-24 19:07:58 +00:00
my $ version = "3.3.3" ;
2019-05-22 20:13:24 +00:00
# Default f<> r clientReadings setzen. Die Readings waren der Standard vor Einf<6E> hrung des Attributes customClientReadings.
2019-03-20 19:15:01 +00:00
# Eine <20> nderung hat Auswirkungen auf (alte) Moduldefinitionen ohne dieses Attribut.
2019-03-24 07:37:28 +00:00
my $ defaultClientReadings = ".:^accesspoint|^essid|^hostname|^last_seen|^snr|^uptime" ; #ist wegen snr vs rssi nur halb korrekt, wird aber auch nicht wirklich verwendet ;-)
2019-03-25 20:02:14 +00:00
my $ customClientName = "" ;
2015-08-23 00:13:22 +00:00
use strict ;
use warnings ;
use HttpUtils ;
2015-08-29 19:25:28 +00:00
use POSIX ;
2015-08-23 00:13:22 +00:00
use JSON qw( decode_json ) ;
2018-05-27 10:45:08 +00:00
use JSON qw( encode_json ) ;
2015-08-31 22:29:29 +00:00
##############################################################################}
### Forward declarations ####################################################{
sub Unifi_Initialize ($$) ;
sub Unifi_Define ($$) ;
sub Unifi_Undef ($$) ;
sub Unifi_Notify ($$) ;
sub Unifi_Set ($@) ;
sub Unifi_Get ($@) ;
sub Unifi_Attr (@) ;
2019-05-19 06:19:20 +00:00
sub Unifi_Write ($@) ;
2015-08-31 22:29:29 +00:00
sub Unifi_DoUpdate ($@) ;
sub Unifi_Login_Send ($) ;
sub Unifi_Login_Receive ($) ;
sub Unifi_GetClients_Send ($) ;
sub Unifi_GetClients_Receive ($) ;
2019-05-19 06:19:20 +00:00
sub Unifi_GetClientInsights_Send ($) ;
sub Unifi_GetClientInsights_Receive ($) ;
2015-08-31 22:29:29 +00:00
sub Unifi_GetWlans_Send ($) ;
sub Unifi_GetWlans_Receive ($) ;
sub Unifi_GetHealth_Send ($) ;
sub Unifi_GetHealth_Receive ($) ;
2019-03-27 22:12:52 +00:00
sub Unifi_GetSysinfo_Send ($) ;
sub Unifi_GetSysinfo_Receive ($) ;
2015-08-31 22:29:29 +00:00
sub Unifi_GetWlanGroups_Send ($) ;
sub Unifi_GetWlanGroups_Receive ($) ;
sub Unifi_GetUnarchivedAlerts_Send ($) ;
sub Unifi_GetUnarchivedAlerts_Receive ($) ;
sub Unifi_GetEvents_Send ($) ;
sub Unifi_GetEvents_Receive ($) ;
sub Unifi_GetAccesspoints_Send ($) ;
sub Unifi_GetAccesspoints_Receive ($) ;
sub Unifi_ProcessUpdate ($) ;
2019-05-22 20:13:24 +00:00
sub Unifi_SetClientReadings ($$) ;
2015-09-01 20:57:16 +00:00
sub Unifi_SetHealthReadings ($) ;
2015-08-31 22:29:29 +00:00
sub Unifi_SetAccesspointReadings ($) ;
2018-01-21 19:51:41 +00:00
sub Unifi_SetWlanReadings ($) ;
2015-08-31 22:29:29 +00:00
sub Unifi_DisconnectClient_Send ($@) ;
sub Unifi_DisconnectClient_Receive ($) ;
sub Unifi_ApCmd_Send ($$@) ;
2019-05-19 06:19:20 +00:00
sub Unifi_DeviceRestJson_Send ($$$) ;
sub Unifi_UserRestJson_Send ($$$) ;
sub Unifi_DeviceCmd_Receive ($) ;
sub Unifi_UsergroupRestJson_Send ($) ;
sub Unifi_UsergroupRestJson_Receive ($) ;
2015-08-31 22:29:29 +00:00
sub Unifi_ArchiveAlerts_Send ($) ;
sub Unifi_Cmd_Receive ($) ;
sub Unifi_ClientNames ($@) ;
sub Unifi_ApNames ($@) ;
2018-01-21 19:51:41 +00:00
sub Unifi_SSIDs ($@) ;
2018-06-10 15:42:35 +00:00
sub Unifi_BlockClient_Send ($$) ;
2018-01-12 20:39:58 +00:00
sub Unifi_BlockClient_Receive ($) ;
2018-06-10 15:42:35 +00:00
sub Unifi_UnblockClient_Send ($$) ;
2018-01-12 20:39:58 +00:00
sub Unifi_UnblockClient_Receive ($) ;
2018-03-11 14:54:39 +00:00
sub Unifi_UpdateClient_Send ($$) ;
sub Unifi_UpdateClient_Receive ($) ;
2018-01-17 22:38:27 +00:00
sub Unifi_SwitchSiteLEDs_Send ($$) ;
sub Unifi_SwitchSiteLEDs_Receive ($) ;
2018-01-12 20:39:58 +00:00
sub Unifi_WlanconfRest_Send ($$@) ;
sub Unifi_WlanconfRest_Receive ($) ;
2018-02-05 20:45:17 +00:00
sub Unifi_GetVoucherList_Send ($) ;
sub Unifi_GetVoucherList_Receive ($) ;
sub Unifi_CreateVoucher_Send ($%) ;
sub Unifi_CreateVoucher_Receive ($) ;
sub Unifi_SetVoucherReadings ($) ;
sub Unifi_initVoucherCache ($) ;
2019-03-27 22:12:52 +00:00
sub Unifi_isUCversionHigherThan ($$) ;
2019-03-20 19:15:01 +00:00
sub Unifi_initCustomClientReadings ($) ;
2018-02-05 20:45:17 +00:00
sub Unifi_getNextVoucherForNote ($$) ;
2015-08-31 22:29:29 +00:00
sub Unifi_NextUpdateFn ($$) ;
sub Unifi_ReceiveFailure ($$) ;
sub Unifi_CONNECTED ($@) ;
2018-03-11 14:54:39 +00:00
sub Unifi_encrypt ($) ;
sub Unifi_encrypt ($) ;
2015-08-31 22:29:29 +00:00
sub Unifi_Whoami () ;
sub Unifi_Whowasi () ;
##############################################################################}
2015-08-23 00:13:22 +00:00
sub Unifi_Initialize ($$) {
my ( $ hash ) = @ _ ;
2015-08-23 16:53:57 +00:00
$ hash - > { DefFn } = "Unifi_Define" ;
2018-06-10 15:42:35 +00:00
$ hash - > { WriteFn } = "Unifi_Write" ;
2015-08-23 16:53:57 +00:00
$ hash - > { UndefFn } = "Unifi_Undef" ;
$ hash - > { SetFn } = "Unifi_Set" ;
$ hash - > { GetFn } = "Unifi_Get" ;
$ hash - > { AttrFn } = 'Unifi_Attr' ;
$ hash - > { NotifyFn } = "Unifi_Notify" ;
$ hash - > { AttrList } = "disable:1,0 "
2015-08-25 21:29:35 +00:00
. "devAlias "
2017-04-27 22:46:25 +00:00
. "ignoreWiredClients:1,0 "
. "ignoreWirelessClients:1,0 "
2015-08-31 22:29:29 +00:00
. "httpLoglevel:1,2,3,4,5 "
. "eventPeriod "
2018-02-05 20:45:17 +00:00
. "voucherCache "
2019-03-24 07:37:28 +00:00
. "customClientReadings:textField-long "
2019-03-25 20:02:14 +00:00
. "customClientNames "
2019-05-19 06:19:20 +00:00
# ."readClientInsights "
2015-08-23 22:14:04 +00:00
. $ readingFnAttributes ;
2018-06-10 15:42:35 +00:00
2019-05-19 06:19:20 +00:00
$ hash - > { Clients } = "UnifiSwitch:UnifiClient" ;
$ hash - > { MatchList } = { "1:UnifiSwitch" = > "^UnifiSwitch" ,
"2:UnifiClient" = > "^UnifiClient" } ;
2015-08-23 00:13:22 +00:00
}
###############################################################################
sub Unifi_Define ($$) {
my ( $ hash , $ def ) = @ _ ;
my @ a = split ( "[ \t][ \t]*" , $ def ) ;
2019-03-16 13:16:35 +00:00
return "Wrong syntax: use define <name> Unifi <ip> <port> <username> <password> [<interval> [<siteID>]]" if ( int ( @ a ) < 6 ) ;
2015-08-23 00:13:22 +00:00
return "Wrong syntax: <port> is not a number!" if ( ! looks_like_number ( $ a [ 3 ] ) ) ;
return "Wrong syntax: <interval> is not a number!" if ( $ a [ 6 ] && ! looks_like_number ( $ a [ 6 ] ) ) ;
2015-08-27 20:37:29 +00:00
return "Wrong syntax: <interval> too small, must be at least 5" if ( $ a [ 6 ] && $ a [ 6 ] < 5 ) ;
2015-08-23 00:13:22 +00:00
my $ name = $ a [ 0 ] ;
%$ hash = ( %$ hash ,
2015-08-29 19:25:28 +00:00
NOTIFYDEV = > 'global' ,
unifi = > {
2015-08-31 22:29:29 +00:00
CONNECTED = > 0 ,
eventPeriod = > int ( AttrVal ( $ name , "eventPeriod" , 24 ) ) ,
interval = > $ a [ 6 ] || 30 ,
url = > "https://" . $ a [ 2 ] . ( ( $ a [ 3 ] == 443 ) ? '' : ':' . $ a [ 3 ] ) . '/api/s/' . ( ( $ a [ 7 ] ) ? $ a [ 7 ] : 'default' ) . '/' ,
2015-08-29 19:25:28 +00:00
} ,
2015-08-23 00:13:22 +00:00
) ;
$ hash - > { httpParams } = {
hash = > $ hash ,
2015-08-31 22:29:29 +00:00
timeout = > 5 ,
2015-08-23 00:13:22 +00:00
method = > "POST" ,
noshutdown = > 0 ,
ignoreredirects = > 1 ,
2015-08-31 22:29:29 +00:00
loglevel = > AttrVal ( $ name , "httpLoglevel" , 5 ) ,
2015-11-06 18:42:44 +00:00
sslargs = > { SSL_verify_mode = > 0 } ,
2015-08-23 00:13:22 +00:00
} ;
2018-03-11 14:54:39 +00:00
2018-07-18 10:48:39 +00:00
$ hash - > { VERSION } = $ version ;
2019-03-27 22:12:52 +00:00
$ hash - > { UC_VERSION } = "unknown" ;
2018-03-11 14:54:39 +00:00
my $ username = Unifi_encrypt ( $ a [ 4 ] ) ;
my $ password = Unifi_encrypt ( $ a [ 5 ] ) ;
$ hash - > { helper } { username } = $ username ;
$ hash - > { helper } { password } = $ password ;
my $ define = "$a[2] $a[3] $username $password" ;
$ define . = " $a[6]" if ( $ a [ 6 ] ) ;
$ define . = " $a[7]" if ( $ a [ 7 ] ) ;
$ hash - > { DEF } = $ define ;
2019-03-20 19:15:01 +00:00
2019-03-16 13:16:35 +00:00
Log3 $ name , 5 , "$name: Defined with url:$hash->{unifi}->{url}, interval:$hash->{unifi}->{interval}" ;
2015-08-23 00:13:22 +00:00
return undef ;
}
###############################################################################
sub Unifi_Undef ($$) {
my ( $ hash , $ arg ) = @ _ ;
RemoveInternalTimer ( $ hash ) ;
return undef ;
}
###############################################################################
2015-08-23 16:53:57 +00:00
sub Unifi_Notify ($$) {
my ( $ hash , $ dev ) = @ _ ;
2015-08-25 21:29:35 +00:00
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
2018-06-23 11:22:34 +00:00
Log3 $ name , 5 , "$name ($self) - executed." ;
2015-08-23 16:53:57 +00:00
return if ( $ dev - > { NAME } ne "global" ) ;
2019-03-27 22:12:52 +00:00
2018-06-23 11:22:34 +00:00
return if ( ! grep ( m/^DEFINED $name|MODIFIED $name|INITIALIZED|REREADCFG$/ , @ { $ dev - > { CHANGED } } ) ) ;
2015-08-23 16:53:57 +00:00
2019-05-25 16:19:00 +00:00
#restore clients
for my $ readingName ( keys % { $ hash - > { READINGS } } ) {
Log3 $ name , 5 , "$name ($self) - checking 1 $readingName" ;
if ( $ readingName =~ m/\..*_mac$/ ) {
Log3 $ name , 5 , "$name ($self) - found 1 $readingName" ;
my $ mac = ReadingsVal ( $ name , $ readingName , "" ) ;
$ hash - > { restoreClients } - > { $ mac } = 1 ;
}
}
2015-08-23 16:53:57 +00:00
if ( AttrVal ( $ name , "disable" , 0 ) ) {
2015-08-31 22:29:29 +00:00
Log3 $ name , 5 , "$name ($self) - executed. - Device '$name' is disabled, do nothing..." ;
2015-08-25 21:29:35 +00:00
Unifi_CONNECTED ( $ hash , 'disabled' ) ;
2015-08-23 16:53:57 +00:00
} else {
2015-08-31 22:29:29 +00:00
Log3 $ name , 5 , "$name ($self) - executed. - Remove all Timers & Call DoUpdate..." ;
2015-08-25 21:29:35 +00:00
Unifi_CONNECTED ( $ hash , 'initialized' ) ;
2015-08-23 16:53:57 +00:00
Unifi_DoUpdate ( $ hash ) ;
}
2019-05-19 06:19:20 +00:00
if ( $ dev - > { NAME } eq "global" ) { #INITIALIZED|REREADCFG
$ hash - > { unifi } - > { customClientReadings } - > { attr_value } = AttrVal ( $ name , "customClientReadings" , $ defaultClientReadings ) ;
Unifi_initCustomClientReadings ( $ hash ) ;
2019-05-25 16:19:00 +00:00
# TODO: der folgende Block kann Ende 2019 entfernt werden. Es ist der alte Restore-Mechanismus
# Dieser wurde ersetzt durch de restore von mac-Adressen und anschlie<69> endem updateClient in doUpdate()
#for my $readingName (keys %{$hash->{READINGS}}) {
# #Log3 $name, 1, "$name ($self) - checking 1 $readingName";
# if($readingName =~ m/\..*_id$/){
# #Log3 $name, 1, "$name ($self) - found 1 $readingName";
# my $readingValue=ReadingsVal($name,$readingName,"");
# if($readingValue =~ m/^[a-fA-F0-9]*$/g){
# my $clientName=substr($readingName,1,index($readingName,"_id")-1);
# $hash->{clients}->{$readingValue}->{name} = $clientName;
# Log3 $name, 5, "$name ($self) - restored client $clientName with ID $readingValue";
# }
# }
#}
#for my $clientID (keys %{$hash->{clients}}) {
# my $clientName=$hash->{clients}->{$clientID}->{name}."_";
# # TODO: Pr<50> fen, ob es f<> r $clientName ein UnifiClient-Devices gibt und die Werte aus den Readings des UnifiClients wiederherstellen.
# for my $readingName (keys %{$hash->{READINGS}}) {
# #Log3 $name, 1, "$name ($self) - checking 2 $readingName for $clientName";
# if($readingName =~ m/^$clientName.*/){
# #Log3 $name, 1, "$name ($self) - found 2 $readingName";
# my $readingValue=ReadingsVal($name,$readingName,"");
# my $readingName=substr($readingName,length($clientName));
# $hash->{clients}->{$clientID}->{$readingName} = $readingValue;
# Log3 $name, 5, "$name ($self) - restored internal $readingName = $readingValue for client $clientName";
# }
# }
#}
2019-05-19 06:19:20 +00:00
}
2015-08-23 16:53:57 +00:00
return undef ;
}
###############################################################################
2015-08-23 00:13:22 +00:00
sub Unifi_Set ($@) {
my ( $ hash , @ a ) = @ _ ;
return "\"set $hash->{NAME}\" needs at least an argument" if ( @ a < 2 ) ;
2018-02-05 20:45:17 +00:00
# setVal4 enth<74> lt nur erstes Wort der note f<> r voucher!!!
# in Doku aufgenommen, dass genau drei Leerzeichen enthalten sein m<> ssen, also note keine Leerzeichen enthalten kann
my ( $ name , $ setName , $ setVal , $ setVal2 , $ setVal3 , $ setVal4 ) = @ a ;
2015-08-23 00:13:22 +00:00
Log3 $ name , 5 , "$name: set called with $setName " . ( $ setVal ? $ setVal : "" ) if ( $ setName ne "?" ) ;
2015-08-28 05:50:10 +00:00
if ( Unifi_CONNECTED ( $ hash ) eq 'disabled' && $ setName !~ /clear/ ) {
2018-02-05 20:45:17 +00:00
return "Unknown argument $setName, choose one of clear:all,readings,clientData,voucherCache" ;
2015-08-28 05:50:10 +00:00
Log3 $ name , 5 , "$name: set called with $setName but device is disabled!" if ( $ setName ne "?" ) ;
return undef ;
2015-08-23 16:53:57 +00:00
}
2019-05-19 06:19:20 +00:00
my $ blockedClientNames = "" ;
my $ unblockedClientNames = "" ;
my $ connectedClientNames = "" ;
my $ disconnectedClientNames = "" ;
my $ clientName = "" ;
for my $ clientID ( keys % { $ hash - > { clients } } ) {
my $ clientName = Unifi_ClientNames ( $ hash , $ clientID , 'makeAlias' ) ;
if ( defined $ hash - > { clients } - > { $ clientID } - > { blocked } && $ hash - > { clients } - > { $ clientID } - > { blocked } eq JSON:: true ) {
$ blockedClientNames . = $ clientName . ',' ;
} else {
$ unblockedClientNames . = $ clientName . ',' ;
}
if ( defined $ hash - > { unifi } - > { connectedClients } - > { $ clientID } ) {
$ connectedClientNames . = $ clientName . ',' ;
} else {
$ disconnectedClientNames . = $ clientName . ',' ;
}
}
$ blockedClientNames =~ s/.$// ;
$ unblockedClientNames =~ s/.$// ;
$ connectedClientNames =~ s/.$// ;
$ disconnectedClientNames =~ s/.$// ;
#my $clientNames = Unifi_ClientNames($hash);
2015-08-31 22:29:29 +00:00
my $ apNames = Unifi_ApNames ( $ hash ) ;
2018-01-12 20:39:58 +00:00
my $ SSIDs = Unifi_SSIDs ( $ hash ) ;
2015-08-31 22:29:29 +00:00
2019-05-19 06:19:20 +00:00
if ( $ setName !~ /archiveAlerts|restartAP|setLocateAP|unsetLocateAP|disconnectClient|update|updateClient|clear|blockClient|unblockClient|enableWLAN|disableWLAN|switchSiteLEDs|createVoucher|removeClientReadings|refreshUsergroups/ ) {
2015-08-31 22:29:29 +00:00
return "Unknown argument $setName, choose one of update:noArg "
2018-02-05 20:45:17 +00:00
. "clear:all,readings,clientData,allData,voucherCache "
2015-08-31 22:29:29 +00:00
. ( ( defined $ hash - > { alerts_unarchived } [ 0 ] && scalar @ { $ hash - > { alerts_unarchived } } ) ? "archiveAlerts:noArg " : "" )
. ( ( $ apNames && Unifi_CONNECTED ( $ hash ) ) ? "restartAP:all,$apNames setLocateAP:all,$apNames unsetLocateAP:all,$apNames " : "" )
2019-05-19 06:19:20 +00:00
. ( ( $ connectedClientNames && Unifi_CONNECTED ( $ hash ) ) ? "disconnectClient:all,$connectedClientNames " : "" )
. ( ( $ disconnectedClientNames && Unifi_CONNECTED ( $ hash ) ) ? "removeClientReadings:$disconnectedClientNames " : "" )
. ( ( $ unblockedClientNames && Unifi_CONNECTED ( $ hash ) ) ? "blockClient:$unblockedClientNames " : "" )
. ( ( $ blockedClientNames && Unifi_CONNECTED ( $ hash ) ) ? "unblockClient:$blockedClientNames " : "" )
2019-02-24 17:53:04 +00:00
. "createVoucher enableWLAN:$SSIDs disableWLAN:$SSIDs "
2019-05-19 06:19:20 +00:00
. "switchSiteLEDs:on,off updateClient refreshUsergroups:noArg" ;
2015-08-23 16:53:57 +00:00
}
else {
2015-08-23 00:13:22 +00:00
Log3 $ name , 4 , "$name: set $setName" ;
2015-08-31 22:29:29 +00:00
if ( Unifi_CONNECTED ( $ hash ) ) {
if ( $ setName eq 'disconnectClient' ) {
if ( $ setVal && $ setVal ne 'all' ) {
$ setVal = Unifi_ClientNames ( $ hash , $ setVal , 'makeID' ) ;
if ( defined $ hash - > { clients } - > { $ setVal } ) {
Unifi_DisconnectClient_Send ( $ hash , $ setVal ) ;
}
else {
2019-05-19 06:19:20 +00:00
return "$hash->{NAME}: Unknown client '$setVal' in command '$setName', choose one of: all,$connectedClientNames" ;
2015-08-31 22:29:29 +00:00
}
}
elsif ( ! $ setVal || $ setVal eq 'all' ) {
Unifi_DisconnectClient_Send ( $ hash , keys ( % { $ hash - > { clients } } ) ) ;
}
}
2018-01-12 20:39:58 +00:00
elsif ( $ setName eq 'blockClient' ) {
2018-06-10 15:42:35 +00:00
my $ id = Unifi_ClientNames ( $ hash , $ setVal , 'makeID' ) ;
my $ mac = "x" ;
if ( defined $ hash - > { clients } - > { $ id } ) {
$ mac = $ hash - > { clients } - > { $ id } - > { mac } ;
} elsif ( $ setVal =~ m/^[a-fA-F0-9:]{17}$/g ) {
$ mac = $ setVal ;
2018-01-12 20:39:58 +00:00
}
2018-06-10 15:42:35 +00:00
if ( $ mac ne "x" ) {
Unifi_BlockClient_Send ( $ hash , $ mac ) ;
2019-05-19 06:19:20 +00:00
$ hash - > { clients } - > { $ id } - > { blocked } = JSON:: true ; # eigentlich vorauseilender Gehorsam, aber leider kommt beim blockClient_Receive keine ID zur<75> ck um dort zu setzen.
delete $ hash - > { unifi } - > { connectedClients } - > { $ id } ;
2018-06-10 15:42:35 +00:00
} else {
2019-05-19 06:19:20 +00:00
return "$hash->{NAME}: Unknown client '$setVal' in command '$setName', use mac or choose one of: $unblockedClientNames" ;
2018-01-12 20:39:58 +00:00
}
}
elsif ( $ setName eq 'unblockClient' ) {
2018-06-10 15:42:35 +00:00
my $ id = Unifi_ClientNames ( $ hash , $ setVal , 'makeID' ) ;
my $ mac = "x" ;
if ( defined $ hash - > { clients } - > { $ id } ) {
$ mac = $ hash - > { clients } - > { $ id } - > { mac } ;
} elsif ( $ setVal =~ m/^[a-fA-F0-9:]{17}$/g ) {
$ mac = $ setVal ;
2018-01-12 20:39:58 +00:00
}
2018-06-10 15:42:35 +00:00
if ( $ mac ne "x" ) {
Unifi_UnblockClient_Send ( $ hash , $ mac ) ;
2019-05-19 06:19:20 +00:00
$ hash - > { clients } - > { $ id } - > { blocked } = JSON:: false ; # eigentlich vorauseilender Gehorsam, aber leider kommt beim unblockClient_Receive keine ID zur<75> ck um dort zu setzen.
2018-06-10 15:42:35 +00:00
} else {
2019-05-19 06:19:20 +00:00
return "$hash->{NAME}: Unknown client '$setVal' in command '$setName', use mac or choose one of: $blockedClientNames" ;
2018-01-12 20:39:58 +00:00
}
}
2018-01-17 22:38:27 +00:00
elsif ( $ setName eq 'switchSiteLEDs' ) {
my $ state = "true" ;
if ( $ setVal && $ setVal eq 'off' ) {
$ state = "false" ;
}
Unifi_SwitchSiteLEDs_Send ( $ hash , $ state ) ;
}
2018-01-12 20:39:58 +00:00
elsif ( $ setName eq 'disableWLAN' ) {
2018-01-27 12:27:57 +00:00
my $ wlanid = Unifi_SSIDs ( $ hash , $ setVal , 'makeID' ) ;
if ( defined $ hash - > { wlans } - > { $ wlanid } ) {
my $ wlanconf = $ hash - > { wlans } - > { $ wlanid } ;
2018-01-17 22:38:27 +00:00
$ wlanconf - > { enabled } = JSON:: false ;
2018-01-27 12:27:57 +00:00
Unifi_WlanconfRest_Send ( $ hash , $ wlanid , $ wlanconf ) ;
2018-01-12 20:39:58 +00:00
}
else {
return "$hash->{NAME}: Unknown SSID '$setVal' in command '$setName', choose one of: all,$SSIDs" ;
}
}
elsif ( $ setName eq 'enableWLAN' ) {
2018-01-27 12:27:57 +00:00
my $ wlanid = Unifi_SSIDs ( $ hash , $ setVal , 'makeID' ) ;
if ( defined $ hash - > { wlans } - > { $ wlanid } ) {
my $ wlanconf = $ hash - > { wlans } - > { $ wlanid } ;
2018-01-17 22:38:27 +00:00
$ wlanconf - > { enabled } = JSON:: true ;
2018-01-27 12:27:57 +00:00
Unifi_WlanconfRest_Send ( $ hash , $ wlanid , $ wlanconf ) ;
2018-01-12 20:39:58 +00:00
}
else {
return "$hash->{NAME}: Unknown SSID '$setVal' in command '$setName', choose one of: all,$SSIDs" ;
}
}
2018-03-11 14:54:39 +00:00
elsif ( $ setName eq 'updateClient' ) {
return "enter mac of client" if ( ! defined $ setVal ) ;
Unifi_UpdateClient_Send ( $ hash , $ setVal ) ;
}
2015-08-31 22:29:29 +00:00
elsif ( $ setName eq 'archiveAlerts' && defined $ hash - > { alerts_unarchived } [ 0 ] ) {
Unifi_ArchiveAlerts_Send ( $ hash ) ;
undef @ { $ hash - > { alerts_unarchived } } ;
}
elsif ( $ setName eq 'restartAP' ) {
if ( $ setVal && $ setVal ne 'all' ) {
$ setVal = Unifi_ApNames ( $ hash , $ setVal , 'makeID' ) ;
if ( defined $ hash - > { accespoints } - > { $ setVal } ) {
Unifi_ApCmd_Send ( $ hash , 'restart' , $ setVal ) ;
}
else {
return "$hash->{NAME}: Unknown accesspoint '$setVal' in command '$setName', choose one of: all,$apNames" ;
}
}
elsif ( ! $ setVal || $ setVal eq 'all' ) {
Unifi_ApCmd_Send ( $ hash , 'restart' , keys ( % { $ hash - > { accespoints } } ) ) ;
}
}
elsif ( $ setName eq 'setLocateAP' ) {
if ( $ setVal && $ setVal ne 'all' ) {
$ setVal = Unifi_ApNames ( $ hash , $ setVal , 'makeID' ) ;
if ( defined $ hash - > { accespoints } - > { $ setVal } ) {
Unifi_ApCmd_Send ( $ hash , 'set-locate' , $ setVal ) ;
}
else {
return "$hash->{NAME}: Unknown accesspoint '$setVal' in command '$setName', choose one of: all,$apNames" ;
}
}
elsif ( ! $ setVal || $ setVal eq 'all' ) {
Unifi_ApCmd_Send ( $ hash , 'set-locate' , keys ( % { $ hash - > { accespoints } } ) ) ;
}
}
elsif ( $ setName eq 'unsetLocateAP' ) {
if ( $ setVal && $ setVal ne 'all' ) {
$ setVal = Unifi_ApNames ( $ hash , $ setVal , 'makeID' ) ;
if ( defined $ hash - > { accespoints } - > { $ setVal } ) {
Unifi_ApCmd_Send ( $ hash , 'unset-locate' , $ setVal ) ;
}
else {
return "$hash->{NAME}: Unknown accesspoint '$setVal' in command '$setName', choose one of: all,$apNames" ;
}
}
elsif ( ! $ setVal || $ setVal eq 'all' ) {
Unifi_ApCmd_Send ( $ hash , 'unset-locate' , keys ( % { $ hash - > { accespoints } } ) ) ;
}
}
2019-05-19 06:19:20 +00:00
elsif ( $ setName eq 'removeClientReadings' ) {
if ( $ setVal && $ setVal ne "" ) {
my $ id = Unifi_ClientNames ( $ hash , $ setVal , 'makeID' ) ;
if ( defined $ hash - > { clients } - > { $ id } ) {
readingsDelete ( $ hash , $ setVal ) ;
my $ readingspec = '^' . $ setVal . '_.*$' ;
foreach my $ reading ( grep { /$readingspec/ }
keys % { $ hash - > { READINGS } } ) {
readingsDelete ( $ hash , $ reading ) ;
}
delete $ hash - > { clients } - > { $ id } ;
} else {
return "$hash->{NAME}: Unknown clientName '$setVal' in command '$setName', choose one of: $disconnectedClientNames" ;
}
} else {
return "$hash->{NAME}: No clientName in command '$setName', choose one of: $disconnectedClientNames" ;
}
}
2018-02-05 20:45:17 +00:00
elsif ( $ setName eq 'createVoucher' ) {
if ( ! looks_like_number ( $ setVal ) || int ( $ setVal ) < 1 ||
! looks_like_number ( $ setVal2 ) || int ( $ setVal2 ) < 1 ||
! looks_like_number ( $ setVal3 ) || int ( $ setVal3 ) < 1 ||
$ setVal4 eq "" ) {
return "$hash->{NAME} $setName: First three arguments (expire, n, quota) must be numeric. Forth argument is note of voucher."
}
if ( $ setVal4 =~ /,/ ) {
return "$hash->{NAME} $setName: Note of voucher has invalid character (,)."
}
my % params = ( "expire" = > $ setVal , "n" = > $ setVal2 , "quota" = > $ setVal3 , "note" = > $ setVal4 ) ;
Unifi_CreateVoucher_Send ( $ hash , % params ) ;
}
2019-03-27 22:12:52 +00:00
elsif ( $ setName eq 'refreshUCversion' ) {
Unifi_GetSysinfo_Send ( $ hash ) ;
2019-05-19 06:19:20 +00:00
}
elsif ( $ setName eq 'refreshUsergroups' ) {
Unifi_UsergroupRestJson_Send ( $ hash ) ;
}
2015-08-31 22:29:29 +00:00
}
2015-08-23 00:13:22 +00:00
if ( $ setName eq 'update' ) {
2015-08-25 21:29:35 +00:00
RemoveInternalTimer ( $ hash ) ;
2015-08-23 00:13:22 +00:00
Unifi_DoUpdate ( $ hash , 1 ) ;
}
elsif ( $ setName eq 'clear' ) {
if ( $ setVal eq 'readings' || $ setVal eq 'all' ) {
for ( keys % { $ hash - > { READINGS } } ) {
delete $ hash - > { READINGS } - > { $ _ } if ( $ _ ne 'state' ) ;
}
}
2018-01-27 12:27:57 +00:00
if ( $ setVal eq 'clientData' ) {
2015-08-25 21:29:35 +00:00
% { $ hash - > { clients } } = ( ) ;
2015-08-23 00:13:22 +00:00
}
2018-01-27 12:27:57 +00:00
if ( $ setVal eq 'allData' || $ setVal eq 'all' ) {
% { $ hash - > { clients } } = ( ) ;
% { $ hash - > { wlans } } = ( ) ;
% { $ hash - > { wlan_health } } = ( ) ;
% { $ hash - > { accespoints } } = ( ) ;
# %{$hash->{events}} = ();
% { $ hash - > { wlangroups } } = ( ) ;
# %{$hash->{alerts_unarchived}} = ();
}
2018-02-05 20:45:17 +00:00
if ( $ setVal eq 'voucherCache' || $ setVal eq 'all' ) {
my $ cache_attr_value = $ hash - > { hotspot } - > { voucherCache } - > { attr_value } ;
% { $ hash - > { hotspot } - > { voucherCache } } = ( ) ;
$ hash - > { hotspot } - > { voucherCache } - > { attr_value } = $ cache_attr_value ;
Unifi_initVoucherCache ( $ hash ) ;
}
2015-08-23 00:13:22 +00:00
}
}
return undef ;
}
###############################################################################
sub Unifi_Get ($@) {
my ( $ hash , @ a ) = @ _ ;
return "\"get $hash->{NAME}\" needs at least one argument" if ( @ a < 2 ) ;
my ( $ name , $ getName , $ getVal ) = @ a ;
2018-02-05 20:45:17 +00:00
if ( defined $ getVal ) {
Log3 $ name , 5 , "$name: get called with $getName $getVal." ;
} else {
Log3 $ name , 5 , "$name: get called with $getName." ;
}
my % voucherNotesHash = ( ) ;
my $ voucherNote = '' ;
if ( defined $ hash - > { hotspot } - > { vouchers } [ 0 ] ) {
for my $ voucher ( @ { $ hash - > { hotspot } - > { vouchers } } ) {
if ( defined $ voucher - > { note } && $ voucher - > { note } =~ /^((?!,).)*$/ && $ voucher - > { note } ne "" ) {
$ voucherNote = $ voucher - > { note } ;
$ voucherNote =~ s/( )/ /og ;
$ voucherNotesHash { $ voucherNote } = $ voucherNote ;
} else {
Log3 $ name , 4 , "$name Info: vouchers without note or containing comma(,) in note or with empty note are ignored in drop-downs." ;
}
}
}
my $ voucherNotes = join ( "," , keys % voucherNotesHash ) ;
2015-08-25 21:29:35 +00:00
2015-08-31 22:29:29 +00:00
my $ clientNames = Unifi_ClientNames ( $ hash ) ;
2019-02-24 17:53:04 +00:00
if ( $ getName !~ /events|clientData|unarchivedAlerts|voucherList|voucher|showAccount/ ) {
2015-08-31 22:29:29 +00:00
return "Unknown argument $getName, choose one of "
. ( ( defined $ hash - > { events } [ 0 ] && scalar @ { $ hash - > { events } } ) ? "events:noArg " : "" )
. ( ( defined $ hash - > { alerts_unarchived } [ 0 ] && scalar @ { $ hash - > { alerts_unarchived } } ) ? "unarchivedAlerts:noArg " : "" )
2017-05-27 20:20:30 +00:00
. ( ( $ clientNames ) ? "clientData:all,$clientNames " : "" )
2019-02-24 17:53:04 +00:00
. "voucherList:all,$voucherNotes voucher:$voucherNotes showAccount" ;
2015-08-31 22:29:29 +00:00
}
elsif ( $ getName eq 'unarchivedAlerts' && defined $ hash - > { alerts_unarchived } [ 0 ] && scalar @ { $ hash - > { alerts_unarchived } } ) {
my $ alerts = "====================================================\n" ;
for my $ alert ( @ { $ hash - > { alerts_unarchived } } ) {
for ( sort keys % { $ alert } ) {
if ( $ _ !~ /^(archived|_id|handled_admin_id|site_id|datetime|handled_time)$/ ) {
$ alert - > { $ _ } = strftime "%Y-%m-%d %H:%M:%S" , localtime ( $ alert - > { $ _ } / 1000 ) if ( $ _ eq 'time' ) ;
$ alerts . = "$_ = " . ( ( defined $ alert - > { $ _ } ) ? $ alert - > { $ _ } : '' ) . "\n" ;
}
}
$ alerts . = "====================================================\n" ;
2015-08-25 21:29:35 +00:00
}
2015-08-31 22:29:29 +00:00
return $ alerts ;
2015-08-25 21:29:35 +00:00
}
2015-08-31 22:29:29 +00:00
elsif ( $ getName eq 'events' && defined $ hash - > { events } [ 0 ] && scalar @ { $ hash - > { events } } ) {
my $ events = "==================================================================\n" ;
for my $ event ( @ { $ hash - > { events } } ) {
for ( sort keys % { $ event } ) {
if ( $ _ !~ /^(_id|site_id|subsystem|datetime|is_admin)$/ ) {
$ event - > { $ _ } = strftime "%Y-%m-%d %H:%M:%S" , localtime ( $ event - > { $ _ } / 1000 ) if ( $ _ eq 'time' ) ;
$ events . = "$_ = " . ( ( defined $ event - > { $ _ } ) ? $ event - > { $ _ } : '' ) . "\n" ;
2015-08-27 20:37:29 +00:00
}
2015-08-25 21:29:35 +00:00
}
2015-08-31 22:29:29 +00:00
$ events . = "==================================================================\n" ;
2015-08-25 21:29:35 +00:00
}
2015-08-31 22:29:29 +00:00
return $ events ;
}
elsif ( $ getName eq 'clientData' && $ clientNames ) {
2015-08-23 16:53:57 +00:00
my $ clientData = '' ;
2015-08-31 22:29:29 +00:00
if ( $ getVal && $ getVal ne 'all' ) {
$ getVal = Unifi_ClientNames ( $ hash , $ getVal , 'makeID' ) ;
}
if ( ! $ getVal || $ getVal eq 'all' ) {
2015-08-23 16:53:57 +00:00
$ clientData . = "======================================\n" ;
for my $ client ( sort keys % { $ hash - > { clients } } ) {
for ( sort keys % { $ hash - > { clients } - > { $ client } } ) {
2015-08-25 21:29:35 +00:00
$ clientData . = "$_ = " . ( ( defined ( $ hash - > { clients } - > { $ client } - > { $ _ } ) ) ? $ hash - > { clients } - > { $ client } - > { $ _ } : '' ) . "\n" ;
2015-08-23 16:53:57 +00:00
}
$ clientData . = "======================================\n" ;
2015-08-23 00:13:22 +00:00
}
2015-08-23 16:53:57 +00:00
return $ clientData ;
}
elsif ( defined ( $ hash - > { clients } - > { $ getVal } ) ) {
$ clientData . = "======================================\n" ;
for ( sort keys % { $ hash - > { clients } - > { $ getVal } } ) {
2015-08-25 21:29:35 +00:00
$ clientData . = "$_ = " . ( ( defined ( $ hash - > { clients } - > { $ getVal } - > { $ _ } ) ) ? $ hash - > { clients } - > { $ getVal } - > { $ _ } : '' ) . "\n" ;
2015-08-23 16:53:57 +00:00
}
$ clientData . = "======================================\n" ;
return $ clientData ;
}
else {
2015-08-31 22:29:29 +00:00
return "$hash->{NAME}: Unknown client '$getVal' in command '$getName', choose one of: all,$clientNames" ;
2015-08-23 16:53:57 +00:00
}
}
2018-02-05 20:45:17 +00:00
elsif ( $ getName eq 'voucherList' && defined $ hash - > { hotspot } - > { vouchers } [ 0 ] ) {
my $ anzahl = 0 ;
my $ vouchers = "==================================================================\n" ;
for my $ voucher ( @ { $ hash - > { hotspot } - > { vouchers } } ) {
my $ note = '' ;
if ( defined $ voucher - > { note } ) {
$ note = $ voucher - > { note } ;
}
my $ gv = $ getVal ;
$ note =~ tr /a-zA-Z<> <5A> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> _0-9.,/ / cd ;
$ gv =~ tr /a-zA-Z<> <5A> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> _0-9.,/ / cd ;
if ( $ gv eq 'all' || ( ( $ gv =~ /^$note/ ) && $ note ne '' ) ) {
for ( sort keys % { $ voucher } ) {
if ( $ _ !~ /^(_id|admin_name|for_hotspot|qos_overwrite|site_id|create_time)$/ ) {
$ vouchers . = "$_ = " . ( ( defined $ voucher - > { $ _ } ) ? $ voucher - > { $ _ } : '' ) . "\n" ;
}
}
if ( defined $ hash - > { hotspot } - > { voucherCache } - > { $ note } - > { $ voucher - > { _id } } - > { delivered_at } ) {
$ vouchers . = "delivered_at = " . localtime ( $ hash - > { hotspot } - > { voucherCache } - > { $ note } - > { $ voucher - > { _id } } - > { delivered_at } ) . "\n" ;
}
$ vouchers . = "==================================================================\n" ;
$ anzahl += 1 ;
}
}
$ vouchers . = "Count: " . $ anzahl . "\n" ;
return $ vouchers ;
}
elsif ( $ getName eq 'voucher' && defined $ hash - > { hotspot } - > { vouchers } [ 0 ] ) {
my $ returnedVoucher = Unifi_getNextVoucherForNote ( $ hash , $ getVal ) ;
if ( $ returnedVoucher eq "" ) {
2018-04-15 18:33:31 +00:00
return "No voucher with note: $getVal!" ;
2018-02-05 20:45:17 +00:00
}
my $ returnedVoucherCode = "" ;
if ( defined $ returnedVoucher - > { _id } ) {
$ returnedVoucherCode = $ returnedVoucher - > { code } ;
2018-04-15 18:33:31 +00:00
if ( defined $ hash - > { hotspot } - > { voucherCache } - > { $ getVal } - > { setCmd } ) {
$ hash - > { hotspot } - > { voucherCache } - > { $ getVal } - > { $ returnedVoucher - > { _id } } - > { delivered_at } = time ( ) ;
readingsSingleUpdate ( $ hash , "-VC_" . $ getVal , Unifi_getNextVoucherForNote ( $ hash , $ getVal ) - > { code } , 1 ) ;
}
2018-02-05 20:45:17 +00:00
}
return $ returnedVoucherCode ;
}
2018-03-11 14:54:39 +00:00
elsif ( $ getName eq 'showAccount' ) {
my $ user = $ hash - > { helper } { username } ;
my $ password = $ hash - > { helper } { password } ;
return 'no user set' if ( ! $ user ) ;
return 'no password set' if ( ! $ password ) ;
$ user = Unifi_decrypt ( $ user ) ;
$ password = Unifi_decrypt ( $ password ) ;
return "user: $user\npassword: $password" ;
}
2015-08-23 16:53:57 +00:00
return undef ;
}
###############################################################################
sub Unifi_Attr (@) {
my ( $ cmd , $ name , $ attr_name , $ attr_value ) = @ _ ;
my $ hash = $ defs { $ name } ;
if ( $ cmd eq "set" ) {
if ( $ attr_name eq "disable" ) {
if ( $ attr_value == 1 ) {
2015-08-25 21:29:35 +00:00
Unifi_CONNECTED ( $ hash , 'disabled' ) ;
2015-08-23 16:53:57 +00:00
}
2015-08-25 21:29:35 +00:00
elsif ( $ attr_value == 0 && Unifi_CONNECTED ( $ hash ) eq "disabled" ) {
Unifi_CONNECTED ( $ hash , 'initialized' ) ;
2015-08-23 16:53:57 +00:00
Unifi_DoUpdate ( $ hash ) ;
}
}
2015-08-27 20:37:29 +00:00
elsif ( $ attr_name eq "devAlias" ) {
if ( ! $ attr_value ) {
CommandDeleteAttr ( undef , $ name . ' ' . $ attr_name ) ;
return 1 ;
}
elsif ( $ attr_value !~ /^([\w\.\-]+:[\w\.\-]+\s?)+$/ ) {
return "$name: Value \"$attr_value\" is not allowed for devAlias!\n"
2015-08-28 05:50:10 +00:00
. "Must be \"<ID>:<ALIAS> <ID2>:<ALIAS2>\", e.g. 123abc:MyIphone\n"
. "Only these characters are allowed: [alphanumeric - _ .]" ;
2015-08-27 20:37:29 +00:00
}
}
2015-08-31 22:29:29 +00:00
elsif ( $ attr_name eq "httpLoglevel" ) {
$ hash - > { httpParams } - > { loglevel } = $ attr_value ;
}
elsif ( $ attr_name eq "eventPeriod" ) {
if ( ! looks_like_number ( $ attr_value ) || int ( $ attr_value ) < 1 || int ( $ attr_value ) > 168 ) {
return "$name: Value \"$attr_value\" is not allowed.\n"
. "eventPeriod must be a number between 1 and 168."
}
$ hash - > { unifi } - > { eventPeriod } = int ( $ attr_value ) ;
}
2018-02-05 20:45:17 +00:00
elsif ( $ attr_name eq "voucherCache" ) {
#ToDo: n<> chste Zeile entfernen wenn in Unifi_initVoucherCache das L<> schen alter Caches implementiert ist
# So l<> scht man die delivery_at der verbleibenden Caches mit
# Ist aber ja nur ein kurzzeitiges Problem, da die delivery_at eh nach 2 Stunden entfernt werden, daher egal.
$ hash - > { hotspot } - > { voucherCache } = ( ) ;
$ hash - > { hotspot } - > { voucherCache } - > { attr_value } = $ attr_value ;
return Unifi_initVoucherCache ( $ hash ) ;
}
2019-03-20 19:15:01 +00:00
elsif ( $ attr_name eq "customClientReadings" ) {
$ hash - > { unifi } - > { customClientReadings } = ( ) ;
$ hash - > { unifi } - > { customClientReadings } - > { attr_value } = $ attr_value ;
Unifi_initCustomClientReadings ( $ hash ) ;
}
2019-03-25 20:02:14 +00:00
elsif ( $ attr_name eq "customClientNames" ) {
$ hash - > { unifi } - > { customClientNames } - > { attr_value } = $ attr_value ;
}
2019-05-19 06:19:20 +00:00
#elsif($attr_name eq "readClientInsights") {
# if (!looks_like_number($attr_value) || int($attr_value) < 1 || int($attr_value) > 365) {
# return "$name: Value \"$attr_value\" is not allowed.\n"
# ."readClientInsights must be a number between 1 and 365."
# }
# $hash->{unifi}->{readClientInsights}->{attr_value} = $attr_value*24;
#}
2015-08-23 16:53:57 +00:00
}
elsif ( $ cmd eq "del" ) {
2015-08-25 21:29:35 +00:00
if ( $ attr_name eq "disable" && Unifi_CONNECTED ( $ hash ) eq "disabled" ) {
Unifi_CONNECTED ( $ hash , 'initialized' ) ;
2015-08-23 16:53:57 +00:00
Unifi_DoUpdate ( $ hash ) ;
2015-08-23 00:13:22 +00:00
}
2015-08-31 22:29:29 +00:00
elsif ( $ attr_name eq "httpLoglevel" ) {
$ hash - > { httpParams } - > { loglevel } = 5 ;
}
elsif ( $ attr_name eq "eventPeriod" ) {
$ hash - > { unifi } - > { eventPeriod } = 24 ;
}
2018-02-05 20:45:17 +00:00
elsif ( $ attr_name eq "voucherCache" ) {
% { $ hash - > { hotspot } - > { voucherCache } } = ( ) ;
}
2019-03-20 19:15:01 +00:00
elsif ( $ attr_name eq "customClientReadings" ) {
$ hash - > { unifi } - > { customClientReadings } = ( ) ;
$ hash - > { unifi } - > { customClientReadings } - > { attr_value } = $ defaultClientReadings ;
Unifi_initCustomClientReadings ( $ hash ) ;
}
2019-03-25 20:02:14 +00:00
elsif ( $ attr_name eq "customClientNames" ) {
$ hash - > { unifi } - > { customClientNames } - > { attr_value } = $ customClientName ;
}
2019-05-19 06:19:20 +00:00
#elsif($attr_name eq "readClientInsights") {
# $hash->{unifi}->{readClientInsights} = undef;
#}
2015-08-23 00:13:22 +00:00
}
return undef ;
}
2018-06-10 15:42:35 +00:00
###############################################################################
2019-05-19 06:19:20 +00:00
sub Unifi_Write ($@) {
my ( $ hash , @ args ) = @ _ ;
my ( $ type , $ id , $ data ) = @ args ;
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
2019-05-22 20:13:24 +00:00
Log3 $ name , 4 , "$name ($self) - executed with " . $ type ;
2019-05-19 06:19:20 +00:00
if ( $ type eq "Unifi_DeviceRestJson_Send" ) {
Unifi_DeviceRestJson_Send ( $ hash , $ id , { port_overrides = > $ data } ) ; #id=ap_id
} elsif ( $ type eq "Unifi_ApJson_Send" ) {
Unifi_ApJson_Send ( $ hash , $ data ) ;
} elsif ( $ type eq "Unifi_BlockClient_Send" ) {
Unifi_BlockClient_Send ( $ hash , $ id ) ; # id=mac
} elsif ( $ type eq "Unifi_UnblockClient_Send" ) {
Unifi_UnblockClient_Send ( $ hash , $ id ) ; # id=mac
} elsif ( $ type eq "Unifi_UserRestJson_Send" ) {
Unifi_UserRestJson_Send ( $ hash , $ id , $ data ) ; # id=_id
2019-05-20 18:53:51 +00:00
} elsif ( $ type eq "Unifi_UpdateClient_Send" ) {
Unifi_UpdateClient_Send ( $ hash , $ id ) ; # id=mac
2019-05-19 06:19:20 +00:00
}
2018-06-10 15:42:35 +00:00
return undef ;
}
2015-08-23 00:13:22 +00:00
###############################################################################
sub Unifi_DoUpdate ($@) {
my ( $ hash , $ manual ) = @ _ ;
2015-08-25 21:29:35 +00:00
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
Log3 $ name , 5 , "$name ($self) - executed." ;
2015-08-23 00:13:22 +00:00
2015-08-25 21:29:35 +00:00
if ( Unifi_CONNECTED ( $ hash ) eq "disabled" ) {
Log3 $ name , 5 , "$name ($self) - Device '$name' is disabled, End now..." ;
2015-08-23 16:53:57 +00:00
return undef ;
}
2015-08-25 21:29:35 +00:00
if ( Unifi_CONNECTED ( $ hash ) ) {
2019-05-25 16:19:00 +00:00
# nach Neustart wird restoreClients in notify gef<65> llt. Muss beim ersten Update nach dem Login erledigt werden
if ( defined $ hash - > { restoreClients } ) {
Log3 $ name , 5 , "$name ($self) - restore clients" ;
for my $ mac ( keys % { $ hash - > { restoreClients } } ) {
Log3 $ name , 5 , "$name ($self) - restore mac $mac" ;
Unifi_UpdateClient_Send ( $ hash , $ mac ) ;
}
delete $ hash - > { restoreClients } ;
}
2015-08-29 19:25:28 +00:00
$ hash - > { unifi } - > { updateStartTime } = time ( ) ;
2015-08-25 21:29:35 +00:00
$ hash - > { updateDispatch } = { # {updateDispatch}->{callFn}[callFnRef,'receiveFn',receiveFnRef]
Unifi_GetClients_Send = > [ \ & Unifi_GetClients_Send , 'Unifi_GetClients_Receive' , \ & Unifi_GetClients_Receive ] ,
2019-05-19 06:19:20 +00:00
Unifi_GetClientInsights_Send = > [ \ & Unifi_GetClientInsights_Send , 'Unifi_GetClientInsights_Receive' , \ & Unifi_GetClientInsights_Receive ] ,
#Unifi_UsergroupRestJson_Send => [\&Unifi_UsergroupRestJson_Send,'Unifi_UsergroupRestJson_Receive',\&Unifi_UsergroupRestJson_Receive],
2015-08-29 19:25:28 +00:00
Unifi_GetAccesspoints_Send = > [ \ & Unifi_GetAccesspoints_Send , 'Unifi_GetAccesspoints_Receive' , \ & Unifi_GetAccesspoints_Receive ] ,
Unifi_GetWlans_Send = > [ \ & Unifi_GetWlans_Send , 'Unifi_GetWlans_Receive' , \ & Unifi_GetWlans_Receive ] ,
2018-02-05 20:45:17 +00:00
Unifi_GetVoucherList_Send = > [ \ & Unifi_GetVoucherList_Send , 'Unifi_GetVoucherList_Receive' , \ & Unifi_GetVoucherList_Receive ] ,
2015-08-29 19:25:28 +00:00
Unifi_GetUnarchivedAlerts_Send = > [ \ & Unifi_GetUnarchivedAlerts_Send , 'Unifi_GetUnarchivedAlerts_Receive' , \ & Unifi_GetUnarchivedAlerts_Receive ] ,
Unifi_GetEvents_Send = > [ \ & Unifi_GetEvents_Send , 'Unifi_GetEvents_Receive' , \ & Unifi_GetEvents_Receive ] ,
2015-08-31 22:29:29 +00:00
# Unifi_GetWlanGroups_Send => [\&Unifi_GetWlanGroups_Send,'Unifi_GetWlanGroups_Receive',\&Unifi_GetWlanGroups_Receive],
Unifi_GetHealth_Send = > [ \ & Unifi_GetHealth_Send , 'Unifi_GetHealth_Receive' , \ & Unifi_GetHealth_Receive ] ,
2015-08-29 19:25:28 +00:00
Unifi_ProcessUpdate = > [ \ & Unifi_ProcessUpdate , '' ] ,
2015-08-25 21:29:35 +00:00
} ;
Unifi_NextUpdateFn ( $ hash , $ self ) ;
}
else {
Unifi_CONNECTED ( $ hash , 'disconnected' ) ;
2015-08-24 21:43:54 +00:00
Unifi_Login_Send ( $ hash )
2015-08-23 00:13:22 +00:00
}
return undef ;
}
###############################################################################
sub Unifi_Login_Send ($) {
my ( $ hash ) = @ _ ;
2015-08-25 21:29:35 +00:00
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
Log3 $ name , 5 , "$name ($self) - executed." ;
2018-03-11 14:54:39 +00:00
my ( $ loginurl , $ logindata ) ;
my $ user = $ hash - > { helper } { username } ;
my $ password = $ hash - > { helper } { password } ;
$ user = Unifi_decrypt ( $ user ) ;
$ password = Unifi_decrypt ( $ password ) ;
2019-03-16 13:16:35 +00:00
( $ loginurl = $ hash - > { unifi } - > { url } ) =~ s/api\/s.+/api\/login/ ;
$ logindata = '{"username":"' . $ user . '", "password":"' . $ password . '"}' ;
2015-08-29 19:25:28 +00:00
HttpUtils_NonblockingGet ( {
% { $ hash - > { httpParams } } ,
2018-03-11 14:54:39 +00:00
url = > $ loginurl ,
data = > $ logindata ,
2015-08-29 19:25:28 +00:00
callback = > \ & Unifi_Login_Receive
} ) ;
2015-08-23 00:13:22 +00:00
return undef ;
}
sub Unifi_Login_Receive ($) {
my ( $ param , $ err , $ data ) = @ _ ;
2015-08-25 21:29:35 +00:00
my ( $ name , $ self , $ hash ) = ( $ param - > { hash } - > { NAME } , Unifi_Whoami ( ) , $ param - > { hash } ) ;
Log3 $ name , 5 , "$name ($self) - executed." ;
2015-08-23 00:13:22 +00:00
if ( $ err ne "" ) {
2015-08-25 21:29:35 +00:00
Log3 $ name , 5 , "$name ($self) - Error while requesting " . $ param - > { url } . " - $err" ;
2015-08-23 00:13:22 +00:00
}
2019-03-16 13:16:35 +00:00
elsif ( $ data ne "" ) {
if ( $ param - > { code } == 200 || $ param - > { code } == 400 || $ param - > { code } == 401 || $ param - > { code } == 200 ) {
2015-08-29 19:25:28 +00:00
eval { $ data = decode_json ( $ data ) ; 1 ; } or do { $ data = { meta = > { rc = > 'error.decode_json' , msg = > $@ } } ; } ;
2019-03-16 13:16:35 +00:00
if ( $ data - > { meta } - > { rc } eq "ok" ) {
Log3 $ name , 5 , "$name ($self) - state=ok" ;
2015-08-29 19:25:28 +00:00
$ hash - > { httpParams } - > { header } = '' ;
2015-08-23 00:13:22 +00:00
for ( split ( "\r\n" , $ param - > { httpheader } ) ) {
if ( /^Set-Cookie/ ) {
s/Set-Cookie:\s(.*?);.*/Cookie: $1/ ;
2018-05-10 14:43:22 +00:00
$ hash - > { httpParams } - > { header } . = 'Cookie: ' . $ 1 . ';\r\n' ;
2015-08-23 00:13:22 +00:00
}
}
2015-08-29 19:25:28 +00:00
if ( $ hash - > { httpParams } - > { header } ne '' ) {
$ hash - > { httpParams } - > { header } =~ s/\\r\\n$// ;
Log3 $ name , 5 , "$name ($self) - Login successfully! $hash->{httpParams}->{header}" ;
2015-08-25 21:29:35 +00:00
Unifi_CONNECTED ( $ hash , 'connected' ) ;
2019-03-27 22:12:52 +00:00
Unifi_GetSysinfo_Send ( $ hash ) ;
2019-05-19 06:19:20 +00:00
Unifi_UsergroupRestJson_Send ( $ hash ) ;
2019-03-27 22:12:52 +00:00
#Unifi_DoUpdate($hash);
InternalTimer ( time ( ) + $ hash - > { unifi } - > { interval } , 'Unifi_DoUpdate' , $ hash , 0 ) ;
2015-08-25 21:29:35 +00:00
return undef ;
} else {
2015-08-29 19:25:28 +00:00
$ hash - > { httpParams } - > { header } = undef ;
2015-08-25 21:29:35 +00:00
Log3 $ name , 5 , "$name ($self) - Something went wrong, login seems ok but no cookies received." ;
2015-08-24 21:43:54 +00:00
}
2015-08-23 00:13:22 +00:00
}
else {
if ( defined ( $ data - > { meta } - > { msg } ) ) {
2015-08-24 21:43:54 +00:00
if ( $ data - > { meta } - > { msg } eq 'api.err.Invalid' ) {
2015-08-25 21:29:35 +00:00
Log3 $ name , 1 , "$name ($self) - Login Failed! Invalid username or password!"
. " - state:'$data->{meta}->{rc}' - msg:'$data->{meta}->{msg}'" ;
2015-08-24 21:43:54 +00:00
} elsif ( $ data - > { meta } - > { msg } eq 'api.err.LoginRequired' ) {
2015-08-25 21:29:35 +00:00
Log3 $ name , 1 , "$name ($self) - Login Failed! - state:'$data->{meta}->{rc}' - msg:'$data->{meta}->{msg}' -"
2019-03-16 13:16:35 +00:00
. " This error while login indicates that you use an unsupported UnifiController-version" ;
2015-08-25 21:29:35 +00:00
} else {
Log3 $ name , 5 , "$name ($self) - Login Failed! - state:'$data->{meta}->{rc}' - msg:'$data->{meta}->{msg}'" ;
2015-08-24 21:43:54 +00:00
}
2015-08-23 00:13:22 +00:00
} else {
2015-08-27 20:37:29 +00:00
Log3 $ name , 5 , "$name ($self) - Login Failed (without msg)! - state:'$data->{meta}->{rc}'" ;
2015-08-23 00:13:22 +00:00
}
2015-08-29 19:25:28 +00:00
$ hash - > { httpParams } - > { header } = undef ;
2015-08-23 00:13:22 +00:00
}
} else {
2015-08-25 21:29:35 +00:00
Log3 $ name , 5 , "$name ($self) - Failed with HTTP Code $param->{code}!" ;
2015-08-23 00:13:22 +00:00
}
2015-08-25 21:29:35 +00:00
} else {
Log3 $ name , 5 , "$name ($self) - Failed because no data was received!" ;
2015-08-23 00:13:22 +00:00
}
2015-08-25 21:29:35 +00:00
Log3 $ name , 5 , "$name ($self) - Connect/Login to Unifi-Controller failed. Will try again after interval..." ;
Unifi_CONNECTED ( $ hash , 'disconnected' ) ;
2015-08-29 19:25:28 +00:00
InternalTimer ( time ( ) + $ hash - > { unifi } - > { interval } , 'Unifi_Login_Send' , $ hash , 0 ) ;
2015-08-23 00:13:22 +00:00
return undef ;
}
###############################################################################
sub Unifi_GetClients_Send ($) {
my ( $ hash ) = @ _ ;
2015-08-25 21:29:35 +00:00
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
Log3 $ name , 5 , "$name ($self) - executed." ;
2015-08-23 16:53:57 +00:00
2015-08-29 19:25:28 +00:00
HttpUtils_NonblockingGet ( {
% { $ hash - > { httpParams } } ,
2016-02-29 13:38:53 +00:00
method = > "GET" ,
2015-08-29 19:25:28 +00:00
url = > $ hash - > { unifi } - > { url } . "stat/sta" ,
2015-08-25 21:29:35 +00:00
callback = > $ hash - > { updateDispatch } - > { $ self } [ 2 ]
2015-08-29 19:25:28 +00:00
} ) ;
2015-08-23 00:13:22 +00:00
return undef ;
}
2019-03-24 07:37:28 +00:00
###############################################################################
2015-08-23 00:13:22 +00:00
sub Unifi_GetClients_Receive ($) {
my ( $ param , $ err , $ data ) = @ _ ;
2015-08-25 21:29:35 +00:00
my ( $ name , $ self , $ hash ) = ( $ param - > { hash } - > { NAME } , Unifi_Whoami ( ) , $ param - > { hash } ) ;
Log3 $ name , 5 , "$name ($self) - executed." ;
2015-08-23 00:13:22 +00:00
if ( $ err ne "" ) {
2015-08-29 19:25:28 +00:00
Unifi_ReceiveFailure ( $ hash , { rc = > 'Error while requesting' , msg = > $ param - > { url } . " - $err" } ) ;
2015-08-23 00:13:22 +00:00
}
elsif ( $ data ne "" ) {
2015-08-24 21:43:54 +00:00
if ( $ param - > { code } == 200 || $ param - > { code } == 400 || $ param - > { code } == 401 ) {
2015-08-29 19:25:28 +00:00
eval { $ data = decode_json ( $ data ) ; 1 ; } or do { $ data = { meta = > { rc = > 'error.decode_json' , msg = > $@ } } ; } ;
2015-08-23 00:13:22 +00:00
if ( $ data - > { meta } - > { rc } eq "ok" ) {
2015-08-25 21:29:35 +00:00
Log3 $ name , 5 , "$name ($self) - state:'$data->{meta}->{rc}'" ;
2019-05-19 06:19:20 +00:00
2015-08-29 19:25:28 +00:00
$ hash - > { unifi } - > { connectedClients } = undef ;
2015-08-23 00:13:22 +00:00
for my $ h ( @ { $ data - > { data } } ) {
2015-09-03 18:15:12 +00:00
$ hash - > { unifi } - > { connectedClients } - > { $ h - > { user_id } } = 1 ;
$ hash - > { clients } - > { $ h - > { user_id } } = $ h ;
2019-05-19 06:19:20 +00:00
# mergen mit den clientInsights. ACHTUNG: dasselbe muss aufgrund unbekannter Reihenfolge der Aufrufe auch in GetClientInsights_Receive und UpdateClient_Receive durchgef<65> hrt werden.
if ( defined $ hash - > { unifi } - > { clientInsights } - > { $ h - > { user_id } } ) {
if ( defined $ hash - > { unifi } - > { clientInsights } - > { $ h - > { user_id } } - > { blocked } && $ hash - > { unifi } - > { clientInsights } - > { $ h - > { user_id } } - > { blocked } eq JSON:: true ) {
$ hash - > { clients } - > { $ h - > { user_id } } - > { blocked } = JSON:: true ;
} else {
$ hash - > { clients } - > { $ h - > { user_id } } - > { blocked } = JSON:: false ;
}
}
2015-08-23 00:13:22 +00:00
}
2015-08-29 19:25:28 +00:00
}
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 ;
}
###############################################################################
2019-03-24 07:37:28 +00:00
2019-05-19 06:19:20 +00:00
sub Unifi_GetClientInsights_Send ($) {
my ( $ hash ) = @ _ ;
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
Log3 $ name , 5 , "$name ($self) - executed." ;
#my $within=$hash->{unifi}->{readClientInsights}->{attr_value} if defined $hash->{unifi}->{readClientInsights};
#if (defined $within){
HttpUtils_NonblockingGet ( {
% { $ hash - > { httpParams } } ,
method = > "GET" ,
url = > $ hash - > { unifi } - > { url } . "stat/alluser?within=" . ( 365 * 24 ) ,
callback = > \ & Unifi_GetClientInsights_Receive ,
} ) ;
#}
return undef ;
}
sub Unifi_GetClientInsights_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}'" ;
$ hash - > { unifi } - > { clientInsights } = undef ;
for my $ h ( @ { $ data - > { data } } ) {
$ hash - > { unifi } - > { clientInsights } - > { $ h - > { _id } } = $ h ;
# mergen mit den clients. ACHTUNG: dasselbe muss aufgrund unbekannter Reihenfolge der Aufrufe auch in GetClients_Receive und UpdateClient_Receive durchgef<65> hrt werden.
if ( defined $ hash - > { clients } - > { $ h - > { _id } } ) {
if ( defined $ h - > { blocked } && $ h - > { blocked } eq JSON:: true ) {
$ hash - > { clients } - > { $ h - > { _id } } - > { blocked } = JSON:: true ;
} else {
$ hash - > { clients } - > { $ h - > { _id } } - > { blocked } = JSON:: false ;
}
}
}
}
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 ;
}
###############################################################################
2019-03-24 07:37:28 +00:00
sub Unifi_UpdateClient_Send ($$) {
my ( $ hash , $ mac ) = @ _ ;
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
2019-05-25 16:19:00 +00:00
if ( defined $ mac && $ mac ne "" ) {
Log3 $ name , 5 , "$name ($self) - executed with mac " . $ mac ;
HttpUtils_NonblockingGet ( {
% { $ hash - > { httpParams } } ,
method = > "GET" ,
url = > $ hash - > { unifi } - > { url } . "stat/user/" . $ mac ,
callback = > \ & Unifi_UpdateClient_Receive
} ) ;
} else {
Log3 $ name , 4 , "$name ($self) - executed without mac." ;
}
2019-03-24 07:37:28 +00:00
return undef ;
}
###############################################################################
sub Unifi_UpdateClient_Receive ($) {
my ( $ param , $ err , $ data ) = @ _ ;
my ( $ name , $ self , $ hash ) = ( $ param - > { hash } - > { NAME } , Unifi_Whoami ( ) , $ param - > { hash } ) ;
Log3 $ name , 5 , "$name ($self) - executed." ;
2019-05-22 20:13:24 +00:00
#Log3 $name, 1, "$name ($self) - executed. $data";
2019-03-24 07:37:28 +00:00
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}'" ;
2019-05-22 20:13:24 +00:00
2019-03-24 07:37:28 +00:00
for my $ h ( @ { $ data - > { data } } ) {
2019-05-22 20:13:24 +00:00
if ( defined $ h - > { ip } ) {
$ hash - > { unifi } - > { connectedClients } - > { $ h - > { _id } } = 1 ;
} else {
delete $ hash - > { unifi } - > { connectedClients } - > { $ h - > { _id } } ;
}
$ hash - > { clients } - > { $ h - > { _id } } = $ h ;
2019-05-19 06:19:20 +00:00
# mergen mit den clientInsights. ACHTUNG: dasselbe muss aufgrund unbekannter Reihenfolge der Aufrufe auch in GetClientInsights_Receive und GetClients_Receive durchgef<65> hrt werden.
2019-05-22 20:13:24 +00:00
if ( defined $ hash - > { unifi } - > { clientInsights } - > { $ h - > { _id } } ) {
if ( defined $ hash - > { unifi } - > { clientInsights } - > { $ h - > { _id } } - > { blocked } && $ hash - > { unifi } - > { clientInsights } - > { $ h - > { _id } } - > { blocked } eq JSON:: true ) {
$ hash - > { clients } - > { $ h - > { _id } } - > { blocked } = JSON:: true ;
2019-05-19 06:19:20 +00:00
} else {
2019-05-22 20:13:24 +00:00
$ hash - > { clients } - > { $ h - > { _id } } - > { blocked } = JSON:: false ;
2019-05-19 06:19:20 +00:00
}
}
2019-03-24 07:37:28 +00:00
readingsBeginUpdate ( $ hash ) ;
2019-05-22 20:13:24 +00:00
Unifi_SetClientReadings ( $ hash , $ h - > { _id } ) ;
2019-03-24 07:37:28 +00:00
readingsEndUpdate ( $ hash , 1 ) ;
}
}
else { Unifi_ReceiveFailure ( $ hash , $ data - > { meta } ) ; }
} else {
Unifi_ReceiveFailure ( $ hash , { rc = > $ param - > { code } , msg = > "Failed with HTTP Code $param->{code}." } ) ;
}
}
return undef ;
}
###############################################################################
2015-08-29 19:25:28 +00:00
sub Unifi_GetWlans_Send ($) {
my ( $ hash ) = @ _ ;
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
Log3 $ name , 5 , "$name ($self) - executed." ;
HttpUtils_NonblockingGet ( {
% { $ hash - > { httpParams } } ,
2016-02-29 13:38:53 +00:00
method = > "GET" ,
2015-08-29 19:25:28 +00:00
url = > $ hash - > { unifi } - > { url } . "list/wlanconf" ,
callback = > $ hash - > { updateDispatch } - > { $ self } [ 2 ] ,
} ) ;
return undef ;
}
sub Unifi_GetWlans_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 - > { wlans } - > { $ h - > { _id } } = $ h ;
2018-01-17 22:38:27 +00:00
#TODO: Passphrase ggf. verschl<68> sseln?!
#Ich musste diese Zeile rausnehmen, sonst ist das Json f<> r enable/disableWLAN bei offenem WLAN (ohne Passphrase) falsch
#Aussternen geht nicht, sonst wird das PW unter Umst<73> nden darauf ge<67> ndert.
2018-01-12 20:39:58 +00:00
#$hash->{wlans}->{$h->{_id}}->{x_passphrase} = '***'; # Don't show passphrase in list
2018-02-05 20:45:17 +00:00
delete $ hash - > { wlans } - > { $ h - > { _id } } - > { x_passphrase } ;
2015-08-23 00:13:22 +00:00
}
}
2015-08-29 19:25:28 +00:00
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 ;
}
###############################################################################
2015-08-31 22:29:29 +00:00
sub Unifi_GetHealth_Send ($) {
my ( $ hash ) = @ _ ;
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
Log3 $ name , 5 , "$name ($self) - executed." ;
HttpUtils_NonblockingGet ( {
% { $ hash - > { httpParams } } ,
2016-02-29 13:38:53 +00:00
method = > "GET" ,
2015-08-31 22:29:29 +00:00
url = > $ hash - > { unifi } - > { url } . "stat/health" ,
callback = > $ hash - > { updateDispatch } - > { $ self } [ 2 ] ,
} ) ;
return undef ;
}
sub Unifi_GetHealth_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 } } ) {
if ( defined ( $ h - > { subsystem } ) && $ h - > { subsystem } eq 'wlan' ) {
$ hash - > { wlan_health } = $ h ;
}
2018-10-31 10:53:51 +00:00
if ( defined ( $ h - > { subsystem } ) && $ h - > { subsystem } eq 'www' ) {
$ hash - > { www_health } = $ h ;
}
if ( defined ( $ h - > { subsystem } ) && $ h - > { subsystem } eq 'wan' ) {
$ hash - > { wan_health } = $ h ;
}
2015-08-31 22:29:29 +00:00
}
}
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 ;
}
###############################################################################
2019-03-27 22:12:52 +00:00
sub Unifi_GetSysinfo_Send ($) {
my ( $ hash ) = @ _ ;
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
Log3 $ name , 5 , "$name ($self) - executed." ;
HttpUtils_NonblockingGet ( {
% { $ hash - > { httpParams } } ,
method = > "GET" ,
url = > $ hash - > { unifi } - > { url } . "stat/sysinfo" ,
callback = > \ & Unifi_GetSysinfo_Receive ,
} ) ;
return undef ;
}
sub Unifi_GetSysinfo_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 - > { UC_VERSION } = $ h - > { version } if defined $ h - > { version } ;
Log3 $ name , 5 , "$name ($self) - uc_version: " . $ hash - > { UC_VERSION } ;
}
}
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 ;
}
###############################################################################
2015-08-29 19:25:28 +00:00
sub Unifi_GetWlanGroups_Send ($) {
my ( $ hash ) = @ _ ;
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
Log3 $ name , 5 , "$name ($self) - executed." ;
HttpUtils_NonblockingGet ( {
% { $ hash - > { httpParams } } ,
2016-02-29 13:38:53 +00:00
method = > "GET" ,
2015-08-29 19:25:28 +00:00
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 } } ) {
2015-08-31 22:29:29 +00:00
$ hash - > { wlangroup } - > { $ h - > { _id } } = $ h ;
2015-08-23 00:13:22 +00:00
}
}
2015-08-29 19:25:28 +00:00
else { Unifi_ReceiveFailure ( $ hash , $ data - > { meta } ) ; }
} else {
Unifi_ReceiveFailure ( $ hash , { rc = > $ param - > { code } , msg = > "Failed with HTTP Code $param->{code}." } ) ;
2015-08-23 00:13:22 +00:00
}
2015-08-29 19:25:28 +00:00
}
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 ] ,
2019-03-28 17:30:26 +00:00
data = > "{\"_sort\":\"-time\", \"archived\":false}" ,
2015-08-29 19:25:28 +00:00
} ) ;
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}'" ;
2015-08-31 22:29:29 +00:00
$ hash - > { alerts_unarchived } = $ data - > { data } ; #array
2015-08-29 19:25:28 +00:00
}
else { Unifi_ReceiveFailure ( $ hash , $ data - > { meta } ) ; }
} else {
Unifi_ReceiveFailure ( $ hash , { rc = > $ param - > { code } , msg = > "Failed with HTTP Code $param->{code}." } ) ;
2015-08-25 21:29:35 +00:00
}
}
2015-08-29 19:25:28 +00:00
2015-08-25 21:29:35 +00:00
Unifi_NextUpdateFn ( $ hash , $ self ) ;
return undef ;
}
###############################################################################
2015-08-29 19:25:28 +00:00
sub Unifi_GetEvents_Send ($) {
2015-08-25 21:29:35 +00:00
my ( $ hash ) = @ _ ;
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
Log3 $ name , 5 , "$name ($self) - executed." ;
2015-08-29 19:25:28 +00:00
HttpUtils_NonblockingGet ( {
% { $ hash - > { httpParams } } ,
url = > $ hash - > { unifi } - > { url } . "stat/event" ,
callback = > $ hash - > { updateDispatch } - > { $ self } [ 2 ] ,
2019-03-28 17:30:26 +00:00
data = > "{\"_sort\":\"-time\", \"within\":" . $ hash - > { unifi } - > { eventPeriod } . "}" , # last 24 hours
2015-08-29 19:25:28 +00:00
} ) ;
2015-08-25 21:29:35 +00:00
return undef ;
}
2015-08-29 19:25:28 +00:00
sub Unifi_GetEvents_Receive ($) {
2015-08-25 21:29:35 +00:00
my ( $ param , $ err , $ data ) = @ _ ;
my ( $ name , $ self , $ hash ) = ( $ param - > { hash } - > { NAME } , Unifi_Whoami ( ) , $ param - > { hash } ) ;
2015-08-29 19:25:28 +00:00
Log3 $ name , 5 , "$name ($self) - executed." ;
2015-08-25 21:29:35 +00:00
2015-08-29 19:25:28 +00:00
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}'" ;
2015-08-31 22:29:29 +00:00
$ hash - > { events } = $ data - > { data } ; #array
2015-08-29 19:25:28 +00:00
}
else { Unifi_ReceiveFailure ( $ hash , $ data - > { meta } ) ; }
} else {
Unifi_ReceiveFailure ( $ hash , { rc = > $ param - > { code } , msg = > "Failed with HTTP Code $param->{code}." } ) ;
}
}
2015-08-25 21:29:35 +00:00
Unifi_NextUpdateFn ( $ hash , $ self ) ;
return undef ;
}
###############################################################################
2015-08-29 19:25:28 +00:00
sub Unifi_GetAccesspoints_Send ($) {
2015-08-25 21:29:35 +00:00
my ( $ hash ) = @ _ ;
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
Log3 $ name , 5 , "$name ($self) - executed." ;
2015-08-29 19:25:28 +00:00
HttpUtils_NonblockingGet ( {
% { $ hash - > { httpParams } } ,
url = > $ hash - > { unifi } - > { url } . "stat/device" ,
callback = > $ hash - > { updateDispatch } - > { $ self } [ 2 ] ,
2019-03-28 17:30:26 +00:00
data = > "{\"_depth\":2, \"test\":0}" ,
2015-08-29 19:25:28 +00:00
} ) ;
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 ;
2018-06-10 15:42:35 +00:00
#TODO: Switch-Modelle anders festlegen ? Oder passt usw?
if ( defined $ h - > { model } && $ h - > { type } eq "usw" ) {
my $ usw_name = "" ;
if ( defined $ h - > { name } ) {
$ usw_name = makeDeviceName ( $ h - > { name } ) ;
} else {
$ usw_name = makeDeviceName ( $ h - > { ip } ) ;
}
Dispatch ( $ hash , "UnifiSwitch_" . $ usw_name . encode_json ( $ h ) , undef ) ;
}
2015-08-29 19:25:28 +00:00
}
}
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_ProcessUpdate ($) {
my ( $ hash ) = @ _ ;
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
Log3 $ name , 5 , "$name ($self) - executed after " . sprintf ( '%.4f' , time ( ) - $ hash - > { unifi } - > { updateStartTime } ) . " seconds." ;
readingsBeginUpdate ( $ hash ) ;
#'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''#
2015-08-31 22:29:29 +00:00
Unifi_SetHealthReadings ( $ hash ) ;
2019-05-22 20:13:24 +00:00
Unifi_SetClientReadings ( $ hash , undef ) ;
2015-08-31 22:29:29 +00:00
Unifi_SetAccesspointReadings ( $ hash ) ;
2018-01-21 19:51:41 +00:00
Unifi_SetWlanReadings ( $ hash ) ;
2018-02-05 20:45:17 +00:00
Unifi_SetVoucherReadings ( $ hash ) ;
2015-08-31 22:29:29 +00:00
## WLANGROUPS ???
#'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''#
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 ;
}
###############################################################################
2019-05-22 20:13:24 +00:00
sub Unifi_SetClientReadings ($$) {
my ( $ hash , $ updatedClientID ) = @ _ ;
2015-08-31 22:29:29 +00:00
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
Log3 $ name , 5 , "$name ($self) - executed." ;
2019-03-25 20:02:14 +00:00
2017-04-27 22:46:25 +00:00
my $ apNames = { } ;
for my $ apID ( keys % { $ hash - > { accespoints } } ) {
my $ apRef = $ hash - > { accespoints } - > { $ apID } ;
$ apNames - > { $ apRef - > { mac } } = $ apRef - > { name } ? $ apRef - > { name } : $ apRef - > { ip } ;
}
my $ ignoreWired = AttrVal ( $ name , "ignoreWiredClients" , undef ) ;
my $ ignoreWireless = AttrVal ( $ name , "ignoreWirelessClients" , undef ) ;
my ( $ apName , $ clientName , $ clientRef ) ;
2018-06-10 15:42:35 +00:00
my $ newClients = "" ;
2019-05-19 06:19:20 +00:00
my $ blockedClients = "" ;
2015-08-29 19:25:28 +00:00
for my $ clientID ( keys % { $ hash - > { clients } } ) {
$ clientRef = $ hash - > { clients } - > { $ clientID } ;
2019-05-22 20:13:24 +00:00
if ( ! defined $ updatedClientID || $ updatedClientID eq $ clientID ) {
$ clientName = Unifi_ClientNames ( $ hash , $ clientID , 'makeAlias' ) ;
next if ( $ ignoreWired && $ clientRef - > { is_wired } ) ;
next if ( $ ignoreWireless && ! $ clientRef - > { is_wired } ) ;
{
$ apName = "unknown" ;
if ( $ clientRef - > { is_wired }
&& defined $ clientRef - > { sw_mac } && defined ( $ apNames - > { $ clientRef - > { sw_mac } } ) ) {
$ apName = $ apNames - > { $ clientRef - > { sw_mac } } ;
} elsif ( defined $ clientRef - > { ap_mac } && defined ( $ apNames - > { $ clientRef - > { ap_mac } } ) ) {
$ apName = $ apNames - > { $ clientRef - > { ap_mac } } ;
}
$ clientRef - > { accesspoint } = $ apName ;
2019-03-20 19:15:01 +00:00
2019-05-22 20:13:24 +00:00
# ein paar Daten auch formatiert zur Verf<72> gung stellen
# falls man Sonderzeichen im WLAN-Namen hat und damit auf ein entsprechendes WLAN-Reading zugreifen m<> chte
$ clientRef - > { _f_essid } = makeReadingName ( $ clientRef - > { essid } ) ;
# Einige Zeitformatierungen:
$ clientRef - > { _f_last_seen } = strftime "%Y-%m-%d %H:%M:%S" , localtime ( $ clientRef - > { last_seen } ) if defined $ clientRef - > { last_seen } ;
$ clientRef - > { _f_latest_assoc_time } = strftime "%Y-%m-%d %H:%M:%S" , localtime ( $ clientRef - > { latest_assoc_time } ) if defined $ clientRef - > { latest_assoc_time } ;
$ clientRef - > { _f_first_seen } = strftime "%Y-%m-%d %H:%M:%S" , localtime ( $ clientRef - > { first_seen } ) if defined $ clientRef - > { first_seen } ;
$ clientRef - > { _f_last_seen_by_usw } = strftime "%Y-%m-%d %H:%M:%S" , localtime ( $ clientRef - > { _last_seen_by_usw } ) if defined $ clientRef - > { _last_seen_by_usw } ;
$ clientRef - > { _f_last_seen_by_ugw } = strftime "%Y-%m-%d %H:%M:%S" , localtime ( $ clientRef - > { _last_seen_by_ugw } ) if defined $ clientRef - > { _last_seen_by_ugw } ;
$ clientRef - > { _f_last_seen_by_uap } = strftime "%Y-%m-%d %H:%M:%S" , localtime ( $ clientRef - > { _last_seen_by_uap } ) if defined $ clientRef - > { _last_seen_by_uap } ;
if ( defined $ clientRef - > { last_seen } ) {
my ( $ sec , $ min , $ hour , $ mday , $ mon , $ year , $ wday , $ yday , $ isdst ) = gmtime ( time ( ) - $ clientRef - > { last_seen } ) ;
$ clientRef - > { _f_last_seen_duration } = $ yday . "d " . $ hour . "h " . $ min . "m " . $ sec . "s" ;
}
if ( defined $ clientRef - > { uptime } ) {
my ( $ sec , $ min , $ hour , $ mday , $ mon , $ year , $ wday , $ yday , $ isdst ) = gmtime ( $ clientRef - > { uptime } ) ;
$ clientRef - > { _f_uptime } = $ yday . "d " . $ hour . "h " . $ min . "m " . $ sec . "s" ;
}
if ( defined $ clientRef - > { dhcpend_time } ) {
my ( $ sec , $ min , $ hour , $ mday , $ mon , $ year , $ wday , $ yday , $ isdst ) = gmtime ( $ clientRef - > { dhcpend_time } ) ;
$ clientRef - > { _f_dhcpend_time } = $ yday . "d " . $ hour . "h " . $ min . "m " . $ sec . "s" ;
}
if ( defined $ clientRef - > { assoc_time } ) {
my ( $ sec , $ min , $ hour , $ mday , $ mon , $ year , $ wday , $ yday , $ isdst ) = gmtime ( $ clientRef - > { assoc_time } ) ;
$ clientRef - > { _f_assoc_time } = $ yday . "d " . $ hour . "h " . $ min . "m " . $ sec . "s" ;
}
if ( defined $ clientRef - > { _uptime_by_usw } ) {
my ( $ sec , $ min , $ hour , $ mday , $ mon , $ year , $ wday , $ yday , $ isdst ) = gmtime ( $ clientRef - > { _uptime_by_usw } ) ;
$ clientRef - > { _f_uptime_by_usw } = $ yday . "d " . $ hour . "h " . $ min . "m " . $ sec . "s" ;
}
if ( defined $ clientRef - > { _uptime_by_ugw } ) {
my ( $ sec , $ min , $ hour , $ mday , $ mon , $ year , $ wday , $ yday , $ isdst ) = gmtime ( $ clientRef - > { _uptime_by_ugw } ) ;
$ clientRef - > { _f_uptime_by_ugw } = $ yday . "d " . $ hour . "h " . $ min . "m " . $ sec . "s" ;
}
if ( defined $ clientRef - > { _uptime_by_uap } ) {
my ( $ sec , $ min , $ hour , $ mday , $ mon , $ year , $ wday , $ yday , $ isdst ) = gmtime ( $ clientRef - > { _uptime_by_uap } ) ;
$ clientRef - > { _f_uptime_by_uap } = $ yday . "d " . $ hour . "h " . $ min . "m " . $ sec . "s" ;
}
my $ tx = ReadingsVal ( $ name , $ clientName . "_tx_bytes" , "" ) ;
if ( $ tx ne "" && defined $ clientRef - > { tx_bytes } ) {
$ clientRef - > { _f_diff_tx_bytes } = ( $ clientRef - > { tx_bytes } ) - ( $ tx ) ;
}
if ( defined $ clientRef - > { usergroup_id } && defined $ hash - > { unifi } - > { usergroups } - > { $ clientRef - > { usergroup_id } } ) {
$ clientRef - > { _f_usergroup_name } = $ hash - > { unifi } - > { usergroups } - > { $ clientRef - > { usergroup_id } } - > { name } ;
} else {
$ clientRef - > { _f_usergroup_name } = "Default" ;
}
$ clientRef - > { fhem_clientName } = $ clientName ;
2019-03-20 19:15:01 +00:00
}
2019-05-22 20:13:24 +00:00
if ( defined $ hash - > { unifi } - > { connectedClients } - > { $ clientID } ) {
if ( ! defined ReadingsVal ( $ hash - > { NAME } , $ clientName , undef ) ) {
$ newClients . = $ clientName . "," ;
}
$ clientRef - > { fhem_state } = "connected" ;
readingsBulkUpdate ( $ hash , $ clientName , 'connected' ) ;
2019-05-25 16:19:00 +00:00
#readingsBulkUpdate($hash,".".$clientName."_id",$clientRef->{_id});
# mac-Adresse in den Readings versteckt (statet mit .) speichern, um nach einem Neustart den client restoren zu k<> nnen
readingsBulkUpdate ( $ hash , "." . $ clientName . "_mac" , $ clientRef - > { mac } ) if defined $ clientRef - > { mac } ;
2019-03-20 19:15:01 +00:00
}
2019-05-22 20:13:24 +00:00
elsif ( ( ! defined ( $ hash - > { READINGS } - > { $ clientName } ) ) || ( defined ( $ hash - > { READINGS } - > { $ clientName } ) && $ hash - > { READINGS } - > { $ clientName } ne "disconnected" ) ) {
Log3 $ name , 5 , "$name ($self) - Client '$clientName' previously connected is now disconnected." ;
if ( defined $ clientRef - > { blocked } && $ clientRef - > { blocked } eq JSON:: true ) {
$ blockedClients . = $ clientName . ',' ;
}
$ clientRef - > { fhem_state } = "disconnected" ;
readingsBulkUpdate ( $ hash , $ clientName , 'disconnected' ) ;
2019-05-19 06:19:20 +00:00
}
2019-05-22 20:13:24 +00:00
# altes Standardverhalten kann man auch ohne RegEx-Auswertungen beibehalten
if ( AttrVal ( $ name , "customClientReadings" , $ defaultClientReadings ) eq $ defaultClientReadings ) {
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 . "_snr" , $ clientRef - > { rssi } ) ;
# Da essid auch im Readingnamen bei WLAN verwendet wird, wird aus Konsistenzgr<67> nden hier beim ReadingValue ebenfalls makeReadingName() verwendet.
readingsBulkUpdate ( $ hash , $ clientName . "_essid" , makeReadingName ( $ clientRef - > { essid } ) ) ;
readingsBulkUpdate ( $ hash , $ clientName . "_accesspoint" , $ clientRef - > { accesspoint } ) ;
2019-05-19 06:19:20 +00:00
}
2019-05-22 20:13:24 +00:00
else { # Auswerten des Attribute customClientReadings
for my $ customClientReadingsPart ( keys % { $ hash - > { unifi } - > { customClientReadings } - > { parts } } ) {
my $ reName = "" ;
my $ nameRegEx = $ hash - > { unifi } - > { customClientReadings } - > { parts } - > { $ customClientReadingsPart } - > { nameRegEx } ;
eval { $ reName = qr/$nameRegEx/ ; } ;
if ( $@ ) {
Log3 $ name , 2 , "$name ($self) - Wrong RegEx (" . $ nameRegEx . ") in name-part in attribute customClientReadings!" ;
}
else {
if ( $ clientName =~ m/$reName/ ) { #matched der ClientName?
my $ reReading = "" ;
my $ readingRegEx = $ hash - > { unifi } - > { customClientReadings } - > { parts } - > { $ customClientReadingsPart } - > { ReadingRegEx } ;
eval { $ reReading = qr/($readingRegEx)/ ; } ;
if ( $@ ) {
Log3 $ name , 2 , "$name ($self) - Wrong RegEx (" . $ readingRegEx . ") in reading-part in attribute customClientReadings!" ;
}
else {
for my $ readingName ( sort keys % { $ clientRef } ) {
if ( $ readingName =~ m/$reReading/ ) { #matched der ReadingName?
my $ readingData = ( ( defined ( $ clientRef - > { $ readingName } ) ) ? $ clientRef - > { $ readingName } : '' ) ;
readingsBulkUpdate ( $ hash , $ clientName . "_" . $ readingName , $ readingData ) ;
}
2019-03-20 19:15:01 +00:00
}
}
}
}
}
}
2019-05-22 20:13:24 +00:00
Log3 $ name , 5 , "$name ($self) - Dispatch: " . $ clientName ;
Dispatch ( $ hash , "UnifiClient_" . $ clientName . encode_json ( $ clientRef ) , undef ) ;
2019-03-20 19:15:01 +00:00
}
2015-08-29 19:25:28 +00:00
}
2019-05-19 06:19:20 +00:00
$ newClients =~ s/.$// if $ newClients ne "" ;
$ blockedClients =~ s/.$// if $ blockedClients ne "" ;
2018-07-22 15:16:09 +00:00
readingsBulkUpdate ( $ hash , "-UC_newClients" , $ newClients ) ;
2019-05-19 06:19:20 +00:00
readingsBulkUpdate ( $ hash , "-UC_blockedClients" , $ blockedClients ) ;
2015-08-29 19:25:28 +00:00
2015-08-31 22:29:29 +00:00
return undef ;
}
###############################################################################
sub Unifi_SetHealthReadings ($) {
my ( $ hash ) = @ _ ;
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
Log3 $ name , 5 , "$name ($self) - executed." ;
2015-08-29 19:25:28 +00:00
2018-10-31 10:53:51 +00:00
if ( defined ( $ hash - > { www_health } ) ) {
readingsBulkUpdate ( $ hash , '-UC_speed_ping' , $ hash - > { www_health } - > { speedtest_ping } ) ;
readingsBulkUpdate ( $ hash , '-UC_speed_down' , $ hash - > { www_health } - > { xput_down } ) ;
readingsBulkUpdate ( $ hash , '-UC_speed_up' , $ hash - > { www_health } - > { xput_up } ) ;
}
if ( defined ( $ hash - > { wan_health } ) ) {
readingsBulkUpdate ( $ hash , '-UC_wan_ip' , $ hash - > { wan_health } - > { wan_ip } ) ;
}
2016-02-29 13:38:53 +00:00
readingsBulkUpdate ( $ hash , '-UC_wlan_state' , $ hash - > { wlan_health } - > { status } ) ;
readingsBulkUpdate ( $ hash , '-UC_wlan_users' , $ hash - > { wlan_health } - > { num_user } ) ;
readingsBulkUpdate ( $ hash , '-UC_wlan_accesspoints' , $ hash - > { wlan_health } - > { num_ap } ) ;
readingsBulkUpdate ( $ hash , '-UC_wlan_guests' , $ hash - > { wlan_health } - > { num_guest } ) ;
2017-04-06 07:34:29 +00:00
readingsBulkUpdate ( $ hash , '-UC_unarchived_alerts' , scalar @ { $ hash - > { alerts_unarchived } } ) if ( ref ( $ hash - > { alerts_unarchived } ) eq 'ARRAY' ) ;
readingsBulkUpdate ( $ hash , '-UC_events' , scalar ( @ { $ hash - > { events } } ) . ' (last ' . $ hash - > { unifi } - > { eventPeriod } . 'h)' ) if ( ref ( $ hash - > { events } ) eq 'ARRAY' ) ;
2015-08-31 22:29:29 +00:00
return undef ;
}
###############################################################################
sub Unifi_SetAccesspointReadings ($) {
my ( $ hash ) = @ _ ;
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
Log3 $ name , 5 , "$name ($self) - executed." ;
2018-07-22 15:16:09 +00:00
2015-08-31 22:29:29 +00:00
my ( $ apName , $ apRef , $ essid ) ;
2018-07-22 15:16:09 +00:00
my $ utiliz ;
2015-08-31 22:29:29 +00:00
for my $ apID ( keys % { $ hash - > { accespoints } } ) {
$ essid = '' ;
2018-07-22 15:16:09 +00:00
$ utiliz = '' ;
2015-08-31 22:29:29 +00:00
$ apRef = $ hash - > { accespoints } - > { $ apID } ;
$ apName = ( $ apRef - > { name } ) ? $ apRef - > { name } : $ apRef - > { ip } ;
2018-07-22 15:16:09 +00:00
2015-08-31 22:29:29 +00:00
if ( defined $ apRef - > { vap_table } && scalar @ { $ apRef - > { vap_table } } ) {
for my $ vap ( @ { $ apRef - > { vap_table } } ) {
2018-01-27 12:27:57 +00:00
$ essid . = makeReadingName ( $ vap - > { essid } ) . ',' ;
2015-08-31 22:29:29 +00:00
}
$ essid =~ s/.$// ;
} else {
my $ essid = 'none' ;
}
2018-07-22 15:16:09 +00:00
2019-05-19 06:19:20 +00:00
#nochmal genauer ins json schauen, ob hier wirklich eine Schleife notwendig ist. (cu_total mehrfach vorhanden?)
2018-07-22 15:16:09 +00:00
if ( defined $ apRef - > { 'radio_table_stats' } ) {
for my $ rts ( @ { $ apRef - > { 'radio_table_stats' } } ) {
$ utiliz . = makeReadingName ( $ rts - > { 'cu_total' } ) . ',' ; # TODO: hier nicht unbedingt notwendig, aufgrund des funktionierenden schnellen fixes wegen neuer controller-Version bleibt es aber erstmal so drin.
}
$ utiliz =~ s/.$// ;
} else {
my $ utiliz = 'none' ;
}
2016-02-29 13:38:53 +00:00
readingsBulkUpdate ( $ hash , '-AP_' . $ apName . '_state' , ( $ apRef - > { state } == 1 ) ? 'ok' : 'error' ) ;
readingsBulkUpdate ( $ hash , '-AP_' . $ apName . '_clients' , $ apRef - > { 'num_sta' } ) ;
2017-05-27 20:20:30 +00:00
if ( $ apRef - > { type } eq 'uap' ) {
readingsBulkUpdate ( $ hash , '-AP_' . $ apName . '_essid' , $ essid ) ;
2018-07-22 15:16:09 +00:00
readingsBulkUpdate ( $ hash , '-AP_' . $ apName . '_utilization' , $ utiliz ) if ( $ utiliz ne '' ) ;
2017-05-27 20:20:30 +00:00
readingsBulkUpdate ( $ hash , '-AP_' . $ apName . '_utilizationNA' , $ apRef - > { 'na_cu_total' } ) if ( defined ( $ apRef - > { 'na_cu_total' } ) ) ;
readingsBulkUpdate ( $ hash , '-AP_' . $ apName . '_utilizationNG' , $ apRef - > { 'ng_cu_total' } ) if ( defined ( $ apRef - > { 'ng_cu_total' } ) ) ;
}
2016-02-29 13:38:53 +00:00
readingsBulkUpdate ( $ hash , '-AP_' . $ apName . '_locate' , ( ! defined $ apRef - > { locating } ) ? 'unknown' : ( $ apRef - > { locating } ) ? 'on' : 'off' ) ;
2019-02-24 17:53:04 +00:00
#my $poe_power;
#for my $port (@{$apRef->{port_table}}) {
# next if( !$port->{port_poe} );
# $poe_power += $port->{poe_power} if( defined($port->{poe_power}) );
#}
#readingsBulkUpdate($hash,'-AP_'.$apName.'_poePower', $poe_power) if( defined($poe_power) );
2017-05-27 20:20:30 +00:00
2016-02-29 13:38:53 +00:00
# readingsBulkUpdate($hash,'-AP_'.$apName.'_guests',$apRef->{'guest-num_sta'});
# readingsBulkUpdate($hash,'-AP_'.$apName.'_users',$apRef->{'user-num_sta'});
# readingsBulkUpdate($hash,'-AP_'.$apName.'_last_seen',$apRef->{'last_seen'});
2015-08-31 22:29:29 +00:00
}
2018-07-22 15:16:09 +00:00
2015-08-31 22:29:29 +00:00
return undef ;
}
2018-01-21 19:51:41 +00:00
###############################################################################
sub Unifi_SetWlanReadings ($) {
my ( $ hash ) = @ _ ;
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
Log3 $ name , 5 , "$name ($self) - executed." ;
my ( $ wlanName , $ wlanRef ) ;
for my $ wlanID ( keys % { $ hash - > { wlans } } ) {
$ wlanRef = $ hash - > { wlans } - > { $ wlanID } ;
2018-01-27 12:27:57 +00:00
$ wlanName = makeReadingName ( $ wlanRef - > { name } ) ;
2018-06-23 11:22:34 +00:00
readingsBulkUpdate ( $ hash , '-WLAN_' . $ wlanName . '_state' , ( $ wlanRef - > { enabled } eq JSON:: true ) ? 'enabled' : 'disabled' ) ;
2018-01-21 19:51:41 +00:00
}
return undef ;
}
2018-02-05 20:45:17 +00:00
###############################################################################
sub Unifi_SetVoucherReadings ($) {
my ( $ hash ) = @ _ ;
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
Log3 $ name , 5 , "$name ($self) - executed." ;
#f<> r jeden Vouchercache den n<> chsten Vouchercode als Reading anzeigen
for my $ cache ( keys % { $ hash - > { hotspot } - > { voucherCache } } ) {
if ( ref ( $ hash - > { hotspot } - > { voucherCache } - > { $ cache } ) eq "HASH" ) {
2018-02-05 22:35:27 +00:00
if ( defined $ hash - > { hotspot } - > { voucherCache } - > { $ cache } - > { setCmd } ) {
my $ voucher = Unifi_getNextVoucherForNote ( $ hash , $ cache ) ;
if ( ref ( $ voucher ) eq "HASH" ) {
readingsBulkUpdate ( $ hash , "-VC_" . $ cache , $ voucher - > { code } ) ;
} else {
readingsBulkUpdate ( $ hash , "-VC_" . $ cache , "-" ) ;
}
2018-02-05 20:45:17 +00:00
}
}
}
}
2015-08-31 22:29:29 +00:00
###############################################################################
sub Unifi_DisconnectClient_Send ($@) {
my ( $ hash , @ clients ) = @ _ ;
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
Log3 $ name , 5 , "$name ($self) - executed with count:'" . scalar ( @ clients ) . "', ID:'" . $ clients [ 0 ] . "'" ;
my $ id = shift @ clients ;
HttpUtils_NonblockingGet ( {
% { $ hash - > { httpParams } } ,
url = > $ hash - > { unifi } - > { url } . "cmd/stamgr" ,
callback = > \ & Unifi_DisconnectClient_Receive ,
clients = > [ @ clients ] ,
2019-03-28 17:30:26 +00:00
data = > "{\"mac\":\"" . $ hash - > { clients } - > { $ id } - > { mac } . "\", \"cmd\":\"kick-sta\"}" ,
2015-08-31 22:29:29 +00:00
} ) ;
return undef ;
}
###############################################################################
sub Unifi_DisconnectClient_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}'" ;
}
else { Unifi_ReceiveFailure ( $ hash , $ data - > { meta } ) ; }
} else {
Unifi_ReceiveFailure ( $ hash , { rc = > $ param - > { code } , msg = > "Failed with HTTP Code $param->{code}." } ) ;
}
}
if ( scalar @ { $ param - > { clients } } ) {
Unifi_DisconnectClient_Send ( $ hash , @ { $ param - > { clients } } ) ;
}
return undef ;
}
2018-01-19 21:11:09 +00:00
###############################################################################
2018-03-11 14:54:39 +00:00
2018-06-10 15:42:35 +00:00
sub Unifi_BlockClient_Send ($$) {
my ( $ hash , $ mac ) = @ _ ;
2018-01-19 21:11:09 +00:00
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
2018-06-10 15:42:35 +00:00
Log3 $ name , 5 , "$name ($self) - executed with mac: '" . $ mac . "'" ;
2018-01-19 21:11:09 +00:00
HttpUtils_NonblockingGet ( {
% { $ hash - > { httpParams } } ,
url = > $ hash - > { unifi } - > { url } . "cmd/stamgr" ,
callback = > \ & Unifi_BlockClient_Receive ,
2019-06-24 19:07:58 +00:00
data = > "{\"cmd\":\"block-sta\", \"mac\":\"" . $ mac . "\"}" ,
2018-01-19 21:11:09 +00:00
} ) ;
2019-03-27 22:12:52 +00:00
2018-01-19 21:11:09 +00:00
return undef ;
}
###############################################################################
sub Unifi_BlockClient_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}'" ;
}
else { Unifi_ReceiveFailure ( $ hash , $ data - > { meta } ) ; }
} else {
Unifi_ReceiveFailure ( $ hash , { rc = > $ param - > { code } , msg = > "Failed with HTTP Code $param->{code}." } ) ;
}
}
return undef ;
}
2015-08-31 22:29:29 +00:00
###############################################################################
2018-06-10 15:42:35 +00:00
sub Unifi_UnblockClient_Send ($$) {
my ( $ hash , $ mac ) = @ _ ;
2018-01-12 20:39:58 +00:00
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
2018-06-10 15:42:35 +00:00
Log3 $ name , 5 , "$name ($self) - executed with mac: '" . $ mac . "'" ;
2018-01-12 20:39:58 +00:00
HttpUtils_NonblockingGet ( {
% { $ hash - > { httpParams } } ,
url = > $ hash - > { unifi } - > { url } . "cmd/stamgr" ,
callback = > \ & Unifi_UnblockClient_Receive ,
2019-06-24 19:07:58 +00:00
data = > "{\"cmd\":\"unblock-sta\", \"mac\":\"" . $ mac . "\"}" ,
2019-03-27 22:12:52 +00:00
} ) ;
2018-01-12 20:39:58 +00:00
return undef ;
}
###############################################################################
sub Unifi_UnblockClient_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}'" ;
}
else { Unifi_ReceiveFailure ( $ hash , $ data - > { meta } ) ; }
} else {
Unifi_ReceiveFailure ( $ hash , { rc = > $ param - > { code } , msg = > "Failed with HTTP Code $param->{code}." } ) ;
}
}
return undef ;
}
2018-01-17 22:38:27 +00:00
###############################################################################
sub Unifi_SwitchSiteLEDs_Send ($$) {
my ( $ hash , $ state ) = @ _ ;
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
Log3 $ name , 5 , "$name ($self) - executed with command: '" . $ state . "'" ;
HttpUtils_NonblockingGet ( {
% { $ hash - > { httpParams } } ,
url = > $ hash - > { unifi } - > { url } . "set/setting/mgmt" ,
callback = > \ & Unifi_SwitchSiteLEDs_Receive ,
2019-03-28 17:39:12 +00:00
data = > "{\"led_enabled\":" . $ state . "}" ,
2018-01-17 22:38:27 +00:00
} ) ;
return undef ;
}
###############################################################################
sub Unifi_SwitchSiteLEDs_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}'" ;
}
else { Unifi_ReceiveFailure ( $ hash , $ data - > { meta } ) ; }
} else {
Unifi_ReceiveFailure ( $ hash , { rc = > $ param - > { code } , msg = > "Failed with HTTP Code $param->{code}." } ) ;
}
}
return undef ;
}
2018-01-12 20:39:58 +00:00
###############################################################################
sub Unifi_WlanconfRest_Send ($$@) {
my ( $ hash , $ id , $ data ) = @ _ ;
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
my $ json = encode_json ( $ data ) ;
Log3 $ name , 5 , "$name ($self) - executed with $json." ;
HttpUtils_NonblockingGet ( {
% { $ hash - > { httpParams } } ,
method = > "PUT" ,
url = > $ hash - > { unifi } - > { url } . "rest/wlanconf/" . $ id ,
callback = > \ & Unifi_WlanconfRest_Receive ,
aps = > [] ,
data = > $ json ,
} ) ;
return undef ;
}
sub Unifi_WlanconfRest_Receive ($) {
my ( $ param , $ err , $ data ) = @ _ ;
my ( $ name , $ self , $ hash ) = ( $ param - > { hash } - > { NAME } , Unifi_Whoami ( ) , $ param - > { hash } ) ;
2019-05-20 18:53:51 +00:00
Log3 $ name , 5 , "$name ($self) - executed." ;
2018-01-12 20:39:58 +00:00
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 = > $@ } } ; } ;
} else {
Unifi_ReceiveFailure ( $ hash , { rc = > $ param - > { code } , msg = > "Failed with HTTP Code $param->{code}." } ) ;
}
}
return undef ;
}
2018-02-05 20:45:17 +00:00
###############################################################################
sub Unifi_GetVoucherList_Send ($) {
my ( $ hash ) = @ _ ;
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
Log3 $ name , 5 , "$name ($self) - executed." ;
HttpUtils_NonblockingGet ( {
% { $ hash - > { httpParams } } ,
method = > "GET" ,
url = > $ hash - > { unifi } - > { url } . "stat/voucher" ,
callback = > \ & Unifi_GetVoucherList_Receive ,
} ) ;
return undef ;
}
#######################################
sub Unifi_GetVoucherList_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 "" ) {
my $ dataString = $ data ;
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}'" ;
$ hash - > { hotspot } - > { vouchers } = $ data - > { data } ; #array
}
else { Unifi_ReceiveFailure ( $ hash , $ data - > { meta } ) ; }
} else {
Unifi_ReceiveFailure ( $ hash , { rc = > $ param - > { code } , msg = > "Failed with HTTP Code $param->{code}." } ) ;
}
# VoucherCache bereinigen um bereits verwendete / zu lange gecachte Voucher
my $ cachetime = time ( ) - 2 * 60 * 60 ; #Maximal zwei Stunden
for my $ cache ( keys % { $ hash - > { hotspot } - > { voucherCache } } ) {
my $ expand = 0 ;
if ( ref ( $ hash - > { hotspot } - > { voucherCache } - > { $ cache } ) eq "HASH" ) {
for my $ voucher ( keys % { $ hash - > { hotspot } - > { voucherCache } - > { $ cache } } ) {
if ( ref ( $ hash - > { hotspot } - > { voucherCache } - > { $ cache } - > { $ voucher } ) eq "HASH" && defined $ hash - > { hotspot } - > { voucherCache } - > { $ cache } - > { $ voucher } - > { delivered_at } ) {
if ( $ hash - > { hotspot } - > { voucherCache } - > { $ cache } - > { $ voucher } - > { delivered_at } lt $ cachetime ) {
delete $ hash - > { hotspot } - > { voucherCache } - > { $ cache } - > { $ voucher } ;
}
}
}
#wenn Cache zu leer neue Voucher anlegen
if ( $ expand == 0 ) { #Der Unifi-Controller mag es nicht, wenn man kurz hintereinander zwei requests sendet, daher gleich mehrere auf einmal
my $ minSize = $ hash - > { hotspot } - > { voucherCache } - > { $ cache } - > { minSize } ;
2019-03-27 22:12:52 +00:00
my $ aktSize = $ dataString =~ s/note.{1,5}$cache//g ;
2018-02-05 20:45:17 +00:00
if ( defined $ minSize && $ aktSize < $ minSize ) {
my $ setCmd = $ hash - > { hotspot } - > { voucherCache } - > { $ cache } - > { setCmd } ;
my @ words = split ( "[ \t][ \t]*" , $ setCmd ) ;
my % params = ( "expire" = > $ words [ 0 ] , "n" = > $ words [ 1 ] , "quota" = > $ words [ 2 ] , "note" = > $ words [ 3 ] ) ;
2019-05-20 18:53:51 +00:00
Log3 $ name , 4 , "$name ($self) - expand VoucherCache ($cache)." ;
2018-02-05 20:45:17 +00:00
Unifi_CreateVoucher_Send ( $ hash , % params ) ;
$ expand = 1 ;
}
}
}
}
}
Unifi_NextUpdateFn ( $ hash , $ self ) ;
return undef ;
}
###############################################################################
sub Unifi_CreateVoucher_Send ($%) {
my ( $ hash , % a ) = @ _ ;
my $ expire = $ a { "expire" } ;
my $ n = $ a { "n" } ;
my $ quota = $ a { "quota" } ;
my $ note = $ a { "note" } ;
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
Log3 $ name , 5 , "$name ($self) - executed. expire: " . $ expire . " - n: " . $ n . " - quota: " . $ quota . " - note: " . $ note . " - " . % a ;
HttpUtils_NonblockingGet ( {
% { $ hash - > { httpParams } } ,
url = > $ hash - > { unifi } - > { url } . "cmd/hotspot" ,
callback = > \ & Unifi_CreateVoucher_Receive ,
2019-03-27 22:12:52 +00:00
data = > "{\"cmd\":\"create-voucher\", \"expire\":" . $ expire . ", \"n\":" . $ n . ", \"quota\":" . $ quota . ", \"note\":\"" . $ note . "\"}" ,
2018-02-05 20:45:17 +00:00
} ) ;
return undef ;
}
#######################################
sub Unifi_CreateVoucher_Receive ($) {
my ( $ param , $ err , $ data ) = @ _ ;
my ( $ name , $ self , $ hash ) = ( $ param - > { hash } - > { NAME } , Unifi_Whoami ( ) , $ param - > { hash } ) ;
2019-05-20 18:53:51 +00:00
Log3 $ name , 5 , "$name ($self) - executed." ;
2018-02-05 20:45:17 +00:00
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 = > $@ } } ; } ;
} else {
Unifi_ReceiveFailure ( $ hash , { rc = > $ param - > { code } , msg = > "Failed with HTTP Code $param->{code}." } ) ;
}
}
# der Voucher ist im Unifi-Modul dann erst mit dem n<> chsten Update enthalten.
return undef ;
}
2018-01-12 20:39:58 +00:00
###############################################################################
2015-08-31 22:29:29 +00:00
sub Unifi_ApCmd_Send ($$@) { #cmd: 'set-locate', 'unset-locate', 'restart'
my ( $ hash , $ cmd , @ aps ) = @ _ ;
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
Log3 $ name , 5 , "$name ($self) - executed with cmd:'" . $ cmd . "', count:'" . scalar ( @ aps ) . "', ID:'" . $ aps [ 0 ] . "'" ;
my $ id = shift @ aps ;
HttpUtils_NonblockingGet ( {
% { $ hash - > { httpParams } } ,
url = > $ hash - > { unifi } - > { url } . "cmd/devmgr" ,
2019-05-19 06:19:20 +00:00
callback = > \ & Unifi_DeviceCmd_Receive ,
2015-08-31 22:29:29 +00:00
aps = > [ @ aps ] ,
cmd = > $ cmd ,
2019-03-28 17:30:26 +00:00
data = > "{\"mac\":\"" . $ hash - > { accespoints } - > { $ id } - > { mac } . "\", \"cmd\":\"" . $ cmd . "\"}" ,
2015-08-31 22:29:29 +00:00
} ) ;
return undef ;
}
2017-05-27 20:20:30 +00:00
sub Unifi_ApJson_Send ($$) {
my ( $ hash , $ data ) = @ _ ;
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
my $ json = encode_json ( $ data ) ;
Log3 $ name , 5 , "$name ($self) - executed with $json." ;
HttpUtils_NonblockingGet ( {
% { $ hash - > { httpParams } } ,
url = > $ hash - > { unifi } - > { url } . "cmd/devmgr" ,
2019-05-19 06:19:20 +00:00
callback = > \ & Unifi_DeviceCmd_Receive ,
2017-05-27 20:20:30 +00:00
aps = > [] ,
data = > $ json ,
} ) ;
return undef ;
}
2019-05-19 06:19:20 +00:00
sub Unifi_DeviceRestJson_Send ($$$) {
2017-05-27 20:20:30 +00:00
my ( $ hash , $ id , $ data ) = @ _ ;
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
my $ json = encode_json ( $ data ) ;
Log3 $ name , 5 , "$name ($self) - executed with $json." ;
HttpUtils_NonblockingGet ( {
% { $ hash - > { httpParams } } ,
method = > "PUT" ,
url = > $ hash - > { unifi } - > { url } . "rest/device/" . $ id ,
2019-05-19 06:19:20 +00:00
callback = > \ & Unifi_DeviceCmd_Receive ,
aps = > [] ,
data = > $ json ,
} ) ;
return undef ;
}
sub Unifi_UserRestJson_Send ($$$) {
my ( $ hash , $ id , $ json ) = @ _ ;
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
Log3 $ name , 5 , "$name ($self) - executed for id $id with $json." ;
HttpUtils_NonblockingGet ( {
% { $ hash - > { httpParams } } ,
method = > "PUT" ,
url = > $ hash - > { unifi } - > { url } . "rest/user/" . $ id ,
callback = > \ & Unifi_DeviceCmd_Receive ,
2017-05-27 20:20:30 +00:00
aps = > [] ,
data = > $ json ,
} ) ;
return undef ;
}
2015-08-31 22:29:29 +00:00
###############################################################################
2019-05-19 06:19:20 +00:00
sub Unifi_DeviceCmd_Receive ($) {
2015-08-31 22:29:29 +00:00
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}'" ;
}
else { Unifi_ReceiveFailure ( $ hash , $ data - > { meta } ) ; }
} else {
Unifi_ReceiveFailure ( $ hash , { rc = > $ param - > { code } , msg = > "Failed with HTTP Code $param->{code}." } ) ;
}
}
if ( scalar @ { $ param - > { aps } } ) {
Unifi_ApCmd_Send ( $ hash , $ param - > { cmd } , @ { $ param - > { aps } } ) ;
}
2015-08-29 19:25:28 +00:00
2015-08-25 21:29:35 +00:00
return undef ;
}
###############################################################################
2019-05-19 06:19:20 +00:00
sub Unifi_UsergroupRestJson_Send ($) {
my ( $ hash ) = @ _ ;
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
Log3 $ name , 5 , "$name ($self) - executed." ;
HttpUtils_NonblockingGet ( {
% { $ hash - > { httpParams } } ,
method = > "GET" ,
url = > $ hash - > { unifi } - > { url } . "rest/usergroup/" ,
callback = > \ & Unifi_UsergroupRestJson_Receive ,
} ) ;
return undef ;
}
sub Unifi_UsergroupRestJson_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 - > { unifi } - > { usergroups } - > { $ h - > { _id } } = $ h ;
}
}
else { Unifi_ReceiveFailure ( $ hash , $ data - > { meta } ) ; }
} else {
Unifi_ReceiveFailure ( $ hash , { rc = > $ param - > { code } , msg = > "Failed with HTTP Code $param->{code}." } ) ;
}
}
return undef ;
}
###############################################################################
2015-08-25 21:29:35 +00:00
2015-08-31 22:29:29 +00:00
sub Unifi_ArchiveAlerts_Send ($) {
my ( $ hash ) = @ _ ;
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
Log3 $ name , 5 , "$name ($self) - executed." ;
HttpUtils_NonblockingGet ( {
% { $ hash - > { httpParams } } ,
url = > $ hash - > { unifi } - > { url } . "cmd/evtmgr" ,
callback = > \ & Unifi_Cmd_Receive ,
2019-03-28 17:30:26 +00:00
data = > "{\"cmd\":\"archive-all-alarms\"}" ,
2015-08-31 22:29:29 +00:00
} ) ;
return undef ;
}
###############################################################################
sub Unifi_Cmd_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}'" ;
}
else { Unifi_ReceiveFailure ( $ hash , $ data - > { meta } ) ; }
} else {
Unifi_ReceiveFailure ( $ hash , { rc = > $ param - > { code } , msg = > "Failed with HTTP Code $param->{code}." } ) ;
}
}
return undef ;
}
###############################################################################
sub Unifi_ClientNames ($@) {
my ( $ hash , $ ID , $ W ) = @ _ ;
my $ clientRef ;
my $ devAliases = AttrVal ( $ hash - > { NAME } , "devAlias" , 0 ) ;
2019-03-25 20:02:14 +00:00
my $ attrCustomClientNames = AttrVal ( $ hash - > { NAME } , "customClientNames" , 0 ) ;
2015-08-31 22:29:29 +00:00
if ( defined $ ID && defined $ W && $ W eq 'makeAlias' ) { # Return Alias from ID
$ clientRef = $ hash - > { clients } - > { $ ID } ;
2019-03-20 19:15:01 +00:00
if ( ( $ devAliases && $ devAliases =~ /$ID:(.+?)(\s|$)/ )
2015-08-31 22:29:29 +00:00
|| ( $ devAliases && defined $ clientRef - > { name } && $ devAliases =~ /$clientRef->{name}:(.+?)(\s|$)/ )
|| ( $ devAliases && defined $ clientRef - > { hostname } && $ devAliases =~ /$clientRef->{hostname}:(.+?)(\s|$)/ )
) {
$ ID = $ 1 ;
2019-03-25 20:02:14 +00:00
} elsif ( $ attrCustomClientNames && defined $ clientRef - > { $ attrCustomClientNames } ) {
$ ID = makeReadingName ( $ clientRef - > { $ attrCustomClientNames } ) ;
} elsif ( ( defined $ clientRef - > { name } && $ clientRef - > { name } =~ /^([\w\.\-]+)$/ )
|| ( defined $ clientRef - > { hostname } && $ clientRef - > { hostname } =~ /^([\w\.\-]+)$/ )
) {
$ ID = $ 1 ;
}
2015-08-31 22:29:29 +00:00
return $ ID ;
}
elsif ( defined $ ID && defined $ W && $ W eq 'makeID' ) { # Return ID from Alias
for my $ clientID ( keys % { $ hash - > { clients } } ) {
$ clientRef = $ hash - > { clients } - > { $ clientID } ;
2018-01-31 13:28:11 +00:00
my $ goodName = makeReadingName ( $ clientRef - > { name } ) if defined $ clientRef - > { name } ;
my $ goodHostname = makeReadingName ( $ clientRef - > { hostname } ) if defined $ clientRef - > { hostname } ;
2015-08-31 22:29:29 +00:00
if ( ( $ devAliases && $ devAliases =~ /$clientID:$ID/ )
2018-01-31 13:28:11 +00:00
|| ( $ devAliases && defined $ clientRef - > { name } && ( $ devAliases =~ /$clientRef->{name}:$ID/ || $ devAliases =~ /$goodName:$ID/ ) )
|| ( $ devAliases && defined $ clientRef - > { hostname } && ( $ devAliases =~ /$clientRef->{hostname}:$ID/ || $ devAliases =~ /$goodHostname:$ID/ ) )
2019-03-25 20:02:14 +00:00
) {
$ ID = $ clientID ;
last ;
} elsif ( $ attrCustomClientNames && defined $ clientRef - > { $ attrCustomClientNames } && $ ID eq makeReadingName ( $ clientRef - > { $ attrCustomClientNames } ) ) {
$ ID = $ clientID ;
last ;
} elsif ( ( defined $ clientRef - > { name } && ( $ clientRef - > { name } eq $ ID || $ goodName eq $ ID ) )
|| ( defined $ clientRef - > { hostname } && ( $ clientRef - > { hostname } eq $ ID || $ goodHostname eq $ ID ) )
2015-08-31 22:29:29 +00:00
) {
$ ID = $ clientID ;
last ;
}
}
return $ ID ;
}
else { # Return all clients in a scalar
my $ clients = '' ;
for my $ clientID ( keys % { $ hash - > { clients } } ) {
$ clients . = Unifi_ClientNames ( $ hash , $ clientID , 'makeAlias' ) . ',' ;
}
$ clients =~ s/.$// ;
return $ clients ;
}
}
###############################################################################
2018-01-12 20:39:58 +00:00
sub Unifi_SSIDs ($@) {
my ( $ hash , $ ID , $ W ) = @ _ ;
my $ wlanRef ;
if ( defined $ ID && defined $ W && $ W eq 'makeName' ) { # Return Name from ID
$ wlanRef = $ hash - > { wlans } - > { $ ID } ;
2018-01-27 12:27:57 +00:00
if ( defined $ wlanRef - > { name } ) { #&& $wlanRef->{name} =~ /^([\w\.\-]+)$/) {
$ ID = makeReadingName ( $ wlanRef - > { name } ) ;
2018-01-12 20:39:58 +00:00
}
return $ ID ;
}
elsif ( defined $ ID && defined $ W && $ W eq 'makeID' ) { # Return ID from Name
for ( keys % { $ hash - > { wlans } } ) {
$ wlanRef = $ hash - > { wlans } - > { $ _ } ;
2018-01-27 12:27:57 +00:00
if ( defined $ wlanRef - > { name } && makeReadingName ( $ wlanRef - > { name } ) eq $ ID ) {
2018-01-12 20:39:58 +00:00
$ ID = $ _ ;
last ;
}
}
return $ ID ;
}
2018-01-21 19:51:41 +00:00
else { # Return all wlans in a scalar
my $ wlans = '' ;
for my $ wlanID ( keys % { $ hash - > { wlans } } ) {
$ wlans . = Unifi_SSIDs ( $ hash , $ wlanID , 'makeName' ) . ',' ;
2018-01-12 20:39:58 +00:00
}
2018-01-21 19:51:41 +00:00
$ wlans =~ s/.$// ;
2018-01-12 20:39:58 +00:00
2018-01-21 19:51:41 +00:00
return $ wlans ;
2018-01-12 20:39:58 +00:00
}
}
###############################################################################
2015-08-31 22:29:29 +00:00
sub Unifi_ApNames ($@) {
my ( $ hash , $ ID , $ W ) = @ _ ;
2018-01-31 13:28:11 +00:00
my $ apRef ;
2015-08-31 22:29:29 +00:00
if ( defined $ ID && defined $ W && $ W eq 'makeName' ) { # Return Name or IP from ID
2018-01-31 13:28:11 +00:00
$ apRef = $ hash - > { accespoints } - > { $ ID } ;
if ( ( defined $ apRef - > { name } && $ apRef - > { name } =~ /^([\w\.\-]+)$/ )
|| ( defined $ apRef - > { ip } && $ apRef - > { ip } =~ /^([\w\.\-]+)$/ )
2015-08-31 22:29:29 +00:00
) {
$ ID = $ 1 ;
}
return $ ID ;
}
elsif ( defined $ ID && defined $ W && $ W eq 'makeID' ) { # Return ID from Name or IP
for ( keys % { $ hash - > { accespoints } } ) {
2018-01-31 13:28:11 +00:00
$ apRef = $ hash - > { accespoints } - > { $ _ } ;
if ( ( defined $ apRef - > { name } && $ apRef - > { name } eq $ ID )
|| ( defined $ apRef - > { ip } && $ apRef - > { ip } eq $ ID )
2015-08-31 22:29:29 +00:00
) {
$ ID = $ _ ;
last ;
}
}
return $ ID ;
}
else { # Return all aps in a scalar
my $ aps = '' ;
for my $ apID ( keys % { $ hash - > { accespoints } } ) {
$ aps . = Unifi_ApNames ( $ hash , $ apID , 'makeName' ) . ',' ;
}
$ aps =~ s/.$// ;
return $ aps ;
}
}
###############################################################################
2019-03-27 22:12:52 +00:00
sub Unifi_isUCversionHigherThan ($$) {
my ( $ hash , $ check ) = @ _ ;
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
my $ ucversion = $ hash - > { UC_VERSION } ;
if ( $ ucversion eq "unknown" ) {
Log3 $ name , 2 , "$name ($self) - unknown UC-Version. Please use set refreshUCversion" ;
return 1 ; # Trotzdem true zur<75> ckgeben, k<> nnte ja auch daran liegen, dass sysinfo bei neuer Version anders funktioniert
} else {
my ( $ majorCheck , $ minorCheck , $ patchCheck ) = split ( /./ , $ ucversion ) ;
my ( $ majorUC , $ minorUC , $ patchUC ) = split ( /./ , $ ucversion ) ;
if ( defined $ majorCheck && defined $ majorUC && looks_like_number ( $ majorCheck ) && looks_like_number ( $ majorUC ) && $ majorCheck < $ majorUC ) {
return 0 ;
} elsif ( defined $ minorCheck && defined $ minorUC && looks_like_number ( $ minorCheck ) && looks_like_number ( $ minorUC ) && $ minorCheck < $ minorUC ) {
return 0 ;
} elsif ( defined $ patchCheck && defined $ patchUC && looks_like_number ( $ patchCheck ) && looks_like_number ( $ patchUC ) && $ patchCheck < $ patchUC ) {
return 0 ;
}
}
return 1 ;
}
###############################################################################
2015-08-31 22:29:29 +00:00
2019-03-20 19:15:01 +00:00
sub Unifi_initCustomClientReadings ($) {
my ( $ hash ) = @ _ ;
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whoami ( ) ) ;
my $ ccr = $ hash - > { unifi } - > { customClientReadings } - > { attr_value } ;
my @ clientNameRegEx ;
my @ parts = split ( / / , $ ccr ) ;
if ( scalar @ parts < 1 ) {
return "Attr customClientReadings: Define at least one customClientReadings-part!" ;
}
my $ partCount = 0 ;
foreach ( @ parts ) {
my @ part = split ( /:/ , $ _ ) ;
if ( scalar @ part > 2 || scalar @ part < 1 ) {
return "Attr customClientReadings: Exactly one : per part allowed!" ;
}
elsif ( scalar @ part == 1 ) {
push @ part , "" ;
}
push @ clientNameRegEx , $ part [ 0 ] ;
Log3 $ name , 5 , "$name ($self) - parsed part: $part[0] -> $part[1]" ;
my $ pc = substr ( "00000000" . $ partCount . "_part" , - 12 ) ;
$ hash - > { unifi } - > { customClientReadings } - > { parts } - > { $ pc } - > { nameRegEx } = $ part [ 0 ] ;
$ hash - > { unifi } - > { customClientReadings } - > { parts } - > { $ pc } - > { ReadingRegEx } = $ part [ 1 ] ;
$ partCount + + ;
}
my $ json = encode_json ( $ hash - > { unifi } - > { customClientReadings } ) ;
Log3 $ name , 5 , "$name ($self) - parsed Attribute customClientReadings: $json." ;
return undef ;
}
###############################################################################
2018-02-05 20:45:17 +00:00
sub Unifi_initVoucherCache ($) {
my ( $ hash ) = @ _ ;
2018-10-31 10:53:51 +00:00
#return if ( ! defined $hash->{hotspot}->{voucherCache}->{attr_value});
2018-02-05 20:45:17 +00:00
my @ voucherCaches = split ( /,/ , $ hash - > { hotspot } - > { voucherCache } - > { attr_value } ) ;
my @ notes = ( ) ;
foreach ( @ voucherCaches ) {
my $ voucherCache = $ _ ;
my @ words = split ( "[ \t][ \t]*" , $ voucherCache ) ;
if ( scalar ( @ words ) != 4 ) {
return "$hash->{NAME} voucherCache: Four arguments per cache needed!."
}
if ( ! looks_like_number ( $ words [ 0 ] ) || int ( $ words [ 0 ] ) < 1 ||
! looks_like_number ( $ words [ 1 ] ) || int ( $ words [ 1 ] ) < 1 ||
! looks_like_number ( $ words [ 2 ] ) || int ( $ words [ 2 ] ) < 1
) {
return "$hash->{NAME} voucherCache: First three arguments (expire, n, quota) must be numeric."
}
my $ note = $ words [ 3 ] ;
push ( @ notes , $ note ) ;
$ hash - > { hotspot } - > { voucherCache } - > { $ note } - > { setCmd } = $ voucherCache ;
$ hash - > { hotspot } - > { voucherCache } - > { $ note } - > { minSize } = $ words [ 1 ] ;
}
#ToDo: L<> schen nicht mehr verwendeter Caches
# dazu iterieren <20> ber $hash->{hotspot}->{voucherCache}
# immer wenn es darin setCmd gibt ist oder war es ein Cache, ansonsten ist es attr_value
# wenn $hash->{hotspot}->{voucherCache}->{$note} nicht in @notes, dann l<> schen
return undef ;
}
2019-03-20 19:15:01 +00:00
2018-02-05 20:45:17 +00:00
###############################################################################
sub Unifi_getNextVoucherForNote ($$) {
my ( $ hash , $ getVal ) = @ _ ;
my $ deliverytime = time ( ) ;
my $ returnedVoucher = "" ;
for my $ voucher ( @ { $ hash - > { hotspot } - > { vouchers } } ) {
my $ note = '' ;
if ( defined $ voucher - > { note } ) {
$ note = $ voucher - > { note } ;
}
my $ gv = $ getVal ;
$ note =~ tr /a-zA-Z<> <5A> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> _0-9.,/ / cd ;
$ gv =~ tr /a-zA-Z<> <5A> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> _0-9.,/ / cd ;
if ( $ gv eq 'all' || ( ( $ gv =~ /^$note/ ) && $ note ne '' ) ) {
if ( ! defined $ hash - > { hotspot } - > { voucherCache } - > { $ getVal } - > { $ voucher - > { _id } } - > { delivered_at } ) {
$ returnedVoucher = $ voucher ;
last ;
} else {
if ( $ hash - > { hotspot } - > { voucherCache } - > { $ getVal } - > { $ voucher - > { _id } } - > { delivered_at } < $ deliverytime ) {
$ deliverytime = $ hash - > { hotspot } - > { voucherCache } - > { $ getVal } - > { $ voucher - > { _id } } - > { delivered_at } ;
$ returnedVoucher = $ voucher ;
}
}
}
}
return $ returnedVoucher ;
}
###############################################################################
2015-08-25 21:29:35 +00:00
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 } - > { $ _ } ;
2015-08-29 19:25:28 +00:00
} elsif ( ! $ NextUpdateFn && $ hash - > { updateDispatch } - > { $ _ } [ 0 ] && $ _ ne 'Unifi_ProcessUpdate' ) {
2015-08-25 21:29:35 +00:00
$ NextUpdateFn = $ hash - > { updateDispatch } - > { $ _ } [ 0 ] ;
2015-08-23 00:13:22 +00:00
}
}
2015-08-29 19:25:28 +00:00
if ( ! $ NextUpdateFn && $ hash - > { updateDispatch } - > { Unifi_ProcessUpdate } [ 0 ] ) {
$ NextUpdateFn = $ hash - > { updateDispatch } - > { Unifi_ProcessUpdate } [ 0 ] ;
delete $ hash - > { updateDispatch } - > { Unifi_ProcessUpdate } ;
2015-08-25 21:29:35 +00:00
}
$ NextUpdateFn - > ( $ hash ) if ( $ NextUpdateFn ) ;
2015-08-23 00:13:22 +00:00
return undef ;
}
###############################################################################
2015-08-31 22:29:29 +00:00
sub Unifi_ReceiveFailure ($$) {
2015-08-29 19:25:28 +00:00
my ( $ hash , $ meta ) = @ _ ;
my ( $ name , $ self ) = ( $ hash - > { NAME } , Unifi_Whowasi ( ) ) ;
if ( defined $ meta - > { msg } ) {
2019-02-24 17:53:04 +00:00
if ( ( $ meta - > { msg } eq 'api.err.LoginRequired' ) || ( $ meta - > { msg } =~ /Connection refused$/ ) || ( $ meta - > { msg } =~ /SSL connect attempt failed$/ ) ) {
2015-08-29 19:25:28 +00:00
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 ;
}
}
2019-03-16 13:16:35 +00:00
elsif ( $ meta - > { msg } eq "api.err.NoSiteContext" ) {
2015-08-29 19:25:28 +00:00
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}'" ;
}
}
###############################################################################
2015-08-25 21:29:35 +00:00
sub Unifi_CONNECTED ($@) {
my ( $ hash , $ set ) = @ _ ;
if ( $ set ) {
2015-08-29 19:25:28 +00:00
$ hash - > { unifi } - > { CONNECTED } = $ set ;
2015-08-25 21:29:35 +00:00
RemoveInternalTimer ( $ hash ) ;
% { $ hash - > { updateDispatch } } = ( ) ;
2015-08-29 19:25:28 +00:00
if ( ! defined ( $ hash - > { READINGS } - > { state } - > { VAL } ) || $ hash - > { READINGS } - > { state } - > { VAL } ne $ set ) {
2015-08-25 21:29:35 +00:00
readingsSingleUpdate ( $ hash , "state" , $ set , 1 ) ;
}
return undef ;
}
else {
2015-08-29 19:25:28 +00:00
if ( $ hash - > { unifi } - > { CONNECTED } eq 'disabled' ) {
2015-08-25 21:29:35 +00:00
return 'disabled' ;
}
2015-08-29 19:25:28 +00:00
elsif ( $ hash - > { unifi } - > { CONNECTED } eq 'connected' ) {
2015-08-25 21:29:35 +00:00
return 1 ;
} else {
return 0 ;
}
}
}
2018-03-11 14:54:39 +00:00
###############################################################################
sub
Unifi_encrypt ( $ )
{
my ( $ decoded ) = @ _ ;
my $ key = getUniqueId ( ) ;
my $ encoded ;
return $ decoded if ( $ decoded =~ /^crypt:(.*)/ ) ;
for my $ char ( split // , $ decoded ) {
my $ encode = chop ( $ key ) ;
$ encoded . = sprintf ( "%.2x" , ord ( $ char ) ^ ord ( $ encode ) ) ;
$ key = $ encode . $ key ;
}
return 'crypt:' . $ encoded ;
}
sub
Unifi_decrypt ( $ )
{
my ( $ encoded ) = @ _ ;
my $ key = getUniqueId ( ) ;
my $ decoded ;
$ encoded = $ 1 if ( $ encoded =~ /^crypt:(.*)/ ) ;
for my $ char ( map { pack ( 'C' , hex ( $ _ ) ) } ( $ encoded =~ /(..)/g ) ) {
my $ decode = chop ( $ key ) ;
$ decoded . = chr ( ord ( $ char ) ^ ord ( $ decode ) ) ;
$ key = $ decode . $ key ;
}
return $ decoded ;
}
2015-08-25 21:29:35 +00:00
###############################################################################
sub Unifi_Whoami () { return ( split ( '::' , ( caller ( 1 ) ) [ 3 ] ) ) [ 1 ] || '' ; }
2015-08-29 19:25:28 +00:00
sub Unifi_Whowasi () { return ( split ( '::' , ( caller ( 2 ) ) [ 3 ] ) ) [ 1 ] || '' ; }
2015-08-24 21:43:54 +00:00
###############################################################################
2015-08-23 00:13:22 +00:00
1 ;
2015-08-23 16:53:57 +00:00
2015-08-23 00:13:22 +00:00
= pod
2016-08-19 18:11:24 +00:00
= item device
= item summary Interpret / control of Ubiquiti Networks UniFi - controller
= item summary_DE Auswertung / Steuerung eines Ubiquiti Networks UniFi - Controller
2015-08-23 00:13:22 +00:00
= begin html
< a name = "Unifi" > </a>
<h3> Unifi </h3>
<ul>
2015-08-31 22:29:29 +00:00
Unifi is the FHEM module for the Ubiquiti Networks ( UBNT ) - Unifi Controller . <br>
<br>
e . g . you can use the 'presence' function , which will tell you if a device is connected to your WLAN ( even in PowerSave Mode ! ) . <br>
2015-08-23 00:13:22 +00:00
Immediately after connecting to your WLAN it will set the device - reading to 'connected' and about 5 minutes after leaving your WLAN it will set the reading to 'disconnected' . <br>
2015-08-31 22:29:29 +00:00
The device will be still connected , even it is in PowerSave - Mode . ( In this mode the devices are not pingable , but the connection to the unifi - controller does not break off . ) <br>
<br>
Or you can use the other readings or set and get features to control your unifi - controller , accesspoints and wlan - clients .
2015-08-23 00:24:03 +00:00
<br>
<h4> Prerequisites </h4>
<ul>
The Perl module JSON is required . <br>
On Debian /Raspbian: <code>apt-get install libjson-perl </co de > <br>
Via CPAN: <code> cpan install JSON </code>
</ul>
2015-08-23 00:13:22 +00:00
<h4> Define </h4>
<ul>
2019-03-16 13:16:35 +00:00
<code> define & lt ; name & gt ; Unifi & lt ; ip & gt ; & lt ; port & gt ; & lt ; username & gt ; & lt ; password & gt ; [ & lt ; interval & gt ; [ & lt ; siteID & gt ; ] ] </code>
2015-08-23 00:13:22 +00:00
<br> <br>
<br>
& lt ; name & gt ; :
<ul>
<code> The FHEM device name for the device . </code> <br>
</ul>
& lt ; ip & gt ; :
<ul>
<code> The ip of your unifi - controller . </code> <br>
</ul>
& lt ; port & gt ; :
<ul>
<code> The port of your unifi - controller . Normally it ' s 8443 or 443 . </code> <br>
</ul>
& lt ; username & gt ; :
<ul>
<code> The Username to log on . </code> <br>
</ul>
& lt ; password & gt ; :
<ul>
<code> The password to log on . </code> <br>
</ul>
[ & lt ; interval & gt ; ] :
<ul>
2019-03-16 13:16:35 +00:00
<code> ( optional without & lt ; siteID & gt ) <br>
2015-08-24 21:43:54 +00:00
Interval to fetch the information from the unifi - api . <br>
2015-08-23 00:13:22 +00:00
default: 30 seconds </code> <br>
</ul>
[ & lt ; siteID & gt ; ] :
<ul>
2019-03-16 13:16:35 +00:00
<code> ( optional ) <br>
2015-08-24 21:43:54 +00:00
You can find the site - ID by selecting the site in the UniFi web interface . <br>
e . g . https: // 192.168 .12 .13 : 8443 /manage/s / foobar the siteId you must use is : foobar . <br>
default: default </code> <br>
2015-08-23 16:53:57 +00:00
</ul> <br>
2015-08-23 00:13:22 +00:00
</ul>
2015-08-25 21:29:35 +00:00
<h4> Examples </h4>
2015-08-23 00:13:22 +00:00
<ul>
2015-08-25 21:29:35 +00:00
<code> define my_unifi_controller Unifi 192.168 .1 .15 443 admin secret </code> <br>
<br>
2019-03-16 13:16:35 +00:00
Or with optional parameters & lt ; interval & gt ; and & lt ; siteID & gt ; : <br>
<code> define my_unifi_controller Unifi 192.168 .1 .15 443 admin secret 30 default </code> <br>
2015-08-23 00:13:22 +00:00
</ul>
<h4> Set </h4>
<ul>
2015-08-31 22:29:29 +00:00
<code> Note: Some setters are not available if controller is not connected , or no data is available for them . </code> <br>
<br>
2015-08-23 00:13:22 +00:00
<li> <code> set & lt ; name & gt ; update </code> <br>
2015-08-24 21:43:54 +00:00
Makes immediately a manual update . </li>
2015-08-31 22:29:29 +00:00
<br>
2018-03-11 14:54:39 +00:00
<li> <code> set & lt ; name & gt ; updateClient & lt ; mac & gt ; </code> <br>
Makes immediately a manual update of the client specified by MAC - Adress . </li>
<br>
2018-02-05 20:45:17 +00:00
<li> <code> set & lt ; name & gt ; clear & lt ; readings | clientData | voucherCache | all & gt ; </code> <br>
Clears the readings , clientData , voucherCache or all . </li>
2015-08-31 22:29:29 +00:00
<br>
<li> <code> set & lt ; name & gt ; archiveAlerts </code> <br>
Archive all unarchived Alerts . </li>
<br>
2015-09-03 18:15:12 +00:00
<li> <code> set & lt ; name & gt ; disconnectClient & lt ; all | user_id | controllerAlias | hostname | devAlias & gt ; </code> <br>
2015-08-31 22:29:29 +00:00
Disconnect one ore all clients . </li>
<br>
<li> <code> set & lt ; name & gt ; restartAP & lt ; all | _id | name | ip & gt ; </code> <br>
Restart one ore all accesspoints . </li>
<br>
<li> <code> set & lt ; name & gt ; setLocateAP & lt ; all | _id | name | ip & gt ; </code> <br>
Start 'locate' on one or all accesspoints . </li>
<br>
<li> <code> set & lt ; name & gt ; unsetLocateAP & lt ; all | _id | name | ip & gt ; </code> <br>
Stop 'locate' on one or all accesspoints . </li>
2018-06-10 15:42:35 +00:00
<br>
2018-01-12 20:39:58 +00:00
<li> <code> set & lt ; name & gt ; blockClient & lt ; clientname & gt ; </code> <br>
2018-06-10 15:42:35 +00:00
Block the & lt ; clientname & gt ; . Can also be called with the mac - address of the client . </li>
<br>
2018-01-12 20:39:58 +00:00
<li> <code> set & lt ; name & gt ; unblockClient & lt ; clientname & gt ; </code> <br>
2018-06-10 15:42:35 +00:00
Unblocks the & lt ; clientname & gt ; . Can also be called with the mac - address of the client . </li>
<br>
2018-01-12 20:39:58 +00:00
<li> <code> set & lt ; name & gt ; disableWLAN & lt ; ssid & gt ; </code> <br>
Disables WLAN with & lt ; ssid & gt ; </li>
2018-06-10 15:42:35 +00:00
<br>
2018-01-12 20:39:58 +00:00
<li> <code> set & lt ; name & gt ; enableWLAN & lt ; ssid & gt ; </code> <br>
Enables WLAN with & lt ; ssid & gt ; </li>
2018-06-10 15:42:35 +00:00
<br>
2018-01-17 22:38:27 +00:00
<li> <code> set & lt ; name & gt ; switchSiteLEDs & lt ; on | off & gt ; </code> <br>
Enables or disables the Status - LED settings of the site . </li>
2018-06-10 15:42:35 +00:00
<br>
2018-02-05 20:45:17 +00:00
<li> <code> set & lt ; name & gt ; createVoucher & lt ; expire & gt ; & lt ; n & gt ; & lt ; quota & gt ; & lt ; note & gt ; </code> <br>
Creates & lt ; n & gt ; vouchers that expires after & lt ; expire & gt ; minutes , are usable & lt ; quota & gt ; - times with a & lt ; note & gt ; no spaces in note allowed </li>
2018-06-10 15:42:35 +00:00
<br>
2019-05-19 06:19:20 +00:00
<li> <code> set & lt ; name & gt ; removeClientReadings & lt ; clientname & gt ; </code> <br>
Deletes the readings for & lt ; clientname & gt ; . Only disconnected clients should be removed , because connected clients will create readings in next update - cycle . </li>
<br>
<li> <code> set & lt ; name & gt ; refreshUCversion </code> <br>
Refresh the INTERNAL - value for the version of your unifi - controller . </li>
<br>
<li> <code> set & lt ; name & gt ; refreshUsergroups </code> <br>
Usergroups won ' t be updated automatically . Use this setter to update usergroups manually . </li>
<br>
2015-08-23 00:13:22 +00:00
</ul>
<h4> Get </h4>
<ul>
2015-08-31 22:29:29 +00:00
<code> Note: Some getters are not available if no data is available for them . </code> <br>
<br>
2015-09-03 18:15:12 +00:00
<li> <code> get & lt ; name & gt ; clientData & lt ; all | user_id | controllerAlias | hostname | devAlias & gt ; </code> <br>
2015-08-23 16:53:57 +00:00
Show more details about clients . </li>
2015-08-31 22:29:29 +00:00
<br>
<li> <code> get & lt ; name & gt ; events </code> <br>
2015-09-01 20:57:16 +00:00
Show events in specified 'eventPeriod' . </li>
2015-08-31 22:29:29 +00:00
<br>
<li> <code> get & lt ; name & gt ; unarchivedAlerts </code> <br>
Show all unarchived Alerts . </li>
2018-06-10 15:42:35 +00:00
<br>
2018-02-05 20:45:17 +00:00
<li> <code> get & lt ; name & gt ; voucher [ note ] </code> <br>
Show next voucher - code with specified note . If & lt ; note & gt ; is used in voucherCache the voucher will be marked as delivered </li>
2018-06-10 15:42:35 +00:00
<br>
2018-02-05 20:45:17 +00:00
<li> <code> get & lt ; name & gt ; voucherList [ all | note ] </code> <br>
Show list of vouchers ( all or with specified note only ) . </li>
2018-06-10 15:42:35 +00:00
<br>
2018-03-11 14:54:39 +00:00
<li> <code> get & lt ; name & gt ; showAccount </code> <br>
Show decrypted user and passwort . </li>
2018-06-10 15:42:35 +00:00
<br>
2015-08-23 00:13:22 +00:00
</ul>
<h4> Attributes </h4>
<ul>
2015-08-25 21:29:35 +00:00
<li> attr devAlias <br>
2015-09-03 18:15:12 +00:00
Can be used to rename device names in the format <code> & lt ; user_id | controllerAlias | hostname & gt ; : Aliasname . </code> <br>
2015-08-25 21:29:35 +00:00
Separate using blank to rename multiple devices . <br>
2015-09-03 18:15:12 +00:00
Example ( user_id ) : <code> attr unifi devAlias 5537 d138e4b033c1832c5c84:iPhone - Claudiu </code> <br>
2015-08-27 20:37:29 +00:00
Example ( controllerAlias ) : <code> attr unifi devAlias iPhoneControllerAlias:iPhone - Claudiu </code> <br>
Example ( hostname ) : <code> attr unifi devAlias iphone:iPhone - Claudiu </code> <br> </li>
2015-08-25 21:29:35 +00:00
<br>
2015-08-31 22:29:29 +00:00
<li> attr eventPeriod & lt ; 1 ... 168 & gt ; <br>
Can be used to configure the time - period ( hours ) of fetched events from controller . <br>
<code> default: 24 </code> </li>
<br>
2015-08-23 16:53:57 +00:00
<li> attr disable & lt ; 1 | 0 & gt ; <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 0 the automatic updating will performed . </li>
2015-08-25 21:29:35 +00:00
<br>
2018-02-05 20:45:17 +00:00
<li> attr ignoreWiredClients & lt ; 1 | 0 & gt ; <br>
With this attribute you can disable readings for wired clients . <br>
If set to 1 readings for wired clients are not generated . <br>
If set to 0 or not defined , readings for wired clients will be generated . </li>
<br>
<li> attr ignoreWirelessClients & lt ; 1 | 0 & gt ; <br>
With this attribute you can disable readings for wireless clients . <br>
If set to 1 readings for wireless clients are not generated . <br>
If set to 0 or not defined , readings for wireless clients will be generated . </li>
<br>
2015-08-23 00:13:22 +00:00
<li> attr < a href = "#verbose" > verbose </a> 5 <br>
2015-08-23 16:53:57 +00:00
This attribute will help you if something does not work as espected . </li>
2015-08-25 21:29:35 +00:00
<br>
2015-08-31 22:29:29 +00:00
<li> attr httpLoglevel <1,2,3,4,5> <br>
Can be used to debug the HttpUtils - Module . Set it smaller or equal as your 'global verbose level' . <br>
<code> default: 5 </code> </li>
<br>
2018-02-05 20:45:17 +00:00
<li> attr voucherCache & lt ; expire n quota note , ... & gt ; <br>
Define voucher - cache ( s ) . Comma separeted list of four parameters that are separated by spaces ; no spaces in note ! . <br>
By calling <code> get voucher & lt ; note & gt ; </code> the delivery - time of the voucher will be saved in the cache .
The voucher with the oldest delivery - time will be returned by <code> get voucher & lt ; note & gt ; </code> .
If the voucher is not used for 2 hours , the delivery - time in the cache will be deleted . <br>
<code> e . g . : 120 2 1 2 h , 180 5 2 3 h </code> defines two caches . <br>
The first cache has a min size of 2 vouchers . The vouchers expire after 120 minutes and can be used one - time . <br>
The second cache has a min size of 5 vouchers . The vouchers expire after 180 minutes and can be used two - times . </li>
<br>
2019-03-20 19:15:01 +00:00
<li> attr customClientReadings clientNameRegEx1:ClientReadingRegEx1 clientNameRegEx2:ClientReadingRegEx2 ... <br>
Can be used to customize the readings for clients . <br>
2019-03-24 09:59:38 +00:00
<code> default: . : ^ accesspoint $| ^ essid $| ^ hostname $| ^ last_seen $| ^ snr $| ^ uptime $< /code> Note: rssi ist called snr in old default before attr customClientReadings.</ li >
2019-03-20 19:15:01 +00:00
<br>
2019-03-25 20:02:14 +00:00
<li> attr customClientNames & lt ; value & gt ; <br>
Can be used to control the naming convention for client readings . Any valid clientData field is allowed , though only <code> mac </code> seems to be useful . For a list , see <code> & lt ; unifi & gt ; get ClientData all </code> . <br>
2019-05-19 06:19:20 +00:00
When using formatted readings ( reading is named like & lt ; clientName & gt ; <b> _f_ </b> ... ) with disconnected clients e . g . in DOIF or notifies , also specify the unformatted value as customClientReading . <br>
e . g . ^ _f_last_seen_duration $| ^ last_seen $ < br >
Reason: Disconnected clients won ' t be send by UnifiController and are loosing their values when restarting fhem .
The UnifiModul tries to restore the clients from existing readings . This won 't work for formatted readings if the unformatted value hasn' t a reading itself . <br>
Client naming follows these rules:
2019-03-25 20:02:14 +00:00
<ol>
<li> <code> devAlias </code> ( if present for this client ) </li>
<li> attribute <code> customClientNames </code> ( if it is set <i> and </i> the corresponding data field exists for client ) </li>
<li> name ( alias ) in Unifi - Controller </li>
<li> hostname of the client </li>
</ol>
</li>
<br>
2015-08-23 22:14:04 +00:00
<li> < a href = "#readingFnAttributes" > readingFnAttributes </a> </li>
2015-08-23 00:13:22 +00:00
</ul>
<h4> Readings </h4>
<ul>
2015-08-23 16:53:57 +00:00
Note: All readings generate events . You can control this with < a href = "#readingFnAttributes" > these global attributes </a> .
2019-05-19 06:19:20 +00:00
<li> When clientnames start with a . ( dot ) , FHEMWEB hides readings for this client when global showInternal Values ne 1 . </li>
2019-03-20 19:15:01 +00:00
<li> Each client has 7 readings for connection - state , SNR , uptime , last_seen - time , connected - AP , essid and hostname if attribute customClientReadings is not used . </li>
2019-05-19 06:19:20 +00:00
<li> <code> - UC_newClients </code> & nbsp ; shows names of a new clients , could be a comma - separated list . Will be set to empty at next interval . </li>
<li> <code> - UC_blockedClients </code> & nbsp ; shows names of a blocked clients , could be a comma - separated list . </li>
2018-07-22 15:16:09 +00:00
<li> Each AP has 5 readings for state ( can be 'ok' or 'error' ) , essid ' s , utilization , locate and count of connected - clients . </li>
2015-08-31 22:29:29 +00:00
<li> The unifi - controller has 6 readings for event - count in configured 'timePeriod' , unarchived - alert count , accesspoint count , overall wlan - state ( can be 'ok' , 'warning' , or other ? ) , connected user count and connected guest count . </li>
2018-10-31 10:53:51 +00:00
<li> The unifi - controller has also readings for wan_ip and results of the speedtest ( UC_speed_ping , UC_speed_down , UC_speed_up ) . </li>
2015-08-31 22:29:29 +00:00
<li> The Unifi - device reading 'state' represents the connection - state to the unifi - controller ( can be 'connected' , 'disconnected' , 'initialized' and 'disabled' ) . </li>
2018-02-05 20:45:17 +00:00
<li> Each voucher - cache has a reading with the next free voucher code . </li>
2015-08-23 00:13:22 +00:00
</ul>
<br>
</ul>
= end html
= cut