diff --git a/fhem/FHEM/42_SYSMON.pm b/fhem/FHEM/42_SYSMON.pm index 3255fdfac..367ecebde 100644 --- a/fhem/FHEM/42_SYSMON.pm +++ b/fhem/FHEM/42_SYSMON.pm @@ -30,7 +30,11 @@ package main; use strict; use warnings; -my $VERSION = "1.9.4.7"; +use Blocking; + +use Data::Dumper; + +my $VERSION = "1.9.5.0"; use constant { PERL_VERSION => "perl_version", @@ -87,14 +91,14 @@ SYSMON_Initialize($) { my ($hash) = @_; - Log 5, "SYSMON Initialize"; + SYSMON_Log($hash, 5, ""); $hash->{DefFn} = "SYSMON_Define"; $hash->{UndefFn} = "SYSMON_Undefine"; $hash->{GetFn} = "SYSMON_Get"; $hash->{SetFn} = "SYSMON_Set"; $hash->{AttrFn} = "SYSMON_Attr"; - $hash->{AttrList} = "filesystems network-interfaces user-defined disable:0,1 ". + $hash->{AttrList} = "filesystems network-interfaces user-defined disable:0,1 nonblocking:0,1 ". $readingFnAttributes; } ### attr NAME user-defined osUpdates:1440:Aktualisierungen:cat ./updates.txt [,:::] @@ -104,7 +108,7 @@ SYSMON_Define($$) { my ($hash, $def) = @_; - logF($hash, "Define", "$def"); + SYSMON_Log($hash, 5, "$def"); my @a = split("[ \t][ \t]*", $def); @@ -156,7 +160,7 @@ SYSMON_setInterval($@) } -my $cur_readings_map; +#my $cur_readings_map; => $hash->{helper}{cur_readings_map} sub SYSMON_updateCurrentReadingsMap($) { my ($hash) = @_; @@ -452,7 +456,7 @@ $rMap->{"io_sda_raw"} = "TEST"; $rMap->{"io_sda_diff"} = "TEST"; $rMap->{"io_sda"} = "TEST"; - $cur_readings_map = $rMap; + $hash->{helper}{cur_readings_map} = $rMap; return $rMap; } @@ -465,7 +469,7 @@ SYSMON_getObsoleteReadingsMap($) { #return $rMap; # TODO TEST - if(!defined($cur_readings_map)) { + if(!defined($hash->{helper}{cur_readings_map})) { SYSMON_updateCurrentReadingsMap($hash); } @@ -474,7 +478,7 @@ SYSMON_getObsoleteReadingsMap($) { foreach my $aName (@cKeys) { if(defined ($aName)) { # alles hinzufuegen, was nicht in der Aktuellen Liste ist - if(!defined($cur_readings_map->{$aName})) { + if(!defined($hash->{helper}{cur_readings_map}->{$aName})) { #Log 3, "SYSMON>>>>>>>>>>>>>>>>> SYSMON_getObsoleteReadingsMap >>> $aName"; $rMap->{$aName} = 1; } @@ -489,9 +493,13 @@ SYSMON_Undefine($$) { my ($hash, $arg) = @_; - logF($hash, "Undefine", ""); + SYSMON_Log($hash, 5, "$arg"); RemoveInternalTimer($hash); + + BlockingKill( $hash->{helper}{READOUT_RUNNING_PID} ) + if exists $hash->{helper}{READOUT_RUNNING_PID}; + return undef; } @@ -504,13 +512,13 @@ SYSMON_Get($@) if(@a < 2) { - logF($hash, "Get", "@a: get needs at least one parameter"); + SYSMON_Log($hash, 3, "@a: get needs at least one parameter"); return "$name: get needs at least one parameter"; } my $cmd= $a[1]; - logF($hash, "Get", "@a"); + SYSMON_Log($hash, 5, "@a"); if($cmd eq "update") { @@ -557,18 +565,18 @@ SYSMON_Set($@) if(@a < 2) { - logF($hash, "Set", "@a: set needs at least one parameter"); + SYSMON_Log($hash, 3, "@a: set needs at least one parameter"); return "$name: set needs at least one parameter"; } my $cmd= $a[1]; - logF($hash, "Set", "@a"); + SYSMON_Log($hash, 5, "@a"); if($cmd eq "interval_multipliers") { if(@a < 3) { - logF($hash, "Set", "$name: not enought parameters"); + SYSMON_Log($hash, 3, "$name: not enought parameters"); return "$name: not enought parameters"; } @@ -605,7 +613,8 @@ SYSMON_Attr($$$) { my ($cmd, $name, $attrName, $attrVal) = @_; - Log 5, "SYSMON Attr: $cmd $name $attrName $attrVal"; + my $hash = $main::defs{$name}; + SYSMON_Log($hash, 5, "SYSMON Attr: $cmd $name ".$attrName?$attrName:''." $attrVal"); $attrVal= "" unless defined($attrVal); my $orig = AttrVal($name, $attrName, ""); @@ -613,7 +622,6 @@ SYSMON_Attr($$$) if( $cmd eq "set" ) {# set, del if( $orig ne $attrVal ) { - my $hash = $main::defs{$name}; if($attrName eq "disable") { RemoveInternalTimer($hash); @@ -637,14 +645,16 @@ SYSMON_Attr($$$) return; } -my $u_first_mark = undef; +#my $u_first_mark = undef; sub -SYSMON_Update($@) +SYSMON_Update($;$) { my ($hash, $refresh_all) = @_; + + $refresh_all="0" unless defined $refresh_all; - logF($hash, "Update", ""); + SYSMON_Log($hash, 5, "refresh_all: ".$refresh_all); my $name = $hash->{NAME}; @@ -653,52 +663,160 @@ SYSMON_Update($@) InternalTimer(gettimeofday()+$hash->{INTERVAL_BASE}, "SYSMON_Update", $hash, 1); } - readingsBeginUpdate($hash); - if( AttrVal($name, "disable", "") eq "1" ) { - logF($hash, "Update", "disabled"); + SYSMON_Log($hash, 5, "disabled"); $hash->{STATE} = "Inactive"; } else { - # Beim ersten mal alles aktualisieren! - if(!$u_first_mark) { + # Beim ersten mal alles aktualisieren! + if(!$hash->{helper}{u_first_mark}) { $refresh_all = 1; } - # Parameter holen - my $map = SYSMON_obtainParameters($hash, $refresh_all); + if(!AttrVal($name, "nonblocking", 1)) { + # direkt call + + # Parameter holen + my $map = SYSMON_obtainParameters($hash, $refresh_all); - # Mark setzen - if(!$u_first_mark) { - $u_first_mark = 1; - } + # Mark setzen + if(!$hash->{helper}{u_first_mark}) { + $hash->{helper}{u_first_mark} = 1; + } - $hash->{STATE} = "Active"; - #my $state = $map->{LOADAVG}; - #readingsBulkUpdate($hash,"state",$state); - - foreach my $aName (keys %{$map}) { - my $value = $map->{$aName}; - # Nur aktualisieren, wenn ein gueltiges Value vorliegt - if(defined $value) { - readingsBulkUpdate($hash,$aName,$value); - } - + SYSMON_updateReadings($hash,$map); + $hash->{STATE} = "Active"; + } else { + # blocking call + if ( exists( $hash->{helper}{READOUT_RUNNING_PID} ) ) { + SYSMON_Log($hash, 5, "blockingCall: Old readout process still running. Killing old process ".$hash->{helper}{READOUT_RUNNING_PID}); + BlockingKill( $hash->{helper}{READOUT_RUNNING_PID} ); + delete($hash->{helper}{READOUT_RUNNING_PID}); + } + + $hash->{helper}{READOUT_RUNNING_PID} = BlockingCall("SYSMON_blockingCall", $name."|".$refresh_all, "SYSMON_blockingFinish", 55, "SYSMON_blockingAbort", $hash); } - - # Nicht mehr benoetigte Readings loeschen - my $omap = SYSMON_getObsoleteReadingsMap($hash); - foreach my $aName (keys %{$omap}) { - delete $defs{$name}{READINGS}{$aName}; - } - + } - readingsEndUpdate($hash,defined($hash->{LOCAL}) ? 0 : 1); } +sub SYSMON_blockingCall($) { + my ($tparam) = @_; + my ($name, $refresh_all) = split(/\|/,$tparam); + my $hash = $main::defs{$name}; + SYSMON_Log($hash, 5, "$name, ".($refresh_all?$refresh_all:'')); + + my $map = SYSMON_obtainParameters($hash, $refresh_all); + + # Device-Name mitnehmen + my $ret = "name|".$name; + # to String + foreach my $aName (keys %{$map}) { + my $value = $map->{$aName}; + # Nur wenn ein gueltiges Value vorliegt + if(defined $value) { + $ret.="|".$aName."|".$value; + } + } + + return $ret; +} + +sub SYSMON_test() { + + #foreach my $d (sort keys %defs) { + # my $h = $defs{$d}; + # if(defined ($h->{TYPE})) {} else {return $d."-".Dumper($h);} + #} + + my $map; + + my $name="TESTNAME"; + + $map->{test1}="val1"; + $map->{test2}="val2"; + $map->{test3}="val3"; + + #return Dumper($map); + + my $ret = "name|".$name; + # to ret String + foreach my $aName (keys %{$map}) { + my $value = $map->{$aName}; + # Nur wenn ein gueltiges Value vorliegt + if(defined $value) { + $ret.="|".$aName."|".$value; + } + } + + my @ta = split(/\|/,$ret); + #return Dumper(@ta); + my %map2 = @ta; + + return Dumper(\%map2); + + return $ret; +} + +sub SYSMON_blockingAbort($) { + my ($hash) = @_; + SYSMON_Log($hash, 5, ""); + $hash->{STATE} = "Error"; + delete($hash->{helper}{READOUT_RUNNING_PID}); +} + +sub SYSMON_blockingFinish($) { + my ($map_str) = @_; + + my $map; + # to map + my @ta = split(/\|/,$map_str); + my %tm = @ta; + $map = \%tm; + + my $name=$map->{name}; + delete $map->{name}; + + my $hash = $main::defs{$name}; + SYSMON_Log($hash, 5, $map_str); + # Mark setzen + if(!$hash->{helper}{u_first_mark}) { + $hash->{helper}{u_first_mark} = 1; + } + delete($hash->{helper}{READOUT_RUNNING_PID}); + + SYSMON_updateReadings($hash,$map); + $hash->{STATE} = "Active"; +} + +sub SYSMON_updateReadings($$) { + my ($hash,$map) = @_; + SYSMON_Log($hash, 5, ""); + my $name = $hash->{NAME}; + + readingsBeginUpdate($hash); + + foreach my $aName (keys %{$map}) { + my $value = $map->{$aName}; + # Nur aktualisieren, wenn ein gueltiges Value vorliegt + if(defined $value) { + readingsBulkUpdate($hash,$aName,$value); + } + } + + # Nicht mehr benoetigte Readings loeschen + my $omap = SYSMON_getObsoleteReadingsMap($hash); + foreach my $aName (keys %{$omap}) { + delete $defs{$name}{READINGS}{$aName}; + } + + readingsEndUpdate($hash,defined($hash->{LOCAL}) ? 0 : 1); +} + + # Schattenmap mit den zuletzt gesammelten Werten (merged) -my %shadow_map; +#my %shadow_map; sub SYSMON_obtainParameters($$) { @@ -721,7 +839,8 @@ SYSMON_obtainParameters($$) my ($m1, $m2, $m3, $m4) = split(/\s+/, $im); # Einmaliges - if(!$u_first_mark) { + if(!$hash->{helper}{u_first_mark}) { + #TODO: nur local # Perl version $map->{+PERL_VERSION} = "$]"; @@ -740,6 +859,7 @@ SYSMON_obtainParameters($$) } else { $map = SYSMON_getUptime2($hash, $map); } + #TODO: nur local $map = SYSMON_getFHEMUptime($hash, $map); if($m1 gt 0) { # Nur wenn > 0 @@ -883,7 +1003,7 @@ SYSMON_obtainParameters($$) # ::: my $ud = $_; my($uName, $uInterval, $uComment, $uCmd) = split(/:/, $ud); - logF($hash, "User-Defined Reading", "[$uName][$uInterval][$uComment][$uCmd]"); + SYSMON_Log($hash, 5, "User-Defined Reading: [$uName][$uInterval][$uComment][$uCmd]"); if(defined $uCmd) { # Also, wenn alle Parameter vorhanden my $iInt = int($uInterval); if($iInt>0) { @@ -898,7 +1018,10 @@ SYSMON_obtainParameters($$) # Aktuelle Werte in ShattenHash mergen my %hashT = %{$map}; + #@shadow_map{ keys %hashT } = values %hashT; + my %shadow_map; @shadow_map{ keys %hashT } = values %hashT; + $hash->{helper}{shadow_map} = \%shadow_map; return $map; } @@ -907,18 +1030,22 @@ SYSMON_obtainParameters($$) # Liefert gesammelte Werte ( = Readings) # Parameter: array der gewuenschten keys (Readings names) # Beispiele: -# {(SYSMON_getValues())->{'fs_root'}} -# {(SYSMON_getValues(("cpu_freq","cpu_temp")))->{"cpu_temp"}} -# {join(" ", keys (SYSMON_getValues()))} -# {join(" ", keys (SYSMON_getValues(("cpu_freq","cpu_temp"))))} +# {(SYSMON_getValues("sysmon"))->{'cpu_temp'}} +# {(SYSMON_getValues("sysmon",("cpu_freq","cpu_temp")))->{"cpu_temp"}} +# {join(" ", values (SYSMON_getValues("sysmon")))} +# {join(" ", values (SYSMON_getValues("sysmon",("cpu_freq","cpu_temp"))))} #------------------------------------------------------------------------------ sub -SYSMON_getValues(;@) +SYSMON_getValues($;@) { - my @filter_keys = @_; + my ($name,@filter_keys) = @_; + + my $hash = $main::defs{$name}; + my %shadow_map = %{$hash->{helper}{shadow_map}}; if(scalar(@filter_keys)>0) { my %clean_hash; - @clean_hash{ @filter_keys } = @shadow_map{ @filter_keys }; + #@clean_hash{ @filter_keys } = @shadow_map{ @filter_keys }; + @clean_hash{ @filter_keys } = @shadow_map{ @filter_keys }; return \%clean_hash; } # alles liefern @@ -932,7 +1059,7 @@ sub SYSMON_getUserDefined($$$$) { my ($hash, $map, $uName, $uCmd) = @_; - logF($hash, "SYSMON_getUserDefined", "Name=[$uName] Cmd=[$uCmd]"); + SYSMON_Log($hash, 5, "Name=[$uName] Cmd=[$uCmd]"); my $out_str = SYSMON_execute($hash, $uCmd); chomp $out_str; @@ -941,13 +1068,13 @@ SYSMON_getUserDefined($$$$) return $map; } -my $sys_cpu_core_num = undef; +#my $sys_cpu_core_num = undef; sub SYSMON_getCPUCoreNum($) { my ($hash) = @_; - return $sys_cpu_core_num if $sys_cpu_core_num; + return $hash->{helper}{sys_cpu_core_num} if $hash->{helper}{sys_cpu_core_num}; # nur wenn verfuegbar if(SYSMON_isSysCpuNum($hash)) { @@ -955,16 +1082,16 @@ SYSMON_getCPUCoreNum($) if(defined($str)) { if($str ne "") { if(int($str)!=0) { - $sys_cpu_core_num = int($str)+1; - return $sys_cpu_core_num; + $hash->{helper}{sys_cpu_core_num} = int($str)+1; + return $hash->{helper}{sys_cpu_core_num}; } } } } # Default / unbekannt - $sys_cpu_core_num = 1; - return $sys_cpu_core_num; + $hash->{helper}{sys_cpu_core_num} = 1; + return $hash->{helper}{sys_cpu_core_num}; } #------------------------------------------------------------------------------ @@ -1294,7 +1421,7 @@ SYSMON_getDiskStat_intern($$$) my ($d1, $d2, $pName, $nf1, $nf2, $nf3, $nf4, $nf5, $nf6, $nf7, $nf8, $nf9, $nf10, $nf11) = split(/\s+/, trim($entry)); - Log 3, "SYSMON-DEBUG-IOSTAT: ".$pName." = ".$nf1." ".$nf2." ".$nf3." ".$nf4." ".$nf5." ".$nf6." ".$nf7." ".$nf8." ".$nf9." ".$nf10." ".$nf11; + SYSMON_Log($hash, 5, "SYSMON-DEBUG-IOSTAT: ".$pName." = ".$nf1." ".$nf2." ".$nf3." ".$nf4." ".$nf5." ".$nf6." ".$nf7." ".$nf8." ".$nf9." ".$nf10." ".$nf11); # Nur nicht-null-Werte if($nf1 eq "0") { @@ -1314,13 +1441,13 @@ SYSMON_getDiskStat_intern($$$) #$map->{"iostat_test"}="TEST"; my $lastVal = ReadingsVal($hash->{NAME},$pName."_raw",undef); if(defined($lastVal)) { - Log 3, "SYSMON-DEBUG-IOSTAT: lastVal: $pName=".$lastVal; + SYSMON_Log($hash,5, "SYSMON-DEBUG-IOSTAT: lastVal: $pName=".$lastVal); } if(defined $lastVal) { # Diff. ausrechnen, falls vorherigen Werte vorhanden sind. my($af1, $af2, $af3, $af4, $af5, $af6, $af7, $af8, $af9, $af10, $af11) = split(/\s+/, $lastVal); - Log 3, "SYSMON-DEBUG-IOSTAT: X: ".$pName." = ".$af1." ".$af2." ".$af3." ".$af4." ".$af5." ".$af6." ".$af7." ".$af8." ".$af9." ".$af10." ".$af11; + SYSMON_Log($hash,5, "SYSMON-DEBUG-IOSTAT: X: ".$pName." = ".$af1." ".$af2." ".$af3." ".$af4." ".$af5." ".$af6." ".$af7." ".$af8." ".$af9." ".$af10." ".$af11); my $sectorsRead; my $sectorsWritten; @@ -1734,7 +1861,7 @@ sub SYSMON_getFileSystemInfo ($$$) { my ($hash, $map, $fs) = @_; - logF($hash, "SYSMON_getFileSystemInfo", "get $fs"); + SYSMON_Log($hash, 5, "get $fs"); # Neue Syntax: benannte Filesystems: : my($fName, $fDef, $fComment) = split(/:/, $fs); @@ -1745,12 +1872,12 @@ sub SYSMON_getFileSystemInfo ($$$) #my $disk = "df ".$fs." -m 2>&1"; # in case of failure get string from stderr my $disk = "df ".$fs." -m 2>/dev/null"; - logF($hash, "SYSMON_getFileSystemInfo", "exec $disk"); + SYSMON_Log($hash, 5, "exec $disk"); #my @filesystems = qx($disk); my @filesystems = SYSMON_execute($hash, $disk); - logF($hash, "SYSMON_getFileSystemInfo", "recieved ".scalar(scalar(@filesystems))." lines"); + SYSMON_Log($hash, 5, "recieved ".scalar(scalar(@filesystems))." lines"); # - DEBUG - #if($fs eq "/test") { @@ -1768,9 +1895,9 @@ sub SYSMON_getFileSystemInfo ($$$) #if(scalar(@filesystems) == 0) { return $map; } # Array leer if(defined($filesystems[0])) { - logF($hash, "SYSMON_getFileSystemInfo", "recieved line0 $filesystems[0]"); + SYSMON_Log($hash, 5, "recieved line0 $filesystems[0]"); } else { - logF($hash, "SYSMON_getFileSystemInfo", "recieved empty line"); + SYSMON_Log($hash, 5, "recieved empty line"); } shift @filesystems; @@ -1786,22 +1913,22 @@ sub SYSMON_getFileSystemInfo ($$$) return $map unless int(@filesystems)>0; #if(!defined $filesystems[0]) { return $map; } # Ausgabe leer - logF($hash, "SYSMON_getFileSystemInfo", "analyse line $filesystems[0] for $fs"); + SYSMON_Log($hash, 5, "analyse line $filesystems[0] for $fs"); #if (!($filesystems[0]=~ /$fs\s*$/)){ shift @filesystems; } if (!($filesystems[0]=~ /$fs$/)){ shift @filesystems; if(int(@filesystems)>0) { - logF($hash, "SYSMON_getFileSystemInfo", "analyse line $filesystems[0] for $fs"); + SYSMON_Log($hash, 5, "analyse line $filesystems[0] for $fs"); } } else { - logF($hash, "SYSMON_getFileSystemInfo", "pattern ($fs) found"); + SYSMON_Log($hash, 5, "pattern ($fs) found"); } #if (index($filesystems[0], $fs) < 0) { shift @filesystems; } # Wenn die Bezeichnung so lang ist, dass die Zeile umgebrochen wird... #if (index($filesystems[0], $fs) >= 0) # check if filesystem available -> gives failure on console if (int(@filesystems)>0 && $filesystems[0]=~ /$fs$/) { - logF($hash, "SYSMON_getFileSystemInfo", "use line $filesystems[0]"); + SYSMON_Log($hash, 5, "use line $filesystems[0]"); my ($fs_desc, $total, $used, $available, $percentage_used, $mnt_point) = split(/\s+/, $filesystems[0]); $percentage_used =~ /^(.+)%$/; @@ -1832,7 +1959,7 @@ sub SYSMON_getFileSystemInfo ($$$) sub SYSMON_getNetworkInfo ($$$) { my ($hash, $map, $device) = @_; - logF($hash, "SYSMON_getNetworkInfo", "get $device"); + SYSMON_Log($hash, 5, "get $device"); my($nName, $nDef) = split(/:/, $device); if(!defined $nDef) { $nDef = $nName; @@ -2000,7 +2127,7 @@ sub SYSMON_getFBWLANState($$) { my ($hash, $map) = @_; - #logF($hash, "SYSMON_getFBWLANState", ""); + #SYSMON_Log($hash, 5, ""); $map->{+FB_WLAN_STATE}=SYSMON_acquireInfo_intern($hash, "ctlmgr_ctl r wlan settings/ap_enabled",1); @@ -2015,7 +2142,7 @@ sub SYSMON_getFBWLANGuestState($$) { my ($hash, $map) = @_; - #logF($hash, "SYSMON_getFBWLANGuestState", ""); + #SYSMON_Log($hash, 5, ""); $map->{+FB_WLAN_GUEST_STATE}=SYSMON_acquireInfo_intern($hash, "ctlmgr_ctl r wlan settings/guest_ap_enabled",1); @@ -2097,7 +2224,7 @@ sub SYSMON_acquireInfo_intern($$;$) { my ($hash, $cmd, $art) = @_; - logF($hash, "SYSMON_acquireInfo_intern", "cmd: ".$cmd); + SYSMON_Log($hash, 5, "cmd: ".$cmd); my $str = trim(SYSMON_execute($hash, $cmd)); my $ret; @@ -2299,9 +2426,9 @@ sub SYSMON_ShowValuesFmt ($$$;@) } # bei der Benutzung mit CloneDummies ist $cur_readings_map nicht unbedingt definiert @dataDescription = (DATE, - #CPU_TEMP.":".$cur_readings_map->{+CPU_TEMP}.": ".$deg."C", + #CPU_TEMP.":".$hash->{helper}{cur_readings_map}->{+CPU_TEMP}.": ".$deg."C", CPU_TEMP.":"."CPU temperature".": ".$deg."C", - #CPU_FREQ.":".$cur_readings_map->{+CPU_FREQ}.": "."MHz", + #CPU_FREQ.":".$hash->{helper}{cur_readings_map}->{+CPU_FREQ}.": "."MHz", CPU_FREQ.":"."CPU frequency".": "."MHz", CPU_BOGOMIPS, UPTIME_TEXT, FHEMUPTIME_TEXT, LOADAVG, RAM, SWAP, @@ -2377,7 +2504,7 @@ sub SYSMON_ShowValuesFmt ($$$;@) my($rName, $rComment, $rPostfix) = split(/:/, $_); if(defined $rName) { if(!defined $rComment) { - $rComment = $cur_readings_map->{$rName}; + $rComment = $hash->{helper}{cur_readings_map}->{$rName}; } my $rVal = $map->{$rName}; if(!defined $rVal) { @@ -2429,48 +2556,48 @@ sub SYSMON_ShowValuesFmt ($$$;@) return $htmlcode; } -my $proc_fs = undef; +#my $proc_fs = undef; sub SYSMON_isProcFS($) { my ($hash) = @_; - if(!defined $proc_fs) { - $proc_fs = int(SYSMON_execute($hash, "[ -d /proc/ ] && echo 1 || echo 0")); + if(!defined $hash->{helper}{proc_fs}) { + $hash->{helper}{proc_fs} = int(SYSMON_execute($hash, "[ -d /proc/ ] && echo 1 || echo 0")); } - return $proc_fs; + return $hash->{helper}{proc_fs}; } -my $sys_cpu_temp_rpi = undef; +#my $sys_cpu_temp_rpi = undef; sub SYSMON_isCPUTempRPi($) { my ($hash) = @_; - if(!defined $sys_cpu_temp_rpi) { - $sys_cpu_temp_rpi = int(SYSMON_execute($hash, "[ -f /sys/class/thermal/thermal_zone0/temp ] && echo 1 || echo 0")); + if(!defined $hash->{helper}{sys_cpu_temp_rpi}) { + $hash->{helper}{sys_cpu_temp_rpi} = int(SYSMON_execute($hash, "[ -f /sys/class/thermal/thermal_zone0/temp ] && echo 1 || echo 0")); } - return $sys_cpu_temp_rpi; + return $hash->{helper}{sys_cpu_temp_rpi}; } -my $sys_cpu_temp_bbb = undef; +#my $sys_cpu_temp_bbb = undef; sub SYSMON_isCPUTempBBB($) { my ($hash) = @_; - if(!defined $sys_cpu_temp_bbb) { - $sys_cpu_temp_bbb = int(SYSMON_execute($hash, "[ -f /sys/class/hwmon/hwmon0/device/temp1_input ] && echo 1 || echo 0")); + if(!defined $hash->{helper}{sys_cpu_temp_bbb}) { + $hash->{helper}{sys_cpu_temp_bbb} = int(SYSMON_execute($hash, "[ -f /sys/class/hwmon/hwmon0/device/temp1_input ] && echo 1 || echo 0")); } - return $sys_cpu_temp_bbb; + return $hash->{helper}{sys_cpu_temp_bbb}; } -my $sys_cpu_freq_rpi_bbb = undef; +#my $sys_cpu_freq_rpi_bbb = undef; sub SYSMON_isCPUFreqRPiBBB($) { my ($hash) = @_; - if(!defined $sys_cpu_freq_rpi_bbb) { - $sys_cpu_freq_rpi_bbb = int(SYSMON_execute($hash, "[ -f /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq ] && echo 1 || echo 0")); + if(!defined $hash->{helper}{sys_cpu_freq_rpi_bbb}) { + $hash->{helper}{sys_cpu_freq_rpi_bbb} = int(SYSMON_execute($hash, "[ -f /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq ] && echo 1 || echo 0")); } - return $sys_cpu_freq_rpi_bbb; + return $hash->{helper}{sys_cpu_freq_rpi_bbb}; } # DUMMY @@ -2479,70 +2606,70 @@ sub SYSMON_isCPUTempFB($) { return SYSMON_isFB($hash); } -my $sys_cpu1_freq = undef; +#my $sys_cpu1_freq = undef; sub SYSMON_isCPU1Freq($) { my ($hash) = @_; - if(!defined $sys_cpu1_freq) { - $sys_cpu1_freq = int(SYSMON_execute($hash, "[ -f /sys/devices/system/cpu/cpu1/cpufreq/scaling_cur_freq ] && echo 1 || echo 0")); + if(!defined $hash->{helper}{sys_cpu1_freq}) { + $hash->{helper}{sys_cpu1_freq} = int(SYSMON_execute($hash, "[ -f /sys/devices/system/cpu/cpu1/cpufreq/scaling_cur_freq ] && echo 1 || echo 0")); } - return $sys_cpu1_freq; + return $hash->{helper}{sys_cpu1_freq}; } -my $sys_fb = undef; +#my $sys_fb = undef; sub SYSMON_isFB($) { my ($hash) = @_; - if(!defined $sys_fb) { - $sys_fb = int(SYSMON_execute($hash, "[ -f /usr/bin/ctlmgr_ctl ] && echo 1 || echo 0")); + if(!defined $hash->{helper}{sys_fb}) { + $hash->{helper}{sys_fb} = int(SYSMON_execute($hash, "[ -f /usr/bin/ctlmgr_ctl ] && echo 1 || echo 0")); } - return $sys_fb; + return $hash->{helper}{sys_fb}; } #-Power------- -my $sys_power_ac = undef; +#my $sys_power_ac = undef; sub SYSMON_isSysPowerAc($) { my ($hash) = @_; - if(!defined $sys_power_ac) { - $sys_power_ac = int(SYSMON_execute($hash, "[ -f /sys/class/power_supply/ac/online ] && echo 1 || echo 0")); + if(!defined $hash->{helper}{sys_power_ac}) { + $hash->{helper}{sys_power_ac} = int(SYSMON_execute($hash, "[ -f /sys/class/power_supply/ac/online ] && echo 1 || echo 0")); } - return $sys_power_ac; + return $hash->{helper}{sys_power_ac}; } -my $sys_power_usb = undef; +#my $sys_power_usb = undef; sub SYSMON_isSysPowerUsb($) { my ($hash) = @_; - if(!defined $sys_power_usb) { - $sys_power_usb = int(SYSMON_execute($hash, "[ -f /sys/class/power_supply/usb/online ] && echo 1 || echo 0")); + if(!defined $hash->{helper}{sys_power_usb}) { + $hash->{helper}{sys_power_usb} = int(SYSMON_execute($hash, "[ -f /sys/class/power_supply/usb/online ] && echo 1 || echo 0")); } - return $sys_power_usb; + return $hash->{helper}{sys_power_usb}; } -my $sys_power_bat = undef; +#my $sys_power_bat = undef; sub SYSMON_isSysPowerBat($) { my ($hash) = @_; - if(!defined $sys_power_bat) { - $sys_power_bat = int(SYSMON_execute($hash, "[ -f /sys/class/power_supply/battery/online ] && echo 1 || echo 0")); + if(!defined $hash->{helper}{sys_power_bat}) { + $hash->{helper}{sys_power_bat} = int(SYSMON_execute($hash, "[ -f /sys/class/power_supply/battery/online ] && echo 1 || echo 0")); } - return $sys_power_bat; + return $hash->{helper}{sys_power_bat}; } -my $sys_cpu_num = undef; +#my $sys_cpu_num = undef; sub SYSMON_isSysCpuNum($) { my ($hash) = @_; - if(!defined $sys_cpu_num) { - $sys_cpu_num = int(SYSMON_execute($hash, "[ -f /sys/devices/system/cpu/kernel_max ] && echo 1 || echo 0")); + if(!defined $hash->{helper}{sys_cpu_num}) { + $hash->{helper}{sys_cpu_num} = int(SYSMON_execute($hash, "[ -f /sys/devices/system/cpu/kernel_max ] && echo 1 || echo 0")); } - return $sys_cpu_num; + return $hash->{helper}{sys_cpu_num}; } sub SYSMON_PowerAcInfo($$) @@ -2663,11 +2790,24 @@ sub SYSMON_decode_time_diff($) # Logging: Funkrionsaufrufe # Parameter: HASH, Funktionsname, Message #------------------------------------------------------------------------------ -sub logF($$$) -{ - my ($hash, $fname, $msg) = @_; - #Log 5, "SYSMON $fname (".$hash->{NAME}."): $msg"; - Log 5, "SYSMON $fname $msg"; +#sub logF($$$) +#{ +# my ($hash, $fname, $msg) = @_; +# #Log 5, "SYSMON $fname (".$hash->{NAME}."): $msg"; +# Log 5, "SYSMON $fname $msg"; +#} + +sub SYSMON_Log($$$) { + my ( $hash, $loglevel, $text ) = @_; + my $xline = ( caller(0) )[2]; + + my $xsubroutine = ( caller(1) )[3]; + my $sub = ( split( ':', $xsubroutine ) )[2]; + $sub =~ s/SMARTMON_//; + + my $instName = ( ref($hash) eq "HASH" ) ? $hash->{NAME} : $hash; + $instName="" unless $instName; + Log3 $hash, $loglevel, "SMARTMON $instName: $sub.$xline " . $text; } #sub trim($) @@ -3052,6 +3192,7 @@ If one (or more) of the multiplier is set to zero, the corresponding readings is If results of the long-running operations required, these should be set up as a CRON job and store results as a text file.

Example: Display of package updates for the operating system:
cron-Job:
+ sudo apt-get update 2>/dev/null >/dev/null apt-get upgrade --dry-run| perl -ne '/(\d*)\s[upgraded|aktualisiert]\D*(\d*)\D*install|^ \S+.*/ and print "$1 aktualisierte, $2 neue Pakete"' 2>/dev/null > /opt/fhem/data/updatestatus.txt
uder-defined attribute
sys_updates:1440:System Aktualisierungen:cat /opt/fhem/data/updatestatus.txt
@@ -3123,9 +3264,13 @@ If one (or more) of the multiplier is set to zero, the corresponding readings is According to SYSMON_ShowValuesHTMLTitled, but formatted as plain text.

- Reading values with perl: SYSMON_getValues([<array of desired keys>])

+ Reading values with perl: SYSMON_getValues(<name>[, <array of desired keys>])

    Returns a hash ref with desired values. If no array is passed, all values are returned.
    + {(SYSMON_getValues("sysmon"))->{'cpu_temp'}}
    + {(SYSMON_getValues("sysmon",("cpu_freq","cpu_temp")))->{"cpu_temp"}}
    + {join(" ", values (SYSMON_getValues("sysmon")))}
    + {join(" ", values (SYSMON_getValues("sysmon",("cpu_freq","cpu_temp"))))}

Examples:

@@ -3614,6 +3759,7 @@ If one (or more) of the multiplier is set to zero, the corresponding readings is und in FHEM nur die davor gespeicherten Ausgaben visualisiert.

Beispiel: Anzeige der vorliegenden Paket-Aktualisierungen für das Betriebssystem:
In einem cron-Job wird folgendes täglich ausgeführt:
+ sudo apt-get update 2>/dev/null >/dev/null apt-get upgrade --dry-run| perl -ne '/(\d*)\s[upgraded|aktualisiert]\D*(\d*)\D*install|^ \S+.*/ and print "$1 aktualisierte, $2 neue Pakete"' 2>/dev/null > /opt/fhem/data/updatestatus.txt
Das Attribute uder-defined wird auf
sys_updates:1440:System Aktualisierungen:cat /opt/fhem/data/updatestatus.txt
gesetzt. @@ -3691,9 +3837,13 @@ If one (or more) of the multiplier is set to zero, the corresponding readings is Wie SYSMON_ShowValuesText, aber mit einer Überschrift darüber.

- Readings-Werte mit Perl lesen: SYSMON_getValues([<Liste der gewünschten Schlüssel>])

+ Readings-Werte mit Perl lesen: SYSMON_getValues(<name>[, <Liste der gewünschten Schlüssel>])

    Liefert ein Hash-Ref mit den gewünschten Werten. Wenn keine Liste (array) übergeben wird, werden alle Werte geliefert.
    + {(SYSMON_getValues("sysmon"))->{'cpu_temp'}}
    + {(SYSMON_getValues("sysmon",("cpu_freq","cpu_temp")))->{"cpu_temp"}}
    + {join(" ", values (SYSMON_getValues("sysmon")))}
    + {join(" ", values (SYSMON_getValues("sysmon",("cpu_freq","cpu_temp"))))}

Beispiele: