try to improve error/close/timeout restarting
[dweather.git] / loop.pl
diff --git a/loop.pl b/loop.pl
index e287ce5913b0370d0aa32345ac6348b42b343541..bdc06d6e01f6e87d8d0d93f2573b3784706af69e 100755 (executable)
--- a/loop.pl
+++ b/loop.pl
@@ -19,6 +19,7 @@ use IO::File;
 
 use constant pi => 3.14159265358979; 
 
+my $randomfn = '/dev/urandom';
 my $devname = "/dev/davis";
 my $datafn = ".loop_data";
 my $dataf;
@@ -32,7 +33,8 @@ my $nlcount;
 my $state = "ready";
 my $buf;
 my $dbg;
-my $ser;                                                       # the serial port Mojo::IOLoop::Stream
+our $ser;                                                      # the serial port Mojo::IOLoop::Stream
+our $ob;                                                       # the Serial Port filehandle
 my $last_min_h;
 my $last_hour_h;
 
@@ -95,7 +97,7 @@ $bar_trend{60} = "Rising Rapidly";
 
 our $ending = 0;
 
-$SIG{TERM} = $SIG{INT} = sub {++$ending; Mojo::IOLoop->stop;};
+$SIG{TERM} = $SIG{INT} = sub {$ending = 1; Mojo::IOLoop->stop;};
 $SIG{HUP} = 'IGNORE';
 
 
@@ -161,14 +163,24 @@ for (my $i = 0-$histdays; $i < 0; ++$i ) {
 @last10minsr = map {my ($t, $js) = split(/\s/, $_, 2); $js} grab_history(SMGLog->new("debug"), "r", $tnow-(60*$windmins), $dayno);
 dbg sprintf("last5days = %d last10mins = %d", scalar @last5daysh, scalar @last10minsr);
 
+sysopen(R, $randomfn, 0) or die "cannot open $randomfn $!\n";
+my $rs;
+sysread(R, $rs, 8) or die "not enough randomness available\n";
+close R;
+
+app->secrets([qw(Here's something that's really seakrett), $rs]);
+
 our $dlog = SMGLog->new("day");
+$did = Mojo::IOLoop->recurring(1 => sub {$dlog->flushall});
+
 dbg "before next tick";
 Mojo::IOLoop->next_tick(sub { loop() });       
 dbg "before app start";
-app->secrets([qw(Here's something that's really seakrett)]);
 app->start;
 dbg "after app start";
 
+doclose();
+
 write_ld();
 $dataf->close if $dataf;
 undef $dataf;
@@ -178,7 +190,7 @@ undef $dataf;
 cycle_loop_data_files();
 
 dbg '***';
-dbg "*** ending $0";
+dbg "*** ending $0 (\$ending = $ending)";
 dbg '***';
 
 exit 0;
@@ -190,9 +202,8 @@ sub loop
        dbg "last_min: " . scalar gmtime($ld->{last_min});
        dbg "last_hour: " . scalar gmtime($ld->{last_hour});
        
-       $did = Mojo::IOLoop->recurring(1 => sub {$dlog->flushall});
-       
-       do_reopen($devname);
+       $ser = doopen($devname);
+       start_loop() if $ser;
 }
 
 
@@ -236,8 +247,7 @@ sub start_loop
        undef $tid;
        $tid = Mojo::IOLoop->recurring(0.6 => sub {
                                                                           if (++$nlcount > 10) {
-                                                                                  dbg "\\n count > 10, closing connection" if isdbg 'chan';
-                                                                                  do_reopen($devname);
+                                                                                  doclose();
                                                                                   return;
                                                                           }
                                                                           dbg "writing $nlcount \\n" if isdbg 'state'; 
@@ -252,47 +262,68 @@ sub chgstate
        $state = $_[0];
 }
 
-sub do_reopen
-{
-       my $name = shift;
-       dbg "do reopen on '$name' ending $ending";
-       unless ($ending) {
-               $ser = do_open($name);
-               start_loop();
-               chgstate('');
-               $nlcount = 0;
-               Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
-       }
-}
+my $closing;
 
-sub do_open
+sub doopen
 {
        my $name = shift;
 
-       $ser->close if $ser;
-       undef $ser;
-
-       my $ob = Serial->new($name, 19200) || die "$name $!\n";
+    $ob = Serial->new($name, 19200) || die "$name $!\n";
        dbg "streaming $name fileno(" . fileno($ob) . ")" if isdbg 'chan';
        
        my $ser = Mojo::IOLoop::Stream->new($ob);
-       $ser->on(error=>sub {dbg "serial $_[1]"; do_reopen($name) unless $ending});
-       $ser->on(close=>sub {dbg "serial closing"; do_reopen($name) unless $ending});
-       $ser->on(timeout=>sub {dbg "serial timeout";});
+       $ser->on(error=>sub {dbg "error serial $_[1]"; doclose();});
+       $ser->on(close=>sub {dbg "event close";  doclose();});
+       $ser->on(timeout=>sub {dbg "event serial timeout"; doclose();});
        $ser->on(read=>sub {on_read(@_)});
        $ser->start;
 
+    $rid = Mojo::IOLoop->recurring($poll_interval => sub {
+                                       start_loop() if !$state;
+                                   });
+
+       chgstate('');
+       $nlcount = 0;
+       
+       return $ser;
+}
+
+sub doclose
+{
+       return if $closing++;
+       
+       dbg "serial port closing" if $ser || $ob;
+       if ($ser) {
+               $ser->stop;
+               $ser->close;
+               undef $ser;
+       }
+       if ($ob) {
+               $ob->close();
+               undef $ob;
+       }
        Mojo::IOLoop->remove($tid) if $tid;
        undef $tid;
        Mojo::IOLoop->remove($rid) if $rid;
        undef $rid;
-       $rid = Mojo::IOLoop->recurring($poll_interval => sub {
-                                                                          start_loop() if !$state;
-                                                                  });
+
+    if (Mojo::IOLoop->is_running && $ending == 0) {
+               Mojo::IOLoop->delay(
+                                                       sub {
+                                                               my $delay = shift;
+                                                               Mojo::IOLoop->timer(5 => $delay->begin);
+                                                               dbg "Waiting 5 seconds before opening serial port";
+                                                        },
+
+                                                       sub {
+                                                               dbg "Opening Serial port";
+                                                               $ser = doopen($devname);
+                                                               $closing = 0;
+                                                       }
+                                                  )->wait;
+       }
        chgstate('');
        $nlcount = 0;
-       
-       return $ser;
 }
 
 my @min;