diff --git a/fhem/FHEM/98_DOIF.pm b/fhem/FHEM/98_DOIF.pm index af0b896a8..598d8344c 100644 --- a/fhem/FHEM/98_DOIF.pm +++ b/fhem/FHEM/98_DOIF.pm @@ -183,7 +183,7 @@ sub DOIF_UpdateCell my $retStyle=""; my $reg=""; my $VALUE=""; - if ($doifId =~ /.*_(.*)_c_(.*)_(.*)_(.*)_(.*)$/) { + if ($doifId =~ /.*_(.*)_c_(.*)_(.*)_(.*)_(.*)$/) { my $command=$hash->{$1}{table}{$2}{$3}{$4}{$5}; eval ($command); if ($@) { @@ -1295,8 +1295,19 @@ sub ReadingValDoIf $hours=$num; } } + if (!defined $hash->{collect}{"$name $reading"}{$hours}) { + return(undef); + } setValue_collect($hash,\%{$hash->{collect}{"$name $reading"}{$hours}}); return (\%{$hash->{collect}{"$name $reading"}{$hours}}); + } elsif ($regExp =~ /^(bar(\d*)(day|week|month|year|decade))/) { + my $num = $2; + my $period = $3; + if (!defined $hash->{bar}{"$name $reading"}{"$num $period"}) { + return(undef); + } + setValue_bar($hash,\%{$hash->{bar}{"$name $reading"}{"$num $period"}}); + return (\%{$hash->{bar}{"$name $reading"}{"$num $period"}}); } elsif ($regExp =~ /^d(\d)?/) { my $round=$1; $r = ($r =~ /(-?\d+(\.\d+)?)/ ? $1 : 0); @@ -1333,11 +1344,22 @@ sub accu_setValue } } -sub DOIF_collect_save_values { +sub DOIF_save_readings { my ($hash)=@_; foreach my $key (keys %{$defs{$hash->{NAME}}{READINGS}}) { - delete $defs{$hash->{NAME}}{READINGS}{$key} if ($key =~ /^\.col/); + delete $defs{$hash->{NAME}}{READINGS}{$key} if ($key =~ /^(\.col|\.bar)/); } + if (defined $hash->{collect}) { + DOIF_collect_save_values($hash); + } + if (defined $hash->{bar}) { + DOIF_bar_save_values($hash); + } +} + + +sub DOIF_collect_save_values { + my ($hash)=@_; foreach my $dev_reading (keys %{$hash->{collect}}) { foreach my $hours (keys %{$hash->{collect}{"$dev_reading"}}) { if (ref($hash->{collect}{$dev_reading}{$hours}{values}) eq "ARRAY") { @@ -1355,13 +1377,168 @@ sub DOIF_collect_save_values { } } +sub DOIF_bar_save_values { + my ($hash)=@_; + foreach my $dev_reading (keys %{$hash->{bar}}) { + foreach my $num_period (keys %{$hash->{bar}{"$dev_reading"}}) { + if (ref($hash->{bar}{$dev_reading}{$num_period}{values}) eq "ARRAY") { + setValue_bar($hash,\%{$hash->{bar}{$dev_reading}{$num_period}}); + my @va=@{$hash->{bar}{$dev_reading}{$num_period}{values}}; + for (@va) { $_ = "" if (!defined $_); }; + my $dim=$hash->{bar}{$dev_reading}{$num_period}{dim}; + my $last_period2=$hash->{bar}{$dev_reading}{$num_period}{last_period2}; + my $last_period1=$hash->{bar}{$dev_reading}{$num_period}{last_period1}; + my $devReading=$dev_reading; + $devReading =~ s/ /_/g; + my $numPeriod=$num_period; + $numPeriod =~ s/ /_/g; + ::readingsSingleUpdate($hash,".bar_".$devReading."_".$numPeriod."_values","$last_period1,$last_period2,".join(",",@va),0); + } + } + } +} + +sub DOIF_setColvalue +{ + my ($collect,$seconds,$value,$optimize)=@_; + my $dim=${$collect}{dim}; + my $hours=${$collect}{hours}; + my $va=${$collect}{values}; + my $ta=${$collect}{times}; + + my $seconds_per_slot=$hours*3600/$dim; + my $slot_nr=int ($seconds/$seconds_per_slot); + my $last_slot=int(${$collect}{time}/$seconds_per_slot); + my $last_value; + + my $diff_slots=$last_slot-$slot_nr; + if ($diff_slots >= 0) { + if ($diff_slots < $dim) { + my $pos=$dim-1-$diff_slots; + if (defined $optimize or $pos > 1) { + for (my $i=$pos-1;$i>=0;$i--) { + if (defined (${$va}[$i])) { + $last_value=${$va}[$i]; + last; + } + } + } + if (!defined $optimize or !defined ${$va}[$pos] or !defined $last_value or (abs($value-$last_value) > abs(${$va}[$pos]-$last_value))) { + ${$va}[$pos]=$value; + ${$ta}[$pos]=$seconds; + } + } + } +} + +sub DOIF_modify_card_data +{ + my ($name,$device,$reading,$colBarDes,$timeOffset,$valueData)=@_; + DOIF_card_data (undef,$name,$device,$reading,$colBarDes,$timeOffset,$valueData); +} + +sub DOIF_set_card_data +{ + my ($name,$device,$reading,$colBarDes,$timeOffset,$valueData)=@_; + DOIF_card_data (1,$name,$device,$reading,$colBarDes,$timeOffset,$valueData); +} + +sub DOIF_card_data +{ + my ($delOpt,$name,$device,$reading,$colBarDes,$timeOffset,$valueData)=@_; + my $collect=ReadingValDoIf($defs{$name},$device,$reading,'',$colBarDes); + if (!defined $collect) { + return ("undefined $name, $device, $reading, $colBarDes combination"); + } + DOIF_delete_values ($collect) if (defined $delOpt); + return(DOIF_setCardValues($defs{$name},$delOpt,ReadingValDoIf($defs{$name},$device,$reading,'',$colBarDes),$timeOffset,$valueData)); +} + +sub DOIF_setCardValues +{ + my ($hash,$optimize,$collect,$timeOffset,$valueData)=@_; + my $seconds; + my $type=${$collect}{type}; + if (!defined $timeOffset or $timeOffset eq "") { + $timeOffset=0; + } + if ($valueData !~ /^\d\d\d\d/) { + return("invalid syntax: $valueData"); + } + if ($type eq "bar") { + setValue_bar($hash,$collect); + } else { + setValue_collect($hash,$collect); + } + my @data=split (/[\n\,]/,$valueData); + #${$collect}{last_v}=undef; + for (my $i=0;$i < scalar (@data);$i++) { + my ($dateTime,$value)=split (/[ \;]/,$data[$i]); + if ($dateTime =~ /^\d\d\d\d/) { + if ($type eq "bar") { + DOIF_setBarvalue ($collect,DOIF_time_sec($dateTime)+$timeOffset,$value); + } else { + DOIF_setColvalue ($collect,DOIF_time_sec($dateTime)+$timeOffset,$value,$optimize); + } + } + } + if ($type eq "bar") { + setValue_bar($hash,$collect,undef,1); + } else { + setValue_collect($hash,$collect); + } + #DOIF_statistic_col ($collect); + return; +} + +sub DOIF_delete_card_data +{ + my ($name,$device,$reading,$colBarDes)=@_; + my $collect=ReadingValDoIf($defs{$name},$device,$reading,'',$colBarDes); + if (!defined $collect) { + return ("undefined $name, $device, $reading, $colBarDes combination"); + } + DOIF_delete_values($collect); + return(undef); +} + + +sub DOIF_delete_values +{ + my ($a)=@_; + @{${$a}{values}}=(); + @{${$a}{times}}=(); + + delete ${$a}{max_value}; + delete ${$a}{max_value_slot}; + delete ${$a}{max_value_time}; + delete ${$a}{min_value}; + delete ${$a}{min_value_slot}; + delete ${$a}{min_value_time}; + + delete ${$a}{average_value}; + # delete ${$a}{begin_period}; + # delete ${$a}{last_period1}; + # delete ${$a}{last_period2}; + + if (${$a}{type} eq "col") { + ${$a}{values}[${$a}{dim}-1]=undef; + ${$a}{times}[${$a}{dim}-1]=undef; + } elsif (${$a}{type} eq "bar") { + ${$a}{values}[${$a}{dim}*${$a}{num}-1]=undef; + } +} sub setValue_collect { my ($hash,$collect)=@_; + if (!defined ${$collect}{dim}) { + return; + } my $name=${$collect}{name}; my $reading=${$collect}{reading}; my $hours=${$collect}{hours}; + my $change; my $r=ReadingsVal($name,$reading,0); if (defined ${$collect}{output}) { @@ -1372,7 +1549,10 @@ sub setValue_collect readingsSingleUpdate ($hash, "error", "${$collect}{output}, ".$@,1); } } + + my ($seconds, $microseconds) = gettimeofday(); + $r = ($r =~ /(-?\d+(\.\d+)?)/ ? $1 : "N/A"); ${$collect}{value}=$r; ${$collect}{time}=$seconds; @@ -1387,7 +1567,8 @@ sub setValue_collect if ($r ne "N/A") { my $seconds_per_slot=$hours*3600/$dim; - if (@{$ta} == $dim) { + # if (@{$ta} == $dim) { + if (defined ${$va}[$dim-1]) { $last_slot=int (${$ta}[-1]/$seconds_per_slot); } my $slot_nr=int ($seconds/$seconds_per_slot); @@ -1416,25 +1597,33 @@ sub setValue_collect } } } - - ##${$collect}{avg} = defined ${$collect}{max_value} ? (${$collect}{max_value}-${$collect}{min_value})/2 + ${$collect}{min_value}: $r; - if (!defined ${$va}[$dim-1] or !defined ${$collect}{last_v} or (abs($r-${$collect}{last_v}) > abs(${$va}[$dim-1]-${$collect}{last_v}))) { - ## if (!defined ${$va}[$dim-1] or ($r >= ${$collect}{avg} and $r > ${$va}[$dim-1] or $r < ${$collect}{avg} and $r < ${$va}[$dim-1])) { ${$va}[$dim-1]=$r; ${$ta}[$dim-1]=$seconds; + $change=1; } elsif (${$va}[$dim-1] != $r) { - ${$collect}{last}=$r; + ${$collect}{last}=$r; } } - + + if (defined $change) { + DOIF_statistic_col ($collect) + } +} + +sub DOIF_statistic_col +{ + my ($collect)=@_; my $maxVal; my $maxValTime; my $maxValSlot; my $minVal; my $minValTime; my $minValSlot; - + my $dim=${$collect}{dim}; + my $va=${$collect}{values}; + my $ta=${$collect}{times}; + for (my $i=0;$i<@{$va};$i++) { my $value=${$va}[$i]; my $time=${$ta}[$i]; @@ -1477,6 +1666,223 @@ sub setValue_collect } } +sub DOIF_time_sec($) +{ + my ($str) = @_; + my @a; + + return time() if(!$str); + @a = split(/[\D]/, $str); + $a[1]=1 if (!defined $a[1]); + $a[2]=1 if (!defined $a[2]); + $a[3]=0 if (!defined $a[3]); + $a[4]=0 if (!defined $a[4]); + $a[5]=0 if (!defined $a[5]); + + return mktime($a[5],$a[4],$a[3],$a[2],$a[1]-1,$a[0]-1900,0,0,-1); +} + +sub DOIF_statistic_bar +{ + my ($bar)=@_; + my $num=${$bar}{num}; + my $numOrig=${$bar}{numOrig}; + my $dim=${$bar}{dim}; + my $maxVal; + my $minVal; + my $maxValSlot; + my $minValSlot; + my $sum=0; + my $numb=0; + my $period2=${$bar}{last_period2}; + my $period1=${$bar}{last_period1}; + my $va=${$bar}{values}; + + for (my $i=0;$i<@{$va};$i++) { + my $value=${$va}[$i]; + # if (defined $value) { + if (defined $value and ($numOrig != 1 or (int($i/$dim) == 0 or $i % $dim > $period1 or $i % $dim == $period1 and !defined ${$va}[$period1]))) { + $numb++; + $sum+=$value; + if (!defined $maxVal or $value >= $maxVal) { + $maxVal=$value; + $maxValSlot=$i; + } + if (!defined $minVal or $value <= $minVal) { + $minVal=$value; + $minValSlot=$i; + } + } + } + if ($numb > 0) { + ${$bar}{max_value}=$maxVal; + ${$bar}{max_value_slot}=$maxValSlot; + ${$bar}{min_value}=$minVal; + ${$bar}{min_value_slot}=$minValSlot; + ${$bar}{average_value}=$sum/$numb; + if (${$bar}{period} eq "decade") { + ${$bar}{max_value_time}=((${$bar}{last_period2}-int($maxValSlot/$dim))*10+$maxValSlot); + ${$bar}{min_value_time}=((${$bar}{last_period2}-int($minValSlot/$dim))*10+$minValSlot); + } elsif (${$bar}{period} eq "year") { + ${$bar}{max_value_time}=qw(Jan Feb Mär Apr Mai Jun Jul Aug Sep Okt Nov Dez)[$maxValSlot % $dim]." ".(($period2-int($maxValSlot/$dim)) % 100); + ${$bar}{min_value_time}=qw(Jan Feb Mär Apr Mai Jun Jul Aug Sep Okt Nov Dez)[$minValSlot % $dim]." ".(($period2-int($minValSlot/$dim)) % 100); + } elsif (${$bar}{period} eq "month") { + # ${$bar}{max_value_time}=(($maxValSlot % $dim)+1).". ".qw(Jan Feb Mär Apr Mai Jun Jul Aug Sep Okt Nov Dez)[($period2-int($maxValSlot/$dim)) % 12]; + ${$bar}{max_value_time}=sprintf("%02d.%02d",(($maxValSlot % $dim)+1),($period2-int($maxValSlot/$dim)) % 12+1); + ${$bar}{min_value_time}=sprintf("%02d.%02d",(($minValSlot % $dim)+1),($period2-int($minValSlot/$dim)) % 12+1); + } elsif (${$bar}{period} eq "week") { + my ($sec,$min,$hour,$mday,$month,$year,$wday,$yday)=gmtime(($period2-int($maxValSlot/$dim))*604800+(($maxValSlot % $dim)-3)*86400); + ${$bar}{max_value_time}=sprintf("%02d.%02d",$mday,$month+1); + ($sec,$min,$hour,$mday,$month,$year,$wday,$yday)=gmtime(($period2-int($minValSlot/$dim))*604800+(($minValSlot % $dim)-3)*86400); + #${$bar}{min_value_time}=sprintf("%s %02d.%02d",qw(So Mo Di Mi Do Fr Sa)[$wday],$mday,$month+1); + ${$bar}{min_value_time}=sprintf("%02d.%02d",$mday,$month+1); + } elsif (${$bar}{period} eq "day") { + my ($sec,$min,$hour,$mday,$month,$year,$wday,$yday)=gmtime(($period2-int($maxValSlot/$dim))*86400+(($maxValSlot % $dim))*3600); + ${$bar}{max_value_time}=qw(So Mo Di Mi Do Fr Sa)[$wday]." ".$hour.":"; + ($sec,$min,$hour,$mday,$month,$year,$wday,$yday)=gmtime(($period2-int($minValSlot/$dim))*86400+(($minValSlot % $dim))*3600); + ${$bar}{min_value_time}=qw(So Mo Di Mi Do Fr Sa)[$wday]." ".$hour.":"; + } + } +} + +sub DOIF_setPeriod +{ + my ($seconds,$period)=@_; + + my $period1; + my $period2; + my $begin_period2; + + # $seconds+=5*3600+30*60; + my ($sec,$min,$hour,$mday,$month,$year,$wday,$yday,$isdst) = localtime($seconds); + $year+=1900; + if ($period eq "decade") { + $period1=$year%10; + $period2=int($year/10); + $begin_period2=($period2)."-"; + } elsif ($period eq "year") { + $period1=$month; + $period2=$year; + $begin_period2=$year; + } elsif ($period eq "month") { + $period1=$mday-1; + $period2=$month+$year*12; + $begin_period2=qw(Jan Feb Mär Apr Mai Jun Jul Aug Sep Okt Nov Dez)[$month]; + } else { + my ($gsec,$gmin,$ghour,$gmday,$gmon,$gyear,$gwday,$gyday) = gmtime($seconds); + $gyear+=1900; + my $offset=($min - $gmin)/60 + $hour - $ghour + 24 * ($year - $gyear || $yday - $gyday); # time zone offset + if ($period eq "week") { + $period1=$wday == 0 ? 6: $wday-1; + $period2=int(($seconds+3*86400+($isdst+$offset)*3600)/604800); + ($sec,$min,$hour,$mday,$month,$year,$wday,$yday) = gmtime($period2*604800-3*86400); + $begin_period2=sprintf("%02d.%02d-",$mday,$month+1); + } elsif ($period eq "day") { + $period1=$hour; + $period2=int(($seconds+($isdst+$offset)*3600)/86400); + #($sec,$min,$hour,$mday,$month,$year,$wday,$yday,$isdst) = localtime($period2*86400+($isdst+$offset)*3600); + #$begin_period2=sprintf("%02d.%02d",$mday,$month+1); + $begin_period2=qw(So Mo Di Mi Do Fr Sa)[$wday]; + } + } + return ($period1,$period2,$begin_period2); +} + +sub DOIF_setBarvalue +{ + my ($bar,$seconds,$value)=@_; + my $period=${$bar}{period}; + my $num=${$bar}{num}; + my $dim=${$bar}{dim}; + + my ($period1,$period2)=DOIF_setPeriod($seconds,$period); + + if (defined ${$bar}{last_period2} and $period2 <= ${$bar}{last_period2}) { + my $diff=(${$bar}{last_period2} - $period2); + if ($diff < $num) { + my $va=${$bar}{values}; + ${$va}[$diff*$dim+$period1]=$value; + } + } +} + +sub setValue_bar +{ + my ($hash,$bar,$trigger,$statistic)=@_; + if (!defined ${$bar}{dim}) { + return; + } + my $name=${$bar}{name}; + my $reading=${$bar}{reading}; + my $period=${$bar}{period}; + my $num=${$bar}{num}; + my $dim=${$bar}{dim}; + my $timeOffset=${$bar}{timeOffset}; + + my $r=ReadingsVal($name,$reading,0); + if (defined ${$bar}{output}) { + $_=$r; + $r=eval(${$bar}{output}); + if ($@) { + Log3 ($hash->{NAME},4 , "$hash->{NAME}: $@"); + readingsSingleUpdate ($hash, "error", "${$bar}{output}, ".$@,1); + } + } + my ($seconds, $microseconds) = gettimeofday(); + + $r = ($r =~ /(-?\d+(\.\d+)?)/ ? $1 : "N/A"); + ${$bar}{value}=$r; + + my ($period1,$period2,$begin_period2)=DOIF_setPeriod($seconds,$period); + + if (defined $trigger) { + if ($r ne "N/A") { + # if (${$bar}{counter}) { + # if (!defined ${$bar}{last_period1}) { + # ${$bar}{last_period1}=$period1; + # } elsif (${$bar}{last_period1} <= $period1) { + # ${$bar}{last_counter}=$r; + # } + # ${$bar}{value}=${$bar}{last_counter}-$r; + # } else { + ${$bar}{value}=$r; + # } + } + } + my $va=${$bar}{values}; + my $change=""; + + if (defined ${$bar}{last_period2} and ${$bar}{last_period2} < $period2) { + my @empty; + my $diff=($period2-${$bar}{last_period2}); + if ($diff < $num) { + $empty [$diff*$dim-1]=undef; + splice (@{$va},($num-$diff)*$dim); + splice (@{$va},0,0,@empty); + } else { + @{$va}=(); + ${$va}[$num*$diff-1]=undef; + } + $change=1; + } + + if (defined $trigger) { + if ($timeOffset == 0) { + ${$va}[$period1]=${$bar}{value}; + } else { + DOIF_setBarvalue ($bar,$seconds+$timeOffset,${$bar}{value}); + } + $change=1; + } + + ${$bar}{last_period2}=$period2; + ${$bar}{last_period1}=$period1; + ${$bar}{begin_period2}=$begin_period2; + + if ($change or defined $statistic) { + DOIF_statistic_bar ($bar) + } +} sub EvalAllDoIf($$) { @@ -1613,7 +2019,7 @@ sub ReplaceEventDoIf($) sub ReplaceReadingDoIf { - my ($hash,$element) = @_; + my ($hash,$element,$cond) = @_; my $beginning; my $tailBlock; my $err; @@ -1678,38 +2084,92 @@ sub ReplaceReadingDoIf my $num=$3; my $time=$4; $output=$5; - my $hours=24; - if ($num ne "") { - if($time eq "d") { - $hours=24*$num; - }elsif ($time eq "w") { - $hours=24*$num*7; - } else { - $hours=$num; + if (defined $cond and $cond >= -7 and $cond <= -4) { #DOIF_Readings,event_Readings,uiTable,uiState + my $hours=24; + if ($num ne "") { + if($time eq "d") { + $hours=24*$num; + }elsif ($time eq "w") { + $hours=24*$num*7; + } else { + $hours=$num; + } } - } - AddRegexpTriggerDoIf($hash,"collect","","collect",$name,$reading); - if (ref($hash->{collect}{"$name $reading"}{$hours}{values}) ne "ARRAY" or $dim != $hash->{collect}{"$name $reading"}{$hours}{dim}) { - delete $hash->{collect}{"$name $reading"}{$hours}; - $hash->{collect}{"$name $reading"}{$hours}{hours}=$hours; - $hash->{collect}{"$name $reading"}{$hours}{dim}=$dim; - $hash->{collect}{"$name $reading"}{$hours}{animate}= (defined $hash->{card}{animate} and $hash->{card}{animate} eq "1") ? 1 :0; - my $values=::ReadingsVal($hash->{NAME},".col_".$hash->{collect}{"$name $reading"}{$hours}{dim}."_".$name."_".$reading."_".$hours."_values",""); - my $times=::ReadingsVal($hash->{NAME},".col_".$hash->{collect}{"$name $reading"}{$hours}{dim}."_".$name."_".$reading."_".$hours."_times",""); - my $va; - my $ta; - @{$va}=split (",",$values); - for (@{$va}) { $_ = undef if ($_ eq ""); }; - @{$ta}=split (",",$times); - for (@{$ta}) { $_ = undef if ($_ eq ""); }; - $hash->{collect}{"$name $reading"}{$hours}{values}=$va; - $hash->{collect}{"$name $reading"}{$hours}{times}=$ta; - $hash->{collect}{"$name $reading"}{$hours}{dim}=$dim; - $hash->{collect}{"$name $reading"}{$hours}{name}=$name; - $hash->{collect}{"$name $reading"}{$hours}{reading}=$reading; - } - $hash->{collect}{"$name $reading"}{$hours}{output}=$output if ($output); - setValue_collect($hash,\%{$hash->{collect}{"$name $reading"}{$hours}}); + AddRegexpTriggerDoIf($hash,"collect","","collect",$name,$reading); + if (ref($hash->{collect}{"$name $reading"}{$hours}{values}) ne "ARRAY" or $dim != $hash->{collect}{"$name $reading"}{$hours}{dim}) { + delete $hash->{collect}{"$name $reading"}{$hours}; + $hash->{collect}{"$name $reading"}{$hours}{hours}=$hours; + $hash->{collect}{"$name $reading"}{$hours}{dim}=$dim; + $hash->{collect}{"$name $reading"}{$hours}{animate}= (defined $hash->{card}{animate} and $hash->{card}{animate} eq "1") ? 1 :0; + my $values=::ReadingsVal($hash->{NAME},".col_".$hash->{collect}{"$name $reading"}{$hours}{dim}."_".$name."_".$reading."_".$hours."_values",""); + my $times=::ReadingsVal($hash->{NAME},".col_".$hash->{collect}{"$name $reading"}{$hours}{dim}."_".$name."_".$reading."_".$hours."_times",""); + my $va; + my $ta; + @{$va}=split (",",$values); + for (@{$va}) { $_ = undef if ($_ eq ""); }; + @{$ta}=split (",",$times); + for (@{$ta}) { $_ = undef if ($_ eq ""); }; + $hash->{collect}{"$name $reading"}{$hours}{values}=$va; + $hash->{collect}{"$name $reading"}{$hours}{times}=$ta; + $hash->{collect}{"$name $reading"}{$hours}{dim}=$dim; + $hash->{collect}{"$name $reading"}{$hours}{name}=$name; + $hash->{collect}{"$name $reading"}{$hours}{reading}=$reading; + $hash->{collect}{"$name $reading"}{$hours}{type}="col"; + } + $hash->{collect}{"$name $reading"}{$hours}{output}=$output if ($output); + setValue_collect($hash,\%{$hash->{collect}{"$name $reading"}{$hours}}); + } + } elsif ($format =~ /^(bar(\d*)(day|week|month|year|decade))(-?\d*)?(?::(.*))?/) { + $regExp = $1; + my $num = $2; + my $period = $3; + my $timeOffset = $4; + $output = $5; + if (defined $cond and $cond >= -7 and $cond <= -4) { #DOIF_Readings,event_Readings,uiTable,uiState + my $dim; + if ($period eq "decade") { + $dim=10; + } elsif ($period eq "year") { + $dim=12; + } elsif ($period eq "month") { + $dim=31; + } elsif ($period eq "week") { + $dim=7; + } elsif ($period eq "day") { + $dim=24; + } + AddRegexpTriggerDoIf($hash,"bar","","bar",$name,$reading); + if (ref($hash->{bar}{"$name $reading"}{"$num $period"}{values}) ne "ARRAY") { + delete $hash->{bar}{"$name $reading"}{"$num $period"}; + $hash->{bar}{"$name $reading"}{"$num $period"}{timeOffset} = (defined $timeOffset and $timeOffset ne "") ? $timeOffset : 0; + my $values=::ReadingsVal($hash->{NAME},".bar_".$name."_".$reading."_".$num."_".$period."_values",""); + my $va; + my $vadim=($num == 1 ? 2 : $num)*$dim; + if ($values ne "") { + ($hash->{bar}{"$name $reading"}{"$num $period"}{last_period1},$hash->{bar}{"$name $reading"}{"$num $period"}{last_period2},@{$va})=split (",",$values); + if (@{$va} < $vadim) { + ${$va}[$vadim-1]=undef; + } + for (@{$va}) { $_ = undef if (defined $_ and $_ eq ""); }; + } else { + ${$va}[$vadim-1]=undef; + } + $hash->{bar}{"$name $reading"}{"$num $period"}{values} = $va; + $hash->{bar}{"$name $reading"}{"$num $period"}{numOrig} = $num; + $hash->{bar}{"$name $reading"}{"$num $period"}{num} = $num == 1 ? 2 : $num; + $hash->{bar}{"$name $reading"}{"$num $period"}{period} = $period; + $hash->{bar}{"$name $reading"}{"$num $period"}{name} = $name; + $hash->{bar}{"$name $reading"}{"$num $period"}{reading} = $reading; + #$hash->{bar}{"$name $reading"}{"$num $period"}{counter}=$counter; + + $hash->{bar}{"$name $reading"}{"$num $period"}{dim} = $dim; + $hash->{bar}{"$name $reading"}{"$num $period"}{type} = "bar"; + $hash->{bar}{"$name $reading"}{"$num $period"}{output} = $output if ($output); + setValue_bar($hash,\%{$hash->{bar}{"$name $reading"}{"$num $period"}},undef,1); + } else { + $hash->{bar}{"$name $reading"}{"$num $period"}{timeOffset} = (defined $timeOffset and $timeOffset ne "") ? $timeOffset : 0; + } + } } elsif ($format =~ /^(d[^:]*)(?::(.*))?/) { $regExp =$1; $output=$2; @@ -1740,10 +2200,10 @@ sub ReplaceReadingDoIf } } -sub ReplaceReadingEvalDoIf($$$) +sub ReplaceReadingEvalDoIf { - my ($hash,$element,$eval) = @_; - my ($block,$err,$device,$reading,$internal)=ReplaceReadingDoIf($hash,$element); + my ($hash,$element,$eval,$cond) = @_; + my ($block,$err,$device,$reading,$internal)=ReplaceReadingDoIf($hash,$element,$cond); return ($block,$err) if ($err); if ($eval) { # return ("[".$element."]","") if(!$defs{$device}); @@ -1910,7 +2370,7 @@ sub ReplaceAllReadingsDoIf } else { $trigger=0 if (substr($block,0,7) eq "\$DEVICE"); if ($block =~ /^(\$DEVICE|[a-z0-9._]*[a-z._]+[a-z0-9._]*)($|:.+$|,.+$)/i) { - ($block,$err,$device,$reading,$internal)=ReplaceReadingEvalDoIf($hash,$block,$eval); + ($block,$err,$device,$reading,$internal)=ReplaceReadingEvalDoIf($hash,$block,$eval,$condition); return ($block,$err) if ($err); if ($condition >= 0) { if ($trigger) { @@ -2885,9 +3345,7 @@ DOIF_Notify($$) return "" if (!$hash->{helper}{globalinit}); if ($dev->{NAME} eq "global" and (EventCheckDoif($dev->{NAME},"global",$eventa,'^SAVE$'))) { - if (defined $hash->{collect}) { - DOIF_collect_save_values($hash); - } + DOIF_save_readings($hash); } #return "" if (!$hash->{itimer}{all} and !$hash->{devices}{all} and !keys %{$hash->{Regex}}); @@ -2940,8 +3398,18 @@ DOIF_Notify($$) } } } - + if (defined $hash->{Regex}{"bar"}{"$dev->{NAME}"}) { + my $device=$dev->{NAME}; + foreach my $reading (keys %{$hash->{Regex}{"bar"}{$device}{"bar"}}) { + my $readingregex=CheckRegexpDoIf($hash,"bar",$dev->{NAME},"bar",$eventa,$eventas,$reading); + if (defined $readingregex) { + foreach my $period (keys %{$hash->{bar}{"$device $readingregex"}}){ + setValue_bar($hash,\%{$hash->{bar}{"$device $readingregex"}{$period}},1); + } + } + } + } if (defined CheckRegexpDoIf($hash,"cond",$dev->{NAME},"",$eventa,$eventas)) { $hash->{helper}{cur_cmd_nr}="Trigger $dev->{NAME}" if (AttrVal($hash->{NAME},"selftrigger","") ne "all"); @@ -3912,9 +4380,8 @@ DOIF_Shutdown { my ($hash) = @_; DOIF_killBlocking($hash); - if (defined $hash->{collect}) { - DOIF_collect_save_values($hash); - } + + DOIF_save_readings($hash); return undef; } @@ -4056,6 +4523,12 @@ package DOIF; #use Date::Parse qw(str2time); use Time::HiRes qw(gettimeofday); +sub set_bar +{ + my ($bar,$timeOffset,$valueData)=@_; + ::DOIF_set_bar_values($hs,$bar,$timeOffset,$valueData); +} + sub DOIF_ExecTimer { my ($timer)=@_; @@ -4580,20 +5053,18 @@ sub get_color { return(int($color),$minColor,$maxColor); } -sub footer { - - -} sub plot { my ($collect,$min_a,$max_a,$minColor,$maxColor,$dec,$func,$steps,$x_prop,$chart_dim,$noColor,$lmm,$ln,$lr,$plot,$bwidth,$footerPos,$fill,$pos,$anchor,$unitColor,$unit)=@_; + $lmm=42 if (!defined $lmm or $lmm eq ""); + my $points=""; my $v; my $last; my $out=""; - my $xpos; + my $yNull; my $nullColor; my $nullProp; my $topVal; @@ -4615,12 +5086,17 @@ sub plot { my $last_value=${$collect}{last_value}; my $minValTime = ${$collect}{min_value_time}; my $minValSlot = ${$collect}{min_value_slot}; + my $averageVal = ${$collect}{average_value}; my $hours = ${$collect}{hours}; my $time = ${$collect}{time}; my $dim=${$collect}{dim}; - my $animate=(${$collect}{animate} eq "1") ? '':''; + my $type=${$collect}{type}; + my $period=${$collect}{period}; + my $period1=${$collect}{last_period1}; + my $num=${$collect}{num}; + my $numOrig=${$collect}{numOrig}; + my $animate=(defined ${$collect}{animate} and ${$collect}{animate} eq "1") ? '':''; - my $min; my $max; if (ref($min_a) eq "ARRAY") { @@ -4676,7 +5152,7 @@ sub plot { my $opacity=0.4; my $minopacity=0.05; if ($minPlot < 0 and $maxPlot > 0) { - $xpos=50-int($n*10)/10; + $yNull=50-int($n*10)/10; $topVal=($maxVal > 0 ? $maxVal : 0); $bottomVal=($minVal < 0 ? $minVal : 0); ($nullColor)=get_color(0,$min,$max,$minColor,$maxColor,$func); @@ -4685,13 +5161,13 @@ sub plot { $bottomOpacity=($bottomVal==0 ? $minopacity: $opacity); $nullOpacity=$minopacity; } elsif ($maxPlot <= 0) { - $xpos=0; + $yNull=0; $topVal=$maxPlot; $topOpacity=0; $bottomOpacity=$opacity; $bottomVal=$minVal; } else { - $xpos=50; + $yNull=50; $topVal=$maxVal; $topOpacity=$opacity; $bottomOpacity=$minopacity; @@ -4703,27 +5179,34 @@ sub plot { my ($maxValColor)=get_color(${$collect}{max_value},$min,$max,$minColor,$maxColor,$func); my ($minValColor)=get_color(${$collect}{min_value},$min,$max,$minColor,$maxColor,$func); + my ($averageValColor)=get_color(${$collect}{average_value},$min,$max,$minColor,$maxColor,$func); $out.= ''; - if (!defined $unitColor) { - $out.= sprintf('',$topValColor,$bottomValColor,(defined $lr ? $lr:0)); - $out.= sprintf('',color($topValColor,$lr),$topOpacity); - $out.= sprintf('',$nullProp,color($nullColor,$lr),$nullOpacity) if (defined $nullProp); - $out.= sprintf('',color($bottomValColor,$lr),$bottomOpacity); - - $out.= sprintf('',$topValColor,$bottomValColor,(defined $lr ? $lr:0)); - for (my $i=0; $i<=1;$i+=0.10) { - my ($color)=get_color(($topVal-$bottomVal)*(1-$i)+$bottomVal,$min,$max,$minColor,$maxColor,$func); - $out.= sprintf('',$i,color($color,$lr)); - } - $out.= ''; + if ($type eq "bar") { + $out.= ''; + $out.= ''; } else { - $out.= sprintf('',$unitColor); - $out.= sprintf('',$unitColor,$topOpacity); - $out.= sprintf('',$nullProp,$unitColor,$nullOpacity) if (defined $nullProp); - $out.= sprintf('',$unitColor,$bottomOpacity); + if (!defined $unitColor) { + $out.= sprintf('',$topValColor,$bottomValColor,(defined $lr ? $lr:0)); + $out.= sprintf('',color($topValColor,$lr),$topOpacity); + $out.= sprintf('',$nullProp,color($nullColor,$lr),$nullOpacity) if (defined $nullProp); + $out.= sprintf('',color($bottomValColor,$lr),$bottomOpacity); + + $out.= sprintf('',$topValColor,$bottomValColor,(defined $lr ? $lr:0)); + for (my $i=0; $i<=1;$i+=0.10) { + my ($color)=get_color(($topVal-$bottomVal)*(1-$i)+$bottomVal,$min,$max,$minColor,$maxColor,$func); + $out.= sprintf('',$i,color($color,$lr)); + } + $out.= ''; + } else { + $out.= sprintf('',$unitColor); + $out.= sprintf('',$unitColor,$topOpacity); + $out.= sprintf('',$nullProp,$unitColor,$nullOpacity) if (defined $nullProp); + $out.= sprintf('',$unitColor,$bottomOpacity); + } } $out.= ''; + if ($noColor ne "-1") { for (my $i=0;$i<=5;$i++) { my $v=($maxPlot-$minPlot)*(1-$i*0.2)+$minPlot; @@ -4732,86 +5215,173 @@ sub plot { } } - my $j=0; - if (@{$a} > 0) { - if (!defined ${$a}[0]) { - if (defined $last_value) { - $v=$last_value; - } else { - for ($j=0;$j<@{$a};$j++) { - if (defined ${$a}[$j]) { - $v=${$a}[$j]; - last; + my $footer=""; + + if ($type eq "bar") { + my $dimdev; + if ($period eq "month") { + $dimdev=32; + } elsif ($period eq "day") { + $dimdev=26; + } else { + $dimdev=$dim; + } + my $wide=$chart_dim/$dimdev; + #my $barWide=$wide*0.7; + #my $barWide=$barWide/$num+($num-1)*$barWide/$num*0.005; + #my $xBar=$barWide/$num; + + + my $xBar=int(0.7*$wide/$numOrig*100)/100; + my $barWide=int($wide/$numOrig*0.8*100)/100; + + + my $xOffset; + if ($period eq "month" or $period eq "day") { + $xOffset=$wide*0.61; + } else { + $xOffset=$wide*0.13; + } + + +# $out.=sprintf('',$yNull,$chart_dim,$yNull); + + if ($averageVal) { + my $yAverage=50-int(($averageVal*$m+$n)*10)/10; + $out.=sprintf('',$yAverage,$chart_dim,$yAverage,color($averageValColor,$lmm)); + } + + for (my $i=0; $i < $numOrig;$i++) { + for (my $j=0; $j < $dim; $j++) { + my $num; + if ($numOrig == 1) { + if ($j < $period1 or $j == $period1 and defined ${$a}[($i)*$dim+$j]) { + $num = 1; + } else { + $num = 2; + } + } else { + $num=$numOrig; + } + my $y=${$a}[($num-1-$i)*$dim+$j]; + if (defined $y) { + my $y_pos=int(($y*$m+$n)*10)/10-(50-$yNull); + my ($color)=get_color($y,$min,$max,$minColor,$maxColor,$func); + my $x=int(($xOffset+$j*$wide+$i*$xBar)*10)/10; + if ($y > 0) { + $out.= sprintf('',$x,$yNull-$y_pos,$barWide,$y_pos,defined $unitColor ? $unitColor:color($color)); + $out.= sprintf('',$x,$yNull-$y_pos+0.1,$barWide,$y_pos-0.1,($i==$num-1 ? "bright" : "dark")); + } else { + $out.= sprintf('',$x,$yNull,$barWide,-$y_pos,defined $unitColor ? $unitColor:color($color)); + $out.= sprintf('',$x,$yNull,$barWide,-$y_pos-0.1,($i==$num-1 ? "bright" : "dark")); } } - } - } else { - $v=${$a}[0]; + } } - - $points.=$j*$x_prop.",$xpos "; - $last=(50-int(($v*$m+$n)*10)/10); - $points.=$j*$x_prop.",$last "; - $j++; - for (my $i=$j;$i<@{$a};$i++) { - if (defined ${$a}[$i]) { - $points.=$i*$x_prop.",$last " if (!defined ${$a}[$i-1] or $steps eq "1"); - $last=(50-int((${$a}[$i]*$m+$n)*10)/10); - $points.=$i*$x_prop.",$last "; - } - } - if ($val ne "N/A") { - $points.=$chart_dim.",".$last." " if ($steps eq "1"); - $points.=$chart_dim.",".(50-int(($val*$m+$n)*10)/10)." "; - } - if (!defined $unitColor) { - $out.=sprintf('',$topValColor,$bottomValColor,(defined $lr ? $lr:0),$topValColor,$bottomValColor,(defined $lr ? $lr:0)); - } else { - $out.=sprintf('',$unitColor,$unitColor); - } - } - $out.=sprintf('',$xpos,$chart_dim,$xpos); + $out.=sprintf('',$yNull,$chart_dim,$yNull); - ##$out.=sprintf('',$maxValSlot*$x_prop,(50-int((${$a}[$maxValSlot]*$m+$n)*10)/10),defined $unitColor ? $unitColor:color($maxValColor,$ln)) if (defined $maxValSlot); - my ($x1,$y1)=($maxValSlot*$x_prop,(50-int((${$a}[$maxValSlot]*$m+$n)*10)/10)-2.3); - $out.=sprintf('',$x1,$y1,$x1+2.4,$y1+4.3,$x1-2.4,$y1+4.3, defined $unitColor ? $unitColor:color($maxValColor,$ln)) if (defined $maxValSlot); - - ##$out.=sprintf(',',$minValSlot*$x_prop,(50-int((${$a}[$minValSlot]*$m+$n)*10)/10),defined $unitColor ? $unitColor:color($minValColor,$ln)) if (defined $minValSlot); - ($x1,$y1)=($minValSlot*$x_prop,(50-int((${$a}[$minValSlot]*$m+$n)*10)/10)+2.3); - $out.=sprintf('',$x1,$y1,$x1+2.4,$y1-4.3,$x1-2.4,$y1-4.3, defined $unitColor ? $unitColor:color($minValColor,$ln)) if (defined $minValSlot); - - $out.=sprintf((''.$animate),$chart_dim,(50-int(($value*$m+$n)*10)/10),defined $unitColor ? $unitColor:color($currColor,$ln)) if ($val ne "N/A"); - - my $footer=""; - - if ($footerPos) { - if (defined $maxValTime) { + my ($x1,$y1); + if (defined $maxValSlot) { + # ($x1,$y1)=(int(($xOffset+($maxValSlot % $dim)*$wide+($numOrig-1-int ($maxValSlot / $dim))*$xBar+$barWide/2)*10)/10 ,(50-int((${$a}[$maxValSlot]*$m+$n)*10)/10)-2.3); + ($x1,$y1)=(int(($xOffset+($maxValSlot % $dim)*$wide+($numOrig-1-($numOrig == 1 ? 0: int ($maxValSlot / $dim)))*$xBar+$barWide/2)*10)/10 ,(50-int((${$a}[$maxValSlot]*$m+$n)*10)/10)-2.3); + $out.=sprintf('',$x1,$y1,$x1+2.4,$y1+4.3,$x1-2.4,$y1+4.3, defined $unitColor ? $unitColor:color($maxValColor,$ln)); + # ($x1,$y1)=(int(($xOffset+($minValSlot % $dim)*$wide+($numOrig-1-int($minValSlot / $dim))*$xBar+$barWide/2)*10)/10,(50-int((${$a}[$minValSlot]*$m+$n)*10)/10)+2.3); + ($x1,$y1)=(int(($xOffset+($minValSlot % $dim)*$wide+($numOrig-1-($numOrig == 1 ? 0: int ($minValSlot / $dim)))*$xBar+$barWide/2)*10)/10,(50-int((${$a}[$minValSlot]*$m+$n)*10)/10)+2.3); + $out.=sprintf('',$x1,$y1,$x1+2.4,$y1-4.3,$x1-2.4,$y1-4.3, defined $unitColor ? $unitColor:color($minValColor,$ln)) if (defined $minValSlot); + } + + + if ($footerPos) { $footer.= sprintf('%s',$footerPos,defined $unitColor ? $unitColor : "#CCCCCC", $unit); - if ($hours > 168) { - $footer.= sprintf('%s',$footerPos,defined $unitColor ? $unitColor : "#CCCCCC", ::strftime("%d.%m %H:%M",localtime($maxValTime))); - } else { - $footer.= sprintf('%s',$footerPos,defined $unitColor ? $unitColor : "#CCCCCC", ::strftime("%a",localtime($maxValTime))); - $footer.= sprintf('%s',$footerPos,::strftime("%H:%M",localtime($maxValTime))); + if (defined $maxValSlot) { + $footer.= sprintf('Ø',$footerPos,defined $unitColor ? $unitColor : "#CCCCCC"); + $footer.= sprintf('%s',$bwidth/2-15,$footerPos,color($averageValColor,$lmm),"",sprintf($format,$averageVal)); + $footer.= sprintf('%s',$bwidth/2-15,$footerPos,defined $unitColor ? $unitColor : "#CCCCCC", $maxValTime) ; + $footer.= sprintf('%s',$bwidth/2+42.5,$footerPos,color($maxValColor,$lmm),"",sprintf($format,${$collect}{max_value})); + $footer.= sprintf('%s',$bwidth/2+42.5,$footerPos,defined $unitColor ? $unitColor : "#CCCCCC", $minValTime); + $footer.= sprintf('%s', $bwidth+8,$footerPos,color($minValColor,$lmm),"",sprintf($format,${$collect}{min_value})); } - $footer.= sprintf('%s',$bwidth/2+25.5,$footerPos,color($maxValColor,$lmm),"",sprintf($format,${$collect}{max_value})); } - if (defined $minValTime) { - if ($hours > 168) { - ## $footer.= sprintf('%s',$bwidth/2+25,$footerPos,defined $unitColor ? $unitColor : "#CCCCCC", ::strftime("%d.%m %H:%M",localtime($minValTime))); - $footer.= sprintf('%s',$bwidth/2+25.5,$footerPos,defined $unitColor ? $unitColor : "#CCCCCC", ::strftime("%d.%m %H:%M",localtime($minValTime))); + } else { # col + my $j=0; + if (@{$a} > 0) { + if (!defined ${$a}[0]) { + if (defined $last_value) { + $v=$last_value; + } else { + for ($j=0;$j<@{$a};$j++) { + if (defined ${$a}[$j]) { + $v=${$a}[$j]; + last; + } + } + } } else { - $footer.= sprintf('%s',$bwidth/2+25.5,$footerPos,defined $unitColor ? $unitColor : "#CCCCCC", ::strftime("%a",localtime($minValTime))); - $footer.= sprintf('%s',$bwidth/2+46,$footerPos,::strftime("%H:%M",localtime($minValTime))); + $v=${$a}[0]; } - $footer.= sprintf('%s', $bwidth+8,$footerPos,color($minValColor,$lmm),"",sprintf($format,${$collect}{min_value})); - } - } + $points.=$j*$x_prop.",$yNull "; + $last=(50-int(($v*$m+$n)*10)/10); + $points.=$j*$x_prop.",$last "; + $j++; + + for (my $i=$j;$i<@{$a};$i++) { + if (defined ${$a}[$i]) { + $points.=$i*$x_prop.",$last " if (!defined ${$a}[$i-1] or $steps eq "1"); + $last=(50-int((${$a}[$i]*$m+$n)*10)/10); + $points.=$i*$x_prop.",$last "; + } + } + if ($val ne "N/A") { + $points.=$chart_dim.",".$last." " if ($steps eq "1"); + $points.=$chart_dim.",".(50-int(($val*$m+$n)*10)/10)." "; + } + if (!defined $unitColor) { + $out.=sprintf('',$topValColor,$bottomValColor,(defined $lr ? $lr:0),$topValColor,$bottomValColor,(defined $lr ? $lr:0)); + } else { + $out.=sprintf('',$unitColor,$unitColor); + } + } + $out.=sprintf('',$yNull,$chart_dim,$yNull); + + ##$out.=sprintf('',$maxValSlot*$x_prop,(50-int((${$a}[$maxValSlot]*$m+$n)*10)/10),defined $unitColor ? $unitColor:color($maxValColor,$ln)) if (defined $maxValSlot); + my ($x1,$y1)=($maxValSlot*$x_prop,(50-int((${$a}[$maxValSlot]*$m+$n)*10)/10)-2.3); + $out.=sprintf('',$x1,$y1,$x1+2.4,$y1+4.3,$x1-2.4,$y1+4.3, defined $unitColor ? $unitColor:color($maxValColor,$ln)) if (defined $maxValSlot); + + ##$out.=sprintf(',',$minValSlot*$x_prop,(50-int((${$a}[$minValSlot]*$m+$n)*10)/10),defined $unitColor ? $unitColor:color($minValColor,$ln)) if (defined $minValSlot); + ($x1,$y1)=($minValSlot*$x_prop,(50-int((${$a}[$minValSlot]*$m+$n)*10)/10)+2.3); + $out.=sprintf('',$x1,$y1,$x1+2.4,$y1-4.3,$x1-2.4,$y1-4.3, defined $unitColor ? $unitColor:color($minValColor,$ln)) if (defined $minValSlot); + + $out.=sprintf((''.$animate),$chart_dim,(50-int(($value*$m+$n)*10)/10),defined $unitColor ? $unitColor:color($currColor,$ln)) if ($val ne "N/A"); + + if ($footerPos) { + if (defined $maxValTime) { + $footer.= sprintf('%s',$footerPos,defined $unitColor ? $unitColor : "#CCCCCC", $unit); + if ($hours > 168) { + $footer.= sprintf('%s',$footerPos,defined $unitColor ? $unitColor : "#CCCCCC", ::strftime("%d.%m %H:%M",localtime($maxValTime))); + } else { + $footer.= sprintf('%s',$footerPos,defined $unitColor ? $unitColor : "#CCCCCC", ::strftime("%a",localtime($maxValTime))); + $footer.= sprintf('%s',$footerPos,::strftime("%H:%M",localtime($maxValTime))); + } + $footer.= sprintf('%s',$bwidth/2+25.5,$footerPos,color($maxValColor,$lmm),"",sprintf($format,${$collect}{max_value})); + } + if (defined $minValTime) { + if ($hours > 168) { + ## $footer.= sprintf('%s',$bwidth/2+25,$footerPos,defined $unitColor ? $unitColor : "#CCCCCC", ::strftime("%d.%m %H:%M",localtime($minValTime))); + $footer.= sprintf('%s',$bwidth/2+25.5,$footerPos,defined $unitColor ? $unitColor : "#CCCCCC", ::strftime("%d.%m %H:%M",localtime($minValTime))); + } else { + $footer.= sprintf('%s',$bwidth/2+25.5,$footerPos,defined $unitColor ? $unitColor : "#CCCCCC", ::strftime("%a",localtime($minValTime))); + $footer.= sprintf('%s',$bwidth/2+46,$footerPos,::strftime("%H:%M",localtime($minValTime))); + } + $footer.= sprintf('%s', $bwidth+8,$footerPos,color($minValColor,$lmm),"",sprintf($format,${$collect}{min_value})); + } + } + } # col return($out,$footer); } @@ -4830,7 +5400,12 @@ sub card my $hours; my $time; my $dim; - + my $type; + my $period; + my $period1; + my $period2; + my $begin_period2; + if (!defined $col) { return(""); } @@ -4841,9 +5416,14 @@ sub card $value1[$i]=${$col}[$i]; $colcount++; if (!defined $dim) { + $type=$value1[$i]{type}; $hours=$value1[$i]{hours}; $time=$value1[$i]{time}; $dim=$value1[$i]{dim}; + $period=$value1[$i]{period}; + $period1=$value1[$i]{last_period1}; + $period2=$value1[$i]{last_period2}; + $begin_period2=$value1[$i]{begin_period2}; } } else { $value1[$i]{value}=${$col}[$i]; @@ -4854,9 +5434,14 @@ sub card $colcount++; $value1[0]=$col; if (!defined $dim) { + $type=$value1[0]{type}; $hours=$value1[0]{hours}; $time=$value1[0]{time}; $dim=$value1[0]{dim}; + $period=$value1[0]{period}; + $period1=$value1[0]{last_period1}; + $period2=$value1[0]{last_period2}; + $begin_period2=$value1[0]{begin_period2}; } } else { $value1[0]{value}=$col; @@ -4881,9 +5466,11 @@ sub card $value2[$i]=${$col2}[$i]; $col2count++; if (!defined $dim) { + $type=$value2[$i]{type}; $hours=$value2[$i]{hours}; $time=$value2[$i]{time}; $dim=$value2[$i]{dim}; + $period=$value2[$i]{period}; } } else { $value2[$i]{value}=${$col2}[$i]; @@ -4894,9 +5481,11 @@ sub card $col2count++; $value2[0]=$col2; if (!defined $dim) { + $type=$value2[0]{type}; $hours=$value2[0]{hours}; $time=$value2[0]{time}; $dim=$value2[0]{dim}; + $period=$value2[0]{period}; } } else { $value2[0]{value}=$col2; @@ -4915,15 +5504,14 @@ sub card } } - - - if (!defined $value1[0]{value}) { - return(""); - } + # if (!defined $value1[0]{value}) { + # return(""); + # } + if (!defined $dim) { return(""); } - + my $bheight=73; my $htrans=0; @@ -4969,7 +5557,9 @@ sub card } - my $chart_dim = $hring eq "" ? $bwidth-90: $bwidth-36 ; + my $chart_dim = ($hring eq "" and $type ne "bar") ? $bwidth-90: $bwidth-36 ; + + $chart_dim+=8 if ($type eq "bar"); $chart_dim += $colcount ? 0: 18; @@ -4994,7 +5584,7 @@ sub card my ($lr,$lir,$lmm,$lu,$ln,$li); ($lr,$lir,$lmm,$lu,$ln,$li)=split (/,/,$lightness) if (defined $lightness); - + my $head; #if (defined $header or $hring eq "1" or (@value1+@value2)>2) { if (defined $header or $hring eq "1") { @@ -5057,8 +5647,6 @@ sub card } } } - - $out.= sprintf ('',$bwidth,$bheight,$svg_width,$svg_height,$svg_width,$svg_height); $out.= ''; $out.= ''; @@ -5119,150 +5707,203 @@ sub card my $y=$i*10; $out.=sprintf('',$y,$chart_dim,$y); } - - my $timebeginn=$time-$hours*3600; - - my $scale; - my $scale_strokes; - my $description=4; - my $strokes=12; - - my $div = $hours > 168 ? ($hours % 168 == 0 ? 168 : ($hours % 24 == 0 ? 24 : 1)):1; - - if ($div==168 and $hours/$div/2 == 1) { #2w - $description=7; - $strokes=$description; - } elsif ($hours <= 168*7) { - for (my $i=7;$i>=3;$i--) { - if ($hours/$div % $i == 0) { - $description=$i; - if ($div == 168 and $chart_dim > 130) { - $strokes=$description*7; - } else { - $strokes=$description; - } - last; - } - } - } - $scale=$hours/$description; - $scale_strokes=$hours/$strokes; - if ($hours > 2) { - my ($sec,$minutes,$hour,$mday,$month,$year,$wday,$yday,$isdst) = localtime($timebeginn); - my $beginhour=int($hour/$scale)*$scale; - my $diffsec=($hour-$beginhour)*3600+$minutes*60+$sec; - my $pos=(1-$diffsec/($scale*3600))*$chart_dim/$description-$x_prop; - my $pos_strokes=(1-$diffsec/($scale_strokes*3600))*$chart_dim/$strokes-$x_prop; - - for (my $i=0;$i<=$strokes;$i++) { - my $x=int((($i)*($chart_dim/$strokes)+$pos_strokes)*10)/10; - $out.=sprintf('',$x,0,$x,50) if ($x >= 0 and $x <= $chart_dim); - } - for (my $i=0;$i<$description;$i++) { - my $h=$beginhour+($i+1)*$scale; - $hour=($h >= 24 ? $h % 24:$h); - my $x=int((($i*($chart_dim/$description)+$pos))*10)/10; - if ($hours <= 2) { - # $out.=sprintf('%s',$x,::strftime("%H:%M",localtime($time-$hours*3600*(1-$i/3)))); - } elsif ($hours <= 168) { - if ($hour != 0) { - $out.=sprintf('%02d:',$x,$hour); - } else { - $out.=sprintf('%s',$x,substr(::strftime("%a",localtime($timebeginn+$h*3600)),0,2)); - } - } elsif ($hours <= 168*7) { - $out.=sprintf('%s',$x,::strftime("%d.",localtime($timebeginn+$h*3600))); - } else { - $out.=sprintf('%s',$x,::strftime("%d.%m",localtime($timebeginn+$h*3600))); - } - } - } else { - for (my $i=0;$i<=12;$i++) { - my $x=int((($i)*($chart_dim/12)+1)*10)/10; - $out.=sprintf('',$x,0,$x,50) if ($x >= 0 and $x <= $chart_dim); - for (my $i=0;$i<=3;$i++) { - my $x=int(($i*($chart_dim/3)-1)*10)/10; - $out.=sprintf('%s',$x+2,::strftime("%H:%M",localtime($time-$hours*3600*(1-$i/3)))); - } - } - } + my ($outplot,$outfooter); my @outfooter; - - my $minVal; - my $maxVal; - for (my $i=0;$i< @value1;$i++) { - if (defined ($value1[$i]{dim})) { - my $min=defined $value1[$i]{min_value} ? $value1[$i]{min_value} : $value1[$i]{value}; - my $max=defined $value1[$i]{max_value} ? $value1[$i]{max_value} : $value1[$i]{value}; - $minVal=$min if (!defined $minVal or $min < $minVal); - $maxVal=$max if (!defined $maxVal or $max > $maxVal); + + if ($type eq "bar") { + my @desc; + my $x; + my $dimplot=$dim; + if ($period eq "decade") { + @desc= qw(0 1 2 3 4 5 6 7 8 9); + } elsif ($period eq "year") { + @desc= qw(Jan Feb Mär Apr Mai Jun Jul Aug Sep Okt Nov Dez); + } elsif ($period eq "month") { + @desc=qw(01 03 05 07 09 11 13 15 17 19 21 23 25 27 29 31); + $dimplot=32; + } elsif ($period eq "week") { + @desc=qw(Mo Di Mi Do Fr Sa So); + } elsif ($period eq "day") { + $dimplot=26; + @desc=qw(00 02 04 06 08 10 12 14 16 18 20 22 24); } - } - my $j=0; - for (my $i=0;$i<@value1;$i++) { - if (defined ($value1[$i]{dim})) { - ($outplot,$outfooter) = plot ($value1[$i],[$min,$minVal],[$max,$maxVal],$minColor,$maxColor,$dec,$func,$steps,$x_prop,$chart_dim, $j == 0 ? $noColor:-1,$lmm,$ln,$lr,$plot,$bwidth,$noFooter eq "1" ? 0:84+$j*10,undef,-2.5,"end",(split(",",$unit1[$i]))[1],(split(",",$unit1[$i]))[0]); - $j++; - $out.=$outplot; - push (@outfooter,$outfooter); + + my $xOffset=0.5*$chart_dim/@desc; + $x=int(($xOffset+$period1*$chart_dim/$dimplot)*10)/10; + $out.= sprintf('%s',$begin_period2); + $out.= sprintf('',$x,53); + + for (my $i=0;$i<@desc;$i++) { + $x=int(($i+0.5)*$chart_dim/@desc*10)/10; + $out.=sprintf('',$x,0,$x,50); + $out.=sprintf('%s',$x,$desc[$i]); } - } - if (defined $col2) { - my $minVal2; - my $maxVal2; - for (my $i=0;$i< @value2;$i++) { - if (defined ($value2[$i]{dim})) { - my $min=defined $value2[$i]{min_value} ? $value2[$i]{min_value} : $value2[$i]{value}; - my $max=defined $value2[$i]{max_value} ? $value2[$i]{max_value} : $value2[$i]{value}; - $minVal2=$min if (!defined $minVal2 or $min < $minVal2); - $maxVal2=$max if (!defined $maxVal2 or $max > $maxVal2); + + my $minVal; + my $maxVal; + for (my $i=0;$i< @value1;$i++) { + if (defined ($value1[$i]{dim})) { + my $min=defined $value1[$i]{min_value} ? $value1[$i]{min_value} : $value1[$i]{value}; + my $max=defined $value1[$i]{max_value} ? $value1[$i]{max_value} : $value1[$i]{value}; + $minVal=$min if (!defined $minVal or $min < $minVal); + $maxVal=$max if (!defined $maxVal or $max > $maxVal); } } - my $offset=@outfooter*10; + my $j=0; - for (my $i=0;$i<@value2;$i++) { - if (defined ($value2[$i]{dim})) { - ($outplot,$outfooter) = plot ($value2[$i],[$min2,$minVal2],[$max2,$maxVal2],$minColor2,$maxColor2,$dec2,$func2,$steps,$x_prop,$chart_dim, $j == 0 ? $noColor:-1,$lmm,$ln,$lr,$plot,$bwidth,$noFooter eq "1" ? 0:84+$offset+$j*10,undef,$chart_dim+3,"start",(split(",",$unit2[$i]))[1],(split(",",$unit2[$i]))[0]); + for (my $i=0;$i<@value1;$i++) { + if (defined ($value1[$i]{dim})) { + ($outplot,$outfooter) = plot ($value1[$i],[$min,$minVal],[$max,$maxVal],$minColor,$maxColor,$dec,$func,$steps,$x_prop,$chart_dim, $noColor,$lmm,$ln,$lr,$plot,$bwidth,$noFooter eq "1" ? 0:84+$j*10,undef,-2.5,"end",(split(",",$unit1[$i]))[1],(split(",",$unit1[$i]))[0]); $j++; $out.=$outplot; push (@outfooter,$outfooter); } } - } - $out.= ''; - $out.= ''; - - if ($hring eq "") { - $out.=sprintf('',$bwidth-49); - if (@value1 >= 2 ) { - my $unit_1=(split(",",$unit1[0]))[0]; - my $unit_2=(split(",",$unit1[1]))[0]; - my $unitColor=(split(",",$unit1[0]))[1]; - my $unitColor2=(split(",",$unit1[1]))[1]; - $decfont="" if (!defined $decfont); - $out.= ui_Table::ring2($value1[0]{value},$min,$max,$minColor,$maxColor,$unit_1,92,$func,defined $unitColor ? $decfont.",,fill:".$unitColor:$decfont, - $value1[1]{value},$min,$max,$minColor,$maxColor,$unit_2,$func,defined $unitColor2 ? $decfont.",,fill:".$unitColor2:$decfont,$lightness,(defined $head or !defined $icon) ? undef: $icon,$model); - } elsif (@value1 == 1 and @value2 >= 1) { - my $unit_1=(split(",",$unit1[0]))[0]; - my $unit_2=(split(",",$unit2[0]))[0]; - $out.= ui_Table::ring2($value1[0]{value},$min,$max,$minColor,$maxColor,$unit_1,92,$func,$decfont,$value2[0]{value},$min2,$max2,$minColor2,$maxColor2,$unit_2,$func2,$decfont2,$lightness,((defined $head or !defined $icon) ? undef: $icon),$model); - } else { - my $unit_1=(split(",",$unit1[0]))[0]; - $out.= ui_Table::ring($value1[0]{value},$min,$max,$minColor,$maxColor,$unit_1,92,$func,$decfont,$model,$lightness,(defined $head or !defined $icon) ? undef: $icon); + $out.= ''; + $out.= ''; + } else { ## col + my $timebeginn=$time-$hours*3600; + + my $scale; + my $scale_strokes; + my $description=4; + my $strokes=12; + + my $div = $hours > 168 ? ($hours % 168 == 0 ? 168 : ($hours % 24 == 0 ? 24 : 1)):1; + + if ($div==168 and $hours/$div/2 == 1) { #2w + $description=7; + $strokes=$description; + } elsif ($hours <= 168*7) { + for (my $i=7;$i>=3;$i--) { + if ($hours/$div % $i == 0) { + $description=$i; + if ($div == 168 and $chart_dim > 130) { + $strokes=$description*7; + } else { + $strokes=$description; + } + last; + } + } } - $out.=''; - $out.=sprintf('%s',$bwidth-21,::strftime("%H:%M:%S",localtime($time))); - } - + $scale=$hours/$description; + $scale_strokes=$hours/$strokes; + if ($hours > 2) { + my ($sec,$minutes,$hour,$mday,$month,$year,$wday,$yday,$isdst) = localtime($timebeginn); + my $beginhour=int($hour/$scale)*$scale; + my $diffsec=($hour-$beginhour)*3600+$minutes*60+$sec; + my $pos=(1-$diffsec/($scale*3600))*$chart_dim/$description-$x_prop; + my $pos_strokes=(1-$diffsec/($scale_strokes*3600))*$chart_dim/$strokes-$x_prop; + + for (my $i=0;$i<=$strokes;$i++) { + my $x=int((($i)*($chart_dim/$strokes)+$pos_strokes)*10)/10; + $out.=sprintf('',$x,0,$x,50) if ($x >= 0 and $x <= $chart_dim); + } + for (my $i=0;$i<$description;$i++) { + my $h=$beginhour+($i+1)*$scale; + $hour=($h >= 24 ? $h % 24:$h); + my $x=int((($i*($chart_dim/$description)+$pos))*10)/10; + if ($hours <= 2) { + # $out.=sprintf('%s',$x,::strftime("%H:%M",localtime($time-$hours*3600*(1-$i/3)))); + } elsif ($hours <= 168) { + if ($hour != 0) { + $out.=sprintf('%02d:',$x,$hour); + } else { + $out.=sprintf('%s',$x,substr(::strftime("%a",localtime($timebeginn+$h*3600)),0,2)); + } + } elsif ($hours <= 168*7) { + $out.=sprintf('%s',$x,::strftime("%d.",localtime($timebeginn+$h*3600))); + } else { + $out.=sprintf('%s',$x,::strftime("%d.%m",localtime($timebeginn+$h*3600))); + } + } + } else { + for (my $i=0;$i<=12;$i++) { + my $x=int((($i)*($chart_dim/12)+1)*10)/10; + $out.=sprintf('',$x,0,$x,50) if ($x >= 0 and $x <= $chart_dim); + for (my $i=0;$i<=3;$i++) { + my $x=int(($i*($chart_dim/3)-1)*10)/10; + $out.=sprintf('%s',$x+2,::strftime("%H:%M",localtime($time-$hours*3600*(1-$i/3)))); + } + } + } + + my $minVal; + my $maxVal; + for (my $i=0;$i< @value1;$i++) { + if (defined ($value1[$i]{dim})) { + my $min=defined $value1[$i]{min_value} ? $value1[$i]{min_value} : $value1[$i]{value}; + my $max=defined $value1[$i]{max_value} ? $value1[$i]{max_value} : $value1[$i]{value}; + $minVal=$min if (!defined $minVal or $min < $minVal); + $maxVal=$max if (!defined $maxVal or $max > $maxVal); + } + } + my $j=0; + for (my $i=0;$i<@value1;$i++) { + if (defined ($value1[$i]{dim})) { + ($outplot,$outfooter) = plot ($value1[$i],[$min,$minVal],[$max,$maxVal],$minColor,$maxColor,$dec,$func,$steps,$x_prop,$chart_dim, $j == 0 ? $noColor:-1,$lmm,$ln,$lr,$plot,$bwidth,$noFooter eq "1" ? 0:84+$j*10,undef,-2.5,"end",(split(",",$unit1[$i]))[1],(split(",",$unit1[$i]))[0]); + $j++; + $out.=$outplot; + push (@outfooter,$outfooter); + } + } + if (defined $col2) { + my $minVal2; + my $maxVal2; + for (my $i=0;$i< @value2;$i++) { + if (defined ($value2[$i]{dim})) { + my $min=defined $value2[$i]{min_value} ? $value2[$i]{min_value} : $value2[$i]{value}; + my $max=defined $value2[$i]{max_value} ? $value2[$i]{max_value} : $value2[$i]{value}; + $minVal2=$min if (!defined $minVal2 or $min < $minVal2); + $maxVal2=$max if (!defined $maxVal2 or $max > $maxVal2); + } + } + my $offset=@outfooter*10; + my $j=0; + for (my $i=0;$i<@value2;$i++) { + if (defined ($value2[$i]{dim})) { + ($outplot,$outfooter) = plot ($value2[$i],[$min2,$minVal2],[$max2,$maxVal2],$minColor2,$maxColor2,$dec2,$func2,$steps,$x_prop,$chart_dim, $j == 0 ? $noColor:-1,$lmm,$ln,$lr,$plot,$bwidth,$noFooter eq "1" ? 0:84+$offset+$j*10,undef,$chart_dim+3,"start",(split(",",$unit2[$i]))[1],(split(",",$unit2[$i]))[0]); + $j++; + $out.=$outplot; + push (@outfooter,$outfooter); + } + } + } + $out.= ''; + $out.= ''; + + if ($hring eq "") { + $out.=sprintf('',$bwidth-49); + if (@value1 >= 2 ) { + my $unit_1=(split(",",$unit1[0]))[0]; + my $unit_2=(split(",",$unit1[1]))[0]; + my $unitColor=(split(",",$unit1[0]))[1]; + my $unitColor2=(split(",",$unit1[1]))[1]; + $decfont="" if (!defined $decfont); + $out.= ui_Table::ring2($value1[0]{value},$min,$max,$minColor,$maxColor,$unit_1,92,$func,defined $unitColor ? $decfont.",,fill:".$unitColor:$decfont, + $value1[1]{value},$min,$max,$minColor,$maxColor,$unit_2,$func,defined $unitColor2 ? $decfont.",,fill:".$unitColor2:$decfont,$lightness,(defined $head or !defined $icon) ? undef: $icon,$model); + } elsif (@value1 == 1 and @value2 >= 1) { + my $unit_1=(split(",",$unit1[0]))[0]; + my $unit_2=(split(",",$unit2[0]))[0]; + $out.= ui_Table::ring2($value1[0]{value},$min,$max,$minColor,$maxColor,$unit_1,92,$func,$decfont,$value2[0]{value},$min2,$max2,$minColor2,$maxColor2,$unit_2,$func2,$decfont2,$lightness,((defined $head or !defined $icon) ? undef: $icon),$model); + } else { + my $unit_1=(split(",",$unit1[0]))[0]; + $out.= ui_Table::ring($value1[0]{value},$min,$max,$minColor,$maxColor,$unit_1,92,$func,$decfont,$model,$lightness,(defined $head or !defined $icon) ? undef: $icon); + } + $out.=''; + $out.=sprintf('%s',$bwidth-21,::strftime("%H:%M:%S",localtime($time))); + } + } # col if ($noFooter ne "1") { for (my $i=0;$i < @outfooter;$i++) { $out.=$outfooter[$i]; } } - $out.=''; + $out.=''; $out.= ''; -return ($out); + return ($out); } sub bar @@ -6067,13 +6708,6 @@ sub ring2 } my $out; - -## my ($lr,$lir,$lmm,$lu,$ln,$li); -## ($lr,$lu,$ln,$li)=split (/,/,$lightness) if (defined $lightness); -## $lr=50 if (!defined $lr or $lr eq ""); -## $lu=40 if (!defined $lu or $lu eq ""); -## $ln=50 if (!defined $ln or $ln eq ""); -## $li=40 if (!defined $li or $li eq ""); my ($lr,$lir,$lmm,$lu,$ln,$li); ($lr,$lir,$lmm,$lu,$ln,$li)=split (/,/,$lightness) if (defined $lightness);