diff --git a/fhem/CHANGED b/fhem/CHANGED index 4985317af..82f3e56ad 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -424,3 +424,8 @@ - ==DATE== (4.5) - feature: further 01_FHEMWEB cleanup + - feature: CUL support for FS20(r/w), FHT(readonly), KS300, EM + - feature: list outputs the device attributes too + - bugfix: rename bugs fixed + - bugfix: better integration of ReadyFn (Windows), slight overall speedup + - bugfix: Ignore/correct "type" casing when autoloading modules diff --git a/fhem/FHEM/00_CUL.pm b/fhem/FHEM/00_CUL.pm index b6037afcb..26fdd561e 100755 --- a/fhem/FHEM/00_CUL.pm +++ b/fhem/FHEM/00_CUL.pm @@ -104,7 +104,12 @@ CUL_Define($$) Log 3, "CUL opened CUL device $dev"; $hash->{PortObj} = $po; - $hash->{FD} = $po->FILENO if !( $^O =~ /Win/ ); + if( $^O !~ /Win/ ) { + $hash->{FD} = $po->FILENO; + $selectlist{"$name.$dev"} = $hash; + } else { + $readyfnlist{"$name.$dev"} = $hash; + } $hash->{DeviceName} = $dev; $hash->{PARTIAL} = ""; @@ -138,7 +143,7 @@ CUL_Set($@) my ($hash, @a) = @_; return "\"set CUL\" needs at least one parameter" if(@a < 2); - return "Unknown argument $a[1], choose one of " . join(",", sort keys %sets) + return "Unknown argument $a[1], choose one of " . join(" ", sort keys %sets) if(!defined($sets{$a[1]})); my $arg = ($a[2] ? $a[2] : ""); @@ -153,7 +158,7 @@ CUL_Get($@) my ($hash, @a) = @_; return "\"get CUL\" needs at least one parameter" if(@a < 2); - return "Unknown argument $a[1], choose one of " . join(",", sort keys %gets) + return "Unknown argument $a[1], choose one of " . join(" ", sort keys %gets) if(!defined($gets{$a[1]})); my $arg = ($a[2] ? $a[2] : ""); @@ -481,12 +486,13 @@ Log 1, "CUL: $dmsg"; goto NEXTMSG if($found[0] eq ""); # Special return: Do not notify + # The trigger needs a device: we create a minimal temporary one if($found[0] =~ m/^(UNDEFINED) ([^ ]*) (.*)$/) { my $d = $1; $defs{$d}{NAME} = $1; $defs{$d}{TYPE} = $last_module; DoTrigger($d, "$2 $3"); - delete $defs{$d}; + CommandDelete(undef, $d); # Remove the device goto NEXTMSG; } diff --git a/fhem/FHEM/00_FHZ.pm b/fhem/FHEM/00_FHZ.pm index 9ca57bbe4..3bc90f009 100755 --- a/fhem/FHEM/00_FHZ.pm +++ b/fhem/FHEM/00_FHZ.pm @@ -60,7 +60,7 @@ FHZ_Initialize($) $hash->{ReadFn} = "FHZ_Read"; $hash->{WriteFn} = "FHZ_Write"; $hash->{Clients} = ":FHZ:FS20:FHT:HMS:KS300:"; - $hash->{ReadyFn} = "FHZ_Ready" if ($^O eq 'MSWin32'); + $hash->{ReadyFn} = "FHZ_Ready"; # Consumer $hash->{Match} = "^81..C9..0102"; @@ -273,7 +273,12 @@ FHZ_Define($$) $hash->{PortObj} = $po; - $hash->{FD} = $po->FILENO if !( $^O =~ /Win/ ); + if( $^O !~ /Win/ ) { + $hash->{FD} = $po->FILENO; + $selectlist{"$name.$dev"} = $hash; + } else { + $readyfnlist{"$name.$dev"} = $hash; + } $hash->{DeviceName} = $dev; @@ -643,12 +648,13 @@ FHZ_Read($) goto NEXTMSG if($found[0] eq ""); # Special return: Do not notify + # The trigger needs a device: we create a minimal temporary one if($found[0] =~ m/^(UNDEFINED) ([^ ]*) (.*)$/) { my $d = $1; $defs{$d}{NAME} = $1; $defs{$d}{TYPE} = $last_module; DoTrigger($d, "$2 $3"); - delete $defs{$d}; + CommandDelete(undef, $d); # Remove the device goto NEXTMSG; } diff --git a/fhem/FHEM/00_LIRC.pm b/fhem/FHEM/00_LIRC.pm index e2e3990b1..e22992e9c 100644 --- a/fhem/FHEM/00_LIRC.pm +++ b/fhem/FHEM/00_LIRC.pm @@ -56,6 +56,7 @@ LIRC_Define($$) $hash->{LircObj} = $lirc; $hash->{FD} = $lirc->sock; + $selectlist{"$name.$config"} = $hash; $hash->{SelectObj} = $select; $hash->{DeviceName} = $name; $hash->{STATE} = "Opened"; diff --git a/fhem/FHEM/10_FS20.pm b/fhem/FHEM/10_FS20.pm index 734ac37be..0baa37eae 100755 --- a/fhem/FHEM/10_FS20.pm +++ b/fhem/FHEM/10_FS20.pm @@ -205,7 +205,7 @@ FS20_Set($@) ########################################### # Set the state of a device to off if on-for-timer is called if($follow{$a[0]}) { - CommandDelete(undef, "at .*setstate.*$a[0]"); + CommandDelete(undef, $a[0] . "_timer"); delete $follow{$a[0]}; } if($a[1] eq "on-for-timer" && $na == 3 && @@ -303,8 +303,12 @@ FS20_Undef($$) my ($hash, $name) = @_; foreach my $c (keys %{ $hash->{CODE} } ) { $c = $hash->{CODE}{$c}; - delete($defptr{$c}{$name}) if($defptr{$c}); - delete($defptr{$c}{$name}) if(!%{$defptr{$c}}); + + # As after a rename the $name my be different from the $defptr{$c}{$n} + # we look for the hash. + foreach my $dname (keys %{ $defptr{$c} }) { + delete($defptr{$c}{$dname}) if($defptr{$c}{$dname} == $hash); + } } return undef; } diff --git a/fhem/FHEM/15_CUL_EM.pm b/fhem/FHEM/15_CUL_EM.pm index 393e47bca..1253420b7 100755 --- a/fhem/FHEM/15_CUL_EM.pm +++ b/fhem/FHEM/15_CUL_EM.pm @@ -81,7 +81,7 @@ CUL_EM_Parse($$) $cum *= $corr; $lst *= $corr; $top *= $corr; - $val = sprintf("CND %d CUM: %0.3f 5MIN: %0.3f TOP: %0.3f", + $val = sprintf("CNT %d CUM: %0.3f 5MIN: %0.3f TOP: %0.3f", $cnt, $cum, $lst, $top); my $n = $hash->{NAME}; Log GetLogLevel($n,1), "CUL_EM $n: $val"; diff --git a/fhem/FHEM/60_EM.pm b/fhem/FHEM/60_EM.pm index 0e3db3974..4817fc080 100755 --- a/fhem/FHEM/60_EM.pm +++ b/fhem/FHEM/60_EM.pm @@ -45,9 +45,6 @@ EM_Define($$) my $po; $hash->{STATE} = "Initialized"; - delete $hash->{PortObj}; - delete $hash->{FD}; - my $name = $a[0]; my $dev = $a[2]; diff --git a/fhem/FHEM/80_M232.pm b/fhem/FHEM/80_M232.pm index d5423f200..99e5dfe91 100644 --- a/fhem/FHEM/80_M232.pm +++ b/fhem/FHEM/80_M232.pm @@ -43,9 +43,6 @@ M232_Define($$) $hash->{STATE} = "Initialized"; - delete $hash->{PortObj}; - delete $hash->{FD}; - my $dev = $a[2]; $attr{$a[0]}{savefirst} = 1; diff --git a/fhem/FHEM/87_WS2000.pm b/fhem/FHEM/87_WS2000.pm index bda30270a..d866b75b7 100644 --- a/fhem/FHEM/87_WS2000.pm +++ b/fhem/FHEM/87_WS2000.pm @@ -4,7 +4,7 @@ package main; # Modul for FHEM # # contributed by thomas dressler 2008 -# $Id: 87_WS2000.pm,v 1.3 2008-05-11 21:17:30 tdressler Exp $ +# $Id: 87_WS2000.pm,v 1.4 2008-09-06 08:33:25 rudolfkoenig Exp $ ########################### use strict; use Switch; @@ -81,6 +81,7 @@ WS2000_Define($$) return "Can't open Device $PortName: $^E\n"; } #$hash->{FD}=$PortObj->{_HANDLE}; + $readyfnlist{"$a[0].$a[2]"} = $hash; } else { eval ("use Device::SerialPort;"); if ($@) { @@ -94,7 +95,8 @@ WS2000_Define($$) Log 1,"Error opening Serial Device $PortName"; return "Can't open Device $PortName: $^E\n"; } - #$hash->{FD}=$PortObj->FILENO; + $hash->{FD}=$PortObj->FILENO; + $selectlist{"$a[0].$a[2]"} = $hash; } #Parameter 19200,8,2,Odd,None $PortObj->baudrate(19200); @@ -125,13 +127,14 @@ WS2000_Define($$) } $xport->autoflush(1); $hash->{FD}=$xport->fileno; + $selectlist{"$a[0].$a[2]"} = $hash; $hash->{socket}=$xport; }else{ - $hash->{STATE} = "$PortName is no device and not implemented"; - Log 1,"$PortName is no device and not implemented"; - return "$PortName is no device and not implemented\n"; + $hash->{STATE} = "$PortName is no device and not implemented"; + Log 1,"$PortName is no device and not implemented"; + return "$PortName is no device and not implemented\n"; } Log 4, "$name connected to device $PortName"; $hash->{STATE} = "open"; diff --git a/fhem/FHEM/90_at.pm b/fhem/FHEM/90_at.pm index ad779939d..33f0725ee 100755 --- a/fhem/FHEM/90_at.pm +++ b/fhem/FHEM/90_at.pm @@ -92,7 +92,7 @@ at_Exec($) my $count = $defs{$name}{REP}; my $def = $defs{$name}{DEF}; - delete $defs{$name}; + CommandDelete(undef, $name); # Recreate ourselves if($count) { $def =~ s/{\d+}/{$count}/ if($def =~ m/^\+?\*{/); # Replace the count } diff --git a/fhem/docs/commandref.html b/fhem/docs/commandref.html index cf7288008..719de77c5 100644 --- a/fhem/docs/commandref.html +++ b/fhem/docs/commandref.html @@ -163,6 +163,18 @@ make editing of multiline commands transparent.

