mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-04-06 06:08:44 +00:00
Rewrite for the new select handling
git-svn-id: https://svn.fhem.de/fhem/trunk@237 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
4a2aa40f12
commit
076f2c8345
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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";
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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";
|
||||
|
@ -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];
|
||||
|
||||
|
@ -43,9 +43,6 @@ M232_Define($$)
|
||||
|
||||
$hash->{STATE} = "Initialized";
|
||||
|
||||
delete $hash->{PortObj};
|
||||
delete $hash->{FD};
|
||||
|
||||
my $dev = $a[2];
|
||||
$attr{$a[0]}{savefirst} = 1;
|
||||
|
||||
|
@ -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";
|
||||
|
@ -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 }
|
||||
|
@ -163,6 +163,18 @@ make editing of multiline commands transparent.<br><br>
|
||||
see the <a href="#FileLog">FileLog</a> section.
|
||||
</li><br>
|
||||
|
||||
<a name="nofork"></a>
|
||||
<li>nofork<br>
|
||||
If set and the logfile is not "-", do not try to background. Needed
|
||||
on some Fritzbox installations.
|
||||
</li><br>
|
||||
|
||||
<a name="mseclog"></a>
|
||||
<li>nofork<br>
|
||||
If set, the timestamp in the logfile will contain a millisecond part.
|
||||
</li><br>
|
||||
|
||||
|
||||
<a name="modpath"></a>
|
||||
<li>modpath<br>
|
||||
Specify the path to the modules directory <code>FHEM</code>. The path
|
||||
|
@ -81,6 +81,7 @@ and <a href="faq.html">faq.html</a> for more documentation.
|
||||
http://developer.berlios.de/projects/fhem</a><br>
|
||||
LinViex (home automation frontend):
|
||||
<a href="http://sourceforge.net/projects/linviex">
|
||||
<a href=http://shop.busware.de/product_info.php?products_id=29">CUL</CUL>
|
||||
|
||||
http://sourceforge.net/projects/linviex</a><br><br>
|
||||
Device/OS Specific installation guides:<br>
|
||||
|
159
fhem/fhem.pl
159
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 <name> 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 <name> 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 <name> <type-dependent-options>\n" .
|
||||
"$namedef" if(int(@a)<1);
|
||||
return "Usage: set <name> <type-dependent-options>\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 <name> <type-dependent-options>\n" .
|
||||
"$namedef" if(int(@a) < 1);
|
||||
return "Usage: get <name> <type-dependent-options>\n$namedef" if(int(@a) < 1);
|
||||
|
||||
|
||||
my @rets;
|
||||
@ -932,25 +938,41 @@ CommandDefine($$)
|
||||
|
||||
return "Usage: define <name> <type> <type dependent arguments>"
|
||||
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 <name>\n" .
|
||||
"$namedef" if(!$def);
|
||||
return "Usage: delete <name>$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 <name> [<attrname>]\n" .
|
||||
"$namedef" if(@a < 1);
|
||||
return "Usage: deleteattr <name> [<attrname>]\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 <name> <attrname> [<attrvalue>]\n" .
|
||||
"$namedef" if(@a && @a < 2);
|
||||
return "Usage: attr <name> <attrname> [<attrvalue>]\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 <name> <state>\n" .
|
||||
"$namedef" if(@a != 2);
|
||||
return "Usage: setstate <name> <state>\n$namedef" if(@a != 2);
|
||||
|
||||
|
||||
my @rets;
|
||||
@ -1528,8 +1562,7 @@ CommandTrigger($$)
|
||||
my ($cl, $param) = @_;
|
||||
|
||||
my ($dev, $state) = split(" ", $param, 2);
|
||||
return "Usage: trigger <name> <state>\n" .
|
||||
"$namedef" if(!$state);
|
||||
return "Usage: trigger <name> <state>\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};
|
||||
|
@ -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 "<td><a href=\"$v\">$d</a></td>\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 "<td>Broken definition: $v</a></td>";
|
||||
} else {
|
||||
if($va[2] eq "CURRENT") {
|
||||
|
@ -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; }
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user