diff --git a/fhem/CHANGED b/fhem/CHANGED index ada28a39b..9e634cc64 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: get deviceData hinzugefügt + - feature: 74_UnifiSwitch: new setter portProfile - bugfix: 60_Watches: avoid JS error which appeared in seldom cases - feature: 98_WeekdayTimer: Add options WDT_sendDelay and WDT_eventMap - change: 98_WeekdayTimer: break compability to Heating_Control diff --git a/fhem/FHEM/74_Unifi.pm b/fhem/FHEM/74_Unifi.pm index 9038fa422..0560d3d77 100644 --- a/fhem/FHEM/74_Unifi.pm +++ b/fhem/FHEM/74_Unifi.pm @@ -77,10 +77,14 @@ # - feature: 74_Unifi: new setter to start RF-Scan # V 3.5.0 # - feature: 74_Unifi: support UDM +# V 3.5.1 +# - fixed: 74_Unifi: autocreate-naming-fallback for udm fixed to mac (from ip) +# V 3.5.2 +# - feature: 74_Unifi: get deviceData hinzugefügt package main; -my $version="3.5.0"; +my $version="3.5.2"; # Default für clientReadings setzen. Die Readings waren der Standard vor Einführung des Attributes customClientReadings. # Eine Änderung hat Auswirkungen auf (alte) Moduldefinitionen ohne dieses Attribut. my $defaultClientReadings=".:^accesspoint|^essid|^hostname|^last_seen|^snr|^uptime"; #ist wegen snr vs rssi nur halb korrekt, wird aber auch nicht wirklich verwendet ;-) @@ -588,13 +592,14 @@ sub Unifi_Get($@) { my $voucherNotes=join(",", keys %voucherNotesHash); my $clientNames = Unifi_ClientNames($hash); + my $deviceNames = Unifi_ApNames($hash); - if($getName !~ /events|clientData|unarchivedAlerts|voucherList|voucher|showAccount/) { + if($getName !~ /events|clientData|unarchivedAlerts|voucherList|voucher|showAccount|deviceData/) { 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 " : "") - ."voucherList:all,$voucherNotes voucher:$voucherNotes showAccount"; + ."voucherList:all,$voucherNotes voucher:$voucherNotes showAccount deviceData:all,$deviceNames"; } elsif ($getName eq 'unarchivedAlerts' && defined $hash->{alerts_unarchived}[0] && scalar @{$hash->{alerts_unarchived}}) { my $alerts = "====================================================\n"; @@ -704,6 +709,21 @@ sub Unifi_Get($@) { return "user: $user\npassword: $password"; } + elsif( $getName eq 'deviceData' ) { + my $deviceData = ''; + if ($getVal && $getVal ne 'all') { + $getVal = Unifi_ApNames($hash,$getVal,'makeID'); + } + if (!$getVal || $getVal eq 'all') { + return Unifi_FormatJson(encode_json($hash->{accespoints})); + } + elsif(defined($hash->{accespoints}->{$getVal})) { + return Unifi_FormatJson(encode_json($hash->{accespoints}->{$getVal})); + } + else { + return "$hash->{NAME}: Unknown device '$getVal' in command '$getName', choose one of: all,$deviceNames"; + } + } return undef; } ############################################################################### @@ -1264,9 +1284,9 @@ sub Unifi_GetSysinfo_Receive($) { 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}; - } + $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 { @@ -1436,11 +1456,12 @@ sub Unifi_GetAccesspoints_Receive($) {# TODO Umbenennen in Unifi_GetDevices_Rece $hash->{accespoints}->{$h->{_id}} = $h; #TODO: Switch-Modelle anders festlegen ? Oder passt usw? if (defined $h->{type} && (($h->{type} eq "usw") || ($h->{type} eq "udm"))){ - my $usw_name=""; + my $usw_name=""; + if ($h->{type} eq "udm") { $usw_name="udm_";} if (defined $h->{name}){ - $usw_name=makeDeviceName($h->{name}); + $usw_name.=makeDeviceName($h->{name}); }else{ - $usw_name=makeDeviceName($h->{ip}); + ($h->{type} eq "udm") ? $usw_name.=makeDeviceName($h->{mac}) : $usw_name.=makeDeviceName($h->{ip});; } Dispatch($hash,"UnifiSwitch_".$usw_name.encode_json($h),undef); } @@ -1703,6 +1724,7 @@ sub Unifi_SetAccesspointReadings($) { 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'); + readingsBulkUpdate($hash,'-AP-lastUpdate', gmtime(time())); #my $poe_power; #for my $port (@{$apRef->{port_table}}) { # next if( !$port->{port_poe} ); @@ -2245,11 +2267,11 @@ sub Unifi_ClientNames($@) { $ID = $1; }elsif ( $attrCustomClientNames && defined $clientRef->{$attrCustomClientNames}){ $ID = makeReadingName($clientRef->{$attrCustomClientNames}); - }elsif ( (defined $clientRef->{name} && $clientRef->{name} =~ /^([\w\.\-]+)$/) + }elsif ( (defined $clientRef->{name} && $clientRef->{name} =~ /^([\w\.\-]+)$/) || (defined $clientRef->{hostname} && $clientRef->{hostname} =~ /^([\w\.\-]+)$/) - ){ + ){ $ID = $1; - } + } return $ID; } elsif (defined $ID && defined $W && $W eq 'makeID') { # Return ID from Alias @@ -2414,7 +2436,7 @@ sub Unifi_initCustomClientReadings($){ sub Unifi_initVoucherCache($){ my ($hash) = @_; - #return if ( ! defined $hash->{hotspot}->{voucherCache}->{attr_value}); + return if ( ! defined $hash->{hotspot}->{voucherCache}->{attr_value}); my @voucherCaches=split(/,/, $hash->{hotspot}->{voucherCache}->{attr_value}); my @notes=(); foreach(@voucherCaches){ @@ -2492,6 +2514,37 @@ sub Unifi_NextUpdateFn($$) { } ############################################################################### +sub Unifi_FormatJson($) { + my ($json) = @_; + my $ret=""; + my $deep=""; + foreach my $char (split('', $json)) { + if ($char eq "{" || $char eq "["){ + $ret=$ret."\n".$deep; + }elsif ($char eq "}" || $char eq "]"){ + chop($deep); + chop($deep); + $ret=$ret."\n".$deep; + } + + $ret=$ret.$char; + + if ($char eq "{" || $char eq "["){ + $deep=$deep." " ; + $ret=$ret."\n".$deep; + }elsif ($char eq "}" || $char eq "]"){ + $ret=$ret."\n".$deep; + }elsif ($char eq ","){ + $ret=$ret."\n".$deep; + } + } + #Zeilenvorschübe vorne und hinten entfernen + $ret =~ s/^.//; + chop($ret); + return $ret; +} +############################################################################### + sub Unifi_ReceiveFailure($$) { my ($hash,$meta) = @_; my ($name,$self) = ($hash->{NAME},Unifi_Whowasi()); @@ -2736,6 +2789,9 @@ Or you can use the other readings or set and get features to control your unifi-
  • get <name> clientData <all|user_id|controllerAlias|hostname|devAlias>
    Show more details about clients.

  • +
  • get <name> deviceData <all|AP-Name;
    + Show data of the specified (or all) device(s) in (simple formatted) json. Can be used for userreadings (use decode_json(..) in myUtils.pm).
  • +
  • get <name> events
    Show events in specified 'eventPeriod'.

  • diff --git a/fhem/FHEM/74_UnifiSwitch.pm b/fhem/FHEM/74_UnifiSwitch.pm index f514deab5..16f3465b3 100755 --- a/fhem/FHEM/74_UnifiSwitch.pm +++ b/fhem/FHEM/74_UnifiSwitch.pm @@ -28,15 +28,17 @@ # V 0.0.96 # - fixed: 74_UnifiSwitch: Log-Messages # V 0.0.97 -# - fixed: 74_UnifiSwitch: new readings for general_temperature, overheating, fan_level, cpu and mem +# - feature: 74_UnifiSwitch: new readings for general_temperature, overheating, fan_level, cpu and mem # V 1.0.00 -# - fixed: 74_UnifiSwitch: supports UDM-Switch +# - feature: 74_UnifiSwitch: supports UDM-Switch +# V 1.0.01 +# - feature: 74_UnifiSwitch: new setter portProfile # # TODOs: # - state des USW für weiter state-Numbers korrekt in Worte übersetzen package main; -my $version="1.0.00"; +my $version="1.0.01"; # Laden evtl. abhängiger Perl- bzw. FHEM-Module use strict; use warnings; @@ -134,9 +136,9 @@ sub UnifiSwitch_Set($@){ my $portProfileDisableID=AttrVal($name,"portProfileDisableID",undef); my $isPortprofileID = ""; $isPortprofileID ="disablePort" if (defined $portProfileDisableID); - if($setName !~ /clear|poeMode|disablePort/) { + if($setName !~ /clear|poeMode|disablePort|portProfile/) { return "Unknown argument $setName, choose one of " - ."clear:all,readings poeMode ".$isPortprofileID; #TODO: PortNamen sowie die Modes als Auswahl anhängen + ."clear:all,readings poeMode ".$isPortprofileID." portProfile"; #TODO: PortNamen sowie die Modes als Auswahl anhängen }elsif ($setName eq 'clear') { if ($setVal eq 'readings' || $setVal eq 'all') { for (keys %{$hash->{READINGS}}) { @@ -180,6 +182,10 @@ sub UnifiSwitch_Set($@){ if( $setName eq 'disablePort' ) { $port_overrides->[$idx]{portconf_id} = $portProfileDisableID; IOWrite($hash, "Unifi_DeviceRestJson_Send", $apRef->{device_id}, $port_overrides); + } + if( $setName eq 'portProfile' ) { + $port_overrides->[$idx]{portconf_id} = $setVal; + IOWrite($hash, "Unifi_DeviceRestJson_Send", $apRef->{device_id}, $port_overrides); }elsif ($setName eq 'poeMode') { return "usage: $setName " if( !$setVal ); return "port $setVal of switch '$apRef->{name}' is not poe capable" if( !@{$apRef->{port_table}}[$setVal-1]->{port_poe} ); @@ -233,9 +239,9 @@ sub UnifiSwitch_Get($@){ elsif ($getName eq 'poeState') { my $poeState; my $apRef = $hash->{usw}; - 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 ); + #next if( $apRef->{type} ne 'usw' ); + return "no ports?!" if( !$apRef->{port_table} ); + return "us with mac, deviceID or deviceName" 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" ); @@ -256,20 +262,20 @@ sub UnifiSwitch_Get($@){ elsif ($getName eq 'portOverrides') { my $portOverrides; my $apRef = $hash->{usw}; - 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 ); + #next if( $apRef->{type} ne 'usw' ); + return "no ports?!" if( !$apRef->{port_table} ); + return "us with mac, deviceID or deviceName" if( $getVal && $getVal ne $apRef->{mac} && $getVal ne $apRef->{device_id} && $apRef->{name} !~ $getVal ); $portOverrides .= "\n" if( $portOverrides ); $portOverrides .= sprintf( "%-20s (mac:%-17s, id:%s)\n", $apRef->{name}, $apRef->{mac}, $apRef->{device_id} ); $portOverrides .= sprintf( " %2s %-15s", "id", "name" ); $portOverrides .= sprintf( " %-10s %-25s", "poe_mode", "PortConfigID" ); $portOverrides .= "\n"; for my $port (@{$apRef->{port_overrides}}) { - if(defined $port->{port_idx}){ - $portOverrides .= sprintf( " %2i %-15s", $port->{port_idx}, $port->{name}?$port->{name}:"" ); - $portOverrides .= sprintf( " %-10s %-25s", $port->{poe_mode}?$port->{poe_mode}:"", $port->{portconf_id}?$port->{portconf_id}:""); - $portOverrides .= "\n"; - } + if(defined $port->{port_idx}){ + $portOverrides .= sprintf( " %2i %-15s", $port->{port_idx}, $port->{name}?$port->{name}:"" ); + $portOverrides .= sprintf( " %-10s %-25s", $port->{poe_mode}?$port->{poe_mode}:"", $port->{portconf_id}?$port->{portconf_id}:""); + $portOverrides .= "\n"; + } } $portOverrides = "====================================================\n". $portOverrides; @@ -416,8 +422,10 @@ You can use the readings or set features to control your unifi-switch. Set PoE mode for <port>.
  • set <name> disablePort <port>
    - Only visible when Attr portProfileDisableID is set.
    + Only visible when Attr portProfileDisableID is set.
    Set the PortProfile from Attr portProfileDisableID for <port>.
  • +
  • set <name> portProfile <port>
    + Set the PortProfile ID. The ID can be found with get portOverrides.
  • Get