garden.pl 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. #!/usr/bin/perl
  2. use warnings;
  3. use strict;
  4. use IO::Socket::INET;
  5. use IO::Handle;
  6. STDOUT->autoflush(1);
  7. #################
  8. # Formula:
  9. # Compute for the last <navg> days + today the avarage temperature and the
  10. # sum of rain, then compute the multiplier: (temp/20)^2 - rain/5
  11. # Now multiply the duration of each vent with this multiplier
  12. # If the value is less than a minimum, then store the value and add it
  13. # the next day
  14. #################
  15. my $test = 0; # Test only, do not switch anything
  16. my $fhzport = 7072; # Where to contact it
  17. my $avg = "/home/rudi/log/avg.log"; # KS300 avarage log file
  18. my $navg = 2; # Number of last avg_days to consider
  19. my $min = 300; # If the duration is < min (sec) then collect
  20. my $col = "/home/rudi/log/gardencoll.log"; # File where it will be collected
  21. my $pmp = "GPumpe"; # Name of the water pump, will be switched in first
  22. my $maxmult = 4; # Maximum factor (corresponds to 40 degree avg.
  23. # temp over $navg days, no rain)
  24. if(@ARGV) {
  25. if($ARGV[0] eq "test") {
  26. $test = 1;
  27. } else {
  28. print "Usage: garden.pl [test]\n";
  29. exit(1);
  30. }
  31. }
  32. my %list = (
  33. GVent1 => { Nr => 1, Dur => 720 },
  34. GVent2 => { Nr => 2, Dur => 480 },
  35. GVent3 => { Nr => 3, Dur => 720 },
  36. GVent4 => { Nr => 4, Dur => 720 },
  37. GVent6 => { Nr => 5, Dur => 720 },
  38. GVent7 => { Nr => 6, Dur => 480 },
  39. GVent8 => { Nr => 7, Dur => 480 },
  40. );
  41. ##############################
  42. # End of config
  43. sub fhzcommand($);
  44. sub doswitch($$);
  45. sub donext($$);
  46. my ($nlines, $temp, $rain) = (0, 0, 0);
  47. my ($KS300name, $server, $last);
  48. my @t = localtime;
  49. printf("%04d-%02d-%02d %02d:%02d:%02d\n",
  50. $t[5]+1900, $t[4]+1, $t[3], $t[2], $t[1], $t[0]);
  51. ###########################
  52. # First read in the last avg_days
  53. open(FH, $avg) || die("$avg: $!\n");
  54. my @avg = <FH>;
  55. close(FH);
  56. my @tarr; # Want the printout in the right order
  57. while(my $l = pop(@avg)) {
  58. next if($l !~ m/avg_day/);
  59. my @v = split(" ", $l);
  60. push(@tarr, "$v[0]: T: $v[4], R: $v[10]") if($test);
  61. $temp += $v[4]; $rain += $v[10];
  62. $KS300name = $v[1];
  63. $nlines++;
  64. last if($nlines >= $navg);
  65. }
  66. ###########################
  67. # Now get the current day
  68. foreach my $l (split("\n", fhzcommand("list $KS300name"))) {
  69. next if($l !~ m/avg_day/);
  70. my @v = split(" ", $l);
  71. print("$v[0] $v[1]: T: $v[4], R: $v[10]\n") if($test);
  72. $temp += $v[4]; $rain += $v[10];
  73. $nlines++;
  74. last;
  75. }
  76. if($test) {
  77. foreach my $l (@tarr) {
  78. print "$l\n";
  79. }
  80. }
  81. ###########################
  82. # the collected data
  83. my %coll;
  84. if(open(FH, $col)) {
  85. while(my $l = <FH>) {
  86. my ($k, $v) = split("[ \n]", $l);
  87. $coll{$k} = $v;
  88. }
  89. close(FH);
  90. }
  91. ###########################
  92. # The formula
  93. $temp /= $nlines;
  94. $rain /= $nlines;
  95. # safety measures
  96. $rain = 0 if($rain < 0);
  97. $temp = 0 if($temp < 0);
  98. $temp = 40 if($temp > 40);
  99. my $mult = exp( 2.0 * log( $temp / 20 )) - $rain/5;
  100. $mult = $maxmult if($mult > $maxmult);
  101. if($mult <= 0) {
  102. print("Multiplier is not positive ($mult), exiting\n");
  103. exit(0);
  104. }
  105. printf("Multiplier is %.2f (T: $temp, R: $rain)\n", $mult, $temp, $rain);
  106. my $have = 0;
  107. if(!$test) {
  108. open(FH, ">$col") || die("Can't open $col: $!\n");
  109. }
  110. foreach my $a (sort { $list{$a}{Nr} <=> $list{$b}{Nr} } keys %list) {
  111. my $dur = int($list{$a}{Dur} * $mult);
  112. if(defined($coll{$a})) {
  113. $dur += $coll{$a};
  114. printf(" $a: $dur ($coll{$a})\n");
  115. } else {
  116. printf(" $a: $dur\n");
  117. }
  118. if($dur > $min) {
  119. $list{$a}{Act} = $dur;
  120. $have += $dur;
  121. } else {
  122. print FH "$a $dur\n" if(!$test);
  123. }
  124. }
  125. print("Total time is $have\n");
  126. exit(0) if($test);
  127. close(FH);
  128. if($have) {
  129. doswitch($pmp, "on") if($pmp);
  130. sleep(3) if(!$test);
  131. foreach my $a (sort { $list{$a}{Nr} <=> $list{$b}{Nr} } keys %list) {
  132. next if(!$list{$a}{Act});
  133. donext($a, $list{$a}{Act});
  134. }
  135. donext("", 0);
  136. doswitch($pmp, "off") if($pmp);
  137. }
  138. ###########################
  139. # Switch the next dev on and the last one off
  140. sub
  141. donext($$)
  142. {
  143. my ($dev, $sl) = @_;
  144. doswitch($dev, "on");
  145. doswitch($last, "off");
  146. $last = $dev;
  147. if($test) {
  148. print "sleeping $sl\n";
  149. } else {
  150. sleep($sl);
  151. }
  152. }
  153. ###########################
  154. # Paranoid setting.
  155. sub
  156. doswitch($$)
  157. {
  158. my ($dev, $how) = @_;
  159. return if(!$dev || !$how);
  160. if($test) {
  161. print "set $dev $how\n";
  162. return;
  163. }
  164. fhzcommand("set $dev $how");
  165. sleep(1);
  166. fhzcommand("set $dev $how");
  167. }
  168. ###########################
  169. sub
  170. fhzcommand($)
  171. {
  172. my $cmd = shift;
  173. my ($ret, $buf) = ("", "");
  174. $server = IO::Socket::INET->new(PeerAddr => "localhost:$fhzport");
  175. die "Can't connect to the server at port $fhzport\n" if(!$server);
  176. syswrite($server, "$cmd;quit\n");
  177. while(sysread($server, $buf, 256) > 0) {
  178. $ret .= $buf;
  179. }
  180. close($server);
  181. return $ret;
  182. }