2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-01-31 06:39:11 +00:00

fhem.pl/devspec: removed range, added :=FILTER=, the = operator is more general

git-svn-id: https://svn.fhem.de/fhem/trunk@4333 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
rudolfkoenig 2013-12-07 11:31:38 +00:00
parent a32f1b58a7
commit 211c4e09ea
4 changed files with 78 additions and 92 deletions

View File

@ -1,6 +1,7 @@
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
# Do not insert empty lines here, update check depends on it.
- SVN
- feature: devspec: removed range, added :FILTER and more general search
- feature: HUEBridge,HUEDevice: support for groups added
- feature: YAMAHA_AVR: new argument "toggle" for mute command
- feature: FB_CALLMONITOR: replace & to & at reverse search

View File

@ -279,34 +279,33 @@ A line ending with \ will be concatenated with the next one, so long lines
<ul>
<li>a single device name. This is the most common case.</li>
<li>a list of devices, separated by comma (,)</li>
<li>a range of devices, separated by dash (-)</li>
<li>a regular expression, if the the spec contains on e of the following
characters: ^*[]$</li>
<li>an attribute of the device, followed by an equal sign (=) and then a
regexp for this attribute. As attribute you can specify either attributes
set with the attr command or one of the "internal" attributes DEF, STATE
and TYPE.</li>
<li>a regular expression</li>
<li>a NAME=VALUE pair, where NAME can be an Internal value like TYPE, a
Reading-Name or an attribute. VALUE is a regexp. To negate the
comparison, use NAME!=VALUE</li>
<li>if the spec is followed by the expression :FILTER=NAME=VALUE, then the
values found in the first round are filtered by the second expression.
</ul>
Example:
Examples:
<ul>
<code>set lamp1 on</code><br>
<code>set lamp1,lamp2,lamp3 on</code><br>
<code>set lamp[1-3] on</code><br>
<code>set lamp.* on</code><br>
<code>set lamp1-lamp3 on</code><br>
<code>set lamp1-lamp3,lamp3 on</code><br>
<code>set room=kitchen off</code><br>
<code>set room=kitchen:FILTER=STATE=on off</code><br>
<code>set room=kitchen:FILTER=STATE!=off off</code><br>
<code>list disabled=</code><br>
<code>list TYPE=FS20</code><br>
<code>list TYPE=FS20 STATE</code><br>
</ul>
Notes:
<ul>
<li>first the spec is separated by komma, then the range or the regular
expression operations are executed.</li>
<li>the spec may not contain space characters.</n>
<li>if there is a device which exactly corresponds to the spec, then
no special processing is done.</li>
<li>first the spec is separated by komma, then the regular expression and
filter operations are executed.</li>
<li>the returned list can contain the same device more than once, so
"set lamp1-lamp3,lamp3 on" switches lamp3 twice.</li>
"set lamp3,lamp3 on" switches lamp3 twice.</li>
<li>for more complex structuring demands see the <a href="#structure">
structure</a> device.
</ul>

View File

@ -265,56 +265,59 @@ Zeilen erstreckende Befehle, indem man keine \ am Zeilenende eingeben muss.</p>
<a name="devspec"></a>
<h3>Ger&auml;te-Spezifikation (devspec)</h3>
<ul>
Befehle wie
Die Befehle
<a href="#attr">attr</a>,
<a href="#set">set</a>,
<a href="#get">get</a>, usw.
<a href="#attr">attr</a>,
<a href="#deleteattr">deleteattr</a>,
<a href="#displayattr">displayattr</a>,
<a href="#delete">delete</a>,
<a href="#get">get</a>,
<a href="#list">list</a>,
<a href="#set">set</a>,
<a href="#setreading">setreading</a>,
<a href="#setstate">setstate</a>,
<a href="#trigger">trigger</a>
k&ouml;nnen eine komplexere Ger&auml;tespezifikation als Argumente enthalten,
die auch eine Anzahl von Ger&auml;ten betreffen kann. Eine
Ger&auml;tespezifikation (Kurzfassung) kann z.B. so aussehen:
Ger&auml;tespezifikation kann folgendes sein:
<ul>
<li>ein einzelner Ger&auml;tename. Dies ist der
meist vorkommende Fall.</li>
<li>
eine Liste von Ger&auml;tenamen, durch Kommata (,) getrennt</li>
<li>
ein Bereich, durch ein Minuszeichen getrennt (-)</li>
<li>ein regul&auml;rer Ausdruck der eines der
folgenden Zeichen enth&auml;lt: ^*[]$</li>
<li>
ein Ger&auml;teattribut, gefolgt von einem Gleichheitszeichen (=) und einem
regul&auml;ren Ausdruck f&uuml;r dieses Attribut.
Als Attribut k&ouml;nnen Sie entweder Attribute die mittels "attr"-Befehl oder
eines der "internen" Attribute wie DEF, STATE oder TYPE angeben.</li>
<li>ein einzelner Ger&auml;tename. Dies ist der Normalfall</li>
<li>eine durch Komma(,) getrennte Liste von Ger&auml;tenamen</li>
<li>ein regul&auml;rer Ausdruck</li>
<li>ein NAME=WERT Ausdruck, wo NAME ein "Internal" Wert wie TYPE ist, ein
Reading-Name oder ein Attribut. WERT ist ein regul&auml;rer Ausdruck.
Um die Bedingung zu negieren, sollte NAME!=WERT verwendet werden.
</li>
<li>Falls die Spezifikation von :FILTER=NAME=WERT gefolgt wird,
dann wird die zuvor gefundene Liste durch diesen neuen Ausdruck
gefiltert.
</ul>
Beispiele:
<ul>
<code>set lamp1 on</code><br>
<code>set lamp1,lamp2,lamp3 on</code><br>
<code>set lamp[1-3] on</code><br>
<code>set lamp.* on</code><br>
<code>set lamp1-lamp3 on</code><br>
<code>set lamp1-lamp3,lamp3 on</code><br>
<code>set room=kitchen off</code><br>
<code>set room=kitchen:FILTER=STATE=on off</code><br>
<code>set room=kitchen:FILTER=STATE!=off off</code><br>
<code>list disabled=</code><br>
<code>list TYPE=FS20</code><br>
<code>list TYPE=FS20 STATE</code><br>
</ul>
Bemerkungen:
<ul>
<li>zuerst wird die durch Kommata getrennte
Spezifikation abgearbeitet, dann folgen die Bereichsspezifikationen und die
regul&auml;ren Ausdr&uuml;cke</li>
<li>
wenn f&uuml;r ein Ger&auml;t eine Spezifikation exakt zutrifft, werden keine weiteren
Vergleiche vorgenommen.</li>
<li>
die Befehlszeile kann die selbe Ger&auml;tebezeichnung mehrfach enthalten z.B.: &quot;set
lamp1-lamp3, lamp3 on&quot;.
Lamp3 wird hier zwei Mal eingeschalten.</li>
<li>um Strukturen mit komplexeren Anforderungen zu realisieren lesen Sie bitte
den Abschnitt zu <a href="#structure">
structure</a>.
</li></ul>
<li>die Spezifikation kann keine Leerzeichen enthalten.</li>
<li>falls ein Ger&auml;tename exakt dem Spezifikation entspricht, dann werden
keine regul&auml;re Ausdr&uuml;cke oder Filter ausgewertet.
<li>zuerst wird die durch Komma getrennte Spezifikation abgearbeitet, dann
folgen die regul&auml;ren Ausdr&uuml;cke und die Filter</li>
<li>die Befehlszeile kann die selbe Ger&auml;tebezeichnung mehrfach enthalten
z.B.: &quot;set lamp3,lamp3 on&quot;. Lamp3 wird hier zwei Mal
eingeschalten.</li>
<li>um Strukturen mit komplexeren Anforderungen zu realisieren lesen Sie
bitte den Abschnitt zu <a href="#structure"> structure</a>.
</ul>
</ul>
<a name="help"></a>

