PageRenderTime 60ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/v2-75/mh/code/common/trigger_code.pl

#
Perl | 222 lines | 178 code | 27 blank | 17 comment | 25 complexity | 8e87a687de5ec5d4ed86c30f5cc2bc4e MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, GPL-3.0
  1. # Category = MisterHouse
  2. #@ Monitors trigger code, used by code like tv_grid and the web alarm page,
  3. #@ that specifies events that trigger actions. View, add, modify, or
  4. #@ delete triggers with <a href=/bin/triggers.pl>/bin/triggers.pl</a>.
  5. use vars '%triggers'; # use vars so we can use in the web server
  6. my ($trigger_write_code_flag, $prev_triggers, $prev_script);
  7. my $trigger_file = "$config_parms{data_dir}/triggers.current";
  8. my $expired_file = "$config_parms{data_dir}/triggers.expired";
  9. my $script_file = "$config_parms{code_dir}/triggers.mhp";
  10. # No need to save right after startup
  11. $prev_triggers = &file_read($trigger_file) if $Reload and -e $trigger_file;
  12. $prev_script = &file_read($script_file) if $Reload and -e $script_file;
  13. &Exit_add_hook(\&triggers_save) if $Reload;
  14. &triggers_save if new_minute 5;
  15. &triggers_read if $Startup;
  16. &trigger_write_code if $trigger_write_code_flag;
  17. # Read current triggers file at startup
  18. sub triggers_read {
  19. # Read trigger data
  20. return unless -e $trigger_file;
  21. my $i = 0;
  22. undef %triggers;
  23. my ($trigger, $code, $name, $type, $triggered);
  24. for my $record (&file_read($trigger_file), '') {
  25. if ($record =~ /\S/) {
  26. next if $record =~ /^ *#/;
  27. if ($record =~ /^name=(.+?)\s+type=(\S+)\s+triggered=(\d*)/) {
  28. $name = $1; $type = $2; $triggered = $3;
  29. }
  30. elsif (!$trigger) {
  31. $trigger = $record;;
  32. }
  33. else {
  34. next if $record =~ /^\d+ \d+$/; # Old trigger format ... ignore
  35. $code .= $record . "\n";
  36. }
  37. }
  38. # Assume there is always a blank line at end of file
  39. elsif ($trigger) {
  40. trigger_set($trigger, $code, $type, $name, 1, $triggered);
  41. $trigger = $code = $name = $type = $triggered = '';
  42. $i++;
  43. }
  44. }
  45. print_log "Read $i trigger entries";
  46. }
  47. # Write trigger code
  48. sub trigger_write_code {
  49. $trigger_write_code_flag = 0;
  50. my $script;
  51. foreach my $name (trigger_list()) {
  52. my ($trigger, $code, $type, $triggered) = trigger_get($name);
  53. $script .= "\n# name=$name type=$type\n";
  54. $script .= "if (($trigger) and &trigger_active('$name')) {\n";
  55. $script .= " &trigger_expire('$name');\n";
  56. $script .= " $code;\n}\n";
  57. }
  58. $script = "#\n#@ Do NOT edit. This file is auto-generated by mh/code/common/trigger_code.pl\n" .
  59. "#@ and reflects the data in data_dir/triggers.current\n#\n" . $script;
  60. return if $script eq $prev_script;
  61. $prev_script = $script;
  62. &file_write($script_file, $script);
  63. # Replace (faster) or reload (if there was no file previously)
  64. if ($Run_Members{'triggers_table'}) {
  65. &do_user_file("$config_parms{code_dir}/triggers.mhp");
  66. }
  67. else {
  68. # Must be done before the user code eval
  69. push @Nextpass_Actions, \&read_code;
  70. }
  71. }
  72. # Save and prune out expired triggers
  73. sub triggers_save {
  74. my ($data, $data1, $data2, $i1, $i2);
  75. $i1 = $i2 = 0;
  76. $data1 = $data2 = '';
  77. foreach my $name (trigger_list()) {
  78. my ($trigger, $code, $type, $triggered) = trigger_get($name);
  79. $data = "name=$name type=$type triggered=$triggered\n";
  80. $data .= $trigger . "\n";
  81. $data .= $code . ";\n";
  82. # Prune it out if it is expired and > 1 week old
  83. if (trigger_expired($name) and ($triggers{$name}{triggered} + 60*60*24*7) < $Time) {
  84. $data2 .= $data . "\n";
  85. $i2++;
  86. delete $triggers{$name};
  87. }
  88. else {
  89. $data1 .= $data . "\n";
  90. $i1++;
  91. }
  92. }
  93. print_log "Saving triggers: $i2 expired, $i1 saved" if $i2;
  94. $data1 = '#
  95. # Note: Do NOT edit this file while mh is running (edits will be lost).
  96. # It is used by mh/code/common/trigger_code.pl to auto-generate code_dir/triggers.mhp.
  97. # It is updated by various trigger_ functions like trigger_set.
  98. # Syntax is:
  99. # name=trigger name type=trigger_type triggered=triggered_time
  100. # trigger_clause
  101. # code_to_run
  102. # code_to_run
  103. #
  104. # Expired triggers will be pruned to triggers.expired a week after they expire.
  105. #
  106. ' . $data1;
  107. $data2 = "# Expired on $Time_Date\n" . $data2 if $data2;
  108. unless ($data1 eq $prev_triggers) {
  109. &file_write($trigger_file, $data1);
  110. &logit($expired_file, $data2, 0) if $data2;
  111. $trigger_write_code_flag++;
  112. }
  113. $prev_triggers = $data1;
  114. return;
  115. }
  116. sub trigger_set {
  117. my ($trigger, $code, $type, $name, $replace, $triggered) = @_;
  118. print "trigger: trigger=$trigger code=$code name=$name\n" if $config_parms{debug} eq 'trigger';
  119. return unless $trigger and $code;
  120. # Find a uniq name
  121. if ($triggers{$name} and $replace) {
  122. print_log "trigger $name already exists, modifying";
  123. }
  124. else {
  125. $name = time_date_stamp(12) unless $name;
  126. if ($triggers{$name}) {
  127. my $i = 2;
  128. while ($triggers{"$name $i"}) { $i++; }
  129. $name = "$name $i";
  130. }
  131. }
  132. $code =~ s/;?\n?$//; # So we can consistenly add ;\n when used
  133. $triggered = 0 unless $triggered;
  134. $type = 'OneShot' unless $type;
  135. $triggers{$name}{trigger} = $trigger;
  136. $triggers{$name}{code} = $code;
  137. $triggers{$name}{triggered} = $triggered;
  138. $triggers{$name}{type} = $type;
  139. $trigger_write_code_flag++;
  140. return;
  141. }
  142. sub trigger_get {
  143. my $name = shift;
  144. return $triggers{$name}{trigger}, $triggers{$name}{code}, $triggers{$name}{type}, $triggers{$name}{triggered};
  145. }
  146. sub trigger_delete {
  147. my $name = shift;
  148. delete $triggers{$name};
  149. $trigger_write_code_flag++;
  150. return;
  151. }
  152. sub trigger_copy {
  153. my $name = shift;
  154. my $name2 = "$name 2";
  155. if (my ($r, $i) = $name =~ /(.+) (\d+)$/) {
  156. $name2 = "$r " . ++$i;
  157. }
  158. $triggers{$name2}{trigger} = $triggers{$name}{trigger};
  159. $triggers{$name2}{code} = $triggers{$name}{code};
  160. $triggers{$name2}{type} = $triggers{$name}{type};
  161. $triggers{$name2}{triggered} = 0;
  162. return;
  163. }
  164. sub trigger_rename {
  165. my ($name1, $name2) = @_;
  166. $triggers{$name2}{trigger} = $triggers{$name1}{trigger};
  167. $triggers{$name2}{code} = $triggers{$name1}{code};
  168. $triggers{$name2}{type} = $triggers{$name1}{type};
  169. $triggers{$name2}{triggered} = $triggers{$name1}{triggered};
  170. delete $triggers{$name1};
  171. $trigger_write_code_flag++;
  172. return;
  173. }
  174. sub trigger_list {
  175. return sort keys %triggers;
  176. }
  177. sub trigger_active {
  178. my $name = shift;
  179. # print "db n=$name t=$triggers{$name}{type} e=!$triggers{$name}{triggered}\n";
  180. return ($triggers{$name}{type} eq 'NoExpire' or $triggers{$name}{type} eq 'OneShot');
  181. }
  182. sub trigger_expired {
  183. my $name = shift;
  184. return ($triggers{$name}{type} eq 'Expired');
  185. }
  186. sub trigger_expire {
  187. my $name = shift;
  188. $triggers{$name}{triggered} = $Time;
  189. return unless $triggers{$name}{type} eq 'OneShot';
  190. # print "db setting name=$name expire_time=$Time\n";
  191. $triggers{$name}{type} = 'Expired';
  192. return;
  193. }
  194. # $Included_HTML{MisterHouse} = '<!--#include code="&trigger_html"-->' if $Reload;