diff --git a/fhem/FHEM/95_YAAHM.pm b/fhem/FHEM/95_YAAHM.pm index 12a6fde60..e52204a1e 100644 --- a/fhem/FHEM/95_YAAHM.pm +++ b/fhem/FHEM/95_YAAHM.pm @@ -6,6 +6,8 @@ # # Prof. Dr. Peter A. Henning # +# TODO: Löschen readings, wenn timer gelöscht +# # $Id$ # ######################################################################################## @@ -48,7 +50,7 @@ my $yaahmname; my $yaahmlinkname = "Profile"; # link text my $yaahmhiddenroom = "ProfileRoom"; # hidden room my $yaahmpublicroom = "Unsorted"; # public room -my $yaahmversion = "1.17"; +my $yaahmversion = "1.21"; my $firstcall = 1; my %yaahm_transtable_EN = ( @@ -83,6 +85,9 @@ my %yaahm_transtable_EN = ( "description" => "Description", "profile" => "Profile", "profiles" => "Profiles", + "transition" => "Transition to", + "onlposfrm" => "only possible from", + "notposfrm" => "not possible from", #-- "aftermidnight" => "After Midnight", "beforesunrise" => "Before Sunrise", @@ -121,7 +126,7 @@ my %yaahm_transtable_EN = ( "locked" => "Locked", "unsecured" => "Not Secured", "secured" => "Secured", - "protected" => "Geschützt", + "protected" => "Protected", "guarded" => "Guarded", #-- "monday" => ["Monday","Mon"], @@ -170,6 +175,9 @@ my %yaahm_transtable_EN = ( "description" => "Beschreibung", "profile" => "Profil", "profiles" => "Profile", + "transition" => "Übergang zu", + "onlposfrm" => "nur möglich aus", + "notposfrm" => "nicht möglich aus", #-- "aftermidnight" => "Nach Mitternacht", "beforesunrise" => "Vor Sonnenaufgang", @@ -316,9 +324,19 @@ my @seasons = ( "winter","spring","summer","fall"); #-- modes or day types that affect the profile -my @profmode = ("party","absence"); +my @profmode = ("party","absence","donotdisturb"); my @profday = ("vacation","holiday"); +#-- color schemes +my $csnum=2; +my @csmode; +my @csmode1 = ("#53f3c7","#8bfa56","#ff9458","#fd5777"); +my @csmode2 = ("#35ffc7","#77ff35","#ff7e35","#ff355e"); + +my @csstate; +my @csstate1 = ("#53f3c7","#ff9458","#f554e2","#fd5777"); +my @csstate2 = ("#35ffc7","#ff7e35","#ff35e2","#ff355e"); + #-- temporary fix for update purpose sub YAAHM_restore($$){}; sub YAAHM_sayWeeklyTime($$$){}; @@ -340,7 +358,7 @@ sub YAAHM_Initialize ($) { $hash->{UndefFn} = "YAAHM_Undef"; $hash->{AttrFn} = "YAAHM_Attr"; my $attst = "linkname publicroom hiddenroom lockstate:locked,unlocked simulation:0,1 ". - "timeHelper modeHelper modeAuto:0,1 stateDevices:textField-long stateInterval stateWarning stateHelper stateAuto:0,1 ". + "timeHelper modeHelper modeAuto:0,1 stateDevices:textField-long stateInterval noicons:0,1 colorscheme:1,2 stateWarning stateHelper stateAuto:0,1 ". "holidayDevices:textField-long vacationDevices:textField-long specialDevices:textField-long"; $hash->{AttrList} = $attst; @@ -355,12 +373,15 @@ sub YAAHM_Initialize ($) { } } $yaahmlinkname = $yaahm_tt->{"profiles"}; + #-- default colors + @csmode = @csmode1; + @csstate = @csstate1; $data{FWEXT}{YAAHMx}{LINK} = "?room=".$yaahmhiddenroom; $data{FWEXT}{YAAHMx}{NAME} = $yaahmlinkname; $data{FWEXT}{"/YAAHM_timewidget"}{FUNC} = "YAAHM_timewidget"; - $data{FWEXT}{"/YAAHM_timewidget"}{FORKABLE} = 0; + $data{FWEXT}{"/YAAHM_timewidget"}{FORKABLE} = 0; return undef; } @@ -389,7 +410,10 @@ sub YAAHM_Define ($$) { }else{ $yaahm_tt = \%yaahm_transtable_EN; } - #$hash->{DATA}{"TT"}=$yaahm_tt; + + #-- default colors + @csmode = @csmode1; + @csstate = @csstate1; # NOTIFYDEV my $NOTIFYDEV = "global,$name"; @@ -556,6 +580,17 @@ sub YAAHM_Attr($$$) { } } #--------------------------------------- + }elsif ( ($cmd eq "set") && ($attrName eq "colorscheme") ) { + Log 1,"==================> colorscheme"; + if( $attrVal == 2 ){ + @csmode = @csmode2; + @csstate = @csstate2; + }else{ + @csmode = @csmode2; + @csstate = @csstate2; + } + + #--------------------------------------- }elsif ( ($cmd eq "delete") && ($attrName eq "stateDevices") ) { fhem("deletereading $name sdev_housestate"); fhem("deletereading $name sec_housestate"); @@ -658,7 +693,7 @@ sub YAAHM_Set($@) { if( $args[0] =~ /^\d+/ ) { #-- check if valid if( $args[0] >= int(@{$hash->{DATA}{"WT"}}) ){ - $msg = "Error, timer number ".$args[0]." does not exist, number musst be smaller than ".int( @{$hash->{DATA}{"WT"}}); + $msg = "Error, timer number ".$args[0]." does not exist, number must be smaller than ".int( @{$hash->{DATA}{"WT"}}); Log3 $name,1,"[YAAHM_Set] ".$msg; return $msg; } @@ -1210,6 +1245,7 @@ sub YAAHM_mode { my $prevmode = defined($hash->{DATA}{"HSM"}{"mode"}) ? $hash->{DATA}{"HSM"}{"mode"} : "normal"; my $currstate = defined($hash->{DATA}{"HSM"}{"state"}) ? $hash->{DATA}{"HSM"}{"state"} : "unsecured"; my $msg = ""; + my $tr_msg = ""; #-- local checks #-- double change @@ -1218,23 +1254,32 @@ sub YAAHM_mode { #-- transition into party and absence is only possible from normal mode }elsif( $prevmode ne "normal" && $targetmode ne "normal"){ - $msg = "transition into $targetmode mode is only possible from normal mode"; - + $msg = "Transition into $targetmode mode is only possible from normal mode"; + $tr_msg = $yaahm_tt->{transition}.' "'.$yaahm_tt->{$targetmode}.'" '.$yaahm_tt->{"onlposfrm"}.' '.$yaahm_tt->{"mode"}.'="'.$yaahm_tt->{"normal"}.'"'; #-- global checks #-- transition into party mode only possible in unlocked state }elsif( $targetmode eq "party" && $currstate ne "unsecured" ){ - $msg = "transition into party mode is only possible in unsecured state" + $msg = "Transition into party mode is only possible from unsecured state"; + $tr_msg = $yaahm_tt->{transition}.' "'.$yaahm_tt->{$targetmode}.'" '.$yaahm_tt->{"onlposfrm"}.' '.$yaahm_tt->{"state"}.'="'.$yaahm_tt->{"unsecured"}.'"'; } #-- don't if( $msg ne "" ){ Log3 $name,1,"[YAAHM_mode] ".$msg; + readingsSingleUpdate($hash,"tr_errmsg",$tr_msg,1); return $msg; } $hash->{DATA}{"HSM"}{"mode"} = $targetmode; + readingsBeginUpdate($hash); + readingsBulkUpdate($hash,"tr_errmsg",""); + readingsBulkUpdate($hash,"prev_housemode",$prevmode); + readingsBulkUpdate($hash,"housemode",$targetmode); + readingsBulkUpdate($hash,"tr_housemode",$yaahm_tt->{$targetmode}); + readingsEndUpdate($hash,1); + #-- doit, if not simulation if (defined($attr{$name}{"modeHelper"})){ if( !defined($exec) || $exec==1 ){ @@ -1246,12 +1291,6 @@ sub YAAHM_mode { } } - readingsBeginUpdate($hash); - readingsBulkUpdate($hash,"prev_housemode",$prevmode); - readingsBulkUpdate($hash,"housemode",$targetmode); - readingsBulkUpdate($hash,"tr_housemode",$yaahm_tt->{$targetmode}); - readingsEndUpdate($hash,1); - } ######################################################################################### @@ -1269,6 +1308,7 @@ sub YAAHM_state { my $prevstate = defined($hash->{DATA}{"HSM"}{"state"}) ? $hash->{DATA}{"HSM"}{"state"} : "unsecured"; my $currmode = defined($hash->{DATA}{"HSM"}{"mode"}) ? $hash->{DATA}{"HSM"}{"mode"} : "normal"; my $msg = ""; + my $tr_msg = ""; #-- local checks #-- double change @@ -1278,15 +1318,25 @@ sub YAAHM_state { #-- global checks #-- changing away from unlocked in party mode is not possible if( $targetstate ne "unlocked" && $currmode eq "party" ){ - $msg = "not possible in party mode"; + $msg = "Not possible in party mode"; + $tr_msg = $yaahm_tt->{transition}.' "'.$yaahm_tt->{$targetstate}.'" '.$yaahm_tt->{"notposfrm"}.' '.$yaahm_tt->{"mode"}.'="'.$yaahm_tt->{"party"}.'"'; } #-- don't if( $msg ne "" ){ Log3 $name,1,"[YAAHM_state] ".$msg; + readingsSingleUpdate($hash,"tr_errmsg",$tr_msg,1); return $msg; } + $hash->{DATA}{"HSM"}{"state"} = $targetstate; + readingsBeginUpdate($hash); + readingsBulkUpdate($hash,"tr_errmsg",""); + readingsBulkUpdate($hash,"prev_housestate",$prevstate); + readingsBulkUpdate($hash,"housestate",$targetstate); + readingsBulkUpdate($hash,"tr_housestate",$yaahm_tt->{$targetstate}); + readingsEndUpdate($hash,1); + #-- doit, if not simulation if (defined($attr{$name}{"stateHelper"})){ if( !defined($exec) || $exec==1 ){ @@ -1298,15 +1348,7 @@ sub YAAHM_state { } } - $hash->{DATA}{"HSM"}{"state"} = $targetstate; - readingsBeginUpdate($hash); - readingsBulkUpdate($hash,"prev_housestate",$prevstate); - readingsBulkUpdate($hash,"housestate",$targetstate); - readingsBulkUpdate($hash,"tr_housestate",$yaahm_tt->{$targetstate}); - readingsEndUpdate($hash,1); - YAAHM_InternalTimer("check",time()+ 30, "YAAHM_checkstate", $hash, 0); - } ######################################################################################### @@ -1332,7 +1374,7 @@ sub YAAHM_checkstate($) { my $next; - $next = gettimeofday()+AttrVal($name,"stateInterval",60)*60; + $next = gettimeofday()+AttrVal($name,"stateInterval",1)*60; YAAHM_RemoveInternalTimer("check",$hash); YAAHM_InternalTimer("check",$next, "YAAHM_checkstate", $hash, 0); @@ -1796,21 +1838,21 @@ sub YAAHM_sayWeeklyTime($$$) { if( ($ton =~ /(\d?\d):(\d\d)(:(\d\d))?/) && ($tom ne $ton) ){ $hw = $1*1; $mw = $2*1; - $pt = sprintf("%d:%02d",$hw,$mw)." ".tolower($yaahm_tt->{"today"}); + $pt = sprintf("%d:%02d",$hw,$mw)." ".lc($yaahm_tt->{"today"}); - $msg .= " ".tolower($yaahm_tt->{"tomorrow"})." ".$yaahm_tt->{"exceptly"}." $hw ".$yaahm_tt->{"clock"}; + $msg .= " ".lc($yaahm_tt->{"tomorrow"})." ".$yaahm_tt->{"exceptly"}." $hw ".$yaahm_tt->{"clock"}; $msg .=" $mw" if( $mw != 0 ); }elsif( $tom =~ /(\d?\d):(\d\d)(:(\d\d))?/ && $tom !~ /.*\(off\)$/ ){ $hw = $1*1; $mw = $2*1; - $pt = sprintf("%d:%02d",$hw,$mw)." ".tolower($yaahm_tt->{"tomorrow"}); - $msg .= " ".tolower($yaahm_tt->{"tomorrow"})." $hw ".$yaahm_tt->{"clock"}; + $pt = sprintf("%d:%02d",$hw,$mw)." ".lc($yaahm_tt->{"tomorrow"}); + $msg .= " ".lc($yaahm_tt->{"tomorrow"})." $hw ".$yaahm_tt->{"clock"}; $msg .=" $mw" if( $mw != 0 ); }elsif( $tom eq "off" || $tom =~ /.*\(off\)$/ ){ - $pt = "off ".tolower($yaahm_tt->{"today"})." ".$yaahm_tt->{"and"}." ".tolower($yaahm_tt->{"tomorrow"}); - $msg .= " ".tolower($yaahm_tt->{"today"})." ".$yaahm_tt->{"and"}." ".tolower($yaahm_tt->{"tomorrow"})." ".$yaahm_tt->{"swoff"}; + $pt = "off ".lc($yaahm_tt->{"today"})." ".$yaahm_tt->{"and"}." ".lc($yaahm_tt->{"tomorrow"}); + $msg .= " ".lc($yaahm_tt->{"today"})." ".$yaahm_tt->{"and"}." ".lc($yaahm_tt->{"tomorrow"})." ".$yaahm_tt->{"swoff"}; }else{ $pt = $yaahm_tt->{"undecid"}; $msg .= " ".$yaahm_tt->{"undecid"}; @@ -1824,14 +1866,14 @@ sub YAAHM_sayWeeklyTime($$$) { if( $tt >= $tl ){ $hw = $1*1; $mw = $2*1; - $pt = sprintf("%d:%02d",$hw,$mw)." ".tolower($yaahm_tt->{"today"}); - $msg .= " ".tolower($yaahm_tt->{"today"})." $hw ".$yaahm_tt->{"clock"}; + $pt = sprintf("%d:%02d",$hw,$mw)." ".lc($yaahm_tt->{"today"}); + $msg .= " ".lc($yaahm_tt->{"today"})." $hw ".$yaahm_tt->{"clock"}; $msg .=" $mw" if( $mw != 0 ); #-- todays time already past => tomorrow - but this may be off }elsif( ($tom eq "off") || ($tom =~ /.*\(off\)/) ){ - $pt = "off ".tolower($yaahm_tt->{"tomorrow"}); - $msg .= " ".tolower($yaahm_tt->{"tomorrow"})." ".$yaahm_tt->{"swoff"}; + $pt = "off ".lc($yaahm_tt->{"tomorrow"}); + $msg .= " ".lc($yaahm_tt->{"tomorrow"})." ".$yaahm_tt->{"swoff"}; }elsif( $tom =~ /(\d?\d):(\d\d)(:(\d\d))?( \((\d?\d):(\d\d)(:(\d\d))?\))?/ ){ #Log 1,"===========> |$1|$2|$3|$4|$5|$6"; if( defined($5) && $5 ne ""){ @@ -1841,8 +1883,8 @@ sub YAAHM_sayWeeklyTime($$$) { $hw = $1*1; $mw = $2*1; } - $pt = sprintf("%d:%02d",$hw,$mw)." ".tolower($yaahm_tt->{"tomorrow"}); - $msg .= " ".tolower($yaahm_tt->{"tomorrow"})." $hw ".$yaahm_tt->{"clock"}; + $pt = sprintf("%d:%02d",$hw,$mw)." ".lc($yaahm_tt->{"tomorrow"}); + $msg .= " ".lc($yaahm_tt->{"tomorrow"})." $hw ".$yaahm_tt->{"clock"}; $msg .=" $mw" if( $mw != 0 ); }else{ @@ -1877,7 +1919,7 @@ sub YAAHM_checkMonthly($$$) { my ($ret,$line,$fline,$date); my (@lines,@chunks,@tday,@eday,@sday,@tmor,@two); - my ($stoday,$stom,$stwom); + my ($stoday,$stom,$stwom,$tod); my $todaylong = ""; my $tomlong = ""; my $twodaylong= ""; @@ -1899,57 +1941,68 @@ sub YAAHM_checkMonthly($$$) { my ($todaydesc,$tomdesc,$twomdesc); #-- device of type holiday if( IsDevice( $specialDev, "holiday" )){ - $stoday = strftime('%2m-%2d', localtime(time)); - $stom = strftime('%2m-%2d', localtime(time+86400)); - $stwom = strftime('%2m-%2d', localtime(time+2*86400)); - my $tod = holiday_refresh( $specialDev, $stoday ); + $stoday = strftime('%m-%d', localtime(time)); + $stom = strftime('%m-%d', localtime(time+86400)); + $stwom = strftime('%m-%d', localtime(time+2*86400)); + $tod = holiday_refresh( $specialDev, $stoday ); if ( $tod ne "none" ) { - $todaydesc = $tod; - Log3 $name, 5,"[YAAHM] found today=special date \"$todaydesc\" in holiday $specialDev"; + $todaydesc .= $tod.","; + Log3 $name, 5,"[YAAHM] found today=special date \"$tod\" in holiday $specialDev"; } $tod = holiday_refresh( $specialDev, $stom ); if ( $tod ne "none" ) { - $tomdesc = $tod; - Log3 $name, 5,"[YAAHM] found tomorrow=special date \"$tomdesc\" in holiday $specialDev"; + $tomdesc .= $tod.","; + Log3 $name, 5,"[YAAHM] found tomorrow=special date \"$tod\" in holiday $specialDev"; } $tod = holiday_refresh( $specialDev, $stwom ); if ( $tod ne "none" ) { - $twomdesc = $tod; - Log3 $name, 5,"[YAAHM] found twodays=special date \"$twomdesc\" in holiday $specialDev"; + $twomdesc .= $tod.","; + Log3 $name, 5,"[YAAHM] found twodays=special date \"$tod\" in holiday $specialDev"; } #-- device of type calendar }elsif( IsDevice($specialDev, "Calendar" )){ - $stoday = strftime('%2d.%2m.%2Y', localtime(time)); - $stom = strftime('%2d.%2m.%2Y', localtime(time+86400)); - $stwom = strftime('%2d.%2m.%2Y', localtime(time+2*86400)); + $stoday = strftime('%d.%m.%Y', localtime(time)); + $stom = strftime('%d.%m.%Y', localtime(time+86400)); + $stwom = strftime('%d.%m.%Y', localtime(time+2*86400)); @tday = split('\.',$stoday); @tmor = split('\.',$stom); @two = split('\.',$stwom); - #-- more complicated to check here - $fline=Calendar_Get($defs{$specialDev},"get","full","mode=alarm|start|upcoming"); + $fline=Calendar_Get($defs{$specialDev},"get","full","mode=alarm|start|upcoming"); + #-- more complicated to check here, + # format is ' upcoming [ ] - [] + my ($cstart,$cdesc); + if($fline){ #chomp($fline); @lines = split('\n',$fline); foreach $fline (@lines){ chomp($fline); @chunks = split(' ',$fline); - @sday = split('\.',$chunks[4]); + if( int(@chunks)>=7 ){ + $cstart = 4; + $cdesc = 7; + }else{ + $cstart = 2; + $cdesc = 5, + } + @sday = split('\.',$chunks[$cstart]); + $tod = ($chunks[$cdesc]) ? $chunks[$cdesc] : "???"; #-- today my $rets = ($sday[2]-$tday[2])*365+($sday[1]-$tday[1])*31+($sday[0]-$tday[0]); if( $rets==0 ){ - $todaydesc = $chunks[7]; - Log3 $name, 5,"[YAAHM] found today=special date \"$todaydesc\" in calendar $specialDev"; + $todaydesc .= $tod.","; + Log3 $name, 5,"[YAAHM] found today=special date \"$tod\" in calendar $specialDev"; } $rets = ($sday[2]-$tmor[2])*365+($sday[1]-$tmor[1])*31+($sday[0]-$tmor[0]); if( $rets==0 ){ - $tomdesc = $chunks[7]; - Log3 $name, 5,"[YAAHM] found tomorrow=special date \"$tomdesc\" in calendar $specialDev"; + $tomdesc .= $tod.","; + Log3 $name, 5,"[YAAHM] found tomorrow=special date \"$tod\" in calendar $specialDev"; } $rets = ($sday[2]-$two[2])*365+($sday[1]-$two[1])*31+($sday[0]-$two[0]); if( $rets==0 ){ - $twomdesc = $chunks[7]; - Log3 $name, 5,"[YAAHM] found twodays=special date \"$twomdesc\" in calendar $specialDev"; + $twomdesc .= $tod.","; + Log3 $name, 5,"[YAAHM] found twodays=special date \"$tod\" in calendar $specialDev"; } } } @@ -1958,17 +2011,16 @@ sub YAAHM_checkMonthly($$$) { } #-- accumulate descriptions - $todaylong .= $todaydesc.',' - if($todaydesc); - $todaylong =~ s/,$//; - $tomlong .= $tomdesc.',' - if($tomdesc); - $tomlong =~ s/,$//; - $twodaylong .= $twomdesc.',' + $todaylong .= $todaydesc + if($todaydesc); + $tomlong .= $tomdesc + if($tomdesc); + $twodaylong .= $twomdesc if($twomdesc); - $twodaylong =~ s/,$//; - } + $todaylong =~ s/,$//; + $tomlong =~ s/,$//; + $twodaylong =~ s/,$//; $hash->{DATA}{"DD"}[0]{"special"} = $todaylong; $hash->{DATA}{"DD"}[1]{"special"} = $tomlong; #-- put into readings @@ -2160,8 +2212,8 @@ sub YAAHM_GetDayStatus($) { my (@lines,@chunks,@tday,@eday,@sday,@tmor); my ($todaydesc,$todaytype,$tomdesc,$tomtype); - my $stoday = strftime('%2d.%2m.%2Y', localtime(time)); - my $stom = strftime('%2d.%2m.%2Y', localtime(time+86400)); + my $stoday = strftime('%d.%m.%Y', localtime(time)); + my $stom = strftime('%d.%m.%Y', localtime(time+86400)); #-- workday has lowest priority $todaytype = "workday"; @@ -2181,8 +2233,8 @@ sub YAAHM_GetDayStatus($) { foreach my $vacdayDev ( split( /,/, $vacdayDevs ) ) { #-- device of type holiday if( IsDevice( $vacdayDev, "holiday" )){ - $stoday = strftime('%2m-%2d', localtime(time)); - $stom = strftime('%2m-%2d', localtime(time+86400)); + $stoday = strftime('%m-%d', localtime(time)); + $stom = strftime('%m-%d', localtime(time+86400)); my $tod = holiday_refresh( $vacdayDev, $stoday ); if ( $tod ne "none" ) { $todaydesc = $tod; @@ -2197,8 +2249,8 @@ sub YAAHM_GetDayStatus($) { } #-- device of type calendar }elsif( IsDevice($vacdayDev, "Calendar" )){ - $stoday = strftime('%2d.%2m.%2Y', localtime(time)); - $stom = strftime('%2d.%2m.%2Y', localtime(time+86400)); + $stoday = strftime('%d.%m.%Y', localtime(time)); + $stom = strftime('%d.%m.%Y', localtime(time+86400)); @tday = split('\.',$stoday); @tmor = split('\.',$stom); #-- more complicated to check here @@ -2271,8 +2323,8 @@ sub YAAHM_GetDayStatus($) { #-- device of type holiday if( IsDevice( $holidayDev, "holiday" )){ - $stoday = strftime('%2m-%2d', localtime(time)); - $stom = strftime('%2m-%2d', localtime(time+86400)); + $stoday = strftime('%m-%d', localtime(time)); + $stom = strftime('%m-%d', localtime(time+86400)); my $tod = holiday_refresh( $holidayDev, $stoday ); if ( $tod ne "none" ) { $todaydesc = $tod; @@ -2288,8 +2340,8 @@ sub YAAHM_GetDayStatus($) { #-- device of type calendar }elsif( IsDevice($holidayDev, "Calendar" )){ - $stoday = strftime('%2d.%2m.%2Y', localtime(time)); - $stom = strftime('%2d.%2m.%2Y', localtime(time+86400)); + $stoday = strftime('%d.%m.%Y', localtime(time)); + $stom = strftime('%d.%m.%Y', localtime(time+86400)); $line=Calendar_Get($defs{$holidayDev},"get","text","mode=alarm|start|upcoming"); if($line){ chomp($line); @@ -2416,7 +2468,7 @@ sub YAAHM_sun($) { my $strise1 = ""; my ($msg,$stset0,$stseas0,$stset1,$stseas1); - $sttoday = strftime('%4Y-%2m-%2d', localtime(time)); + $sttoday = strftime('%Y-%m-%d', localtime(time)); #-- since the Astro module sometimes gives us strange results, we need to do this more than once while( $strise0 !~ /^\d\d:\d\d:\d\d/ && $count < 5){ @@ -2439,7 +2491,7 @@ sub YAAHM_sun($) { $stseas0 = Astro_Get($hash,"dummy","text", "ObsSeasonN",$sttoday); $hash->{DATA}{"DD"}[0]{"season"} = $seasons[$stseas0]; - $sttom = strftime('%4Y-%2m-%2d', localtime(time+86400)); + $sttom = strftime('%Y-%m-%d', localtime(time+86400)); $count = 0; $msg = ""; #-- since the Astro module sometimes gives us strange results, we need to do this more than once @@ -2594,6 +2646,220 @@ sub YAAHM_sunoffsets($) { $hash->{DATA}{"DT"}{"aftermidnight"}[0] = sprintf("%02d:%02d",$ofh,$ofm); } +######################################################################################### +# +# YAAHM_statewidget - returns SVG code for inclusion into page +# +# Parameter hash = hash of device addressed +# +######################################################################################### + +sub YAAHM_statewidget($){ + my ($hash) = @_; + + my $name = $hash->{NAME}; + return "" + if( AttrVal($name,"noicons",0) == 1); + + my $state = $hash->{DATA}{"HSM"}{"state"}; + my ($color,$locks,$unlocks,$bells,$eyes); + if( $state eq "unsecured" ){ + $color=$csstate[0]; + $locks="hidden"; + $unlocks="visible"; + $bells="hidden"; + $eyes="hidden"; + }elsif( $state eq "secured" ){ + $color=$csstate[1]; + $locks="visible"; + $unlocks="hidden"; + $bells="hidden"; + $eyes="hidden"; + }elsif( $state eq "protected" ){ + $color=$csstate[2]; + $locks="visible"; + $unlocks="hidden"; + $bells="visible"; + $eyes="hidden"; + }elsif( $state eq "guarded" ){ + $color=$csstate[3]; + $locks="visible"; + $unlocks="hidden"; + $bells="visible"; + $eyes="visible"; + }else{ + Log 1,"[YAAHM_statewidget] Error, housestate $state not defined"; + return; + } + + my $ret = ''; + $ret .= '\n'; + #-- shield + $ret .='\n'. + ''. + ''; + #-- small bell + $ret .= '\n'; + $ret .= ''. + '.\n'; + #-- lock + $ret .= '\n'; + $ret .= '\n'. + '\n'; + $ret .= '\n'; + $ret .= '\n'; + $ret .= '\n'; + $ret .= '\n'; + #-- eye + $ret .= '\n'; + $ret .= '\n'; + $ret .= ''; + + return $ret +} + + +######################################################################################### +# +# YAAHM_modewidget - returns SVG code for inclusion into page +# +# Parameter hash = hash of device addressed +# +######################################################################################### + +sub YAAHM_modewidget($){ + my ($hash) = @_; + + my $name = $hash->{NAME}; + return "" + if( AttrVal($name,"noicons",0) == 1); + + my $mode = $hash->{DATA}{"HSM"}{"mode"}; + my ($color,$normals,$absents,$partys,$dnds); + if( $mode eq "normal" ){ + $color=$csmode[0]; + $normals="visible"; + $partys="hidden"; + $absents="hidden"; + $dnds="hidden"; + }elsif( $mode eq "party" ){ + $color=$csmode[1]; + $normals="hidden"; + $partys="visible"; + $absents="hidden"; + $dnds="hidden"; + }elsif( $mode eq "absence" ){ + $color=$csmode[2]; + $normals="hidden"; + $partys="hidden"; + $absents="visible"; + $dnds="hidden"; + }elsif( $mode eq "donotdisturb" ){ + $color=$csmode[3]; + $normals="hidden"; + $partys="hidden"; + $absents="hidden"; + $dnds="visible"; + }else{ + Log 1,"[YAAHM_modewidget] Error, housemode $mode not defined"; + return; + } + + my $ret = ''; + $ret .= ' '; + $ret .= ' '. + ' '; + $ret .= ' '. + ''. + ''. + ''; + $ret .= ''. + ''. + ''. + ''. + ''. + ''. + ''. + ''. + ''; + $ret .= ''. + ''. + ''. + ''. + ''; + $ret .= ''. + ''. + ''. + ''; + $ret .= ''; + + return $ret + } + ######################################################################################### # # YAAHM_timewidget - returns SVG code for inclusion into any room page @@ -2613,11 +2879,7 @@ sub YAAHM_timewidget($){ $FW_RET=""; FW_pO ''; - my $hash = $defs{$name}; - # Midnight = 0 200 - # Noon = 0 -200 - # hh:mm => a = (hh*60 + mm)/1140 - + my $hash = $defs{$name}; my $radius = 250; my ($sec, $min, $hour, $day, $month, $year, $wday,$yday,$isdst) = localtime(time); @@ -2629,6 +2891,7 @@ sub YAAHM_timewidget($){ my $t_sunrise = defined($hash->{DATA}{"DD"}[0]{"sunrise"}) ? $hash->{DATA}{"DD"}[0]{"sunrise"} : "06:00"; $t_sunrise =~ s/^0//; ($hour,$min) = split(":",$t_sunrise); + my $sr = $hour + $min*60; my $a_sunrise = (60*$hour + $min)/1440 * 2 * pi; my $x_sunrise = -int(sin($a_sunrise)*$radius*100)/100; my $y_sunrise = int(cos($a_sunrise)*$radius*100)/100; @@ -2636,6 +2899,7 @@ sub YAAHM_timewidget($){ my $t_morning = defined($hash->{DATA}{"DT"}{"morning"}[0]) ? $hash->{DATA}{"DT"}{"morning"}[0] : "08:00"; $t_morning =~ s/^0//; ($hour,$min) = split(":",$t_morning); + my $mo = $hour + $min*60; my $a_morning = (60*$hour + $min)/1440 * 2 * pi; my $x_morning = -int(sin($a_morning)*$radius*100)/100; my $y_morning = int(cos($a_morning)*$radius*100)/100; @@ -2657,6 +2921,7 @@ sub YAAHM_timewidget($){ my $t_sunset = defined($hash->{DATA}{"DD"}[0]{"sunset"}) ? $hash->{DATA}{"DD"}[0]{"sunset"} : "18:00"; $t_sunset =~ s/^0//; ($hour,$min) = split(":",$t_sunset); + my $ss = $hour + $min*60; my $a_sunset = (60*$hour + $min)/1440 * 2 * pi; my $x_sunset = -int(sin($a_sunset)*$radius*100)/100; my $y_sunset = int(cos($a_sunset)*$radius*100)/100; @@ -2664,6 +2929,7 @@ sub YAAHM_timewidget($){ my $t_evening = defined($hash->{DATA}{"DT"}{"evening"}[0]) ? $hash->{DATA}{"DT"}{"evening"}[0] : "19:00"; $t_evening =~ s/^0//; ($hour,$min) = split(":",$t_evening); + my $ev = $hour + $min*60; my $a_evening = (60*$hour + $min)/1440 * 2 * pi; my $x_evening = -int(sin($a_evening)*$radius*100)/100; my $y_evening = int(cos($a_evening)*$radius*100)/100; @@ -2706,13 +2972,15 @@ sub YAAHM_timewidget($){ FW_pO ''; #-- sunrise to morning sector - FW_pO ''; + my $dir = ( $sr < $mo ) ? 0 : 1; + FW_pO ''; #-- morning to evening sector FW_pO ''; #-- evening to sunset sector - FW_pO ''; + $dir = ( $ss < $ev ) ? 1 : 0; + FW_pO ''; #-- midnight line FW_pO ''; @@ -2798,6 +3066,9 @@ sub YAAHM_toptable($){ #-- $ret .= "\n"; - + $ret .= "
".ReadingsVal($name,"housestate",undef)."
". + "
".ReadingsVal($name,"housemode",undef)."
"; $ret .= "\n"; - $ret .= "\n"; + $ret .= "\n"; ### action ################################################################################################ #-- determine columns - my $cols = max(int(@modes),int(@states),$weeklyno); - $ret .= ""; #-- complete the code of the page $ret .= "
".$yaahm_tt->{"action"}."
".$yaahm_tt->{"action"}. + "
".ReadingsVal($name,"tr_errmsg",undef)."
". + my $cols = max(max(int(@modes),int(@states)),$weeklyno); + $ret .= ""; + $ret .= "
". + "". "". ""; for( my $i=0; $i<$cols; $i++){ @@ -2831,7 +3104,8 @@ sub YAAHM_toptable($){ } } $ret .= ""; - $ret .= "". + $ret .= "". + "". ""; for( my $i=0; $i<$cols; $i++){ @@ -2843,13 +3117,13 @@ sub YAAHM_toptable($){ } } #style=\"height:20px;border-bottom: 10px solid #333333;background-image: linear-gradient(#e5e5e5,#ababab);\" - #$ret .= ""; + $ret .= ""; $ret .= "
".YAAHM_modewidget($hash)."
".$yaahm_tt->{"mode"}."
".ReadingsVal($name,"tr_housemode",undef)."
".$yaahm_tt->{"state"}."
".YAAHM_statewidget($hash)."".$yaahm_tt->{"state"}."
".ReadingsVal($name,"tr_housestate",undef). "
".ReadingsVal($name,"sym_housestate",undef)."

