From ad0d971ab83b3df9ebb38d260926ec5cb5f5d3d1 Mon Sep 17 00:00:00 2001 From: borisneubert <> Date: Sun, 15 Jul 2012 12:18:45 +0000 Subject: [PATCH] pgm2 and 59_Weather.pm prepared for changes in directory structures yet to come 59_Weather.pm ready for Michael Preidel's beautiful icons git-svn-id: https://svn.fhem.de/fhem/trunk@1730 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/FHEM/59_Weather.pm | 74 +++- fhem/webfrontend/pgm2/01_FHEMWEB.pm | 427 ++++++++++++++------- fhem/webfrontend/pgm2/darkstyle.css | 2 +- fhem/webfrontend/pgm2/fhemicon.png | Bin 17976 -> 7911 bytes fhem/webfrontend/pgm2/smallscreenstyle.css | 2 +- fhem/webfrontend/pgm2/style.css | 2 +- 6 files changed, 359 insertions(+), 148 deletions(-) diff --git a/fhem/FHEM/59_Weather.pm b/fhem/FHEM/59_Weather.pm index 53a6194a7..b4b40a489 100755 --- a/fhem/FHEM/59_Weather.pm +++ b/fhem/FHEM/59_Weather.pm @@ -15,7 +15,7 @@ use warnings; use Time::HiRes qw(gettimeofday); my $UseWeatherGoogle= 0; # if you want Weather:Google back please set this to 1 and uncomment below. -# use Weather::Google; +## use Weather::Google; # taken from Daniel "Possum" LeWarne's Google::Weather module # http://cpansearch.perl.org/src/POSSUM/Weather-Google-0.05/lib/Weather/Google.pm @@ -298,4 +298,76 @@ sub Weather_Undef($$) { ##################################### +sub +WeatherIconIMGTag($$$) { + + use constant GOOGLEURL => "http://www.google.de"; + use constant SIZE => "50%"; + + my ($icon,$uselocal,$isday)= @_; + + my $url; + my $style; + + if($uselocal) { + # strip off path and extension + $icon =~ s,^/ig/images/weather/(.*)\.gif$,$1,; + + if($isday) { + $icon= "weather/${icon}.png" + } else { + $icon= "weather/${icon}_night.png" + } + + $url= "fhem/icons/$icon"; + $style= " height=".SIZE." width=".SIZE; + } else { + $url= GOOGLEURL . $icon; + } + + return ""; + +} + +##################################### +# This has to be modularized in the future. +sub +WeatherAsHtml($) +{ + my $uselocal= 0; + + my ($d) = @_; + $d = "" if(!$d); + return "$d is not a Weather instance
" + if(!$defs{$d} || $defs{$d}{TYPE} ne "Weather"); + + my $isday; + if(exists &isday) { + $isday = isday(); + } else { + $isday = 1; #($hour>6 && $hour<19); + } + + my $ret = ""; + $ret .= sprintf('', + WeatherIconIMGTag(ReadingsVal($d, "icon", ""),$uselocal,$isday), + ReadingsVal($d, "condition", ""), + ReadingsVal($d, "temp_c", ""), ReadingsVal($d, "humidity", ""), + ReadingsVal($d, "wind_condition", "")); + + for(my $i=1; $i<=4; $i++) { + $ret .= sprintf('', + WeatherIconIMGTag(ReadingsVal($d, "fc${i}_icon", ""),$uselocal,$isday), + ReadingsVal($d, "fc${i}_day_of_week", ""), + ReadingsVal($d, "fc${i}_condition", ""), + ReadingsVal($d, "fc${i}_low_c", ""), ReadingsVal($d, "fc${i}_high_c", "")); + } + + $ret .= "
%s%s
temp %s, hum %s, %s
%s%s: %s
min %s max %s
"; + return $ret; +} + +##################################### + + 1; diff --git a/fhem/webfrontend/pgm2/01_FHEMWEB.pm b/fhem/webfrontend/pgm2/01_FHEMWEB.pm index dc71d04f1..aca716956 100755 --- a/fhem/webfrontend/pgm2/01_FHEMWEB.pm +++ b/fhem/webfrontend/pgm2/01_FHEMWEB.pm @@ -19,6 +19,7 @@ sub FW_fileList($); sub FW_logWrapper($); sub FW_makeEdit($$$); sub FW_makeTable($$@); +sub FW_ReadIconsFrom($$); sub FW_ReadIcons(); sub FW_roomOverview($); sub FW_select($$$$@); @@ -36,7 +37,12 @@ sub FW_pH(@); sub FW_pHPlain(@); sub FW_pO(@); -use vars qw($FW_dir); # moddir (./FHEM in old structure, www/pgm2 in new structure), needed by SVG +use vars qw($FW_dir); # base directory for web server: the first available from $modpath/www, $modpath/FHEM +use vars qw($FW_icondir); # icon base directory for web server: the first available from $FW_dir/icons, $FW_dir +use vars qw($FW_docdir); # doc directory for web server: the first available from $FW_dir/docs, $modpath/docs, $FW_dir +use vars qw($FW_cssdir); # css directory for web server: the first available from $FW_dir/css, $FW_dir +use vars qw($FW_gplotdir); # gplot directory for web server: the first available from $FW_dir/gplot,$FW_dir +use vars qw($FW_jsdir); # js directory for web server: the first available from $FW_dir/javascript, $FW_dir use vars qw($MW_dir); # moddir (./FHEM), needed by edit Files in new structure use vars qw($FW_ME); # webname (default is fhem), needed by 97_GROUP use vars qw($FW_ss); # is smallscreen, needed by 97_GROUP/95_VIEW @@ -66,7 +72,7 @@ my %FW_icons; # List of icons my $FW_iconsread; # Timestamp of last icondir check my $FW_plotmode; # Global plot mode (WEB attribute) my $FW_plotsize; # Global plot size (WEB attribute) -my $FW_reldoc; # $FW_ME/commandref.html; +my $FW_commandref; # $FW_docdir/commandref.html; my $FW_RETTYPE; # image/png or the like my $FW_room; # currently selected room my %FW_rooms; # hash of all rooms @@ -97,7 +103,7 @@ FHEMWEB_Initialize($) $hash->{AttrList}= "loglevel:0,1,2,3,4,5,6 webname fwmodpath fwcompress:0,1 ". "plotmode:gnuplot,gnuplot-scroll,SVG plotsize refresh " . "touchpad smallscreen plotfork basicAuth basicAuthMsg ". - "stylesheetPrefix hiddenroom HTTPS longpoll:1,0 ". + "stylesheetPrefix iconpath hiddenroom HTTPS longpoll:1,0 ". "redirectCmds:0,1 allowfrom "; ############### @@ -268,6 +274,80 @@ FW_Read($) } ########################### +sub +FW_ServeSpecial($$$) { + + my ($file,$ext,$dir)= @_; + $file =~ s,\.\./,,g; # little bit of security + + #Debug "We serve $dir/$file.$ext"; + open(FH, "$dir/$file.$ext") || return 0; + binmode(FH) if($ext =~ m/gif|png|jpg/); # necessary for Windows + FW_pO join("", ); + close(FH); + $FW_RETTYPE = "text/plain" if($ext eq "txt"); + $FW_RETTYPE = "text/html" if($ext eq "html"); + $FW_RETTYPE = "application/pdf" if($ext eq "pdf"); + $FW_RETTYPE = "text/css" if($ext eq "css"); + $FW_RETTYPE = "image/jpeg" if($ext eq "jpg"); + $FW_RETTYPE = "image/png" if($ext eq "png"); + $FW_RETTYPE = "image/gif" if($ext eq "gif"); + return 1; +} + +sub +FW_SetDirs() { + + # web server root + if(-d "$attr{global}{modpath}/www") { + $FW_dir = AttrVal($FW_wname, "fwmodpath", "$attr{global}{modpath}/www"); + } else { + $FW_dir = AttrVal($FW_wname, "fwmodpath", "$attr{global}{modpath}/FHEM"); + } + # icon dir + if(-d "$FW_dir/images") { + $FW_icondir = "$FW_dir/images"; + } else { + $FW_icondir = $FW_dir; + } + # doc dir + if(-d "$FW_dir/docs") { + $FW_docdir = "$FW_dir/docs"; + } elsif(-d "$attr{global}{modpath}/docs") { + $FW_docdir = "$attr{global}{modpath}/docs"; + } + else { + $FW_docdir = $FW_dir; + } + # css dir + if(-d "$FW_dir/pgm2") { + $FW_cssdir = "$FW_dir/pgm2"; + } else { + $FW_cssdir = $FW_dir; + } + # gplot dir + if(-d "$FW_dir/gplot") { + $FW_gplotdir = "$FW_dir/gplot"; + } else { + $FW_gplotdir = $FW_dir; + } + # javascript dir + if(-d "$FW_dir/pgm2") { + $FW_jsdir = "$FW_dir/pgm2"; + } else { + $FW_jsdir = $FW_dir; + } + +# Debug "web server root: $FW_dir"; +# Debug "icon directory: $FW_icondir"; +# Debug "doc directory: $FW_docdir"; +# Debug "css directory: $FW_cssdir"; +# Debug "gplot directory: $FW_gplotdir"; +# Debug "javascript directory: $FW_jsdir"; + +} + + sub FW_AnswerCall($) { @@ -277,50 +357,52 @@ FW_AnswerCall($) $FW_RET = ""; $FW_RETTYPE = "text/html; charset=$FW_encoding"; $FW_ME = "/" . AttrVal($FW_wname, "webname", "fhem"); - if(-d "$attr{global}{modpath}/www/pgm2") { - $FW_dir = AttrVal($FW_wname, "fwmodpath", "$attr{global}{modpath}/www/pgm2"); - } else { - $FW_dir = AttrVal($FW_wname, "fwmodpath", "$attr{global}{modpath}/FHEM"); - } + + FW_SetDirs; + + $FW_commandref = "$FW_docdir/commandref.html"; + #Debug "commandref.html is at $FW_commandref"; + + + $MW_dir = AttrVal($FW_wname, "fwmodpath", "$attr{global}{modpath}/FHEM"); $FW_ss = AttrVal($FW_wname, "smallscreen", 0); $FW_tp = AttrVal($FW_wname, "touchpad", $FW_ss); my $prf = AttrVal($FW_wname, "stylesheetPrefix", ""); # Lets go: - if($arg =~ m,^${FW_ME}/(.*)\.(css|html|js)$,) { - my ($file, $ext) = ($1, $2); - $file =~ s,\.\./,,g; # little bit of security - open(FH, "$FW_dir/$file.$ext") || return 0; - FW_pO join("", ); - close(FH); - $FW_RETTYPE = "text/css" if($ext eq "css"); - $FW_RETTYPE = "application/javascript" if($ext eq "js"); - return 1; + if($arg =~ m,^$FW_ME/docs/(.*)\.(html|txt|pdf)$,) { + return FW_ServeSpecial($1,$2,$FW_docdir); - } elsif($arg =~ m,^$FW_ME/icons/(.*)$, || - $arg =~ m,^$FW_ME/(.*.png)$,i || - $arg =~ m,^/(favicon.ico)$,) { - my ($img, $cachable) = ($1, 1); - $img =~ s,\.\./,,g; + } elsif($arg =~ m,^${FW_ME}/css/(.*)\.css$,) { + return FW_ServeSpecial($1,"css",$FW_cssdir); - my $fnd; - $fnd = open(FH, "$FW_dir/$prf/$img") if($prf); - $fnd = open(FH, "$FW_dir/$img") if(!$fnd); - if(!$fnd && $arg =~ m,/icons/,) { # Hack: convert device state to icon name - FW_ReadIcons(); - $img = FW_dev2image($img); + } elsif($arg =~ m,^${FW_ME}/js/(.*)\.js$,) { + return FW_ServeSpecial($1,"js",$FW_jsdir); + + } elsif($arg =~ m,^/(favicon.ico)$,) { + return 0; # TODO! + } + + elsif($arg =~ m,^$FW_ME/icons/(.*)$,) { + my ($icon,$cachable) = ($1, 1); + FW_ReadIcons(); + + #Debug "You want $icon which is " . $FW_icons{$icon}; + # if we do not have the icon, we convert the device state to the icon name + if(!$FW_icons{$icon}) { + $icon = FW_dev2image($icon); + #Debug "We do not have it and thus use $icon which is " . $FW_icons{$icon}; $cachable = 0; - $fnd = open(FH, "$FW_dir/$prf/$img") if($img); - $fnd = open(FH, "$FW_dir/$img") if(!$fnd && $img); } - return 0 if(!$fnd); - binmode (FH); # necessary for Windows - FW_pO join("", ); - close(FH); - my @f_ext = split(/\./,$img); #kpb - $FW_RETTYPE = "image/$f_ext[-1]"; - return $cachable; + $FW_icons{$icon} =~ m/(.*)\.(gif|jpg|png)/; + my ($file,$ext)= ($1,$2); + + if(FW_ServeSpecial($file,$ext,$FW_icondir)) { + return $cachable; + } else { + return 0; + } } elsif($arg !~ m/^$FW_ME(.*)/) { my $c = $me->{CD}; @@ -331,7 +413,7 @@ FW_AnswerCall($) return -1; } - + $arg = $1; # The stuff behind FW_ME $FW_plotmode = AttrVal($FW_wname, "plotmode", "SVG"); @@ -359,7 +441,6 @@ FW_AnswerCall($) $cmd !~ /^style / && $cmd !~ /^edit/); - $FW_reldoc = "$FW_ME/commandref.html"; $FW_cmdret = $docmd ? FW_fC($cmd) : ""; if($FW_inform) { # Longpoll header @@ -428,7 +509,7 @@ FW_AnswerCall($) # Enable WebApp if($FW_tp || $FW_ss) { - FW_pO ''; + FW_pO ''; FW_pO ''; if($FW_ss) { FW_pO ''; @@ -442,10 +523,10 @@ FW_AnswerCall($) $prf = "smallscreen" if(!$prf && $FW_ss); $prf = "touchpad" if(!$prf && $FW_tp); - FW_pO ""; - FW_pO "" + FW_pO ""; + FW_pO "" if($FW_plotmode eq "SVG"); - FW_pO ""; + FW_pO ""; my $onload = $FW_longpoll ? "onload=\"FW_delayedStart()\"" : ""; FW_pO "\n"; @@ -688,7 +769,7 @@ FW_doDetail($) } FW_pH "cmd=style iconFor $d", "Select icon"; - FW_pH "$FW_reldoc#${t}", "Device specific help"; + FW_pH "$FW_ME/docs/commandref.html#${t}", "Device specific help"; FW_pO "

