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; }