From 433b72340a26f5eb25b4740af150f31e736c006a Mon Sep 17 00:00:00 2001 From: rudolfkoenig <> Date: Sun, 28 Apr 2013 12:40:28 +0000 Subject: [PATCH] FileLog regexp editor added git-svn-id: https://svn.fhem.de/fhem/trunk@3128 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/CHANGED | 1 + fhem/FHEM/01_FHEMWEB.pm | 5 +- fhem/FHEM/91_eventTypes.pm | 191 ++++++++++++++++++++++++++ fhem/FHEM/92_FileLog.pm | 207 ++++++++++++++++++++++++++--- fhem/FHEM/98_weblink.pm | 9 +- fhem/docs/commandref_frame.html | 1 + fhem/docs/commandref_frame_DE.html | 1 + fhem/fhem.pl | 8 +- fhem/www/pgm2/fhemweb.js | 10 +- 9 files changed, 404 insertions(+), 29 deletions(-) create mode 100755 fhem/FHEM/91_eventTypes.pm diff --git a/fhem/CHANGED b/fhem/CHANGED index 5695e724f..f823c38fb 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,6 @@ # Add changes at the top of the list. Keep it in ASCII - SVN + - feature: eventTypes module added, to help with FileLog details screen - feature: FB_CALLMONITOR: new reverse search provider dasschnelle.at for reverse search of austrian telephone numbers - bugfix: event-on-change-reading in combination with event-change-interval diff --git a/fhem/FHEM/01_FHEMWEB.pm b/fhem/FHEM/01_FHEMWEB.pm index e8dd5d77b..07997e69c 100755 --- a/fhem/FHEM/01_FHEMWEB.pm +++ b/fhem/FHEM/01_FHEMWEB.pm @@ -2205,10 +2205,11 @@ FW_makeEdit($$$) FW_pO ""; FW_pO "
"; + FW_pO FW_hidden("detail", $name); my $cmd = "modify"; my $ncols = $FW_ss ? 30 : 60; - FW_pO ""; + FW_pO ""; FW_pO "
" . FW_submit("cmd.${cmd}$name", "$cmd $name"); FW_pO "
"; FW_pO ""; diff --git a/fhem/FHEM/91_eventTypes.pm b/fhem/FHEM/91_eventTypes.pm new file mode 100755 index 000000000..838173219 --- /dev/null +++ b/fhem/FHEM/91_eventTypes.pm @@ -0,0 +1,191 @@ +############################################## +# $Id: 91_eventTypes.pm 2982 2013-03-24 17:47:28Z rudolfkoenig $ +package main; + +use strict; +use warnings; + +##################################### +sub +eventTypes_Initialize($) +{ + my ($hash) = @_; + + $hash->{DefFn} = "eventTypes_Define"; + $hash->{NotifyFn} = "eventTypes_Notify"; + $hash->{ShutdownFn}="eventTypes_Shutdown"; + $hash->{GetFn} = "eventTypes_Get"; + $hash->{SetFn} = "eventTypes_Set"; + $hash->{AttrFn} = "eventTypes_Attr"; + $hash->{AttrList} = "disable:0,1 loglevel:0,1,2,3,4,5,6"; +} + + +##################################### +sub +eventTypes_Define($$) +{ + my ($hash, $def) = @_; + my @a = split("[ \t][ \t]*", $def); + + return "wrong syntax: define eventTypes filename" if(int(@a) != 3); + + my @t = localtime; + my $f = ResolveDateWildcards($a[2], @t); + my $fh = new IO::File "$f"; + + if($fh) { + while(my $l = <$fh>) { + chomp($l); + my @a = split(" ", $l, 3); + $modules{eventTypes}{ldata}{$a[1]}{$a[2]} = $a[0]; + } + close($fh); + } + + $hash->{STATE} = "active"; + return undef; +} + +##################################### +sub +eventTypes_Notify($$) +{ + my ($me, $eventSrc) = @_; + my $ln = $me->{NAME}; + return "" if($attr{$ln} && $attr{$ln}{disable}); + + return if(!$eventSrc->{CHANGED}); + + my $t = $eventSrc->{TYPE}; + my $n = $eventSrc->{NAME}; + my $ll4 = GetLogLevel($ln, 4); + + my $ret = ""; + foreach my $oe (@{$eventSrc->{CHANGED}}) { + $oe = "" if(!defined($oe)); + my $ne = $oe; + $ne =~ s/\b-?\d*\.?\d+\b/.*/g; + $ne =~ s/set_\d+/set_.*/; # HM special :/ + Log $ll4, "$ln: $t $n $oe -> $ne"; + $modules{eventTypes}{ldata}{$n}{$ne}++; + } + return undef; +} + +sub +eventTypes_Attr(@) +{ + my @a = @_; + my $do = 0; + + if($a[0] eq "set" && $a[2] eq "disable") { + $do = (!defined($a[3]) || $a[3]) ? 1 : 2; + } + $do = 2 if($a[0] eq "del" && (!$a[2] || $a[2] eq "disable")); + return if(!$do); + + $defs{$a[1]}{STATE} = ($do == 1 ? "disabled" : "active"); + return undef; +} + +################################### +sub +eventTypes_Shutdown($$) +{ + my ($hash, $name) = @_; + + my $fName = $hash->{DEF}; + my $fh = new IO::File ">$fName"; + return "Can't open $fName: $!" if(!defined($fh)); + my $ldata = $modules{eventTypes}{ldata}; + + foreach my $t (sort keys %{$ldata}) { + foreach my $e (sort keys %{$ldata->{$t}}) { + print $fh "$ldata->{$t}{$e} $t $e\n"; + } + } + close($fh); + return undef; +} + +################################### +sub +eventTypes_Set($@) +{ + my ($hash, @a) = @_; + + return "Unknown argument $a[1], choose one of flush" if($a[1] ne "flush"); + return eventTypes_Shutdown($hash, $hash->{NAME}); +} + +################################### +sub +eventTypes_Get($@) +{ + my ($hash, @a) = @_; + my $cmd = (defined($a[1]) ? $a[1] : ""); + my $arg = $a[2]; + + return "Unknown argument $cmd, choose one of list" if($cmd ne "list"); + my $out = ""; + my $ldata = $modules{eventTypes}{ldata}; + foreach my $t (sort keys %{$ldata}) { + next if($arg && $t ne $arg); + foreach my $e (sort keys %{$ldata->{$t}}) { + $out .= "$t $e\n"; + } + } + return $out; +} + +1; + +=pod +=begin html + + +

