diff --git a/fhem/FHEM/42_SYSMON.pm b/fhem/FHEM/42_SYSMON.pm index 6bdc79ebb..0a9489c70 100644 --- a/fhem/FHEM/42_SYSMON.pm +++ b/fhem/FHEM/42_SYSMON.pm @@ -37,7 +37,7 @@ use Data::Dumper; my $missingModulRemote; eval "use Net::Telnet;1" or $missingModulRemote .= "Net::Telnet "; -my $VERSION = "2.0.3"; +my $VERSION = "2.1.3"; use constant { PERL_VERSION => "perl_version", @@ -102,6 +102,9 @@ SYSMON_Initialize($) $hash->{SetFn} = "SYSMON_Set"; $hash->{AttrFn} = "SYSMON_Attr"; $hash->{AttrList} = "filesystems network-interfaces user-defined disable:0,1 nonblocking:0,1 ". + "telnet-time-out ". + "user-fn2 user-fn ". + "telnet-prompt-regx telnet-login-prompt-regx ". $readingFnAttributes; } ### attr NAME user-defined osUpdates:1440:Aktualisierungen:cat ./updates.txt [,:::] @@ -496,6 +499,19 @@ SYSMON_updateCurrentReadingsMap($) { } } + # User defined functions + my $userfn = AttrVal($name, "user-fn", undef); + if(defined $userfn) { + my @userfn_list = split(/,\s*/, trim($userfn)); + foreach (@userfn_list) { + # :::... + my($fnName, $uInterval, @readings) = split(/:/, $_); + foreach my $rName (@readings) { + $rMap->{$rName} = "user defined: $fnName"; + } + } + } + # TEST: TODO $rMap->{"io_sda_raw"} = "TEST"; $rMap->{"io_sda_diff"} = "TEST"; @@ -604,8 +620,30 @@ SYSMON_Get($@) { return $hash->{INTERVAL_MULTIPLIERS}; } + + if($cmd eq "list_lan_devices") + { + my $ret=''; + my $map = SYSMON_getFBLanDeviceList($hash); + if(defined($map)) { + foreach my $dname (sort keys %{$map}) { + my $dev_ip = $map->{$dname}{ip}; + $dev_ip='' unless defined $dev_ip; + my $dev_mac = $map->{$dname}{mac}; + my $dev_active = $map->{$dname}{active}; + my $dev_active_txt = $dev_active?'true':'false'; + #$ret.="\n"."$dname : active: $dev_active_txt, IP: $dev_ip, MAC: $dev_mac"; + $ret = "$ret\n".sprintf("%-25s : active: %-5s IP: %-16s MAC: %-17s", $dname, $dev_active_txt, $dev_ip, $dev_mac); + } + } + return $ret; + } - return "Unknown argument $cmd, choose one of list:noArg update:noArg interval_base:noArg interval_multipliers:noArg version:noArg"; + my $sfb=''; + if(SYSMON_isFB($hash)) { + $sfb=' list_lan_devices:noArg'; + } + return "Unknown argument $cmd, choose one of list:noArg update:noArg interval_base:noArg interval_multipliers:noArg version:noArg".$sfb; } sub @@ -667,6 +705,13 @@ SYSMON_Set($@) return $ret; } } + + # TEST + if($cmd eq "reset") + { + delete $defs{$name}->{helper}; + return 'ok'; + } return "Unknown argument $cmd, choose one of password interval_multipliers clean:noArg clear"; } @@ -718,7 +763,7 @@ SYSMON_Update($;$) $refresh_all="0" unless defined $refresh_all; - SYSMON_Log($hash, 5, "refresh_all: ".$refresh_all); + #SYSMON_Log($hash, 5, "refresh_all: ".$refresh_all); my $name = $hash->{NAME}; @@ -729,7 +774,7 @@ SYSMON_Update($;$) if( AttrVal($name, "disable", "") eq "1" ) { - SYSMON_Log($hash, 5, "disabled"); + #SYSMON_Log($hash, 5, "disabled"); $hash->{STATE} = "Inactive"; } else { # Beim ersten mal alles aktualisieren! @@ -879,7 +924,18 @@ sub SYSMON_updateReadings($$) { my $name = $hash->{NAME}; readingsBeginUpdate($hash); - + + + # Wenn UserFn benutzt wird, werden die erstellten Eintraege erfasst und die entsprechenden Readings nicht erhalten + my $h_keys; + my $uFnReadings = $map->{"xuser_fnr"}; + my @a_keys; + if(defined($uFnReadings)) { + delete $map->{"xuser_fnr"}; + @a_keys = split(/,\s*/, trim($uFnReadings)); + #$h_keys = map { $_ => "1" } @a_keys; + } + foreach my $aName (keys %{$map}) { my $value = $map->{$aName}; # Nur aktualisieren, wenn ein gueltiges Value vorliegt @@ -893,8 +949,14 @@ sub SYSMON_updateReadings($$) { # Nicht mehr benoetigte Readings loeschen my $omap = SYSMON_getObsoleteReadingsMap($hash); + + # UserFn Keys entfernen + foreach my $aName (@a_keys) { + delete($omap->{$aName}); + } foreach my $aName (keys %{$omap}) { - delete $defs{$name}{READINGS}{$aName}; + # SYSMON_Log($hash, 5, ">>>>>>>>>>>>>>>>>>>> ".$aName."->".Dumper($defs{$name}{READINGS}{$aName})); + delete $defs{$name}{READINGS}{$aName}; } readingsEndUpdate($hash,defined($hash->{LOCAL}) ? 0 : 1); @@ -910,7 +972,7 @@ sub SYSMON_obtainParameters($$) { my $openedTelnet = 0; my $telnet = $hash->{".telnet"}; #$telnet = undef; - my $mode = $hash->{MODE};#AttrVal( $name, 'mode', 'local'); + my $mode = $hash->{MODE}; # Wenn remote: open connection if ($mode eq 'telnet') { unless (defined $telnet) { @@ -1091,7 +1153,7 @@ SYSMON_obtainParameters_intern($$) $map = SYSMON_getFBDECTTemp($hash, $map); #DSL-Downstream und DSL-Upstream abfragen - $map = SYSMON_getFBStreemRate($hash, $map); + $map = SYSMON_getFBStreamRate($hash, $map); #Sync-Zeit mit Vermittlungsstelle abfragen $map = SYSMON_getFBSyncTime($hash, $map); #Uebertragungsfehler abfragen (nicht behebbar und behebbar) @@ -1153,6 +1215,56 @@ SYSMON_obtainParameters_intern($$) } } + #Log 3, "SYSMON >>> USER_DEFINED FUNCTIONS >>>>>>>>>>>>>>> START"; + my $userfn = AttrVal($name, "user-fn", undef); + if(defined $userfn) { + my @userfn_list = split(/,\s*/, trim($userfn)); + foreach my $ud (@userfn_list) { + # :::... + my($fnName, $uInterval, @readings) = split(/:/, $ud); + SYSMON_Log($hash, 5, "User-Defined Fn: [$fnName][$uInterval]"); + if(defined $uInterval) { + my $iInt = int($uInterval); + if($iInt>0) { + my $update_ud = ($refresh_all || ($ref % $iInt) eq 0); + if($update_ud) { + $map = SYSMON_getUserDefinedFn($hash, $map, $fnName, @readings); + } else { + SYSMON_Log($hash, 5, "User-Defined Fn: [$fnName][$uInterval] out of refresh interval"); + } + } + } + } + } + + # User Functions2 + my $uMap; + $userfn = AttrVal($name, "user-fn2", undef); + #TEST$userfn=undef; + if(defined $userfn) { + my @userfn_list = split(/,\s*/, trim($userfn)); + foreach (@userfn_list) { + my $ufn = $_; + SYSMON_Log($hash, 5, "User-Function Reading: [$ufn]"); + if(defined $ufn) { + no strict "refs"; + $uMap = &{$ufn}($hash, $uMap); + use strict "refs"; + } + } + } + # Werte umverpacken, KeyNamen sichern + my $uNames=''; + if(defined($uMap)) { + foreach my $uName (keys %{$uMap}) { + $uNames.=','.$uName; + $map->{$uName}=$uMap->{$uName}; + } + # Erste Komma entfernen + $uNames=substr($uNames,1); + $map->{"xuser_fnr"}=$uNames; + } + #TEST #my $rt = "#"; #$rt=~s/#/[]/g; @@ -1168,6 +1280,16 @@ SYSMON_obtainParameters_intern($$) return $map; } +# For test purpose only +sub SYSMON_TestUserFn($$) { + my ($hash, $map) = @_; + + $map->{"my_test_reading"}="my test"; + #$map->{"my"}="my"; + + return $map; +} + #------------------------------------------------------------------------------ # Liefert gesammelte Werte ( = Readings) # Parameter: array der gewuenschten keys (Readings names) @@ -1221,6 +1343,44 @@ SYSMON_getUserDefined($$$$) return $map; } +sub SYSMON_getUserDefinedFn($$$@) { + my($hash, $map, $fnName, @readings) = @_; + + SYSMON_Log($hash, 5, "call User-Function: [$fnName]"); + if(defined $fnName) { + no strict "refs"; + my @rarr; + if($fnName=~/^{/) { + my $HASH = $hash; + my $NAME = $hash->{NAME}; + @rarr = eval($fnName); + } else { + @rarr = &{$fnName}($hash); + } + use strict "refs"; + SYSMON_Log($hash, 5, "result User-Function [$fnName]: ".Dumper(@rarr)); + + my $cnt1 = scalar(@readings); + my $cnt2 = scalar(@rarr); + my $cnt = min($cnt1,$cnt2); + if($cnt1!=$cnt2) { # zu wenig readings geliefert ($cnt1>$cnt2) oder zu viel + SYSMON_Log($hash, 3, "User-Function [$fnName]: expected readings: [$cnt1], provided [$cnt2]"); + } + #SYSMON_Log($hash, 5, ">>>> User-Function [$fnName]: $cnt1 / $cnt2: $rarr[0]"); + for (my $i=0;$i<$cnt;$i++) { + if(defined($rarr[$i])) { + my $val = trim($rarr[$i]); + #SYSMON_Log($hash, 5, ">>>> User-Function [$fnName]: put: '".$readings[$i]."' => '".$val."'"); + $map->{$readings[$i]} = $val; + #$map->{$readings[$i]}="Dead OWTHERM devices: none"; + #SYSMON_Log($hash, 5, ">>>> User-Function [$fnName]: ok"); + } + } + } + + return $map; +} + #my $sys_cpu_core_num = undef; sub SYSMON_getCPUCoreNum($) @@ -1286,6 +1446,8 @@ SYSMON_getUptime2($$) #TODO my $uptime = SYSMON_execute($hash,"uptime"); + + #SYSMON_Log($hash, 5, ">>>>>>>>>>>>>>>>>>>>>>".$uptime."<"); #$uptime = $1 if( $uptime && $uptime =~ m/[[:alpha:]]{2}\s+(((\d+)\D+,?\s+)?(\d+):(\d+))/ ); $uptime = $1 if( $uptime && $uptime =~ m/[[:alpha:]]{2}\s+(((\d+)\D+,?\s+)?(\d+):(\d+)).*load.*: (.*)/ ); @@ -1452,12 +1614,17 @@ SYSMON_getCPUBogoMIPS($$) my $old_val = ReadingsVal($hash->{NAME},CPU_BOGOMIPS,undef); # nur einmalig ermitteln (wird sich ja nicht aendern if(!defined $old_val) { - my $val = SYSMON_execute($hash, "cat /proc/cpuinfo | grep -m 1 'BogoMIPS'"); - #Log 3,"SYSMON -----------> DEBUG: read BogoMIPS = $val"; - my ($dummy, $val_txt) = split(/:\s+/, $val); - if($val_txt) { - $val_txt = trim($val_txt); - $map->{+CPU_BOGOMIPS}="$val_txt"; + my @aval = SYSMON_execute($hash, "cat /proc/cpuinfo | grep 'BogoMIPS'"); + #SYSMON_Log($hash, 5, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ".Dumper(@aval)); # TODO: Delete + my $val=@aval[0]; + #SYSMON_Log($hash, 5, "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ".$val); # TODO: Delete + if(defined($val)){ + #Log 3,"SYSMON -----------> DEBUG: read BogoMIPS = $val"; + my ($dummy, $val_txt) = split(/:\s+/, $val); + if($val_txt) { + $val_txt = trim($val_txt); + $map->{+CPU_BOGOMIPS}="$val_txt"; + } } } else { $map->{+CPU_BOGOMIPS}=$old_val; @@ -2124,7 +2291,7 @@ sub SYSMON_getNetworkInfo ($$$) #my @dataThroughput = qx($cmd); my @dataThroughput = SYSMON_execute($hash, $cmd); - #Log 3, "SYSMON>>>>>>>>>>>>>>>>> ".$dataThroughput[0]; + SYSMON_Log ($hash, 5, "SYSMON_getNetworkInfo>>>>>>>>>>>>>>>>".Dumper(@dataThroughput)); #--- DEBUG --- if($device eq "_test1") { @@ -2367,6 +2534,79 @@ sub SYSMON_getFBDECTTemp($$) return $map; } +#------------------------------------------------------------------------------ +# Liefert Liste an der FritzBox bekannter Devices. +# Parameter: HASH +# Return Hash mit Devices +#------------------------------------------------------------------------------ +sub SYSMON_getFBLanDeviceList($) +{ + my ($hash) = @_; + + if(!SYSMON_isFB($hash)) { + return undef; + } + + my $map; + + my $name = $hash->{NAME}; + # --- + #TODO: SSH + my $msg = undef; + my $openedTelnet = 0; + my $telnet = $hash->{".telnet"}; + #$telnet = undef; + my $mode = $hash->{MODE}; + # Wenn remote: open connection + if ($mode eq 'telnet') { + unless (defined $telnet) { + SYSMON_Log($hash, 5, "$name: Open single telnet connection"); + $msg = SYSMON_Open_Connection($hash); + $hash->{helper}{error_msg}=$msg; + if (!$msg) { + $openedTelnet = 1; + $hash->{helper}{error_msg}=undef; + } + } + } + # --- + + my $count = SYSMON_execute($hash, "ctlmgr_ctl r landevice settings/landevice/count"); + if(defined($count)) { + for (my $i=0;$i<$count;$i++) { + #landevice0/... + # ip=192.168.178.12, mac=00:1F:3F:MM:AA:CC, name=PC-192-168-178-12, manu_name=0, + # dhcp=0, static_dhcp=0, wlan=0, ethernet=1, active=1, online=0, speed=100, + # deleteable=2, wakeup=0, source=4096, neighbour_name=, is_double_neighbour_name=0 + # ipv6addrs=, ipv6_ifid= + + my $dev_name = SYSMON_execute($hash, "ctlmgr_ctl r landevice settings/landevice".$i."/name"); + my $dev_ip = SYSMON_execute($hash, "ctlmgr_ctl r landevice settings/landevice".$i."/ip"); + my $dev_mac = SYSMON_execute($hash, "ctlmgr_ctl r landevice settings/landevice".$i."/mac"); + my $dev_active = SYSMON_execute($hash, "ctlmgr_ctl r landevice settings/landevice".$i."/active"); + + $map->{$dev_name}{id} = $i; + $map->{$dev_name}{name} = $dev_name; + $map->{$dev_name}{ip} = $dev_ip; + $map->{$dev_name}{mac} = $dev_mac; + $map->{$dev_name}{active} = $dev_active; + } + } + + # --- + # Wenn remote: close connection + if ($mode eq 'telnet') { + if($openedTelnet) { + SYSMON_Log($hash, 5, "$name: Close shared telnet connection"); + SYSMON_Close_Connection( $hash ); + } + } + # --- + + return $map; +} + + # TODO: FritzBox-Infos: Dateien /var/env oder /proc/sys/urlader/environment. #------------------------------------------------------------------------------ @@ -2379,7 +2619,10 @@ sub SYSMON_acquireInfo_intern($$;$) SYSMON_Log($hash, 5, "cmd: ".$cmd); - my $str = trim(SYSMON_execute($hash, $cmd)); + my $str = SYSMON_execute($hash, $cmd); + if(defined($str)) { + $str = trim($str); + } my $ret; if(!defined($art)) { $art= 0; } @@ -2432,10 +2675,13 @@ sub SYSMON_FBVersionInfo($$) #DSL-Downstream und DSL-Upstream abfragen -sub SYSMON_getFBStreemRate($$) { +sub SYSMON_getFBStreamRate($$) { my ($hash, $map) = @_; my $ds_rate = SYSMON_execute($hash, "ctlmgr_ctl r sar status/dsl_ds_rate"); + unless($ds_rate) { + return SYSMON_getFBStreamRate2($hash, $map); + } my $us_rate = SYSMON_execute($hash, "ctlmgr_ctl r sar status/dsl_us_rate"); if($ds_rate ne "" && $us_rate ne "") { @@ -2445,6 +2691,20 @@ sub SYSMON_getFBStreemRate($$) { return $map; } +# DSL-Geschwindigkeit mit neuer FritzOS (6.23) +sub SYSMON_getFBStreamRate2($$) { + my ($hash, $map) = @_; + + my $ds_rate = SYSMON_execute($hash, "ctlmgr_ctl r dslstatglobal status/in")/1000; + my $us_rate = SYSMON_execute($hash, "ctlmgr_ctl r dslstatglobal status/out")/1000; + + if($ds_rate ne "" && $us_rate ne "") { + $map->{+FB_DSL_RATE}="down: ".int($ds_rate)." KBit/s, up: ".int($us_rate)." KBit/s"; + } + + return $map; +} + # Ausrechnet aus der Zahl der Sekunden Anzeige in Tagen:Stunden:Minuten:Sekunden. sub SYSMON_sec2Dauer($){ my ($t) = @_; @@ -2462,6 +2722,9 @@ sub SYSMON_getFBSyncTime($$) { my ($hash, $map) = @_; my $data = SYSMON_execute($hash, "ctlmgr_ctl r sar status/modem_ShowtimeSecs"); + unless($data) { + return SYSMON_getFBSyncTime2($hash, $map); + } if($data ne "") { my $idata = int($data); @@ -2471,6 +2734,19 @@ sub SYSMON_getFBSyncTime($$) { return $map; } +#Sync-Zeit mit Vermittlungsstelle abfragen mit neuer FritzOS (6.23) +sub SYSMON_getFBSyncTime2($$) { + my ($hash, $map) = @_; + + my $data = SYSMON_execute($hash, "ctlmgr_ctl r dslstatistic status/ifacestat0/connect_time"); + + if($data ne "") { + $map->{+FB_DSL_SYNCTIME}=$data; + } + + return $map; +} + #Uebertragungsfehler abfragen (nicht behebbar und behebbar) sub SYSMON_getFBCRCFEC($$) { my ($hash, $map) = @_; @@ -2481,11 +2757,11 @@ sub SYSMON_getFBCRCFEC($$) { my $ds_fec = SYSMON_execute($hash, "ctlmgr_ctl r sar status/ds_fec_per15min"); my $us_fec = SYSMON_execute($hash, "ctlmgr_ctl r sar status/us_fec_per15min"); - if($ds_crc ne "") { + if(defined($ds_crc) && $ds_crc ne "") { # FB_DSL_CRC_15 $map->{+FB_DSL_CRC_15}="down: ".int($ds_crc)." up: ".int($us_crc); } - if($ds_fec ne "") { + if(defined($ds_fec) && $ds_fec ne "") { # FB_DSL_FEC_15 $map->{+FB_DSL_FEC_15}="down: ".int($ds_fec)." up: ".int($us_fec); } @@ -2619,6 +2895,8 @@ sub SYSMON_ShowValuesFmt ($$$;@) } } + #TODO: UserDefinedFn? + my $map; if($hash->{TYPE} eq 'SYSMON') { $map = SYSMON_obtainParameters($hash, 1); @@ -2811,9 +3089,11 @@ SYSMON_isCPU1Freq($) { sub SYSMON_isFB($) { my ($hash) = @_; - if(!defined $hash->{helper}{sys_fb}) { + if(!defined ($hash->{helper}{sys_fb})) { + #SYSMON_Log($hash, 5, "TEST isFB >>> exe >>> "); # TODO: remove $hash->{helper}{sys_fb} = int(SYSMON_execute($hash, "[ -f /usr/bin/ctlmgr_ctl ] && echo 1 || echo 0")); } + #SYSMON_Log($hash, 5, "TEST isFB >>> ret >>> '".$hash->{helper}{sys_fb}."'"); # TODO: remove return $hash->{helper}{sys_fb}; } @@ -3098,8 +3378,10 @@ sub SYSMON_Open_Connection($) } SYSMON_Log($hash, 5, "Open Telnet connection to $host:$port"); - my $timeout = AttrVal( $name, "telnetTimeOut", "10"); - my $telnet = new Net::Telnet ( Host=>$host, Port => $port, Timeout=>$timeout, Errmode=>'return', Prompt=>'/# $/'); + my $timeout = AttrVal( $name, "telnet-time-out", "10"); + my $t_prompt=AttrVal($name,'telnet-prompt-regx','(#|\$)\s*$'); + #my $telnet = new Net::Telnet ( Host=>$host, Port => $port, Timeout=>$timeout, Errmode=>'return', Prompt=>'/(#|\$) $/'); + my $telnet = new Net::Telnet ( Host=>$host, Port => $port, Timeout=>$timeout, Errmode=>'return', Prompt=>'/'.$t_prompt.'/'); if (!$telnet) { $msg = "Could not open telnet connection to $host:$port"; SYSMON_Log($hash, 2, $msg); @@ -3150,7 +3432,9 @@ sub SYSMON_Open_Connection($) $telnet->print( $pwd ); SYSMON_Log($hash, 5, "Wait for command prompt"); - unless ( ($before,$match) = $telnet->waitfor( '/# $|Login failed./i' )) + my $tlogin_prompt=AttrVal($name,'telnet-login-prompt-regx','(#|\$)\s*$|Login failed.'); + #unless ( ($before,$match) = $telnet->waitfor( '/# $|Login failed./i' )) + unless ( ($before,$match) = $telnet->waitfor( '/'.$tlogin_prompt.'/i' )) { $msg = "Telnet error while waiting for command prompt: ".$telnet->errmsg; SYSMON_Log($hash, 2, $msg); @@ -3166,7 +3450,17 @@ sub SYSMON_Open_Connection($) $telnet = undef; return $msg; } - + #SYSMON_Log($hash, 2, "Prompt: ".Dumper($before)." > ".$match); + + # Promptzeile erkenen + if(!($hash->{helper}{recognized_prompt})) { + my @prompt = SYSMON_Exec_Remote($hash, ''); + if(scalar(@prompt) == 1) { + $hash->{helper}{recognized_prompt}=$prompt[0]; + } + } + #SYSMON_Log($hash, 2, "Prompt: '".Dumper(@retVal)."'"); + return undef; } # end SYSMON_Open_Connection @@ -3179,7 +3473,7 @@ sub SYSMON_Close_Connection($) my $name = $hash->{NAME}; my $mode = $hash->{MODE};#AttrVal( $name, 'mode', 'local'); - if ($mode eq 'local') { + if (!defined($mode) || $mode eq 'local') { return undef; } @@ -3199,9 +3493,9 @@ sub SYSMON_Close_Connection($) # Executed the command on the remote Shell ############################################ -sub SYSMON_Exec($$) +sub SYSMON_Exec($$;$) { - my ($hash, $cmd) = @_; + my ($hash, $cmd,$is_arr) = @_; my $openedTelnet = 0; my $telnet = $hash->{".telnet"}; @@ -3227,17 +3521,29 @@ sub SYSMON_Exec($$) SYSMON_Log($hash, 5, "$name: Close single telnet connection"); SYSMON_Close_Connection( $hash ); } + + #Prompt-Zeile entfernen, falls vorhanden + my $recognized_prompt = $hash->{helper}{recognized_prompt}; + if(defined($recognized_prompt)) { + if(scalar(@retVal)>=1) { + if($retVal[-1] eq $recognized_prompt) { + SYSMON_Log ($hash, 5, "remove prompt: ".$retVal[-1]."'"); + splice @retVal, -1, 1;# $retVal[-1]; + } + } + } # Arrays als solche zurueckgeben + #if($is_arr && scalar(@retVal)>1) { if(scalar(@retVal)>1) { - SYSMON_Log ($hash, 5, "Result '".Dumper(@retVal)."'"); + SYSMON_Log ($hash, 5, "Result A: '".Dumper(@retVal)."'"); return @retVal; } # Einzeiler als normale Scalars my $line = $retVal[0]; if(defined($line)) { chomp $line; - SYSMON_Log ($hash, 5, "Result '$line'"); + SYSMON_Log ($hash, 5, "Result L: '$line'"); } else { SYSMON_Log ($hash, 5, "Result undef"); } @@ -3249,6 +3555,39 @@ sub SYSMON_Exec($$) } +sub MYTEST() { + my @output=( + '', +'[~] ', +'', +'[~] # ', +'', +'', +'', +' Interrupt:16 Memory:c0100000-c0120000 ', +'', +' RX bytes:483322579219 (450.1 GiB) TX bytes:3757348645531 (3.4 TiB)', +'', +' collisions:0 txqueuelen:1000 ', +'', +' TX packets:3656315540 errors:0 dropped:0 overruns:0 carrier:0', +'', +' RX packets:2817622543 errors:8 dropped:265294 overruns:0 frame:8', +'', +' UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1', +'', +' inet addr:192.168.178.80 Bcast:192.168.178.255 Mask:255.255.255.0', +'', +'eth0 Link encap:Ethernet HWaddr 00:08:9B:D3:8D:9E' + ); + @output = reverse(@output); + for (my $i=0;$icmd($cmd); + #SYSMON_Log($hash, 5, "Result '".Dumper(@output)."'"); # TODO: remove + + # Sonderlocke fuer QNAP: letzten Zeilen mit "[~] " am Anfang entfernen + #while((scalar(@output)>0) && ($output[-1]=~ /^\[~\]/)) { + # SYSMON_Log ($hash, 5, "Remove line: '".$output[-1]."'"); + # splice @output, -1, 1; + #} + for (my $i=0;$i>> Line >>> '".$output[$i]."'"); # TODO: remove + if($output[$i]=~ /^\[~\]/) {undef ($output[$i]);} + } + #SYSMON_Log($hash, 5, "Result >>> vgrep >>>'".Dumper(@output)."'"); # TODO: remove + @output = grep{ defined($_) && trim($_) ne '' }@output; + #SYSMON_Log($hash, 5, "Result >>> ngrep >>>'".Dumper(@output)."'"); # TODO: remove + return @output; ## Arrays als solche zurueckgeben #if(scalar(@output)>1) { @@ -3495,7 +3849,7 @@ If one (or more) of the multiplier is set to zero, the corresponding readings is
  • user defined
    - These readings provide output of commands, which are passed to the operating system. + These readings provide output of commands, which are passed to the operating system or delivered by user defined functions.

  • FritzBox specific Readings @@ -3686,10 +4040,14 @@ If one (or more) of the multiplier is set to zero, the corresponding readings is Get:

      -
    • interval
      +
    • interval_base
      Lists the specified polling intervalls.

    • +
    • interval_multipliers
      + Displays update intervals. +
    • +
    • list
      Lists all readings.
    • @@ -3702,6 +4060,11 @@ If one (or more) of the multiplier is set to zero, the corresponding readings is Displays the version of SYSMON module.
      +
    • list_lan_devices
      + Displays known LAN Devices (FritzBox only). +
    • +
      +

    Set:

    @@ -3718,6 +4081,10 @@ If one (or more) of the multiplier is set to zero, the corresponding readings is Deletes the Reading entry with the given name. After an update this entry is possibly re-created (if defined). This mechanism allows the selective deleting unnecessary custom entries.

    +
  • password <Passwort>
    + Specify the password for remote access (usually only necessary once). +
  • +

    Attributes:

    @@ -3750,10 +4117,23 @@ If one (or more) of the multiplier is set to zero, the corresponding readings is the number of available updates is daily recorded as 'sys_updates'.
    +
  • user-fn <fn_name>:<interval_minutes>:<reading_name1>:<reading_name2>...[:<reading_nameX>],...
    + List of perl user subroutines.
    + As <fn_name> can be used either the name of a Perl subroutine or a Perl expression. + The perl function gets the device hash as parameter and must provide an array of values. + These values are taken according to the parameter <reading_nameX> in Readings.
    + A Perl expression must be enclosed in curly braces and can use the following parameters: $ HASH (device hash) and $ NAME (device name). + Return is expected analogous to a Perl subroutine. +
  • +
  • disable
    Possible values: 0 and 1. '1' means that the update is stopped.

  • +
  • telnet-prompt-regx, telnet-login-prompt-regx
    + RegExp to detect login and command line prompt. (Only for access via Telnet.) +
  • +

    Plots:

    @@ -4063,7 +4443,7 @@ If one (or more) of the multiplier is set to zero, the corresponding readings is
  • Benutzerdefinierte Einträge
    Diese Readings sind Ausgaben der Kommanden, die an das Betriebssystem übergeben werden. - Die entsprechende Angaben werden im Attribut user-defined vorgenommen. + Die entsprechende Angaben werden durch Attributen user-defined und user-fn definiert.

  • FritzBox-spezifische Readings @@ -4258,6 +4638,10 @@ If one (or more) of the multiplier is set to zero, the corresponding readings is Listet die bei der Definition angegebene Polling-Intervalle auf.
    +
  • interval_multipliers
    + Listet die definierten Multipliers. +
  • +
  • list
    Gibt alle Readings aus.
  • @@ -4270,6 +4654,10 @@ If one (or more) of the multiplier is set to zero, the corresponding readings is Zeigt die Version des SYSMON-Moduls.
    +
    +
  • list_lan_devices
    + Listet bekannte Geräte im LAN (nur FritzBox). +

  • Set:

    @@ -4288,6 +4676,10 @@ If one (or more) of the multiplier is set to zero, the corresponding readings is benutzerdefinierten Einträge.

    +
  • password <Passwort>
    + Definiert das Passwort für den Remote-Zugriff (i.d.R. nur einmalig notwendig). +
  • +

    Attributes:

    @@ -4327,10 +4719,23 @@ If one (or more) of the multiplier is set to zero, the corresponding readings is Danach wird die Anzahl der verfügbaren Aktualisierungen täglich als Reading 'sys_updates' protokolliert.
    +
  • user-fn <fn_name>:<Interval_Minutes>:<reading_name1>:<reading_name2>...[:<reading_nameX>],...
    + Liste der benutzerdefinierten Perlfunktionen.
    + Als <fn_name> können entweder Name einer Perlfunktion oder ein Perlausdruck verwendet werden. + Die Perlfunktion bekommt den Device-Hash als Übergabeparameter und muss ein Array mit Werte liefern. + Diese Werte werden entsprechend den Parameter <reading_nameX> in Readings übernommen.
    + Ein Perlausdruck muss in geschweifte Klammer eingeschlossen werden und kann folgende Paramter verwenden: $HASH (Device-Hash) und $NAME (Device-Name). + Rückgabe wird analog einer Perlfunktion erwartet. +
  • +
  • disable
    Mögliche Werte: 0,1. Bei 1 wird die Aktualisierung gestoppt.

  • +
  • telnet-prompt-regx, telnet-login-prompt-regx
    + RegExp zur Erkennung von Login- und Kommandozeile-Prompt. (Nur für Zugriffe über Telnet relevant.) +
  • +

    Plots: