2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-28 11:01:59 +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. # 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. # Do not insert empty lines here, update check depends on it.
- SVN - SVN
- feature: devspec: removed range, added :FILTER and more general search
- feature: HUEBridge,HUEDevice: support for groups added - feature: HUEBridge,HUEDevice: support for groups added
- feature: YAMAHA_AVR: new argument "toggle" for mute command - feature: YAMAHA_AVR: new argument "toggle" for mute command
- feature: FB_CALLMONITOR: replace & to & at reverse search - 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> <ul>
<li>a single device name. This is the most common case.</li> <li>a single device name. This is the most common case.</li>
<li>a list of devices, separated by comma (,)</li> <li>a list of devices, separated by comma (,)</li>
<li>a range of devices, separated by dash (-)</li> <li>a regular expression</li>
<li>a regular expression, if the the spec contains on e of the following <li>a NAME=VALUE pair, where NAME can be an Internal value like TYPE, a
characters: ^*[]$</li> Reading-Name or an attribute. VALUE is a regexp. To negate the
<li>an attribute of the device, followed by an equal sign (=) and then a comparison, use NAME!=VALUE</li>
regexp for this attribute. As attribute you can specify either attributes <li>if the spec is followed by the expression :FILTER=NAME=VALUE, then the
set with the attr command or one of the "internal" attributes DEF, STATE values found in the first round are filtered by the second expression.
and TYPE.</li>
</ul> </ul>
Example: Examples:
<ul> <ul>
<code>set lamp1 on</code><br> <code>set lamp1 on</code><br>
<code>set lamp1,lamp2,lamp3 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 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 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 disabled=</code><br>
<code>list TYPE=FS20</code><br> <code>list TYPE=FS20 STATE</code><br>
</ul> </ul>
Notes: Notes:
<ul> <ul>
<li>first the spec is separated by komma, then the range or the regular <li>the spec may not contain space characters.</n>
expression operations are executed.</li>
<li>if there is a device which exactly corresponds to the spec, then <li>if there is a device which exactly corresponds to the spec, then
no special processing is done.</li> 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 <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"> <li>for more complex structuring demands see the <a href="#structure">
structure</a> device. structure</a> device.
</ul> </ul>

View File

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

View File

@ -862,8 +862,6 @@ AnalyzeCommand($$)
sub sub
devspec2array($) devspec2array($)
{ {
my %knownattr = ( "DEF"=>1, "STATE"=>1, "TYPE"=>1 );
my ($name) = @_; my ($name) = @_;
return "" if(!defined($name)); return "" if(!defined($name));
@ -872,59 +870,44 @@ devspec2array($)
return "FHEM2FHEM_FAKE_$name" if($defs{$name}{FAKEDEVICE}); return "FHEM2FHEM_FAKE_$name" if($defs{$name}{FAKEDEVICE});
return $name; 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 @res=();
foreach my $d (@names) {
if($l =~ m/(.*)=(.*)/) { next if($attr{$d} && $attr{$d}{ignore});
my ($lattr,$re) = ($1, $2); my $hash = $defs{$d};
if($knownattr{$lattr}) { my $val = $hash->{$n};
eval { # a bad regexp may shut down fhem.pl if(!defined($val)) {
foreach my $l (sort keys %defs) { my $r = $hash->{READINGS};
push @ret, $l $val = $r->{$n}{VAL} if($r && $r->{$n});
if($defs{$l}{$lattr} && (!$re || $defs{$l}{$lattr}=~m/^$re$/)); }
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($@) { if($@) {
Log 1, "devspec2array $name: $@"; Log 1, "devspec2array $name: $@";
return $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; @names = @res;
next;
} }
push @ret,@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;
} }
return $name if(!@ret);
return $name if(!@ret && !$isattr); # No match, return the input
@ret = grep { !$attr{$_} || !$attr{$_}{ignore} } @ret
if($name !~ m/^ignore=/);
return @ret; return @ret;
} }