eventTypes

+ + +=end html +=cut diff --git a/fhem/FHEM/92_FileLog.pm b/fhem/FHEM/92_FileLog.pm index 9432d872e..e17084022 100755 --- a/fhem/FHEM/92_FileLog.pm +++ b/fhem/FHEM/92_FileLog.pm @@ -20,13 +20,14 @@ FileLog_Initialize($) $hash->{SetFn} = "FileLog_Set"; $hash->{GetFn} = "FileLog_Get"; $hash->{UndefFn} = "FileLog_Undef"; + $hash->{DeleteFn} = "FileLog_Delete"; $hash->{NotifyFn} = "FileLog_Log"; $hash->{AttrFn} = "FileLog_Attr"; # logtype is used by the frontend $hash->{AttrList} = "disable:0,1 logtype nrarchive archivedir archivecmd"; - $hash->{FW_summaryFn} = "FW_dumpFileLog"; - $hash->{FW_detailFn} = "FW_dumpFileLog"; + $hash->{FW_summaryFn} = "FileLog_fhemwebFn"; + $hash->{FW_detailFn} = "FileLog_fhemwebFn"; } @@ -66,6 +67,16 @@ FileLog_Undef($$) return undef; } +sub +FileLog_Delete($$) +{ + my ($hash, $name) = @_; + return if(!$hash->{currentlogfile}); + unlink($hash->{currentlogfile}); + return undef; +} + + sub FileLog_Switch($) { @@ -148,27 +159,100 @@ FileLog_Attr(@) } ################################### + sub FileLog_Set($@) { my ($hash, @a) = @_; - - return "no set argument specified" if(int(@a) != 2); - return "Unknown argument $a[1], choose one of reopen" - if($a[1] ne "reopen"); + my $me = $hash->{NAME}; - my $fh = $hash->{FH}; - my $cn = $hash->{currentlogfile}; - $fh->close(); - $fh = new IO::File ">>$cn"; - return "Can't open $cn" if(!defined($fh)); - $hash->{FH} = $fh; + return "no set argument specified" if(int(@a) < 2); + my %sets = (reopen=>0, absorb=>1, addRegexpPart=>2, removeRegexpPart=>1); + + my $cmd = $a[1]; + if(!defined($sets{$cmd})) { + my $r = "Unknown argument $cmd, choose one of ".join(" ",sort keys %sets); + my $fllist = join(",", grep { $me ne $_ } devspec2array("TYPE=FileLog")); + $r =~ s/absorb/absorb:$fllist/; + return $r; + } + return "$cmd needs $sets{$cmd} parameter(s)" if(@a-$sets{$cmd} != 2); + + if($cmd eq "reopen") { + my $fh = $hash->{FH}; + my $cn = $hash->{currentlogfile}; + $fh->close(); + $fh = new IO::File(">>$cn"); + return "Can't open $cn" if(!defined($fh)); + $hash->{FH} = $fh; + + } elsif($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); + eval { "Hallo" =~ m/^$re$/ }; + return "Bad regexp: $@" if($@); + $hash->{REGEXP} = $re; + $hash->{DEF} = $hash->{logfile} ." $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); + eval { "Hallo" =~ m/^$re$/ }; + return "Bad regexp: $@" if($@); + $hash->{REGEXP} = $re; + $hash->{DEF} = $hash->{logfile} ." $re"; + + } elsif($cmd eq "absorb") { + my $victim = $a[2]; + return "need another FileLog as argument." + if(!$victim || + !$defs{$victim} || + $defs{$victim}{TYPE} ne "FileLog" || + $victim eq $me); + my $vh = $defs{$victim}; + my $mylogfile = $hash->{currentlogfile}; + return "Cant open the associated files" + if(!open(FH1, $mylogfile) || + !open(FH2, $vh->{currentlogfile}) || + !open(FH3, ">$mylogfile.new")); + + my $fh = $hash->{FH}; + $fh->close(); + + my $b1 = ; my $b2 = ; + while(defined($b1) && defined($b2)) { + if($b1 lt $b2) { + print FH3 $b1; $b1 = ; + } else { + print FH3 $b2; $b2 = ; + } + } + + while($b1 = ) { print FH3 $b1; } + while($b2 = ) { print FH3 $b2; } + close(FH1); close(FH2); close(FH3); + rename("$mylogfile.new", $mylogfile); + $fh = new IO::File(">>$mylogfile"); + $hash->{FH} = $fh; + + $hash->{REGEXP} .= "|".$vh->{REGEXP}; + $hash->{DEF} = $hash->{logfile} . " ". $hash->{REGEXP}; + CommandDelete(undef, $victim); + + } return undef; } ######################### sub -FW_dumpFileLog($$$$) +FileLog_fhemwebFn($$$$) { my ($FW_wname, $d, $room, $pageHash) = @_; # pageHash is set for summaryFn. @@ -193,6 +277,58 @@ FW_dumpFileLog($$$$) } $ret .= ""; } + $ret .= ""; + return $ret if($pageHash); + + # DETAIL only from here on + my $hash = $defs{$d}; + + $ret .= "
Regexp parts"; + $ret .= "
"; + my @ra = split(/\|/, $hash->{REGEXP}); + if(@ra > 1) { + foreach my $r (@ra) { + $ret .= ""; + my $cmd = "cmd.X=set $d removeRegexpPart&val.X=$r"; + $ret .= ""; + $ret .= FW_pH("$cmd&detail=$d", "removeRegexpPart", 1,undef,1); + $ret .= ""; + } + } + + 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; + $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 .= ""; + } + $ret .= "
$r
"; + $ret .= FW_hidden("detail", $d); + $ret .= FW_hidden("dev.$d", "$d addRegexpPart"); + $ret .= FW_submit("cmd.$d", "set", "set"); + $ret .= "
 $d addRegexpPart 
