From 56517958e9a98288dfa5290af2674fd7cc9de418 Mon Sep 17 00:00:00 2001 From: justme-1968 Date: Sat, 27 May 2017 20:20:30 +0000 Subject: [PATCH] 74_Unifi.pm: added get poeMode and set poeState commands, _utilization and _poePower readings git-svn-id: https://svn.fhem.de/fhem/trunk@14391 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/CHANGED | 2 + fhem/FHEM/74_Unifi.pm | 150 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 145 insertions(+), 7 deletions(-) diff --git a/fhem/CHANGED b/fhem/CHANGED index b29b70ec8..8e2ba7e32 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,7 @@ # Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Do not insert empty lines here, update check depends on it. + - feature: 74_Unifi.pm: added get poeMode and set poeState commands + added _utilization and _poePower readings - feature: 93_DbRep: v4.16.1, json as option of sqlResultFormat - feature: 31_PLAYBULB: add support for ssh remote control - change: 42_Nextion: fault tolerance in reader / fixes diff --git a/fhem/FHEM/74_Unifi.pm b/fhem/FHEM/74_Unifi.pm index f5e8dfbed..92ec8cc11 100644 --- a/fhem/FHEM/74_Unifi.pm +++ b/fhem/FHEM/74_Unifi.pm @@ -143,7 +143,7 @@ sub Unifi_Notify($$) { sub Unifi_Set($@) { my ($hash,@a) = @_; return "\"set $hash->{NAME}\" needs at least an argument" if ( @a < 2 ); - my ($name,$setName,$setVal) = @a; + my ($name,$setName,$setVal,$setVal2,$setVal3) = @a; Log3 $name, 5, "$name: set called with $setName " . ($setVal ? $setVal : "") if ($setName ne "?"); @@ -156,12 +156,13 @@ sub Unifi_Set($@) { my $clientNames = Unifi_ClientNames($hash); my $apNames = Unifi_ApNames($hash); - if($setName !~ /archiveAlerts|restartAP|setLocateAP|unsetLocateAP|disconnectClient|update|clear/) { + if($setName !~ /archiveAlerts|restartAP|setLocateAP|unsetLocateAP|disconnectClient|update|clear|poeMode/) { return "Unknown argument $setName, choose one of update:noArg " - ." clear:all,readings,clientData " + ."clear:all,readings,clientData " .((defined $hash->{alerts_unarchived}[0] && scalar @{$hash->{alerts_unarchived}}) ? "archiveAlerts:noArg " : "") .(($apNames && Unifi_CONNECTED($hash)) ? "restartAP:all,$apNames setLocateAP:all,$apNames unsetLocateAP:all,$apNames " : "") - .(($clientNames && Unifi_CONNECTED($hash)) ? "disconnectClient:all,$clientNames" : ""); + .(($clientNames && Unifi_CONNECTED($hash)) ? "disconnectClient:all,$clientNames " : "") + ."poeMode"; } else { Log3 $name, 4, "$name: set $setName"; @@ -181,6 +182,72 @@ sub Unifi_Set($@) { Unifi_DisconnectClient_Send($hash,keys(%{$hash->{clients}})); } } + elsif ($setName eq 'poeMode') { + return "usage: $setName " if( !$setVal3 ); + my $apRef; + for my $apID (keys %{$hash->{accespoints}}) { + my $ap = $hash->{accespoints}->{$apID}; + next if( !$ap->{port_table} ); + next if( $ap->{type} ne 'usw' ); + next if( $setVal ne $ap->{mac} && $setVal ne $ap->{device_id} && $ap->{name} !~ $setVal ); + return "multiple switches found for $setVal" if( $apRef ); + $apRef = $ap; + } + return "no switch $setVal found" if( !$apRef ); + if( $setVal2 !~ m/\d+/ ) { + for my $port (@{$apRef->{port_table}}) { + next if( $port->{name} !~ $setVal2 ); + $setVal2 = $port->{port_idx}; + last; + } + } + return "port musst be numeric" if( $setVal2 !~ m/\d+/ ); + return "port musst be in [1..". scalar @{$apRef->{port_table}} ."] " if( $setVal2 < 1 || $setVal2 > scalar @{$apRef->{port_table}} ); + return "switch '$apRef->{name}' has no port $setVal2" if( !defined(@{$apRef->{port_table}}[$setVal2-1] ) ); + return "port $setVal2 of switch '$apRef->{name}' is not poe capable" if( !@{$apRef->{port_table}}[$setVal2-1]->{port_poe} ); + + my $port_overrides = $apRef->{port_overrides}; + my $idx; + my $i = 0; + for my $entry (@{$port_overrides}) { + if( $entry->{port_idx} eq $setVal2 ) { + $idx = $i; + last; + } + ++$i; + } + if( !defined($idx) ) { + push @{$port_overrides}, {port_idx => $setVal2+0}; + $idx = scalar @{$port_overrides}; + } + + if( $setVal3 eq 'off' ) { + $port_overrides->[$idx]{poe_mode} = "off"; + Unifi_RestJson_Send($hash, $apRef->{device_id}, {port_overrides => $port_overrides }); + + } elsif( $setVal3 eq 'auto' || $setVal3 eq 'poe+' ) { + #return "port $setVal2 not auto poe capable" if( @{$apRef->{port_table}}[$setVal2-1]->{poe_caps} & 0x03 ) ; + $port_overrides->[$idx]{poe_mode} = "auto"; + Unifi_RestJson_Send($hash, $apRef->{device_id}, {port_overrides => $port_overrides }); + + } elsif( $setVal3 eq 'passive' ) { + #return "port $setVal2 not passive poe capable" if( @{$apRef->{port_table}}[$setVal2-1]->{poe_caps} & 0x04 ) ; + $port_overrides->[$idx]{poe_mode} = "pasv24"; + Unifi_RestJson_Send($hash, $apRef->{device_id}, {port_overrides => $port_overrides }); + + } elsif( $setVal3 eq 'passthrough' ) { + #return "port $setVal2 not passthrough poe capable" if( @{$apRef->{port_table}}[$setVal2-1]->{poe_caps} & 0x08 ) ; + $port_overrides->[$idx]{poe_mode} = "passthrough"; + Unifi_RestJson_Send($hash, $apRef->{device_id}, {port_overrides => $port_overrides }); + + } elsif( $setVal3 eq 'restsart' ) { + Unifi_ApJson_Send($hash,{cmd => 'power-cycle', mac => $apRef->{mac}, port_idx => $setVal2+0}); + + } else { + return "unknwon poe mode $setVal3"; + + } + } elsif ($setName eq 'archiveAlerts' && defined $hash->{alerts_unarchived}[0]) { Unifi_ArchiveAlerts_Send($hash); undef @{$hash->{alerts_unarchived}}; @@ -254,11 +321,36 @@ sub Unifi_Get($@) { my $clientNames = Unifi_ClientNames($hash); - if($getName !~ /events|clientData|unarchivedAlerts/) { + if($getName !~ /events|clientData|unarchivedAlerts|poeState/) { 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 " : "") - .(($clientNames) ? "clientData:all,$clientNames" : ""); + .(($clientNames) ? "clientData:all,$clientNames " : "") + ."poeState"; + } + elsif ($getName eq 'poeState') { + my $poeState; + for my $apID (keys %{$hash->{accespoints}}) { + my $apRef = $hash->{accespoints}->{$apID}; + next if( $apRef->{type} ne 'usw' ); + next if( !$apRef->{port_table} ); + next if( $getVal && $getVal ne $apRef->{mac} && $getVal ne $apRef->{device_id} && $apRef->{name} !~ $getVal ); + $poeState .= "\n" if( $poeState ); + $poeState .= sprintf( "%-20s (mac:%-17s, id:%s)\n", $apRef->{name}, $apRef->{mac}, $apRef->{device_id} ); + $poeState .= sprintf( " %2s %-15s", "id", "name" ); + $poeState .= sprintf( " %s %s %-6s %-4s %-10s", "", "on", "mode", "", "class" ); + $poeState .= "\n"; + for my $port (@{$apRef->{port_table}}) { + #next if( !$port->{port_poe} ); + $poeState .= sprintf( " %2i %-15s", $port->{port_idx}, $port->{name} ); + $poeState .= sprintf( " %s %s %-6s %-4s %-10s", $port->{poe_caps}, $port->{poe_enable}, $port->{poe_mode}, defined($port->{poe_good})?($port->{poe_good}?"good":""):"", defined($port->{poe_class})?$port->{poe_class}:"" ) if( $port->{port_poe} ); + $poeState .= sprintf( " %5.2fW %5.2fV %5.2fmA", $port->{poe_power}?$port->{poe_power}:0, $port->{poe_voltage}, $port->{poe_current}?$port->{poe_current}:0 ) if( $port->{port_poe} ); + $poeState .= "\n"; + } + } + $poeState = "====================================================\n". $poeState; + $poeState .= "====================================================\n"; + return $poeState; } elsif ($getName eq 'unarchivedAlerts' && defined $hash->{alerts_unarchived}[0] && scalar @{$hash->{alerts_unarchived}}) { my $alerts = "====================================================\n"; @@ -883,8 +975,19 @@ sub Unifi_SetAccesspointReadings($) { readingsBulkUpdate($hash,'-AP_'.$apName.'_state',($apRef->{state} == 1) ? 'ok' : 'error'); readingsBulkUpdate($hash,'-AP_'.$apName.'_clients',$apRef->{'num_sta'}); - readingsBulkUpdate($hash,'-AP_'.$apName.'_essid',$essid); + if( $apRef->{type} eq 'uap' ) { + readingsBulkUpdate($hash,'-AP_'.$apName.'_essid',$essid); + 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'}) ); + } readingsBulkUpdate($hash,'-AP_'.$apName.'_locate',(!defined $apRef->{locating}) ? 'unknown' : ($apRef->{locating}) ? 'on' : 'off'); + 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) ); + # 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'}); @@ -956,6 +1059,35 @@ sub Unifi_ApCmd_Send($$@) { #cmd: 'set-locate', 'unset-locate', 'restart' } ); return undef; } +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", + callback => \&Unifi_ApCmd_Receive, + aps => [], + data => $json, + } ); + return undef; +} +sub Unifi_RestJson_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/device/".$id, + callback => \&Unifi_ApCmd_Receive, + aps => [], + data => $json, + } ); + return undef; +} ############################################################################### sub Unifi_ApCmd_Receive($) { my ($param, $err, $data) = @_; @@ -1293,6 +1425,8 @@ Or you can use the other readings or set and get features to control your unifi-
  • set <name> unsetLocateAP <all|_id|name|ip>
    Stop 'locate' on one or all accesspoints.
  • +
  • set <name> poeMode <name|mac|id> <port> <off|auto|passive|passthrough|restart>
    + Set PoE mode for <port>.
  • @@ -1308,6 +1442,8 @@ Or you can use the other readings or set and get features to control your unifi-
  • get <name> unarchivedAlerts
    Show all unarchived Alerts.
  • +
  • get <name> poeState [name|mac|id]
    + Show port PoE state.