"; FW_pO ""; FW_pO ""; @@ -715,7 +796,7 @@ FW_roomOverview($) $FW_room = $1 if($FW_room && $FW_room =~ m/^([^,]*),/); $FW_room = "" if(!$FW_room); FW_pHPlain "room=$FW_room", - "
"; + "
"; FW_pO "
$FW_detail details
"; return; @@ -771,9 +852,9 @@ FW_roomOverview($) my @list = ( "Everything", "$FW_ME?room=all", "", "", - "Howto", "$FW_ME/HOWTO.html", + "Howto", "$FW_ME/docs/HOWTO.html", "Wiki", "http://fhemwiki.de", - "Details", "$FW_ME/commandref.html", + "Details", "$FW_ME/docs/commandref.html", "Definition...", "$FW_ME?cmd=style%20addDef", "Edit files", "$FW_ME?cmd=style%20list", "Select style", "$FW_ME?cmd=style%20select", @@ -818,7 +899,7 @@ FW_roomOverview($) } else { pF "", $l1 eq $FW_room ? " class=\"sel\"" : ""; my $icon = ""; - $icon = " " + $icon = " " if($FW_icons{"ico$l1"}); if($l2 =~ m/.html$/ || $l2 =~ m/^http/) { @@ -1001,6 +1082,25 @@ FW_fileList($) return sort @ret; } +# return a hash name -> path of actual files for a given regexp +sub +FW_fileHash($) +{ + my ($fname) = @_; + $fname =~ m,^(.*)/([^/]*)$,; # Split into dir and file + my ($dir,$re) = ($1, $2); + return if(!$re); + $re =~ s/%./[A-Za-z0-9]*/g; + my %ret; + return %ret if(!opendir(DH, $dir)); + while(my $f = readdir(DH)) { + next if($f !~ m,^$re$,); + $ret{$f}= "${dir}/${f}"; + } + closedir(DH); + return %ret; +} + ###################### # Show the content of the log (plain text), or an image and offer a link # to convert it to a weblink @@ -1160,7 +1260,7 @@ FW_showLog($) my $pm = AttrVal($wl,"plotmode",$FW_plotmode); - my $gplot_pgm = "$FW_dir/$type.gplot"; + my $gplot_pgm = "$FW_gplotdir/$type.gplot"; if(!-r $gplot_pgm) { my $msg = "Cannot read $gplot_pgm"; @@ -1268,7 +1368,7 @@ FW_showLog($) Log 5, "plotcommand: get $d $file INT $f $t " . join(" ", @{$flog}); $ret = FW_fC("get $d $file INT $f $t " . join(" ", @{$flog})); ($cfg, $plot) = FW_substcfg(1, $wl, $cfg, $plot, $file, ""); - FW_pO SVG_render($wl, $f, $t, $cfg, $internal_data, $plot, $FW_wname, $FW_dir); + FW_pO SVG_render($wl, $f, $t, $cfg, $internal_data, $plot, $FW_wname, $FW_cssdir); $FW_RETTYPE = "image/svg+xml"; } @@ -1475,6 +1575,26 @@ FW_calcWeblink($$) } } +################## +# +sub +FW_pFileHash($%) { + + my ($heading,%files)= @_; + FW_pO "$heading
"; + FW_pO ""; + my $row = 0; + my @filenames= sort keys %files; + foreach my $filename (@filenames) { + FW_pO ""; + FW_pH "cmd=style edit $files{$filename}", $filename, 1; + FW_pO ""; + $row = ($row+1)%2; + } + FW_pO "
"; + FW_pO "
"; + } + ################## # List/Edit/Save css and gnuplot files sub @@ -1485,35 +1605,35 @@ FW_style($$) my $start = "
"; my $end = "
"; + if($a[1] eq "list") { - my @fl = ("fhem.cfg"); - push(@fl, ""); - push(@fl, FW_fileList("$MW_dir/.*(sh|[0-9].*Util.*|cfg|holiday)")); - push(@fl, ""); - push(@fl, FW_fileList("$FW_dir/.*.(css|svg)")); - push(@fl, ""); - push(@fl, FW_fileList("$FW_dir/.*.gplot")); + # + # list files for editing + # + my %files; FW_pO $start; FW_pO "$msg

