2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-03 16:56:54 +00:00

90_at.pm/91_notify.pm: add little FHEMWEB wizards

git-svn-id: https://svn.fhem.de/fhem/trunk@7000 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
rudolfkoenig 2014-11-16 16:51:50 +00:00
parent 49203c8074
commit e51c143f4a
6 changed files with 252 additions and 34 deletions

View File

@ -18,6 +18,7 @@ at_Initialize($)
$hash->{StateFn} = "at_State"; $hash->{StateFn} = "at_State";
$hash->{AttrList} = "disable:0,1 disabledForIntervals ". $hash->{AttrList} = "disable:0,1 disabledForIntervals ".
"skip_next:0,1 alignTime"; "skip_next:0,1 alignTime";
$hash->{FW_detailFn} = "at_fhemwebFn";
} }
@ -69,6 +70,10 @@ at_Define($$)
$rel = "" if(!defined($rel)); $rel = "" if(!defined($rel));
$rep = "" if(!defined($rep)); $rep = "" if(!defined($rep));
$cnt = "" if(!defined($cnt)); $cnt = "" if(!defined($cnt));
$hash->{RELATIVE} = ($rel ? "yes" : "no");
$hash->{PERIODIC} = ($rep ? "yes" : "no");
$hash->{TIMESPEC} = $tspec;
$hash->{COMMAND} = $command;
my $ot = $data{AT_TRIGGERTIME} ? $data{AT_TRIGGERTIME} : gettimeofday(); my $ot = $data{AT_TRIGGERTIME} ? $data{AT_TRIGGERTIME} : gettimeofday();
$ot = int($ot) if(!$rel); # No way to specify subseconds $ot = int($ot) if(!$rel); # No way to specify subseconds
@ -132,8 +137,8 @@ at_Exec($)
my $disable = IsDisabled($name); my $disable = IsDisabled($name);
delete $attr{$name}{skip_next} if($skip); delete $attr{$name}{skip_next} if($skip);
my (undef, $command) = split("[ \t]+", $hash->{DEF}, 2);
$command = SemicolonEscape($command); my $command = SemicolonEscape($hash->{COMMAND});
my $ret = AnalyzeCommandChain(undef, $command) if(!$skip && !$disable); my $ret = AnalyzeCommandChain(undef, $command) if(!$skip && !$disable);
Log3 $name, 3, "$name: $ret" if($ret); Log3 $name, 3, "$name: $ret" if($ret);
@ -246,6 +251,74 @@ at_State($$$$)
return undef; return undef;
} }
#########################
sub
at_fhemwebFn($$$$)
{
my ($FW_wname, $d, $room, $pageHash) = @_; # pageHash is set for summaryFn.
my $hash = $defs{$d};
my $ts = $hash->{TIMESPEC}; $ts =~ s/'/\\'/g;
my $isPerl = ($ts =~ m/^{(.*)}/);
$ts = $1 if($isPerl);
return "<br>Timespec wizard:".
"<table id='atWizard' nm='$hash->{NAME}' ts='$ts' rl='$hash->{RELATIVE}' ".
"pr='$hash->{PERIODIC}' ip='$isPerl' class='block wide'>".<<'EOF';
<tr class="even">
<td>Relative &nbsp; <input type="checkbox" id="aw_rl" value="yes"></td>
<td>Periodic &nbsp; <input type="checkbox" id="aw_pr" value="yes"></td>
</tr><tr class="odd"><td>Use perl function for timespec</td>
<td><input type="checkbox" id="aw_ip"></td>
</tr><tr class="even"><td>Timespec</td>
<td><input type="text" id="aw_pts"></td>
</tr><tr class="even"><td>Timespec</td>
<td><input type="text" readonly id="aw_ts" size="5">
<input type='button' value='+' id="aw_tsb"></td>
</tr>
</tr><tr class="even">
<td colspan="2"><input type="button" id="aw_md" value="Modify"></td>
</tr>
</table>
<script type="text/javascript">
loadScript("pgm2/jquery.min.js", atDetails);
function
atDetails()
{
var t=$("#atWizard"), ip=$(t).attr("ip"), ts=$(t).attr("ts");
function tsClick() {
FW_timeCreate(this, function(val) { $("#aw_tsb").click(tsClick) })
}
function ipClick() {
var c = $("#aw_ip").prop("checked");
$("#aw_ts").closest("tr").css("display", !c ? "table-row" : "none");
$("#aw_pts").closest("tr").css("display", c ? "table-row" : "none");
}
$("#aw_rl").prop("checked", $(t).attr("rl")=="yes");
$("#aw_pr").prop("checked", $(t).attr("pr")=="yes");
$("#aw_ip").prop("checked", ip);
$("#aw_ts").val(ip ? "12:00" : ts);
$("#aw_pts").val(ip ? ts : 'sunset()');
$("#aw_tsb").click(tsClick);
$("#aw_ip").change(ipClick);
ipClick();
$("#aw_md").click(function(){
var nm = $(t).attr("nm");
var def = nm+" ";
def += $("#aw_rl").prop("checked") ? "+":"";
def += $("#aw_pr").prop("checked") ? "*":"";
def += $("#aw_ip").prop("checked") ?
"{"+$("#aw_pts").val()+"}" : $("#aw_ts").val();
def = def.replace(/\+/g, "%2b");
def = def.replace(/;/g, ";;");
location = location.pathname+"detail="+nm+"&cmd=modify "+def;
});
}
</script>
EOF
}
1; 1;
=pod =pod