see the FileLog section.
+ +
  • nofork
    + If set and the logfile is not "-", do not try to background. Needed + on some Fritzbox installations. +

  • + + +
  • nofork
    + If set, the timestamp in the logfile will contain a millisecond part. +

  • + +
  • modpath
    Specify the path to the modules directory FHEM. The path diff --git a/fhem/docs/fhem.html b/fhem/docs/fhem.html index 5ec921141..591bfcf43 100644 --- a/fhem/docs/fhem.html +++ b/fhem/docs/fhem.html @@ -81,6 +81,7 @@ and faq.html for more documentation. http://developer.berlios.de/projects/fhem
    LinViex (home automation frontend): + CUL http://sourceforge.net/projects/linviex

    Device/OS Specific installation guides:
    diff --git a/fhem/fhem.pl b/fhem/fhem.pl index b95fb3e6b..682e82ef0 100755 --- a/fhem/fhem.pl +++ b/fhem/fhem.pl @@ -114,7 +114,7 @@ sub CommandTrigger($$); # NR - its "serial" number # DEF - its definition # READINGS- The readings. Each value has a "VAL" and a "TIME" component. -# FD - FileDescriptor. If set, it will be integrated into the global select +# FD - FileDescriptor. Used by selectlist / readyfnlist # IODev - attached to io device # CHANGED - Currently changed attributes of this device. Used by NotifyFn # VOLATILE- Set if the definition should be saved to the "statefile" @@ -122,6 +122,8 @@ sub CommandTrigger($$); use vars qw(%modules); # List of loaded modules (device/log/etc) use vars qw(%defs); # FHEM device/button definitions use vars qw(%attr); # Attributes +use vars qw(%selectlist); # devices which want a "select" +use vars qw(%readyfnlist); # devices which want a "readyfn" use vars qw(%value); # Current values, see commandref.html use vars qw(%oldvalue); # Old values, see commandref.html @@ -143,7 +145,14 @@ my $nextat; # Time when next timer will be triggered. my $intAtCnt=0; my $reread_active = 0; my $AttrList = "room comment"; -my $cvsid = '$Id: fhem.pl,v 1.53 2008-08-25 09:52:29 rudolfkoenig Exp $'; +my $cvsid = '$Id: fhem.pl,v 1.54 2008-09-06 08:33:55 rudolfkoenig Exp $'; +my $namedef = + "where is either:\n" . + "- a single device name\n" . + "- a list seperated by komma (,)\n" . + "- a regexp, if contains one of the following characters: *[]^\$\n" . + "- a range seperated by dash (-)\n"; + $init_done = 0; @@ -152,7 +161,7 @@ $modules{_internal_}{LOADED} = 1; $modules{_internal_}{AttrList} = "archivecmd allowfrom archivedir configfile lastinclude logfile " . "modpath nrarchive pidfilename port statefile title userattr " . - "verbose:1,2,3,4,5 mseclog version"; + "verbose:1,2,3,4,5 mseclog version nofork"; my %cmds = ( @@ -242,7 +251,7 @@ my $ret = CommandInclude(undef, $attr{global}{configfile}); die($ret) if($ret); # Go to background if the logfile is a real file (not stdout) -if($attr{global}{logfile} ne "-") { +if($attr{global}{logfile} ne "-" && !$attr{global}{nofork}) { defined(my $pid = fork) || die "Can't fork: $!"; exit(0) if $pid; } @@ -273,13 +282,15 @@ while (1) { my ($rout, $rin) = ('', ''); vec($rin, $server->fileno(), 1) = 1; - foreach my $p (keys %defs) { - vec($rin, $defs{$p}{FD}, 1) = 1 if($defs{$p}{FD}); + foreach my $p (keys %selectlist) { + vec($rin, $selectlist{$p}{FD}, 1) = 1 } foreach my $c (keys %client) { vec($rin, fileno($client{$c}{fd}), 1) = 1; } - my $timeout=HandleTimeout()||0.2;#0.2s if nothing else defined + + my $timeout = HandleTimeout(); + $timeout = 0.1 if(!defined($timeout) && keys %readyfnlist); my $nfound = select($rout=$rin, undef, undef, $timeout); CommandShutdown(undef, undef) if($sig_term); @@ -290,12 +301,16 @@ while (1) { } ############################### - # Message from the hardware (FHZ1000/WS3000/etc) via FD or from Ready Function - foreach my $p (keys %defs) { - my $ready = CallFn($p,"ReadyFn",$defs{$p}); - if(($defs{$p}{FD} && vec($rout, $defs{$p}{FD}, 1)) || $ready) { - CallFn($p, "ReadFn", $defs{$p}); - } + # Message from the hardware (FHZ1000/WS3000/etc) via select or the Ready + # Function. The latter ist needed for Windows, where USB devices are not + # reported by select. + foreach my $p (keys %selectlist) { + CallFn($selectlist{$p}{NAME}, "ReadFn", $selectlist{$p}) + if(vec($rout, $selectlist{$p}{FD}, 1)); + } + foreach my $p (keys %readyfnlist) { + CallFn($readyfnlist{$p}{NAME}, "ReadFn", $readyfnlist{$p}) + if(CallFn($readyfnlist{$p}{NAME}, "ReadyFn", $readyfnlist{$p})); } if(vec($rout, $server->fileno(), 1)) { @@ -569,18 +584,11 @@ AnalyzeCommand($$) return $ret; } -##################################### -my $namedef = - "where is either:\n" . - "- a single device name\n" . - "- a list seperated by komma (,)\n" . - "- a regexp, if contains one of the following characters: *[]^\$\n" . - "- a range seperated by dash (-)\n"; - sub devspec2array($) { my ($name) = @_; + return "" if(!defined($name)); return $name if(defined($defs{$name})); my @ret; @@ -874,8 +882,7 @@ CommandSet($$) { my ($cl, $param) = @_; my @a = split("[ \t][ \t]*", $param); - return "Usage: set \n" . - "$namedef" if(int(@a)<1); + return "Usage: set \n$namedef" if(int(@a)<1); my @rets; foreach my $sdev (devspec2array($a[0])) { @@ -901,8 +908,7 @@ CommandGet($$) my ($cl, $param) = @_; my @a = split("[ \t][ \t]*", $param); - return "Usage: get \n" . - "$namedef" if(int(@a) < 1); + return "Usage: get \n$namedef" if(int(@a) < 1); my @rets; @@ -932,25 +938,41 @@ CommandDefine($$) return "Usage: define " if(int(@a) < 2); - - my $m = $a[1]; - if($modules{$m} && !$modules{$m}{LOADED}) { # autoload - my $o = $modules{$m}{ORDER}; - CommandReload($cl, "${o}_$m"); - } - - if(!$modules{$m} || !$modules{$m}{DefFn}) { - my @m; - foreach my $i (sort keys %modules) { # Return a list of modules - push @m, $i if($modules{$i}{DefFn} || !$modules{$i}{LOADED}); - } - return "Unknown argument $m, choose one of @m"; - } - return "$a[0] already defined, delete it first" if(defined($defs{$a[0]})); return "Invalid characters in name (not A-Za-z0-9.:_): $a[0]" if($a[0] !~ m/^[a-z0-9.:_]*$/i); + my $m = $a[1]; + if(!$modules{$m}) { # Perhaps just wrong case? + foreach my $i (keys %modules) { + if(uc($m) eq uc($i)) { + $m = $i; + last; + } + } + } + + if($modules{$m} && !$modules{$m}{LOADED}) { # autoload + my $o = $modules{$m}{ORDER}; + CommandReload($cl, "${o}_$m"); + + if(!$modules{$m}{LOADED}) { # Case corrected by reload? + foreach my $i (keys %modules) { + if(uc($m) eq uc($i) && $modules{$i}{LOADED}) { + delete($modules{$m}); + $m = $i; + last; + } + } + } + } + + if(!$modules{$m} || !$modules{$m}{DefFn}) { + my @m = grep { $modules{$_}{DefFn} || !$modules{$_}{LOADED} } + sort keys %modules; + return "Unknown argument $m, choose one of @m"; + } + my %hash; $hash{NAME} = $a[0]; @@ -965,7 +987,8 @@ CommandDefine($$) my $ret = CallFn($a[0], "DefFn", \%hash, $def); if($ret) { - delete $defs{$a[0]} + delete $defs{$a[0]}; # Veto + delete $attr{$a[0]}; } else { foreach my $da (sort keys (%defaultattr)) { # Default attributes CommandAttr($cl, "$a[0] $da $defaultattr{$da}"); @@ -1021,8 +1044,7 @@ CommandDelete($$) { my ($cl, $def) = @_; - return "Usage: delete \n" . - "$namedef" if(!$def); + return "Usage: delete $namedef\n" if(!$def); my @rets; foreach my $sdev (devspec2array($def)) { @@ -1036,8 +1058,18 @@ CommandDelete($$) push @rets, $ret; next; } + + # Delete releated hashes + foreach my $p (keys %selectlist) { + delete $selectlist{$p} if($selectlist{$p}{NAME} eq $sdev); + } + foreach my $p (keys %readyfnlist) { + delete $readyfnlist{$p} if($readyfnlist{$p}{NAME} eq $sdev); + } + delete($attr{$sdev}); - delete($defs{$sdev}); + delete($defs{$sdev}); # Remove the main entry + } return join("\n", @rets); } @@ -1049,8 +1081,7 @@ CommandDeleteAttr($$) my ($cl, $def) = @_; my @a = split(" ", $def, 2); - return "Usage: deleteattr []\n" . - "$namedef" if(@a < 1); + return "Usage: deleteattr []\n$namedef" if(@a < 1); my @rets; foreach my $sdev (devspec2array($a[0])) { @@ -1141,6 +1172,8 @@ CommandList($$) } $str .= "Internals:\n"; $str .= PrintHash($defs{$sdev}, 2); + $str .= "Attributes:\n"; + $str .= PrintHash($attr{$sdev}, 2); } } @@ -1254,6 +1287,7 @@ CommandReload($$) } } $ret = &{ "${fnname}_Initialize" }(\%hash); + $m = $fnname; }; if($@) { @@ -1281,7 +1315,8 @@ CommandRename($$) return "Cannot rename global" if($old eq "global"); $defs{$new} = $defs{$old}; - delete($defs{$old}); + $defs{$new}{NAME} = $new; + delete($defs{$old}); # The new pointer will preserve the hash $attr{$new} = $attr{$old} if(defined($attr{$old})); delete($attr{$old}); @@ -1378,7 +1413,7 @@ GlobalAttr($$) next if($m !~ m/^([0-9][0-9])_(.*)\.pm$/); $modules{$2}{ORDER} = $1; CommandReload(undef, $m) # Always load utility modules - if($1 eq "99" && $modules{$2} && !$modules{$2}{LOADED}); + if($1 eq "99" && !$modules{$2}{LOADED}); $counter++; } closedir(DH); @@ -1403,8 +1438,8 @@ CommandAttr($$) my @a; @a = split(" ", $param, 3) if($param); - return "Usage: attr []\n" . - "$namedef" if(@a && @a < 2); + return "Usage: attr []\n$namedef" + if(@a && @a < 2); my @rets; foreach my $sdev (devspec2array($a[0])) { @@ -1475,8 +1510,7 @@ CommandSetstate($$) my ($cl, $param) = @_; my @a = split(" ", $param, 2); - return "Usage: setstate \n" . - "$namedef" if(@a != 2); + return "Usage: setstate \n$namedef" if(@a != 2); my @rets; @@ -1528,8 +1562,7 @@ CommandTrigger($$) my ($cl, $param) = @_; my ($dev, $state) = split(" ", $param, 2); - return "Usage: trigger \n" . - "$namedef" if(!$state); + return "Usage: trigger \n$namedef" if(!$state); my @rets; foreach my $sdev (devspec2array($dev)) { @@ -1794,11 +1827,11 @@ DoTrigger($$) ################ # Inform - for(my $i = 0; $i < $max; $i++) { - my $state = $defs{$dev}{CHANGED}[$i]; - my $fe = "$dev:$state"; - foreach my $c (keys %client) { - next if(!$client{$c}{inform}); + foreach my $c (keys %client) { # Do client loop first, is cheaper + next if(!$client{$c}{inform}); + for(my $i = 0; $i < $max; $i++) { + my $state = $defs{$dev}{CHANGED}[$i]; + my $fe = "$dev:$state"; syswrite($client{$c}{fd}, "$defs{$dev}{TYPE} $dev $state\n"); } } @@ -1839,9 +1872,13 @@ CallFn(@) { my $d = shift; my $n = shift; + + if(!$defs{$d}) { + Log 0, "Strange call for nonexistent $d: $n"; + return undef; + } if(!$defs{$d}{TYPE}) { - Log 0, "Removing $d, has no TYPE"; - delete($defs{$d}); + Log 0, "Strange call for typeless $d: $n"; return undef; } my $fn = $modules{$defs{$d}{TYPE}}{$n}; diff --git a/fhem/webfrontend/pgm2/01_FHEMWEB.pm b/fhem/webfrontend/pgm2/01_FHEMWEB.pm index b43bf9cf8..f79a30a45 100755 --- a/fhem/webfrontend/pgm2/01_FHEMWEB.pm +++ b/fhem/webfrontend/pgm2/01_FHEMWEB.pm @@ -97,6 +97,8 @@ FW_Define($$) return "Can't open server port at $port: $!" if(!$hash->{PORT}); $hash->{FD} = $hash->{PORT}->fileno(); + + $selectlist{"$name.$port"} = $hash; $hash->{SERVERSOCKET} = 1; Log(2, "FHEMWEB port $port opened"); @@ -108,7 +110,8 @@ sub FW_Undef($$) { my ($hash, $arg) = @_; - close($hash->{PORT}) if(defined($hash->{PORT})); # Clients do not have PORT + close($hash->{CD}) if(defined($hash->{CD})); # Clients + close($hash->{PORT}) if(defined($hash->{PORT})); # Server return undef; } @@ -143,6 +146,8 @@ FW_Read($) $nhash{BUF} = ""; $defs{$nhash{NAME}} = \%nhash; + $selectlist{$nhash{NAME}} = \%nhash; + Log($ll, "Connection accepted from $nhash{NAME}"); return; @@ -157,9 +162,7 @@ FW_Read($) my $ret = sysread($hash->{CD}, $buf, 1024); if(!defined($ret) || $ret <= 0) { - close($hash->{CD}); - delete($defs{$hash->{NAME}}); - # Don't delete the attr entry. + my $r = CommandDelete(undef, $hash->{NAME}); Log($ll, "Connection closed for $hash->{NAME}"); return; } @@ -1212,6 +1215,7 @@ FW_style($$) pO "$f: $!"; return; } + $__data =~ s/\r//g if($^O ne 'MSWin32'); print FH $__data; close(FH); FW_style("style list", "Saved file $f"); @@ -1269,7 +1273,7 @@ FW_showWeblink($$$) pO "$d\n"; } elsif($t eq "fileplot") { my @va = split(":", $v, 3); - if(@va != 3 || !$defs{$va[0]}{currentlogfile}) { + if(@va != 3 || !$defs{$va[0]} || !$defs{$va[0]}{currentlogfile}) { pO "Broken definition: $v"; } else { if($va[2] eq "CURRENT") { diff --git a/fhem/webfrontend/pgm2/style.css b/fhem/webfrontend/pgm2/style.css index d883317c0..a4b29edb2 100644 --- a/fhem/webfrontend/pgm2/style.css +++ b/fhem/webfrontend/pgm2/style.css @@ -29,9 +29,19 @@ table.KS300 tr.odd { background: #A7FFA7; } table.FHZ { border:thin solid; width: 100%; background: #C0C0C0; } table.FHZ tr.odd { background: #D7D7D7; } +table.CUL { border:thin solid; width: 100%; background: #C0C0C0; } +table.CUL tr.odd { background: #D7D7D7; } + table.EM { border:thin solid; width: 100%; background: #E0E0E0; } table.EM tr.odd { background: #F0F0F0; } +table.CUL_EM { border:thin solid; width: 100%; background: #E0E0E0; } +table.CUL_EM tr.odd { background: #F0F0F0; } + +table.CUL_WS { border:thin solid; width: 100%; background: #FFC0C0; } +table.CUL_WS tr.odd { background: #FFD7D7; } + + table.FHEMWEB { border:thin solid; width: 100%; background: #E0E0E0; } table.FHEMWEB tr.odd { background: #F0F0F0; }