From e01639ecfa17966eb054b5d7a1acd3745717de6c Mon Sep 17 00:00:00 2001 From: StefanStrobel <> Date: Thu, 14 Apr 2022 16:47:44 +0000 Subject: [PATCH] 98_FReplacer: convert to own namespace and other smaller changes git-svn-id: https://svn.fhem.de/fhem/trunk@25961 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/FHEM/98_FReplacer.pm | 166 ++++++++++++++++++++++++++++---------- 1 file changed, 125 insertions(+), 41 deletions(-) diff --git a/fhem/FHEM/98_FReplacer.pm b/fhem/FHEM/98_FReplacer.pm index 5397eb578..d5c69090d 100755 --- a/fhem/FHEM/98_FReplacer.pm +++ b/fhem/FHEM/98_FReplacer.pm @@ -1,4 +1,4 @@ -############################################## +############################################################################# # $Id$ # # Basiert auf der Idee Fhem Daten auf einem Kindle anzuzeigen @@ -22,10 +22,12 @@ # 2016-10-31 added SVG # 2016-11-02 RepXXText und RepXXTidy, delay first update for 1 secs after INITIALIZED # Attribute disable, fixed uninitialized wearning at start with SVG -# 2016-11-17 fixed missing REREADCFG in Notify check -# 2016-12-21 set NOTIFYDEV in Define +# 2016-11-17 fixed missing REREADCFG in Notify check +# 2016-12-21 set NOTIFYDEV in Define +# 2019-11-17 precompile regexes like in httpmod # + # to include an SVG Plot # add a group to the template like this: # @@ -49,8 +51,10 @@ # # ToDo: -# fhem blocks during SVG creation. Can we make this async? -# $FW_wname undef -> warning in SVG call at startup +# fhem blocks during SVG creation. Can we make this async? +# $FW_wname undef -> warning in SVG call at startup +# +# change to own namespace # package main; @@ -61,6 +65,8 @@ use warnings; use Time::HiRes qw( time ); use POSIX qw(strftime); use Encode qw(decode encode); +use FHEM::HTTPMOD::Utils qw(:all); + sub FReplacer_Initialize($); sub FReplacer_Define($$); @@ -68,7 +74,8 @@ sub FReplacer_Undef($$); sub FReplacer_Update($); sub FReplacer_Attr(@); -my $FReplacer_Version = '2.4 - 21.12.2016'; +my $FReplacer_Version = '2.5 - 17.11.2019'; + ##################################### sub FReplacer_Initialize($) @@ -95,6 +102,8 @@ sub FReplacer_Initialize($) "ReplacementEncode " . # Ergebnis einer Ersetzung z.B. in UTF-8 Encoden "PostCommand " . # Systembefehl, der nach der Ersetzung ausgeführt wird "LUTimeFormat " . # time format for strftime for LastUpdate + "regexDecode " . + "regexCompile " . "disable:0,1 " . $readingFnAttributes; @@ -125,8 +134,7 @@ sub FReplacer_Define($$) ##################################### -sub -FReplacer_Undef($$) +sub FReplacer_Undef($$) { my ($hash, $arg) = @_; #my $name = $hash->{NAME}; @@ -159,11 +167,9 @@ sub FReplacer_Notify($$) } -# -# Attr command ############################################################## -sub -FReplacer_Attr(@) +# Attr command +sub FReplacer_Attr(@) { my ($cmd,$name,$aName,$aVal) = @_; my $hash = $defs{$name}; @@ -210,7 +216,7 @@ FReplacer_Attr(@) return "Invalid Format $aVal"; } } - addToDevAttrList($name, $aName) + #addToDevAttrList($name, $aName) # todo: use better library function to manage userattr list } if ($aName eq 'disable') { @@ -223,12 +229,13 @@ FReplacer_Attr(@) InternalTimer(gettimeofday()+1, "FReplacer_Update", $hash, 0); } } - + my $err = ManageUserAttr($hash, $aName); + return $err if ($err); return undef; } -# SET command ######################################################################### +# SET command sub FReplacer_Set($@) { my ( $hash, @a ) = @_; @@ -245,12 +252,62 @@ sub FReplacer_Set($@) return "Unknown argument $setName, choose one of ReplaceNow"; } } + + +################################### +# precompile regex attr value +sub FReplacer_PrecompileRegexAttr($$$) +{ + my ($hash, $aName, $aVal) = @_; + my $name = $hash->{NAME}; + my $regDecode = AttrVal($name, 'regexDecode', ""); + if ($regDecode && $regDecode !~ /^[Nn]one$/) { + $aVal = decode($regDecode, $aVal); + Log3 $name, 5, "$name: PrecompileRegexAttr is decoding regex $aName as $regDecode"; + } + + my $oldSig = ($SIG{__WARN__} ? $SIG{__WARN__} : 'DEFAULT'); + $SIG{__WARN__} = sub { Log3 $name, 3, "$name: PrecompileRegexAttr for $aName $aVal created warning: @_"; }; + eval {$hash->{CompiledRegexes}{$aName} = qr/$aVal/}; + $SIG{__WARN__} = $oldSig; + if (!$@) { + Log3 $name, 5, "$name: PrecompileRegexAttr precompiled $aName /$aVal/ to $hash->{CompiledRegexes}{$aName}"; + } +} + + +################################################ +# get a regex from attr and compile if not done +sub FReplacer_GetRegex($$$$$) +{ + my ($name, $context, $num, $type, $default) = @_; + my $hash = $defs{$name}; + my $val; + my $regDecode = AttrVal($name, 'regexDecode', ""); + my $regCompile = AttrVal($name, 'regexCompile', 1); + + if ($num && defined ($attr{$name}{$context . $num . $type})) { # specific regex attr exists + return $attr{$name}{$context . $num . $type} if (!$regCompile); + if ($hash->{CompiledRegexes}{$context . $num . $type}) { # compiled specific regex esists + $val = $hash->{CompiledRegexes}{$context . $num . $type}; + Log3 $name, 5, "$name: GetRegex found precompiled $type for $context$num as $val"; + } else { # not compiled (yet) + $val = $attr{$name}{$context . $num . $type}; + FReplacer_PrecompileRegexAttr($hash, $context . $num . $type, $val); + $val = $hash->{CompiledRegexes}{$context . $num . $type}; + } + + } else { + $val = $default; + return if (!$val) # default is not compiled - should only be "" or similar + } + return $val; +} ##################################### -sub -FReplacer_Update($) { +sub FReplacer_Update($) { my ($hash) = @_; my $name = $hash->{NAME}; InternalTimer(gettimeofday()+$hash->{INTERVAL}, "FReplacer_Update", $hash, 0); @@ -280,11 +337,12 @@ FReplacer_Update($) { if ($key =~ /Rep([0-9]+)Regex/) { my $replacement = ""; my $index = $1; - my $regex = $attr{$name}{"Rep${index}Regex"}; + #my $regex = $attr{$name}{"Rep${index}Regex"}; + my $regex = FReplacer_GetRegex($name, "Rep", $index, "Regex", ""); my $skip = 0; my $isSVG = 0; - if ($attr{$name}{"Rep${index}Reading"}) { + if ($regex && $attr{$name}{"Rep${index}Reading"}) { if ($attr{$name}{"Rep${index}Reading"} !~ '([^\:]+):([^\:]+):?(.*)') { Log3 $name, 3, "$name: wrong format in attr Rep${index}Reading"; next; @@ -426,6 +484,7 @@ FReplacer_Update($) { } } + 1; =pod @@ -434,7 +493,7 @@ FReplacer_Update($) { =item summary_DE ersetzt Platzhalter mit Readings oder SVG Plots in einer Datei =begin html - +
attr FxxRegex
and attr FxxReading
or attr FxxExpr
to define which strings / placeholders in the InputFile should be replaced with which redings / expressions
@@ -487,7 +546,7 @@ FReplacer_Update($) {
attr fr PostCommand convert /opt/fhem/www/images/status.svg
@@ -555,10 +627,22 @@ FReplacer_Update($) {
or even
attr fr PostCommand bash -c 'inkscape /opt/fhem/www/images/status.svg -e=tmp.png -b=rgb\(255,255,255\) --export-height=1024 --export-width=758;; convert tmp.png -type GrayScale -depth 8 /opt/fhem/www/images/status.png' >/dev/null 2>&1 &
Inkscape might be needed because ImageMagick seems to have problems convertig SVG files with embedded icons. However a PNG file created by Inkscape is not in 8 bit greyscale so Imagemagick can be run after Inkscape to convert to 8 bit greyscale
- - ReplacementEncode
+