98_SubProcessTester.pm 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. # $Id: 98_SubProcessTester.pm 8393 2015-04-07 17:24:04Z borisneubert $
  2. ################################################################
  3. #
  4. # Copyright notice
  5. #
  6. # (c) 2015 Copyright: Dr. Boris Neubert
  7. # e-mail: omega at online dot de
  8. #
  9. # This file is part of fhem.
  10. #
  11. # Fhem is free software: you can redistribute it and/or modify
  12. # it under the terms of the GNU General Public License as published by
  13. # the Free Software Foundation, either version 2 of the License, or
  14. # (at your option) any later version.
  15. #
  16. # Fhem is distributed in the hope that it will be useful,
  17. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. # GNU General Public License for more details.
  20. #
  21. # You should have received a copy of the GNU General Public License
  22. # along with fhem. If not, see <http://www.gnu.org/licenses/>.
  23. #
  24. ################################################################################
  25. package main;
  26. use strict;
  27. use warnings;
  28. use SubProcess;
  29. #####################################
  30. sub
  31. SubProcessTester_Initialize($) {
  32. my ($hash) = @_;
  33. my %matchlist= (
  34. "1:SubProcessTesterDevice" => ".*",
  35. );
  36. # Provider
  37. $hash->{WriteFn} = "SubProcessTester_Write";
  38. $hash->{ReadFn} = "SubProcessTester_Read";
  39. $hash->{Clients} = ":VBox:";
  40. $hash->{MatchList} = \%matchlist;
  41. #$hash->{ReadyFn} = "SubProcessTester_Ready";
  42. # Consumer
  43. $hash->{DefFn} = "SubProcessTester_Define";
  44. $hash->{UndefFn} = "SubProcessTester_Undef";
  45. #$hash->{ParseFn} = "SubProcessTeser_Parse";
  46. $hash->{ShutdownFn} = "SubProcessTester_Shutdown";
  47. #$hash->{ReadyFn} = "SubProcessTester_Ready";
  48. #$hash->{GetFn} = "SubProcessTester_Get";
  49. $hash->{SetFn} = "SubProcessTester_Set";
  50. #$hash->{AttrFn} = "SubProcessTester_Attr";
  51. #$hash->{AttrList}= "";
  52. }
  53. #####################################
  54. #
  55. # Functions called from subprocess
  56. #
  57. #####################################
  58. sub onRun($) {
  59. my $subprocess= shift;
  60. my $parent= $subprocess->parent();
  61. Log3 undef, 1, "SUBPROCESS: Running...";
  62. my $foobar= $subprocess->{foobar};
  63. for(my $i= 0; $i< 30; $i++) {
  64. my $msg= $subprocess->readFromParent();
  65. if(defined($msg)) {
  66. Log3 undef, 1, "SUBPROCESS read from parent: $msg";
  67. $subprocess->writeToParent("echo: $msg");
  68. }
  69. #Log3 undef, 1, "Step $i";
  70. # here we write something to the parent process
  71. # this is received via the global select loop
  72. # and evaluated in the ReadFn.
  73. $subprocess->writeToParent("$foobar $i\n");
  74. #print $parent "$foobar $i\n";
  75. #$parent->flush();
  76. # has the pa
  77. sleep 5;
  78. }
  79. }
  80. sub onExit() {
  81. Log3 undef, 1, "EXITED!";
  82. }
  83. #####################################
  84. #
  85. # FHEM functions
  86. #
  87. #####################################
  88. sub SubProcessTester_Define($$) {
  89. # define mySubProcessTester SubProcessTester configuration
  90. my ($hash, $def) = @_;
  91. my @a = split("[ \t]+", $def);
  92. if(int(@a) != 2) {
  93. my $msg = "wrong syntax: define <name> SubProcessTester <configuration>";
  94. Log3 $hash, 2, $msg;
  95. return $msg;
  96. }
  97. SubProcessTester_DoInit($hash);
  98. return undef;
  99. }
  100. sub SubProcessTester_Undef($$) {
  101. my $hash= shift;
  102. SubProcessTester_DoExit($hash);
  103. return undef;
  104. }
  105. sub SubProcessTester_Shutdown($$) {
  106. my $hash= shift;
  107. SubProcessTester_DoExit($hash);
  108. return undef;
  109. }
  110. sub SubProcessTester_Set() {
  111. my ($hash, @a)= @_;
  112. my $name= $hash->{NAME};
  113. my $cmdname= $a[1];
  114. my $value= $a[2];
  115. if($cmdname eq "send") {
  116. my $subprocess= $hash->{fhem}{subprocess};
  117. Log3 $hash, 5, "Before send....";
  118. $subprocess->writeToChild($value);
  119. Log3 $hash, 5, "After send....";
  120. return undef;
  121. } else {
  122. return "Unknown argument $cmdname, choose one of send";
  123. }
  124. }
  125. #####################################
  126. sub SubProcessTester_DoInit($) {
  127. my $hash = shift;
  128. my $name= $hash->{NAME};
  129. $hash->{fhem}{subprocess}= undef;
  130. my $subprocess= SubProcess->new( { onRun => \&onRun, onExit => \&onExit } );
  131. # you can set your own variables like this:
  132. $subprocess->{foobar}= "foo / bar";
  133. # remember: as soon as the subprocess is started, parent and child process live
  134. # in separate processes and cannot share data anymore - changing variables in
  135. # the parent does not affect variables in the child and vice versa.
  136. my $pid= $subprocess->run();
  137. return unless($pid);
  138. $hash->{fhem}{subprocess}= $subprocess;
  139. $hash->{FD}= fileno $subprocess->child();
  140. delete($readyfnlist{"$name.$pid"});
  141. $selectlist{"$name.$pid"}= $hash;
  142. $hash->{STATE} = "Initialized";
  143. return undef;
  144. }
  145. sub SubProcessTester_DoExit($) {
  146. my $hash = shift;
  147. my $name= $hash->{NAME};
  148. my $subprocess= $hash->{fhem}{subprocess};
  149. return unless(defined($subprocess));
  150. my $pid= $subprocess->pid();
  151. return unless($pid);
  152. $subprocess->terminate();
  153. $subprocess->wait();
  154. delete($selectlist{"$name.$pid"});
  155. delete $hash->{FD};
  156. $hash->{STATE} = "Finalized";
  157. return undef;
  158. }
  159. #####################################
  160. # called from the global loop, when the select for hash->{FD} reports data
  161. sub SubProcessTester_Read($) {
  162. my ($hash) = @_;
  163. my $name= $hash->{NAME};
  164. #Debug "$name has data to read!";
  165. my $subprocess= $hash->{fhem}{subprocess};
  166. # here we read from the global select loop what was
  167. # written in the onRun function
  168. my $result= $subprocess->readFromChild();
  169. if(defined($result)) {
  170. chomp $result;
  171. readingsSingleUpdate($hash, "step", $result, 1);
  172. }
  173. return $result;
  174. }
  175. #############################
  176. 1;
  177. #############################
  178. =pod
  179. =begin html
  180. <a name="SubProcessTester"></a>
  181. <h3>SubProcessTester</h3>
  182. <ul>
  183. <br>
  184. <a name="SubProcessTester"></a>
  185. <b>Define</b>
  186. <ul>
  187. <code>define &lt;name&gt; SubProcessTester &lt;config&gt;</code><br>
  188. <br>
  189. </ul>
  190. </ul>
  191. =end html