98_template.pm 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. # $Id: 98_template.pm 13688 2017-03-12 18:16:38Z neubert $
  2. package main;
  3. use strict;
  4. use warnings;
  5. sub template_Initialize($$) {
  6. $cmds{template} =
  7. { Fn=>"CommandTemplate",
  8. Hlp=>"[use] <filename> [<param1>=<value1> [<param2>=<value2> [...]]],use a template" };
  9. }
  10. sub EvaluateTemplate($$) {
  11. my ($filename, $args)= @_;
  12. # load template from file
  13. my ($err, @result)= FileRead($filename);
  14. return ($err, undef, undef, undef) if(defined($err) && $err ne "");
  15. # remove trailing newlines and empty/whitespace lines
  16. @result= grep /\S/, map { s/\r?\n$//; $_ } @result;
  17. # we enumerate the parameters for the show command
  18. my %p;
  19. map { while(m/\%(\w+)%/g) { $p{$1}= 1 } } @result;
  20. my @params= keys %p;
  21. # do parameter substition
  22. Log 5, "Using template from file $filename.";
  23. my ($valuesref,$kvref)= parseParams($args);
  24. my @values= @{$valuesref}; my %kv= %{$kvref};
  25. return "parameters must be of form <param>=<value>" unless($#values<0);
  26. foreach my $key (keys %kv) {
  27. my $value= $kv{$key};
  28. my $count= 0;
  29. map { $count += s/\%$key\%/$value/g } @result;
  30. Log 5, "Using $value for parameter %$key% in template $filename $count time(s).";
  31. }
  32. # count and enumerate not substituted parameters
  33. my $count= 0; %p= ();
  34. map { while(m/\%(\w+)%/g) { $p{$1}= 1; $count++ } } @result;
  35. my $warn= "$count parameter(s) not substituted in template $filename: " .
  36. join(" ", keys %p) if($count);
  37. # return the result
  38. return (undef, $warn, \@params, \@result);
  39. }
  40. sub CommandTemplate($$) {
  41. my ($cl, $param) = @_;
  42. my $usage= "Usage: template [use|show] <filename> [<param1>=<value1> [<param2>=<value2> [...]]]";
  43. # get the arguments and do first sanity checks
  44. my @args= split("[ \t]]*", $param);
  45. return $usage if($#args< 0);
  46. my $action= "use";
  47. $action= shift @args if($args[0] eq "use" || $args[0] eq "show");
  48. return $usage if($#args< 0);
  49. my $filename= shift @args;
  50. # evaluate the template
  51. my ($error, $warn, $paramsref, $resultref)= EvaluateTemplate($filename, join(" ", @args));
  52. return $error if(defined($error));
  53. # we inform the user about missing substitutions but
  54. # we do not make this an error because the actual occurence %...% might be intentional
  55. Log 5, $warn if(defined($warn));
  56. if($action eq "use") {
  57. my @ret;
  58. my $bigcmd = "";
  59. ${main::rcvdquit} = 0;
  60. foreach my $l (@{$resultref}) {
  61. if($l =~ m/^(.*)\\ *$/) { # Multiline commands
  62. $bigcmd .= "$1\n";
  63. } else {
  64. my $tret = AnalyzeCommandChain($cl, $bigcmd . $l);
  65. push @ret, $tret if(defined($tret));
  66. $bigcmd = "";
  67. }
  68. last if(${main::rcvdquit});
  69. }
  70. return join("\n", @ret) if(@ret);
  71. return undef;
  72. } elsif($action eq "show") {
  73. return(
  74. "template: $filename" .
  75. "\nresult:\n" . join("\n", @{$resultref}) .
  76. "\nparameters: " . join(" ", @{$paramsref})
  77. );
  78. } else {
  79. return undef; # we never get here
  80. }
  81. }
  82. 1;
  83. =pod
  84. =item command
  85. =item summary use a template for repetitive configurations and commands.
  86. =item summary_DE verwendet ein Template f&uuml;r wiederkehrende Konfigurationen und Kommandos.
  87. =begin html
  88. <a name="template"></a>
  89. <h3>template</h3>
  90. <ul>
  91. <code>template [use|show] &lt;filename&gt; [&lt;param1&gt;=&lt;value1&gt; [&lt;param2&gt;=&lt;value2&gt; [...]]]</code>
  92. <br><br>
  93. Includes a file with parameter substitution, i.e. read the file and process every line as a FHEM command.
  94. For any given parameter/value pair <code>&lt;param&gt;=&lt;value&gt;</code> on the command line,
  95. a literal <code>%&lt;param&gt;%</code> in the file is replaced by &lt;value&gt; before executing the command.<br><br>
  96. This can be used to to code recurring definitions of one or several devices only once and use it many times.
  97. <code>template show ..</code> shows what would be done, including a parameter listing, while
  98. <code>template use ...</code> actually does the job. The word <code>use</code> can be omitted.<br><br>
  99. <b>Example</b><br><br>
  100. File <i>H.templ</i>:<br><br>
  101. <code>
  102. define %name% FHT %fhtcode%<br>
  103. attr %name% IODev CUN<br>
  104. attr %name% alias %alias%<br>
  105. attr %name% group %group%<br>
  106. attr %name% icon icoTempHeizung.png<br>
  107. attr %name% room %room%,Anlagen/Heizungen<br>
  108. <br>
  109. define watchdog.%name% watchdog %name% 00:15:00 SAME set %name% report2 255<br>
  110. attr watchdog.%name% group %group%<br>
  111. attr watchdog.%name% room Control/Heizungen<br>
  112. <br>
  113. define %name%.log FileLog /opt/fhem/log/%name%-%Y%m.log %name%:.*<br>
  114. attr %name%.log group %group%<br>
  115. attr %name%.log icon icoLog.png<br>
  116. attr %name%.log logtype fht<br>
  117. attr %name%.log room Control/Heizungen<br>
  118. <br>
  119. define %name%.weblink SVG %name%.log:%name%:CURRENT<br>
  120. attr %name%.weblink label sprintf("Temperatur: %.0f °C (%.0f °C .. %.0f °C) Aktor: %.0f %% (%.0f %% .. %.0f %%)", $data{currval1}, $data{min1}, $data{max1}, $data{currval2}, $data{min2}, $data{max2} )<br>
  121. attr %name%.weblink room %room%<br>
  122. attr %name%.weblink alias %alias%<br>
  123. </code><br><br>
  124. Configuration:<br><br>
  125. <code>te H.templ name=3.dz.hzg fhtcode=3f4a alias=Dachzimmerheizung group=Heizung room=Dachzimmer</code><br><br>
  126. Please note that although %Y% in the FileLog definition looks like a parameter, it is not substituted since no parameter
  127. Y is given on the command line. You get detailed information at verbosity level 5 when you run the command.
  128. </ul>
  129. =end html
  130. =begin html_DE
  131. <a name="template"></a>
  132. <h3>template</h3>
  133. <ul>
  134. <code>template [use|show] &lt;filename&gt; [&lt;param1&gt;=&lt;value1&gt; [&lt;param2&gt;=&lt;value2&gt; [...]]]</code>
  135. <br><br>
  136. Includes a file with parameter substitution, i.e. read the file and process every line as a FHEM command.
  137. For any given parameter/value pair <code>&lt;param&gt;=&lt;value&gt;</code> on the command line,
  138. a literal <code>%&lt;param&gt;%</code> in the file is replaced by &lt;value&gt; before executing the command.<br><br>
  139. This can be used to to code recurring definitions of one or several devices only once and use it many times.
  140. <code>template show ..</code> shows what would be done, including a parameter listing, while
  141. <code>template use ...</code> actually does the job. The word <code>use</code> can be omitted.<br><br>
  142. <b>Example</b><br><br>
  143. File <i>H.templ</i>:<br><br>
  144. <code>
  145. define %name% FHT %fhtcode%<br>
  146. attr %name% IODev CUN<br>
  147. attr %name% alias %alias%<br>
  148. attr %name% group %group%<br>
  149. attr %name% icon icoTempHeizung.png<br>
  150. attr %name% room %room%,Anlagen/Heizungen<br>
  151. <br>
  152. define watchdog.%name% watchdog %name% 00:15:00 SAME set %name% report2 255<br>
  153. attr watchdog.%name% group %group%<br>
  154. attr watchdog.%name% room Control/Heizungen<br>
  155. <br>
  156. define %name%.log FileLog /opt/fhem/log/%name%-%Y%m.log %name%:.*<br>
  157. attr %name%.log group %group%<br>
  158. attr %name%.log icon icoLog.png<br>
  159. attr %name%.log logtype fht<br>
  160. attr %name%.log room Control/Heizungen<br>
  161. <br>
  162. define %name%.weblink SVG %name%.log:%name%:CURRENT<br>
  163. attr %name%.weblink label sprintf("Temperatur: %.0f °C (%.0f °C .. %.0f °C) Aktor: %.0f %% (%.0f %% .. %.0f %%)", $data{currval1}, $data{min1}, $data{max1}, $data{currval2}, $data{min2}, $data{max2} )<br>
  164. attr %name%.weblink room %room%<br>
  165. attr %name%.weblink alias %alias%<br>
  166. </code><br><br>
  167. Configuration:<br><br>
  168. <code>te H.templ name=3.dz.hzg fhtcode=3f4a alias=Dachzimmerheizung group=Heizung room=Dachzimmer</code><br><br>
  169. Please note that although %Y% in the FileLog definition looks like a parameter, it is not substituted since no parameter
  170. Y is given on the command line. You get detailed information at verbosity level 5 when you run the command.
  171. </ul>
  172. =end html_DE
  173. =cut