" if($msg); - FW_pO ""; - my $row = 0; - foreach my $file (@fl) { - FW_pO ""; - if($file eq "") { - FW_pO ""; - } else { - FW_pH "cmd=style edit $file", $file, 1; - } - FW_pO ""; - $row = ($row+1)%2; - } - FW_pO "

$end"; + + %files= ("global configuration" => $attr{global}{configfile} ); + FW_pFileHash("configuration", %files); + + %files= FW_fileHash("$MW_dir/.*(sh|Util.*|cfg|holiday)"); + FW_pFileHash("modules and other files", %files); + + %files= FW_fileHash("$FW_cssdir/.*.(css|svg)"); + FW_pFileHash("styles", %files); + + %files= FW_fileHash("$FW_gplotdir/.*.gplot"); + FW_pFileHash("gplot files", %files); + + FW_pO $end; + } elsif($a[1] eq "select") { - my @fl = FW_fileList("$FW_dir/.*style.css"); + my @fl = FW_fileList("$FW_cssdir/.*style.css"); FW_pO "$start"; my $row = 0; @@ -1538,17 +1658,21 @@ FW_style($$) } elsif($a[1] eq "edit") { - $a[2] =~ s,/,,g; # little bit of security + # + # edit a file + # + #$a[2] =~ s,/,,g; # little bit of security #my $f = ($a[2] eq "fhem.cfg" ? $attr{global}{configfile} : # "$FW_dir/$a[2]"); - my $f; - if($a[2] eq "fhem.cfg") { - $f = $attr{global}{configfile}; - } elsif ($a[2] =~ m/.*(sh|Util.*|cfg|holiday)/ && $a[2] ne "fhem.cfg") { - $f = "$MW_dir/$a[2]"; - } else { - $f = "$FW_dir/$a[2]"; - } +# my $f; +# if($a[2] eq "fhem.cfg") { +# $f = $attr{global}{configfile}; +# } elsif ($a[2] =~ m/.*(sh|Util.*|cfg|holiday)/ && $a[2] ne "fhem.cfg") { +# $f = "$MW_dir/$a[2]"; +# } else { +# $f = "$FW_dir/$a[2]"; +# } + my $f= $a[2]; if(!open(FH, $f)) { FW_pO "$f: $!"; return; @@ -1604,15 +1728,15 @@ FW_style($$) FW_pO "
"; foreach my $i (sort grep {/^ico/} keys %FW_icons) { FW_pO ""; } FW_pO "
"; - FW_pO "$i"; + FW_pO "$i"; FW_pO ""; - FW_pO ""; + FW_pO ""; FW_pO "
"; } elsif($a[1] eq "eventMonitor") { - FW_pO ""; + FW_pO ""; FW_pO "
"; FW_pO "
"; FW_pO "Events:
\n"; @@ -1661,7 +1785,7 @@ FW_style($$) FW_pO "

