mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-03-12 22:56:34 +00:00
AttrTemplate.pm: first version
git-svn-id: https://svn.fhem.de/fhem/trunk@17769 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
e9c7b8fd08
commit
183c62c302
@ -1,5 +1,6 @@
|
||||
# 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.
|
||||
- feature: attrTemplate set command added
|
||||
- bugfix: 73_AutoShuttersControl: fix logical bugs,
|
||||
change Antifreeze values
|
||||
- change: DOIFtools: forced change to li-tags in direct help (Forum #93243)
|
||||
|
158
fhem/FHEM/AttrTemplate.pm
Normal file
158
fhem/FHEM/AttrTemplate.pm
Normal file
@ -0,0 +1,158 @@
|
||||
##############################################
|
||||
# $Id$
|
||||
package main;
|
||||
|
||||
my %templates;
|
||||
my $initialized;
|
||||
my %cachedUsage;
|
||||
|
||||
sub
|
||||
AttrTemplate_Initialize()
|
||||
{
|
||||
my $me = "AttrTemplate_Initialize";
|
||||
my $dir = $attr{global}{modpath}."/FHEM/lib/AttrTemplate";
|
||||
if(!opendir(dh, $dir)) {
|
||||
Log 1, "$me: cant open $dir: $!";
|
||||
return;
|
||||
}
|
||||
|
||||
my @files = grep /\.template$/, sort readdir dh;
|
||||
closedir(dh);
|
||||
|
||||
%templates = ();
|
||||
%cachedUsage = ();
|
||||
for my $file (@files) {
|
||||
if(!open(fh,"$dir/$file")) {
|
||||
Log 1, "$me: cant open $dir/$file: $!";
|
||||
continue;
|
||||
}
|
||||
my ($name, %h);
|
||||
while(my $line = <fh>) {
|
||||
chomp($line);
|
||||
next if($line =~ m/^$/ || $line =~ m/^#/);
|
||||
|
||||
if($line =~ m/^name:(.*)/) {
|
||||
$name = $1;
|
||||
my (@p,@c);
|
||||
$templates{$name}{pars} = \@p;
|
||||
$templates{$name}{cmds} = \@c;
|
||||
|
||||
} elsif($line =~ m/^filter:(.*)=(.*)/) {
|
||||
$templates{$name}{filterName} = $1;
|
||||
$templates{$name}{filterVal} = $2;
|
||||
|
||||
} elsif($line =~ m/^par:(.*)/) {
|
||||
push(@{$templates{$name}{pars}}, $1);
|
||||
|
||||
} else {
|
||||
push(@{$templates{$name}{cmds}}, $line);
|
||||
|
||||
}
|
||||
}
|
||||
close(fh);
|
||||
}
|
||||
my $nr = (int keys %templates);
|
||||
$initialized = 1;
|
||||
Log 2, "AttrTemplates: got $nr entries" if($nr);
|
||||
}
|
||||
|
||||
sub
|
||||
AttrTemplate_Set($$@)
|
||||
{
|
||||
my ($hash, $list, $name, $cmd, @a) = @_;
|
||||
|
||||
AttrTemplate_Initialize() if(!$initialized);
|
||||
|
||||
if($cmd ne "attrTemplate") {
|
||||
if(!$cachedUsage{$name}) {
|
||||
my @list;
|
||||
for my $k (sort keys %templates) {
|
||||
my $h = $templates{$k};
|
||||
if(!$h->{filterName} || $hash->{$h->{filterName}} eq $h->{filterVal}) {
|
||||
push @list, $k;
|
||||
}
|
||||
}
|
||||
$cachedUsage{$name} = (@list ? "attrTemplate:".join(",",@list) : "");
|
||||
}
|
||||
$list .= " " if($list ne "");
|
||||
return "Unknown argument $cmd, choose one of $list$cachedUsage{$name}";
|
||||
}
|
||||
|
||||
return "Missing template_entry_name parameter for attrTemplate" if(@a < 1);
|
||||
my $entry = shift(@a);
|
||||
my $h = $templates{$entry};
|
||||
return "Unknown template_entry_name $entry" if(!$h);
|
||||
|
||||
my (%repl, @mComm, @mList, $missing);
|
||||
for my $k (@{$h->{pars}}) {
|
||||
my ($parname, $comment, $perl_code) = split(";",$k,3);
|
||||
|
||||
if(@a) {
|
||||
$repl{$parname} = $a[0];
|
||||
push(@mList, $parname);
|
||||
push(@mComm, "$parname: with the $comment");
|
||||
shift(@a);
|
||||
next;
|
||||
}
|
||||
|
||||
if($perl_code) {
|
||||
$perl_code =~ s/DEVICE/$name/g;
|
||||
my $ret = eval $perl_code;
|
||||
return "Error checking template regexp: $@" if($@);
|
||||
if($ret) {
|
||||
$repl{$parname} = $ret;
|
||||
next;
|
||||
}
|
||||
}
|
||||
|
||||
push(@mList, $parname);
|
||||
push(@mComm, "$parname: with the $comment");
|
||||
$missing = 1;
|
||||
}
|
||||
|
||||
if($missing) {
|
||||
if($hash->{CL} && $hash->{CL}{TYPE} eq "FHEMWEB") {
|
||||
return
|
||||
"<html>".
|
||||
"<input size='60' type='text' spellcheck='false' ".
|
||||
"value='set $name attrTemplate $entry @mList'>".
|
||||
"<br><br>Replace<br>".join("<br>",@mComm).
|
||||
'<script>
|
||||
setTimeout(function(){
|
||||
// TODO: fix multiple dialog calls
|
||||
$("#FW_okDialog").parent().find("button").css("display","block");
|
||||
$("#FW_okDialog").parent().find(".ui-dialog-buttonpane button")
|
||||
.unbind("click").click(function(){
|
||||
var val = encodeURIComponent($("#FW_okDialog input").val());
|
||||
FW_cmd(FW_root+"?cmd="+val+"&XHR=1",
|
||||
function(){ location.reload() } );
|
||||
$("#FW_okDialog").remove();
|
||||
})}, 100);
|
||||
</script>
|
||||
</html>';
|
||||
|
||||
} else {
|
||||
return "Usage: set $name attrTemplate $entry @mList\nReplace\n".
|
||||
join("\n", @mComm);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
my $cmdlist = join("\n",@{$h->{cmds}});
|
||||
$repl{DEVICE} = $name;
|
||||
map { $cmdlist =~ s/$_/$repl{$_}/g; } keys %repl;
|
||||
my $cmd = "";
|
||||
my @ret;
|
||||
map {
|
||||
if($_ =~ m/^(.*)\\$/) {
|
||||
$cmd .= "$1\n";
|
||||
} else {
|
||||
my $r = AnalyzeCommand($hash->{CL}, $cmd.$_);
|
||||
push(@ret, $r) if($r);
|
||||
$cmd = "";
|
||||
}
|
||||
} split("\n", $cmdlist);
|
||||
return @ret ? join("\n", @ret) : undef;
|
||||
}
|
||||
|
||||
1;
|
@ -4,6 +4,7 @@
|
||||
package main;
|
||||
use strict;
|
||||
use warnings;
|
||||
use AttrTemplate;
|
||||
|
||||
sub SetExtensions($$@);
|
||||
sub SetExtensionsFn($);
|
||||
@ -44,7 +45,7 @@ SetExtensions($$@)
|
||||
{
|
||||
my ($hash, $list, $name, $cmd, @a) = @_;
|
||||
|
||||
return "Unknown argument $cmd, choose one of " if(!$list);
|
||||
return AttrTemplate_Set($hash, $list, $name, $cmd, @a) if(!$list);
|
||||
|
||||
my %se_list = (
|
||||
"on-for-timer" => 1,
|
||||
@ -74,14 +75,13 @@ SetExtensions($$@)
|
||||
}
|
||||
|
||||
if(!$hasOn || !$hasOff) { # No extension
|
||||
return "Unknown argument $cmd, choose one of $list";
|
||||
return AttrTemplate_Set($hash, $list, $name, $cmd, @a);
|
||||
}
|
||||
|
||||
if(!defined($se_list{$cmd})) {
|
||||
# Add only "new" commands
|
||||
my @mylist = grep { $list !~ m/\b$_\b/ } keys %se_list;
|
||||
return "Unknown argument $cmd, choose one of $list " .
|
||||
join(" ", @mylist);
|
||||
return AttrTemplate_Set($hash, join(" ", @mylist), $name, $cmd, @a);
|
||||
}
|
||||
if($se_list{$cmd} && $se_list{$cmd} != int(@a)) {
|
||||
return "$cmd requires $se_list{$cmd} parameter";
|
||||
|
40
fhem/FHEM/lib/AttrTemplate/mqtt2.template
Normal file
40
fhem/FHEM/lib/AttrTemplate/mqtt2.template
Normal file
@ -0,0 +1,40 @@
|
||||
# Comments start with #. Empty lines are ignored.
|
||||
# Syntax of one entry: name: line, one optional filter: line, zero or more par: lines, FHEM-Commands
|
||||
# filter:INTERNAL=VALUE (optional)
|
||||
# par: name of the parameter; comment; perl_code (optional)
|
||||
# perl_code returns a value for the parameter, or undef.
|
||||
# If undef, the user has to specify them (the comment is shown to the user)
|
||||
|
||||
name:zigbee2mqtt_bridge
|
||||
filter:TYPE=MQTT2_DEVICE
|
||||
par:BRIDGENAME;name of the zigbee2mqtt bridge in the topics
|
||||
attr DEVICE setList\
|
||||
permit_join:true,false zigbee2mqtt/BRIDGENAME/config/permit_join $EVTPART1\
|
||||
remove:textField zigbee2mqtt/BRIDGENAME/config/remove $EVTPART1\
|
||||
log_level:debug,info,warn,error zigbee2mqtt/BRIDGENAME/config/log_level $EVTPART1\
|
||||
rename:textField zigbee2mqtt/BRIDGENAME/config/rename {"old":"$EVTPART1","new":"$EVTPART2"}\
|
||||
network_map:raw,graphviz zigbee2mqtt/BRIDGENAME/networkmap $EVTPART1\
|
||||
devicelist:noArg zigbee2mqtt/BRIDGENAME/config/devices
|
||||
|
||||
|
||||
name:zigbee2mqtt_bulb
|
||||
filter:TYPE=MQTT2_DEVICE
|
||||
par:NAMEINTHEBRIDGE;name of this device in the bridge;{ AttrVal("DEVICE","readingList","") =~ m,zigbee2mqtt/(.*):, ? $1 : undef }
|
||||
attr DEVICE icon light_control
|
||||
attr DEVICE webCmd brightness
|
||||
attr DEVICE setList \
|
||||
on:noArg zigbee2mqtt/NAMEINTHEBRIDGE/set {"state":"ON"}\
|
||||
off:noArg zigbee2mqtt/NAMEINTHEBRIDGE/set {"state":"OFF"}\
|
||||
brightness:colorpicker,BRI,0,15,255 zigbee2mqtt/NAMEINTHEBRIDGE/set {"state":"on","$EVTPART0":"$EVTPART1"}
|
||||
|
||||
|
||||
name:zigbee2mqtt_colorbulb
|
||||
filter:TYPE=MQTT2_DEVICE
|
||||
par:NAMEINTHEBRIDGE;name of this device in the bridge;{ AttrVal("DEVICE","readingList","") =~ m,zigbee2mqtt/(.*):, ? $1 : undef }
|
||||
attr DEVICE icon light_control
|
||||
attr DEVICE webCmd brightness:color_temp
|
||||
attr DEVICE setList \
|
||||
on:noArg zigbee2mqtt/NAMEINTHEBRIDGE/set {"state":"ON"}\
|
||||
off:noArg zigbee2mqtt/NAMEINTHEBRIDGE/set {"state":"OFF"}\
|
||||
brightness:colorpicker,BRI,0,15,255 zigbee2mqtt/NAMEINTHEBRIDGE/set {"state":"on","$EVTPART0":"$EVTPART1"}\
|
||||
color_temp:colorpicker,CT,250,1,454 zigbee2mqtt/NAMEINTHEBRIDGE/set {"$EVTPART0":"$EVTPART1"}
|
@ -510,6 +510,7 @@ FHEM/98_SmarterCoffee CoolTux Sonstige Systeme
|
||||
FHEM/99_SUNRISE_EL.pm rudolfkoenig Automatisierung
|
||||
FHEM/99_Utils.pm rudolfkoenig Automatisierung
|
||||
FHEM/99_Venetian.pm Christian.Kühnel Automatisierung
|
||||
FHEM/AttrTemplate.pm rudolfkoenig Automatisierung
|
||||
FHEM/Blocking.pm rudolfkoenig Automatisierung
|
||||
FHEM/DevIo.pm rudolfkoenig Sonstiges
|
||||
FHEM/Color.pm justme1968 Sonstiges
|
||||
|
@ -52,6 +52,7 @@ my @filelist2 = (
|
||||
"FHEM/lib/MP3/.*.pm",
|
||||
"FHEM/lib/MP3/Tag/.*",
|
||||
"FHEM/lib/UPnP/.*",
|
||||
"FHEM/lib/AttrTemplate/.*.template",
|
||||
"FHEM/holiday/.*.holiday",
|
||||
"contrib/commandref_join.pl.txt",
|
||||
"contrib/commandref_modular.pl.txt",
|
||||
|
@ -1217,6 +1217,15 @@ The following local attributes are used by a wider range of devices:
|
||||
set switch intervals 08:00-12:00 13:00-18:00<br>
|
||||
</code>
|
||||
</ul>
|
||||
<br><br>
|
||||
|
||||
<a name="attrTemplate"></a>
|
||||
attrTemplate<br>
|
||||
with this command a set of predefined attributes may be set at once. The
|
||||
template files containing the entries are in FHEM/lib/AttrTemplate
|
||||
directory. Template entries can be module specific, and may require further
|
||||
parameters to be specified.
|
||||
|
||||
</ul>
|
||||
<!-- set end -->
|
||||
|
||||
|
@ -1293,7 +1293,15 @@ Die folgenden lokalen Attribute werden von mehreren Geräten verwendet:
|
||||
set switch intervals 08:00-12:00 13:00-18:00<br>
|
||||
</code>
|
||||
</ul>
|
||||
</ul>
|
||||
<br><br>
|
||||
|
||||
<a name="attrTemplate"></a>
|
||||
attrTemplate<br>
|
||||
mit diesem Befehl kann man eine Menge an vordefinierten Attributen setzen.
|
||||
Die Einträge befinden sich in Dateien im FHEM/lib/AttrTemplate
|
||||
Verzeichnis. Einträge können modul-spezifisch sein, und
|
||||
möglicherweise erfordern weitere Parameter.
|
||||
|
||||
</ul>
|
||||
<!-- set end -->
|
||||
|
||||
|
@ -2870,7 +2870,9 @@ CommandAttr($$)
|
||||
$attrVal = "-" if($attrName eq "logfile");
|
||||
$attrVal = 5 if($attrName eq "verbose");
|
||||
}
|
||||
$defs{$sdev}->{CL} = $cl;
|
||||
$ret = CallFn($sdev, "AttrFn", "set", $sdev, $attrName, $attrVal);
|
||||
delete($defs{$sdev}->{CL});
|
||||
if($ret) {
|
||||
push @rets, $ret;
|
||||
next;
|
||||
|
@ -750,7 +750,7 @@ FW_inlineModify() // Do not generate a new HTML page upon pressing modify
|
||||
var ifid = (devName+"-"+arg).replace(/([^_a-z0-9])/gi,
|
||||
function(m){ return "\\"+m });
|
||||
if($(".dval[informid="+ifid+"]").length == 0) {
|
||||
if(cmd == "attr") {
|
||||
if(cmd == "attr" || (cmd == "set" && arg == "attrTemplate")) {
|
||||
reloadIfOk = true;
|
||||
} else {
|
||||
$(this).unbind('click').click();// No element found to replace, reload
|
||||
@ -762,14 +762,15 @@ FW_inlineModify() // Do not generate a new HTML page upon pressing modify
|
||||
newDef = $(this).closest("form").find("[name^=val]").val();
|
||||
cmd = $(this).attr("name")+"="+cmd+" "+devName+" "+arg+" "+newDef;
|
||||
}
|
||||
|
||||
FW_cmd(FW_root+"?"+encodeURIComponent(cmd)+"&XHR=1", function(resp){
|
||||
if(!resp && reloadIfOk)
|
||||
location.reload();
|
||||
if(resp) {
|
||||
resp = FW_htmlQuote(resp);
|
||||
if(resp.indexOf("\n") >= 0)
|
||||
resp = '<pre>'+resp+'</pre>';
|
||||
if(!resp.match(/^<html>[\s\S]*<\/html>/ ) ) {
|
||||
resp = FW_htmlQuote(resp);
|
||||
if(resp.indexOf("\n") >= 0)
|
||||
resp = '<pre>'+resp+'</pre>';
|
||||
}
|
||||
return FW_okDialog(resp);
|
||||
}
|
||||
if(isDef) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user