View File

@ -862,8 +862,6 @@ AnalyzeCommand($$)
sub
devspec2array($)
{
my %knownattr = ( "DEF"=>1, "STATE"=>1, "TYPE"=>1 );
my ($name) = @_;
return "" if(!defined($name));
@ -872,59 +870,44 @@ devspec2array($)
return "FHEM2FHEM_FAKE_$name" if($defs{$name}{FAKEDEVICE});
return $name;
}
# FAKE is set by FHEM2FHEM LOG
my ($isattr, @ret);
my @ret;
foreach my $l (split(",", $name)) { # List of elements
my @names = sort keys %defs;
my @res;
foreach my $dName (split(":FILTER=", $name)) {
my ($n,$op,$re) = ("NAME","=",$dName);
($n,$op,$re) = ($1,$2,$3) if($dName =~ m/^([^!]*)(=|!=)(.*)$/);
foreach my $l (split(",", $name)) { # List
if($l =~ m/(.*)=(.*)/) {
my ($lattr,$re) = ($1, $2);
if($knownattr{$lattr}) {
eval { # a bad regexp may shut down fhem.pl
foreach my $l (sort keys %defs) {
push @ret, $l
if($defs{$l}{$lattr} && (!$re || $defs{$l}{$lattr}=~m/^$re$/));
@res=();
foreach my $d (@names) {
next if($attr{$d} && $attr{$d}{ignore});
my $hash = $defs{$d};
my $val = $hash->{$n};
if(!defined($val)) {
my $r = $hash->{READINGS};
$val = $r->{$n}{VAL} if($r && $r->{$n});
}
if(!defined($val)) {
$val = $attr{$d}{$n} if($attr{$d});
}
next if(!defined($val));
eval { # a bad regexp is deadly
if(($op eq "=" && $val =~ m/^$re$/) ||
($op eq "!=" && $val !~ m/^$re$/)) {
push @res, $d
}
};
if($@) {
Log 1, "devspec2array $name: $@";
return $name;
}
} else {
foreach my $l (sort keys %attr) {
push @ret, $l
if($attr{$l}{$lattr} && (!$re || $attr{$l}{$lattr} =~ m/$re/));
}
}
$isattr = 1;
next;
@names = @res;
}
my $regok;
eval { # a bad regexp may shut down fhem.pl
if($l =~ m/[*\[\]^\$]/) { # Regexp
push @ret, grep($_ =~ m/^$l$/, sort keys %defs);
$regok = 1;
}
};
if($@) {
Log 1, "devspec2array $name: $@";
return $name;
}
next if($regok);
if($l =~ m/-/) { # Range
my ($lower, $upper) = split("-", $l, 2);
push @ret, grep($_ ge $lower && $_ le $upper, sort keys %defs);
next;
}
push @ret, $l;
push @ret,@res;
}
return $name if(!@ret && !$isattr); # No match, return the input
@ret = grep { !$attr{$_} || !$attr{$_}{ignore} } @ret
if($name !~ m/^ignore=/);
return $name if(!@ret);
return @ret;
}