"; if($a[2]) { - if(!open(FH, "$FW_dir/commandref.html")) { + if(!open(FH, "$FW_commandref")) { FW_pO "

comandref.html is missing

"; } else { my $inDef; @@ -1673,7 +1797,7 @@ FW_style($$) last if($l =~ m/

/); } chomp($l); - $l =~ s/href="#/href="$FW_reldoc#/g; + $l =~ s/href="#/href="$FW_commandref#/g; FW_pO $l; } close(FH); @@ -1844,6 +1968,45 @@ FW_Attr(@) return undef; } + +sub +FW_ReadIconsFrom($$) { + # recursively reads .gif .jpg .png files and returns filenames as array + # recursion starts at $FW_icondir/$dir + # filenames are relative to $FW_icondir + + my ($prepend,$dir)= @_; + + #Debug "read icons from \"$dir\", prepend \"$prepend\""; + + my (@entries, @filenames); + if(opendir(DH, "${FW_icondir}/${dir}")) { + @entries= sort readdir(DH); # assures order: .gif .jpg .png + closedir(DH); + } + #Debug "$#entries entries found."; + foreach my $entry (@entries) { + my $filename= "$dir/$entry"; + my $iconname= "${prepend}${entry}"; + #Debug " entry: \"$entry\", filename= \"$filename\", iconname= \"$iconname\""; + if( -d "${FW_icondir}/${filename}" ) { + # entry is a directory + FW_ReadIconsFrom("${iconname}/", $filename) unless($entry eq "." || $entry eq ".."); + } elsif( -f "${FW_icondir}/${filename}") { + # entry is a regular file + if($entry =~ m/\.(png|gif|jpg)$/i) { + # extension is .gif .jpg .png + #my $basename= $entry; + #$basename =~ s/\.[^.]+$//; # cut extension + # priority due to sort: .png (highest) to .gif (lowest) + #$FW_icons{"${prepend}${basename}"}= $filenamerel; + # store icon with extension + $FW_icons{"${prepend}${entry}"}= $filename; + } + } + } +} + sub FW_ReadIcons() { @@ -1851,49 +2014,51 @@ FW_ReadIcons() return if($FW_iconsread && ($now - $FW_iconsread) <= 5); %FW_icons = (); - my @files; - if(opendir(DH, $FW_dir)) { - @files = readdir(DH); - closedir(DH); - } - my $prf = AttrVal($FW_wname, "stylesheetPrefix", ""); - if($prf && opendir(DH, "$FW_dir/$prf")) { - push @files, readdir(DH); - closedir(DH); - } - - foreach my $l (sort @files) { # Order: .gif,.jpg,.png - next if($l !~ m/\.(png|gif|jpg)$/i); - my $x = $l; - $x =~ s/\.[^.]+$//; # Cut .gif/.jpg - $FW_icons{$x} = $l; - } + # read icons from default directory + FW_ReadIconsFrom("", "default"); + # read icons from stylesheet specific directory, icons found here supersede default icons with same name + my $prefix= AttrVal($FW_wname, "stylesheetPrefix", ""); + FW_ReadIconsFrom("", "$prefix") unless($prefix eq ""); + # read icons from explicit directory, icons found here supersede all other icons with same name + my $iconpath= AttrVal($FW_wname, "iconpath", ""); + FW_ReadIconsFrom("", "$iconpath") unless($iconpath eq ""); + # if now icons were found so far, read icons from icondir itself + FW_ReadIconsFrom("", "") unless(%FW_icons); $FW_iconsread = $now; + + #foreach my $k (keys %FW_icons) { + # Debug " icon: $k => " . $FW_icons{$k}; + #} + } +sub +FW_IconOrOld($$) { + my ($old,$new)= @_; + my $icon= "${new}.png"; + return $FW_icons{$icon} ? $icon : $old; +} + + sub FW_dev2image($) { my ($name) = @_; - my $d = $defs{$name}; - return "" if(!$name || !$d); + my $icon = ""; + return $icon if(!$name || !$defs{$name}); - my ($type, $state) = ($d->{TYPE}, $d->{STATE}); - return "" if(!$type || !$state); + my ($type, $state) = ($defs{$name}{TYPE}, $defs{$name}{STATE}); + return $icon if(!$type || !defined($state)); + + #Debug "Looking for an icon for $name $type $state"; - my (undef, $rstate) = ReplaceEventMap($name, [undef, $state], 0); $state =~ s/ .*//; # Want to be able to have icons for "on-for-timer xxx" - - my $icon; - $icon = $FW_icons{"$name.$state"} if(!$icon); # lamp.Aus.png - $icon = $FW_icons{"$name.$rstate"} if(!$icon); # lamp.on.png - $icon = $FW_icons{$name} if(!$icon); # lamp.png - $icon = $FW_icons{"$type.$state"} if(!$icon); # FS20.Aus.png - $icon = $FW_icons{"$type.$rstate"} if(!$icon); # FS20.on.png - $icon = $FW_icons{$type} if(!$icon); # FS20.png - $icon = $FW_icons{$state} if(!$icon); # Aus.png - $icon = $FW_icons{$rstate} if(!$icon); # on.png + $icon= FW_IconOrOld($icon,$state); # on + $icon= FW_IconOrOld($icon,$type); # FS20 + $icon= FW_IconOrOld($icon,"$type.$state"); # FS20.on + $icon= FW_IconOrOld($icon,$name); # MyLamp + $icon= FW_IconOrOld($icon,"$name.$state"); # MyLamp.on return $icon; } @@ -2060,6 +2225,7 @@ FW_devState($$) } else { my $icon; $icon = FW_dev2image($d); + #Debug "Dev2Image returned $icon for $d"; $txt = "\"$txt\"/" if($icon); } @@ -2104,34 +2270,7 @@ FW_devState($$) } ##################################### -# This has to be modularized in the future. -sub -WeatherAsHtml($) -{ - my ($d) = @_; - $d = "" if(!$d); - return "$d is not a Weather instance
" - if(!$defs{$d} || $defs{$d}{TYPE} ne "Weather"); - my $imgHome="http://www.google.com"; - my $ret = ""; - $ret .= sprintf('', - $imgHome, ReadingsVal($d, "icon", ""), - ReadingsVal($d, "condition", ""), - ReadingsVal($d, "temp_c", ""), ReadingsVal($d, "humidity", ""), - ReadingsVal($d, "wind_condition", "")); - - for(my $i=1; $i<=4; $i++) { - $ret .= sprintf('', - $imgHome, ReadingsVal($d, "fc${i}_icon", ""), - ReadingsVal($d, "fc${i}_day_of_week", ""), - ReadingsVal($d, "fc${i}_condition", ""), - ReadingsVal($d, "fc${i}_low_c", ""), ReadingsVal($d, "fc${i}_high_c", "")); - } - - $ret .= "
%s
temp %s, hum %s, %s
%s: %s
min %s max %s
"; - return $ret; -} 1; diff --git a/fhem/webfrontend/pgm2/darkstyle.css b/fhem/webfrontend/pgm2/darkstyle.css index 825dff74a..44ebebad7 100644 --- a/fhem/webfrontend/pgm2/darkstyle.css +++ b/fhem/webfrontend/pgm2/darkstyle.css @@ -1,5 +1,5 @@ /* Author: Till */ -body { background-color: #444444; background-image:url(darklogo.png); background-repeat:no-repeat; color: #CCCCCC; font-family:Arial, Helvetica, sans-serif; font-size:13px;} +body { background-color: #444444; background-image:url(../icons/darklogo.png); background-repeat:no-repeat; color: #CCCCCC; font-family:Arial, Helvetica, sans-serif; font-size:13px;} #logo { position:absolute; top:10px; left:20px; width:140px; visibility:hidden; } #menu { position:absolute; top:170px;left:20px; width:140px; } #hdr { position:absolute; top:10px; left:180px; } diff --git a/fhem/webfrontend/pgm2/fhemicon.png b/fhem/webfrontend/pgm2/fhemicon.png index 87cdf6a2808022c0b8718e8e157e23a65f0ff3d2..e5c13a6c049110f06262d93f134dddcb52403d20 100644 GIT binary patch literal 7911 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 diff --git a/fhem/webfrontend/pgm2/smallscreenstyle.css b/fhem/webfrontend/pgm2/smallscreenstyle.css index 5e4131752..669a18eb1 100644 --- a/fhem/webfrontend/pgm2/smallscreenstyle.css +++ b/fhem/webfrontend/pgm2/smallscreenstyle.css @@ -5,7 +5,7 @@ input { font-family:Arial, sans-serif; font-size:16px;} select { font-family:Arial, sans-serif; font-size:16px;} #back { position:absolute; top: 2px; left:18px; } #logo { position:absolute; top: 2px; left: 2px; - width:64px; height:67px; background-image:url(fhem_smallscreen.png); } + width:64px; height:67px; background-image:url(../icons/fhemicon.png); } #menu { position:absolute; top: 2px; left:65px; } #hdr { position:absolute; top:40px; left:65px; } #content { position:absolute; top:85px; left: 0px; right: 0px;} diff --git a/fhem/webfrontend/pgm2/style.css b/fhem/webfrontend/pgm2/style.css index 1e57a1834..d2142787d 100644 --- a/fhem/webfrontend/pgm2/style.css +++ b/fhem/webfrontend/pgm2/style.css @@ -4,7 +4,7 @@ input { font-family:Arial, sans-serif; font-size:16px; } select { font-family:Arial, sans-serif; font-size:16px; } #logo { position:fixed; top:10px; left:20px; - width:100px; height:105px; background-image:url(fhem.png); } + width:100px; height:105px; background-image:url(../icons/fhemicon.png); } #menu { position:fixed; top:120px;left:20px; width:140px; } #hdr { position:absolute; top:10px; left:180px; } #content { position:absolute; top:50px; left:180px; bottom:20px; right:10px; }