mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-01-31 12:49:34 +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:
parent
a32f1b58a7
commit
211c4e09ea
@ -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
|
||||
|
@ -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>
|
||||
|
@ -265,56 +265,59 @@ Zeilen erstreckende Befehle, indem man keine \ am Zeilenende eingeben muss.</p>
|
||||
<a name="devspec"></a>
|
||||
<h3>Gerä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önnen eine komplexere Gerätespezifikation als Argumente enthalten,
|
||||
die auch eine Anzahl von Geräten betreffen kann. Eine
|
||||
Gerätespezifikation (Kurzfassung) kann z.B. so aussehen:
|
||||
Gerätespezifikation kann folgendes sein:
|
||||
<ul>
|
||||
<li>ein einzelner Gerätename. Dies ist der
|
||||
meist vorkommende Fall.</li>
|
||||
<li>
|
||||
eine Liste von Gerätenamen, durch Kommata (,) getrennt</li>
|
||||
<li>
|
||||
ein Bereich, durch ein Minuszeichen getrennt (-)</li>
|
||||
<li>ein regulärer Ausdruck der eines der
|
||||
folgenden Zeichen enthält: ^*[]$</li>
|
||||
<li>
|
||||
ein Geräteattribut, gefolgt von einem Gleichheitszeichen (=) und einem
|
||||
regulären Ausdruck für dieses Attribut.
|
||||
Als Attribut können Sie entweder Attribute die mittels "attr"-Befehl oder
|
||||
eines der "internen" Attribute wie DEF, STATE oder TYPE angeben.</li>
|
||||
<li>ein einzelner Gerätename. Dies ist der Normalfall</li>
|
||||
<li>eine durch Komma(,) getrennte Liste von Gerätenamen</li>
|
||||
<li>ein regulä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ä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ären Ausdrücke</li>
|
||||
<li>
|
||||
wenn für ein Gerät eine Spezifikation exakt zutrifft, werden keine weiteren
|
||||
Vergleiche vorgenommen.</li>
|
||||
<li>
|
||||
die Befehlszeile kann die selbe Gerätebezeichnung mehrfach enthalten z.B.: "set
|
||||
lamp1-lamp3, lamp3 on".
|
||||
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ätename exakt dem Spezifikation entspricht, dann werden
|
||||
keine reguläre Ausdrücke oder Filter ausgewertet.
|
||||
<li>zuerst wird die durch Komma getrennte Spezifikation abgearbeitet, dann
|
||||
folgen die regulären Ausdrücke und die Filter</li>
|
||||
<li>die Befehlszeile kann die selbe Gerätebezeichnung mehrfach enthalten
|
||||
z.B.: "set lamp3,lamp3 on". 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>
|
||||
|
71
fhem/fhem.pl
71
fhem/fhem.pl
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user