View File

@ -4,6 +4,7 @@ package main;
use strict; use strict;
use warnings; use warnings;
use vars qw($FW_ME); # webname (default is fhem)
##################################### #####################################
sub sub
@ -15,6 +16,8 @@ notify_Initialize($)
$hash->{NotifyFn} = "notify_Exec"; $hash->{NotifyFn} = "notify_Exec";
$hash->{AttrFn} = "notify_Attr"; $hash->{AttrFn} = "notify_Attr";
$hash->{AttrList} = "disable:0,1 disabledForIntervals forwardReturnValue:0,1 showTriggerTime:0,1 addStateEvent:0,1"; $hash->{AttrList} = "disable:0,1 disabledForIntervals forwardReturnValue:0,1 showTriggerTime:0,1 addStateEvent:0,1";
$hash->{SetFn} = "notify_Set";
$hash->{FW_detailFn} = "notify_fhemwebFn";
} }
@ -39,6 +42,7 @@ notify_Define($$)
eval { "Hallo" =~ m/^$re$/ }; eval { "Hallo" =~ m/^$re$/ };
return "Bad regexp: $@" if($@); return "Bad regexp: $@" if($@);
$hash->{REGEXP} = $re; $hash->{REGEXP} = $re;
$hash->{COMMAND} = $command;
$hash->{STATE} = "active"; $hash->{STATE} = "active";
notifyRegexpChanged($hash, $re); notifyRegexpChanged($hash, $re);
@ -74,14 +78,12 @@ notify_Exec($$)
} }
if($found) { if($found) {
Log3 $ln, 5, "Triggering $ln"; Log3 $ln, 5, "Triggering $ln";
my (undef, $exec) = split("[ \t]+", $ntfy->{DEF}, 2);
my %specials= ( my %specials= (
"%NAME" => $n, "%NAME" => $n,
"%TYPE" => $t, "%TYPE" => $t,
"%EVENT" => $s "%EVENT" => $s
); );
$exec= EvalSpecials($exec, %specials); my $exec = EvalSpecials($ntfy->{COMMAND}, %specials);
Log3 $ln, 4, "$ln exec $exec"; Log3 $ln, 4, "$ln exec $exec";
my $r = AnalyzeCommandChain(undef, $exec); my $r = AnalyzeCommandChain(undef, $exec);
@ -111,6 +113,116 @@ notify_Attr(@)
$defs{$a[1]}{STATE} = ($do == 1 ? "disabled" : "active"); $defs{$a[1]}{STATE} = ($do == 1 ? "disabled" : "active");
return undef; return undef;
} }
###################################
sub
notify_Set($@)
{
my ($hash, @a) = @_;
my $me = $hash->{NAME};
return "no set argument specified" if(int(@a) < 2);
my %sets = (addRegexpPart=>2, removeRegexpPart=>1);
my $cmd = $a[1];
return "Unknown argument $cmd, choose one of " # No dropdown in FHEMWEB
if(!defined($sets{$cmd}));
return "$cmd needs $sets{$cmd} parameter(s)" if(@a-$sets{$cmd} != 2);
if($cmd eq "addRegexpPart") {
my %h;
my $re = "$a[2]:$a[3]";
map { $h{$_} = 1 } split(/\|/, $hash->{REGEXP});
$h{$re} = 1;
$re = join("|", sort keys %h);
return "Bad regexp: starting with *" if($re =~ m/^\*/);
eval { "Hallo" =~ m/^$re$/ };
return "Bad regexp: $@" if($@);
$hash->{REGEXP} = $re;
$hash->{DEF} = "$re $hash->{COMMAND}";
notifyRegexpChanged($hash, $re);
} elsif($cmd eq "removeRegexpPart") {
my %h;
map { $h{$_} = 1 } split(/\|/, $hash->{REGEXP});
return "Cannot remove regexp part: not found" if(!$h{$a[2]});
return "Cannot remove last regexp part" if(int(keys(%h)) == 1);
delete $h{$a[2]};
my $re = join("|", sort keys %h);
return "Bad regexp: starting with *" if($re =~ m/^\*/);
eval { "Hallo" =~ m/^$re$/ };
return "Bad regexp: $@" if($@);
$hash->{REGEXP} = $re;
$hash->{DEF} = "$re $hash->{COMMAND}";
notifyRegexpChanged($hash, $re);
}
return undef;
}
#########################
sub
notify_fhemwebFn($$$$)
{
my ($FW_wname, $d, $room, $pageHash) = @_; # pageHash is set for summaryFn.
my $hash = $defs{$d};
my $ret .= "<br>Regexp wizard";
my $row=0;
$ret .= "<br><table class=\"block wide\">";
my @ra = split(/\|/, $hash->{REGEXP});
if(@ra > 1) {
foreach my $r (@ra) {
$ret .= "<tr class=\"".(($row++&1)?"odd":"even")."\">";
my $cmd = "cmd.X= set $d removeRegexpPart&val.X=$r"; # =.set: avoid JS
$ret .= "<td>$r</td>";
$ret .= FW_pH("$cmd&detail=$d", "removeRegexpPart", 1,undef,1);
$ret .= "</tr>";
}
}
my @et = devspec2array("TYPE=eventTypes");
if(!@et) {
$ret .= FW_pH("$FW_ME/docs/commandref.html#eventTypes",
"To add a regexp an eventTypes definition is needed",
1, undef, 1);
} else {
my %dh;
foreach my $l (split("\n", AnalyzeCommand(undef, "get $et[0] list"))) {
my @a = split(/[ \r\n]/, $l);
$a[1] = "" if(!defined($a[1]));
$a[1] =~ s/\.\*//g;
$a[1] =~ s/,.*//g;
next if(@a < 2);
$dh{$a[0]}{".*"} = 1;
$dh{$a[0]}{$a[1].".*"} = 1;
}
my $list = ""; my @al;
foreach my $dev (sort keys %dh) {
$list .= " $dev:" . join(",", sort keys %{$dh{$dev}});
push @al, $dev;
}
$ret .= "<tr class=\"".(($row++&1)?"odd":"even")."\">";
$ret .= "<td colspan=\"2\"><form autocomplete=\"off\">";
$ret .= FW_hidden("detail", $d);
$ret .= FW_hidden("dev.$d", "$d addRegexpPart");
$ret .= FW_submit("cmd.$d", "set", "set");
$ret .= "<div class=\"set downText\">&nbsp;$d addRegexpPart&nbsp;</div>";
$list =~ s/(['"])/./g;
$ret .= FW_select("","arg.$d",\@al, undef, "set",
"FW_selChange(this.options[selectedIndex].text,'$list','val.$d')");
$ret .= FW_textfield("val.$d", 30, "set");
$ret .= "<script type=\"text/javascript\">" .
"FW_selChange('$al[0]','$list','val.$d')</script>";
$ret .= "</form></td></tr>";
}
$ret .= "</table>";
return $ret;
}
1; 1;
=pod =pod
@ -221,7 +333,27 @@ notify_Attr(@)
<a name="notifyset"></a> <a name="notifyset"></a>
<b>Set</b> <ul>N/A</ul><br> <b>Set </b>
<ul>
<li>addRegexpPart &lt;device&gt; &lt;regexp&gt;
<ul>
add a regexp part, which is constructed as device:regexp. The parts
are separated by |. Note: as the regexp parts are resorted, manually
constructed regexps may become invalid.
</ul>
</li>
<li>removeRegexpPart &lt;re&gt;
<ul>
remove a regexp part. Note: as the regexp parts are resorted, manually
constructed regexps may become invalid.<br>
The inconsistency in addRegexpPart/removeRegexPart arguments originates
from the reusage of javascript functions.
</ul>
</li>
<br>
</ul>
<br>
<a name="notifyget"></a> <a name="notifyget"></a>
<b>Get</b> <ul>N/A</ul><br> <b>Get</b> <ul>N/A</ul><br>
@ -395,7 +527,23 @@ notify_Attr(@)
<a name="notifyset"></a> <a name="notifyset"></a>
<b>Set</b> <ul>N/A</ul><br> <b>Set </b>
<ul>
<li>addRegexpPart &lt;device&gt; &lt;regexp&gt;
<ul>
F&uuml;gt ein regexp Teil hinzu, der als device:regexp aufgebaut ist.
Die Teile werden nach Regexp-Regeln mit | getrennt. Achtung: durch
hinzuf&uuml;gen k&ouml;nnen manuell erzeugte Regexps ung&uuml;ltig
werden.
</ul></li>
<li>removeRegexpPart &lt;re&gt;
<ul>
Entfernt ein regexp Teil. Die Inkonsistenz von addRegexpPart /
removeRegexPart-Argumenten hat seinen Ursprung in der Wiederverwendung
von Javascript-Funktionen.
</ul></li>
</ul>
<br>
<a name="notifyget"></a> <a name="notifyget"></a>
<b>Get</b> <ul>N/A</ul><br> <b>Get</b> <ul>N/A</ul><br>

View File

@ -9,7 +9,7 @@ use IO::File;
# This block is only needed when FileLog is loaded bevore FHEMWEB # This block is only needed when FileLog is loaded bevore FHEMWEB
sub FW_pO(@); sub FW_pO(@);
sub FW_pH(@); sub FW_pH(@);
use vars qw($FW_ME); # webname (default is fhem), needed by 97_GROUP use vars qw($FW_ME); # webname (default is fhem)
use vars qw($FW_RET); # Returned data (html) use vars qw($FW_RET); # Returned data (html)
use vars qw($FW_RETTYPE); use vars qw($FW_RETTYPE);
use vars qw($FW_cmdret); # error msg forwarding from toSVG use vars qw($FW_cmdret); # error msg forwarding from toSVG
@ -183,7 +183,6 @@ FileLog_Attr(@)
} }
################################### ###################################
sub sub
FileLog_Set($@) FileLog_Set($@)
{ {
@ -1259,26 +1258,22 @@ FileLog_sampleDataFn($$$$$)
<ul> <ul>
<li>reopen <li>reopen
<ul> <ul>
Erneutes &Ouml;ffnen eines FileLogs nach h&auml;ndischen &Auml;nderungen in dieser Datei. Erneutes &Ouml;ffnen eines FileLogs nach h&auml;ndischen
</ul> &Auml;nderungen in dieser Datei.
</li> </ul></li>
<li>addRegexpPart &lt;device&gt; &lt;regexp&gt; <li>addRegexpPart &lt;device&gt; &lt;regexp&gt;
<ul> <ul>
Hinzuf&uuml;gen eines regexp Teiles, der gem&auml;&szlig; device:regexp F&uuml;gt ein regexp Teil hinzu, der als device:regexp aufgebaut ist.
aufgebaut ist. Die Teile werden mit einem | voneinander getrennt. Die Teile werden nach Regexp-Regeln mit | getrennt. Achtung: durch
Achtung: Wenn die regexp-Teile umsortiert werden, k&ouml;nnen die hinzuf&uuml;gen k&ouml;nnen manuell erzeugte Regexps ung&uuml;ltig
manuell erzeugten regexps ung&uuml;ltig werden. werden.
</ul> </ul></li>
</li>
<li>removeRegexpPart &lt;re&gt; <li>removeRegexpPart &lt;re&gt;
<ul> <ul>
Entfernt ein regexp-Teil. Achtung: Wenn die regexp-Teile umsortiert Entfernt ein regexp Teil. Die Inkonsistenz von addRegexpPart /
werden, k&ouml;nnen die manuell erzeugten regexps ung&uuml;ltig removeRegexPart-Argumenten hat seinen Ursprung in der Wiederverwendung
werden.<br> von Javascript-Funktionen.
Die Inkonsistenz von addRegexpPart/removeRegexPart-Argumenten hat </ul></li>
seinen Ursprung in der Wiederverwendung von Javascript-Funktionen.
</ul>
</li>
<li>absorb secondFileLog <li>absorb secondFileLog
<ul> <ul>
F&uuml;hrt den gegenw&auml;rtigen Log und den secondFileLog zu einer F&uuml;hrt den gegenw&auml;rtigen Log und den secondFileLog zu einer
@ -1296,11 +1291,10 @@ FileLog_sampleDataFn($$$$$)
<li>nur das aktuelle File wird zusammengef&uuml;hrt, keine <li>nur das aktuelle File wird zusammengef&uuml;hrt, keine
archivierten Versionen.</li> archivierten Versionen.</li>
<li>Weblinks, die das secondFilelog benutzen werden unbrauchbar, sie <li>Weblinks, die das secondFilelog benutzen werden unbrauchbar, sie
m&uuml;ssen deshalb auf das neue Logfile angepasst oder gel&ouml;scht m&uuml;ssen deshalb auf das neue Logfile angepasst oder
werden.</li> gel&ouml;scht werden.</li>
</ul> </ul>
</ul> </ul></li>
</li>
<br> <br>
</ul> </ul>
<br> <br>

View File

@ -39,6 +39,7 @@ sub SVG_substcfg($$$$$$);
sub SVG_time_align($$); sub SVG_time_align($$);
sub SVG_time_to_sec($); sub SVG_time_to_sec($);
sub SVG_openFile($$$); sub SVG_openFile($$$);
sub SVG_doShowLog($$$$;$$);
my %SVG_devs; # hash of from/to entries per device my %SVG_devs; # hash of from/to entries per device
@ -809,7 +810,7 @@ SVG_showLog($)
} }
sub sub
SVG_doShowLog($$$$$$) SVG_doShowLog($$$$;$$)
{ {
my ($wl, $d, $type, $file, $styleW, $styleH) = @_; my ($wl, $d, $type, $file, $styleW, $styleH) = @_;
my $pm = AttrVal($wl,"plotmode",$FW_plotmode); my $pm = AttrVal($wl,"plotmode",$FW_plotmode);

View File

@ -146,7 +146,7 @@ FW_longpoll()
} }
} }
if(filter == "") { if(filter == "") {
var sa = document.location.search.substring(1).split("&"); var sa = location.search.substring(1).split("&");
for(var i = 0; i < sa.length; i++) { for(var i = 0; i < sa.length; i++) {
if(sa[i].substring(0,5) == "room=") if(sa[i].substring(0,5) == "room=")
filter=sa[i]; filter=sa[i];
@ -172,7 +172,7 @@ FW_longpoll()
if(iP != null) if(iP != null)
filter = filter +";iconPath="+iP; filter = filter +";iconPath="+iP;
var query = document.location.pathname+"?XHR=1"+ var query = location.pathname+"?XHR=1"+
"&inform=type=status;filter="+filter+ "&inform=type=status;filter="+filter+
"&timestamp="+new Date().getTime(); "&timestamp="+new Date().getTime();
query = addcsrf(query); query = addcsrf(query);
@ -292,7 +292,7 @@ FW_queryValue(cmd, qFn, qArg)
eval(qFn.replace("%", qResp)); eval(qFn.replace("%", qResp));
delete qConn; delete qConn;
} }
var query = document.location.pathname+"?cmd="+cmd+"&XHR=1" var query = location.pathname+"?cmd="+cmd+"&XHR=1"
query = addcsrf(query); query = addcsrf(query);
qConn.open("GET", query, true); qConn.open("GET", query, true);
qConn.send(null); qConn.send(null);

View File

@ -20,7 +20,9 @@ FW_timeCreate(el,cmd)
if(brOff > 0) { if(brOff > 0) {
par.innerHTML = par.innerHTML.substring(0, brOff).replace('"-"','"+"'); par.innerHTML = par.innerHTML.substring(0, brOff).replace('"-"','"+"');
if(cmd) { if(cmd) {
if(typeof FW_pollConn != "undefined") if(typeof cmd == "function")
cmd(v);
else if(typeof FW_pollConn != "undefined")
FW_cmd(cmd.replace('%',v)+"&XHR=1"); FW_cmd(cmd.replace('%',v)+"&XHR=1");
else else
window.location = addcsrf(cmd.replace('%',v)); window.location = addcsrf(cmd.replace('%',v));