"; + $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 .= ""; + $ret .= "
"; return $ret; } @@ -585,12 +721,45 @@ seekTo($$$$) Set
    - set <name> reopen
    - - Used to reopen a FileLog after making some manual changes to the logfile. +
  • reopen +
      + Reopen a FileLog after making some manual changes to the + logfile. +
    +
  • +
  • addRegexpPart <device> <regexp> +
      + 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. +
    +
  • +
  • removeRegexpPart <re> +
      + remove a regexp part. Note: as the regexp parts are resorted, manually + constructed regexps may become invalid.
      + The inconsistency in addRegexpPart/removeRegexPart arguments originates + from the reusage of javascript functions. +
    +
  • +
  • absorb secondFileLog +
      + merge the current and secondFileLog into one file, add the regexp of the + secondFileLog to the current one, and delete secondFileLog.
      + This command is needed to create combined plots (weblinks).
      + Notes: +
        +
      • secondFileLog will be deleted (i.e. the FHEM definition and + the file itself).
      • +
      • only the current files will be merged.
      • +
      • weblinks using secondFilelog will become broken, they have to be + adopted to the new logfile or deleted.
      • +
      +
    +
  • +
    +

- -
@@ -665,7 +834,7 @@ seekTo($$$$)
  • archivecmd / archivedir / nrarchive
    - When a new FileLog file is opened, the FileLog archiver wil be called. + When a new FileLog file is opened, the FileLog archiver wil be called. This happens only, if the name of the logfile has changed (due to time-specific wildcards, see the FileLog section), and there is a new entry to be written into the file. diff --git a/fhem/FHEM/98_weblink.pm b/fhem/FHEM/98_weblink.pm index b55278307..07997e6ee 100755 --- a/fhem/FHEM/98_weblink.pm +++ b/fhem/FHEM/98_weblink.pm @@ -61,12 +61,13 @@ FW_showWeblink($$$$) ################## sub -weblink_FwDetail($) +weblink_FwDetail($@) { - my ($d)= @_; + my ($d, $text)= @_; my $alias= AttrVal($d, "alias", $d); my $ret = "
    "; + $ret .= "$text " if($text); $ret .= FW_pHPlain("detail=$d", $alias) if(!$FW_subdir); $ret .= "
    "; return $ret; @@ -115,10 +116,10 @@ weblink_FwFn($$$$) my @va = split(":", $link, 3); if($wltype eq "fileplot" && (@va != 3 || !$defs{$va[0]} || !$defs{$va[0]}{currentlogfile})) { - $ret .= "Broken definition for fileplot $d: $link
    "; + $ret .= weblink_FwDetail($d, "Broken definition "); } elsif ($wltype eq "dbplot" && (@va != 2 || !$defs{$va[0]})) { - $ret .= "Broken definition for dbplot $d: $link
    "; + $ret .= weblink_FwDetail($d, "Broken definition "); } else { if(defined($va[2]) && $va[2] eq "CURRENT") { diff --git a/fhem/docs/commandref_frame.html b/fhem/docs/commandref_frame.html index 09d422e25..d8e100879 100644 --- a/fhem/docs/commandref_frame.html +++ b/fhem/docs/commandref_frame.html @@ -82,6 +82,7 @@ DbLog   dewpoint   dummy   + eventTypes   FHEM2FHEM   FHEMWEB   FB_CALLMONITOR   diff --git a/fhem/docs/commandref_frame_DE.html b/fhem/docs/commandref_frame_DE.html index f983337c1..a0f50dc13 100644 --- a/fhem/docs/commandref_frame_DE.html +++ b/fhem/docs/commandref_frame_DE.html @@ -82,6 +82,7 @@ DbLog   dewpoint   dummy   + eventTypes   FHEM2FHEM   FHEMWEB   FB_CALLMONITOR   diff --git a/fhem/fhem.pl b/fhem/fhem.pl index d69b09c28..7872029d4 100755 --- a/fhem/fhem.pl +++ b/fhem/fhem.pl @@ -126,7 +126,8 @@ sub CommandTrigger($$); #Special values in %modules (used if set): # DefFn - define a "device" of this type -# UndefFn - clean up at delete +# UndefFn - clean up (delete timer, close fd), called by delete and rereadcfg +# DeleteFn - clean up (delete logfile), called by delete after UndefFn # ParseFn - Interpret a raw message # ListFn - details for this "device" # SetFn - set/activate this device @@ -1412,6 +1413,11 @@ CommandDelete($$) push @rets, $ret; next; } + $ret = CallFn($sdev, "DeleteFn", $defs{$sdev}, $sdev); + if($ret) { + push @rets, $ret; + next; + } # Delete releated hashes foreach my $p (keys %selectlist) { diff --git a/fhem/www/pgm2/fhemweb.js b/fhem/www/pgm2/fhemweb.js index 5e62520fa..c75b73859 100644 --- a/fhem/www/pgm2/fhemweb.js +++ b/fhem/www/pgm2/fhemweb.js @@ -235,9 +235,13 @@ FW_selChange(sel, list, elName) var value; var l = list.split(" "); for(var i=0; i < l.length; i++) { - var nv = l[i].split(":",2); - if(nv[0] == sel) { - value = nv[1]; break; + cmd = l[i]; + var off = l[i].indexOf(":"); + if(off >= 0) + cmd = l[i].substring(0, off); + if(cmd == sel) { + if(off >= 0) + value = l[i].substring(off+1); } } var el = document.getElementsByName(elName)[0];