"; #-- repeat manual next for every weekly table my $nval = ""; my $wupn; - $ret .= ""; + $ret .= ""; for (my $i=0;$i<$weeklyno;$i++){ if($i<$weeklyno-1){ $styl= "border-bottom:1px solid gray;border-top:1px solid gray"; @@ -3183,7 +3457,7 @@ sub YAAHM_Longtable($){ } $ass = ( defined($hash->{DATA}{"WT"}[$i]{"acti_d"}) ) ? $hash->{DATA}{"WT"}[$i]{"acti_d"} : ""; for( my $j=0;$j ",$i); } @@ -3237,7 +3511,7 @@ sub YAAHM_Longtable($){ } $ret .= "\n"; } - $ret .= "
".$yaahm_tt->{"manual"}."
".$yaahm_tt->{"manual"}."
"; @@ -3256,6 +3530,7 @@ sub YAAHM_Longtable($){

YAAHM

+

    Yet Another Auto Home Module to set up a cyclic processing of commands (daily, weekly, monthly, yearly profile)

    Usage

    @@ -3380,7 +3655,14 @@ sub YAAHM_Longtable($){ means that yaahm setups may be changed
  • attr <name> simulation 0|1 -
    a value of 1 means that commands will not be executed, but only simulated
  • +
    a value of 1 means that commands issued directly on the device as "set ... " will not be executed, but only simulated. Does not prevent the button + click commands from the interactive web page to be executed. +
  • attr <name> noicons + 0|1 +
    when set to 1, animated icons are suppressed
  • +
  • attr <name> colorscheme + 1|2 +
    color scheme for the icons
  • attr <name> timeHelper <name of perl program>
    name of a perl function that is called at each time step of the daily profile and for the two default weekly profiles
  • attr <name> modeHelper <name of perl program> @@ -3419,11 +3701,14 @@ sub YAAHM_Longtable($){
    list of devices that provide special date information (like e.g. garbage collection). The devices may be holiday devices or Calendar devices
+ =end html =begin html_DE

YAAHM

+ =end html_DE =cut diff --git a/fhem/www/pgm2/yaahm.js b/fhem/www/pgm2/yaahm.js index ca9e326fc..c55658178 100644 --- a/fhem/www/pgm2/yaahm.js +++ b/fhem/www/pgm2/yaahm.js @@ -1,6 +1,6 @@ //######################################################################################## // yaahm.js -// Version 1.0 +// Version 1.14 // See 95_YAAHM for licensing //######################################################################################## //# Prof. Dr. Peter A. Henning @@ -18,26 +18,27 @@ function encodeParm(oldval) { // $( document ).tooltip(); // } ); -// Expand Text box - $(function () { - $(".expand").focus(function () { - $(this).animate({ - width: '200px' - }, - "slow" - ) - }); +//------------------------------------------------------------------------------------------------------ +// Expand text box +//------------------------------------------------------------------------------------------------------ + +$(function () { + $(".expand").focus(function () { + $(this).animate({ + width: '200px' + }, + "slow") }); - - $(function () { - $(".expand").blur(function () { - $(this).animate({ - width: '100px' - }, - "slow" - ) - }); +}); + +$(function () { + $(".expand").blur(function () { + $(this).animate({ + width: '100px' + }, + "slow") }); +}); //------------------------------------------------------------------------------------------------------ // Write the Attribute Value @@ -57,7 +58,10 @@ function yaahm_setAttribute(name, attr, val) { // Change mode and state, set next time //------------------------------------------------------------------------------------------------------ -function yaahm_mode(name,targetmode) { +var hsold; +var hmold; + +function yaahm_mode(name, targetmode) { var location = document.location.pathname; if (location.substr(location.length -1, 1) == '/') { location = location.substr(0, location.length -1); @@ -67,7 +71,7 @@ function yaahm_mode(name,targetmode) { FW_cmd(url + '?XHR=1&cmd.' + name + '={main::YAAHM_mode("' + name + '","' + targetmode + '")}'); } -function yaahm_state(name,targetstate) { +function yaahm_state(name, targetstate) { var location = document.location.pathname; if (location.substr(location.length -1, 1) == '/') { location = location.substr(0, location.length -1); @@ -77,7 +81,7 @@ function yaahm_state(name,targetstate) { FW_cmd(url + '?XHR=1&cmd.' + name + '={main::YAAHM_state("' + name + '","' + targetstate + '")}'); } -function yaahm_setnext(name,i) { +function yaahm_setnext(name, i) { var location = document.location.pathname; if (location.substr(location.length -1, 1) == '/') { location = location.substr(0, location.length -1); @@ -94,6 +98,97 @@ function yaahm_setnext(name,i) { FW_cmd(url + '?XHR=1&cmd.' + name + '={main::YAAHM_nextWeeklyTime("' + name + '","next_' + i + '","' + nval + '")}'); } +//------------------------------------------------------------------------------------------------------ +// Animate housestate icon +//------------------------------------------------------------------------------------------------------ + +$("body").on('DOMSubtreeModified', "#hid_hs", +function () { + var hsnew = document.getElementById("hid_hs").innerHTML; + if (hsnew != hsold) { + hsold = hsnew; + var w = document.getElementById("wid_hs"); + if (w) { + switch (hsnew) { + case "unsecured": + w.getElementsByClassName("hs_is")[0].setAttribute("fill", csstate[0]); + w.getElementsByClassName("hs_smb")[0].setAttribute("visibility", "hidden"); + w.getElementsByClassName("hs_unlocked")[0].setAttribute("visibility", "visible"); + w.getElementsByClassName("hs_locked")[0].setAttribute("visibility", "hidden"); + w.getElementsByClassName("hs_eye")[0].setAttribute("visibility", "hidden"); + break; + case "secured": + w.getElementsByClassName("hs_is")[0].setAttribute("fill", csstate[1]); + w.getElementsByClassName("hs_smb")[0].setAttribute("visibility", "hidden"); + w.getElementsByClassName("hs_unlocked")[0].setAttribute("visibility", "hidden"); + w.getElementsByClassName("hs_locked")[0].setAttribute("visibility", "visible"); + w.getElementsByClassName("hs_eye")[0].setAttribute("visibility", "hidden"); + break; + case "protected": + w.getElementsByClassName("hs_is")[0].setAttribute("fill", csstate[2]); + w.getElementsByClassName("hs_smb")[0].setAttribute("visibility", "visible"); + w.getElementsByClassName("hs_unlocked")[0].setAttribute("visibility", "hidden"); + w.getElementsByClassName("hs_locked")[0].setAttribute("visibility", "visible"); + w.getElementsByClassName("hs_eye")[0].setAttribute("visibility", "hidden"); + break; + case "guarded": + w.getElementsByClassName("hs_is")[0].setAttribute("fill", csstate[3]); + w.getElementsByClassName("hs_smb")[0].setAttribute("visibility", "visible"); + w.getElementsByClassName("hs_unlocked")[0].setAttribute("visibility", "hidden"); + w.getElementsByClassName("hs_locked")[0].setAttribute("visibility", "visible"); + w.getElementsByClassName("hs_eye")[0].setAttribute("visibility", "visible"); + break; + } + } else { + alert("state widget not found"); + } + } +}); + +$("body").on('DOMSubtreeModified', "#hid_hm", +function () { + var hmnew = document.getElementById("hid_hm").innerHTML; + if (hmnew != hmold) { + hmold = hmnew; + var w = document.getElementById("wid_hm"); + if (w) { + switch (hmnew) { + case "normal": + w.getElementsByClassName("hm_is")[0].setAttribute("fill", csmode[0]); + w.getElementsByClassName("hm_n")[0].setAttribute("visibility", "visible"); + w.getElementsByClassName("hm_p")[0].setAttribute("visibility", "hidden"); + w.getElementsByClassName("hm_a")[0].setAttribute("visibility", "hidden"); + w.getElementsByClassName("hm_dnd")[0].setAttribute("visibility", "hidden"); + break; + case "party": + w.getElementsByClassName("hm_is")[0].setAttribute("fill", csmode[1]); + w.getElementsByClassName("hm_n")[0].setAttribute("visibility", "hidden"); + w.getElementsByClassName("hm_p")[0].setAttribute("visibility", "visible"); + w.getElementsByClassName("hm_a")[0].setAttribute("visibility", "hidden"); + w.getElementsByClassName("hm_dnd")[0].setAttribute("visibility", "hidden"); + break; + case "absence": + w.getElementsByClassName("hm_is")[0].setAttribute("fill", csmode[2]); + w.getElementsByClassName("hm_n")[0].setAttribute("visibility", "hidden"); + w.getElementsByClassName("hm_p")[0].setAttribute("visibility", "hidden"); + w.getElementsByClassName("hm_a")[0].setAttribute("visibility", "visible"); + w.getElementsByClassName("hm_dnd")[0].setAttribute("visibility", "hidden"); + break; + case "donotdisturb": + w.getElementsByClassName("hm_is")[0].setAttribute("fill", csmode[3]); + w.getElementsByClassName("hm_n")[0].setAttribute("visibility", "hidden"); + w.getElementsByClassName("hm_p")[0].setAttribute("visibility", "hidden"); + w.getElementsByClassName("hm_a")[0].setAttribute("visibility", "hidden"); + w.getElementsByClassName("hm_dnd")[0].setAttribute("visibility", "visible"); + break; + } + } else { + alert("mode widget not found"); + } + } +}); + + //------------------------------------------------------------------------------------------------------ // Start the daily timer //------------------------------------------------------------------------------------------------------ @@ -109,7 +204,7 @@ function yaahm_startDayTimer(name) { // saving start and end times for (var i = 0; i < dailyno; i++) { var sval, eval, xval, aval1, aval2; - if ( (dailykeys[i] != 'wakeup') && (dailykeys[i] != 'sleep') ) { + if ((dailykeys[i] != 'wakeup') && (dailykeys[i] != 'sleep')) { if (document.getElementById('dt' + dailykeys[i] + '_s') !== null) { sval = document.getElementById('dt' + dailykeys[i] + '_s').value; } else { @@ -125,20 +220,20 @@ function yaahm_startDayTimer(name) { } else { xval = "undef" } - aval1 = $("input[name='actim" + dailykeys[i] + "']:checked").map(function(){ - return $(this).val(); - }).get(); - aval2 = $("input[name='actid" + dailykeys[i] + "']:checked").map(function(){ - return $(this).val(); - }).get(); + aval1 = $("input[name='actim" + dailykeys[i] + "']:checked").map(function () { + return $(this).val(); + }).get(); + aval2 = $("input[name='actid" + dailykeys[i] + "']:checked").map(function () { + return $(this).val(); + }).get(); FW_cmd(url + '?XHR=1&cmd.' + name + '={main::YAAHM_setParm("' + name + '","dt","' + dailykeys[i] + '",' + '"' + sval + '","' + eval + '","' + xval + '","' + aval1 + ';' + aval2 + '")}'); } } // really start it now - FW_cmd(url+'?XHR=1&cmd.' + name + ' ={main::YAAHM_startDayTimer("' + name + '")}'); + FW_cmd(url + '?XHR=1&cmd.' + name + ' ={main::YAAHM_startDayTimer("' + name + '")}'); // change link - $('#dtlink').html(''+name+'.dtimer.IF'); + $('#dtlink').html('' + name + '.dtimer.IF'); } //------------------------------------------------------------------------------------------------------ @@ -158,7 +253,7 @@ function yaahm_startWeeklyTimer(name) { for (var i = 0; i < weeklyno; i++) { var xval; var nval; - var aval1,aval2; + var aval1, aval2; var sval =[ "", "", "", "", "", "", ""]; //action if (document.getElementById('wt' + i + '_x') !== null) { @@ -172,34 +267,31 @@ function yaahm_startWeeklyTimer(name) { } else { nval = "undef" } - //activity - aval1 = $("input[name='acti_" + i + "_m']:checked").map(function(){ - return $(this).val(); - }).get(); - - aval2 = $("input[name='acti_" + i + "_d']:checked").map(function(){ - return $(this).val(); - }).get(); + //activity party/absence + aval1 = $("input[name='acti_" + i + "_m']:checked").map(function () { + return $(this).val(); + }).get(); + //activity vacation/holiday + aval2 = $("input[name='acti_" + i + "_d']:checked").map(function () { + return $(this).val(); + }).get(); //iterate over days of week for (var j = 0; j < 7; j++) { - if (document.getElementById('wt' + weeklykeys[j] + i +'_s') !== null) { + if (document.getElementById('wt' + weeklykeys[j] + i + '_s') !== null) { sval[j] = document.getElementById('wt' + weeklykeys[j] + i + '_s').value; } else { sval[j] = "undef"; } } - FW_cmd(url + '?XHR=1&cmd.' + name + '={main::YAAHM_setParm("' + name + '","wt","' + i + '","' + xval + '","' + nval + '","' + aval1 + '","' + aval2 + '","'+ sval.join('","') + '")}'); - } + FW_cmd(url + '?XHR=1&cmd.' + name + '={main::YAAHM_setParm("' + name + '","wt","' + i + '","' + xval + '","' + nval + '","' + aval1 + '","' + aval2 + '","' + sval.join('","') + '")}'); + } // really start it now - FW_cmd(url+'?XHR=1&cmd.' + name + ' ={main::YAAHM_startWeeklyTimer("' + name + '")}'); + FW_cmd(url + '?XHR=1&cmd.' + name + ' ={main::YAAHM_startWeeklyTimer("' + name + '")}'); // change links for (var i = 0; i < weeklyno; i++) { - $('#wt'+i+'link').html('' + name + '.wtimer_' + i + '.IF'); + $('#wt' + i + 'link').html('' + name + '.wtimer_' + i + '.IF'); } -} - - - +} \ No newline at end of file