Index: /trunk/FACT++/scripts/Main.js
===================================================================
--- /trunk/FACT++/scripts/Main.js	(revision 15283)
+++ /trunk/FACT++/scripts/Main.js	(revision 15284)
@@ -5,4 +5,6 @@
 'use strict';
 
+dim.log("Start: "+__FILE__+" ["+__DATE__+"]");
+
 //dimctrl.defineState(37, "TimeOutBeforeTakingData", "MCP took more than 5minutes to start TakingData");
 
@@ -93,4 +95,49 @@
 // ================================================================
 
+var sub_incomplete = new Subscription("FAD_CONTROL/INCOMPLETE");
+
+var incomplete = 0;
+
+sub_incomplete.onchange = function(evt)
+{
+    if (!evt)
+        return;
+
+    var inc = evt.data[0];//obj['incomplete'];
+    if (!inc)
+        return;
+
+    if ((evt.time - this.last_time)<5000 && this.last_inc==inc)
+        return;
+
+    incomplete = inc;
+
+    var reset = [ ];
+
+    for (var i=0; i<40; i++)
+        if (inc&(1<<i))
+        {
+            console.out("  FAD %2d".$(i)+" lost during data taking.");
+            reset.push(parseInt(i/10));
+        }
+
+    if (reset.length>10)
+        return;
+
+    dim.send("MCP/RESET");
+
+    reset = reset.filter(function(elem,pos){return reset.indexOf(elem)==pos;});
+
+    if (reset.length>0)
+    {
+        console.out("");
+        console.out("  FADs belong to crate(s): "+reset);
+        console.out("");
+    }
+
+    this.last_time = evt.time;
+    this.last_inc  = inc;
+}
+
 var sub_connections = new Subscription("FAD_CONTROL/CONNECTIONS");
 
@@ -100,8 +147,7 @@
  *
  */
+/*
 sub_connections.onchange = function(evt)
 {
-    return;
-
     // This happens, but why?
     if (!evt.obj['status'])
@@ -121,4 +167,5 @@
     dim.send("FAD_CONTROL/CLOSE_OPEN_FILES");
 }
+*/
 
 /**
@@ -234,37 +281,62 @@
         console.out("");
 
-        if (dim.state("MCP").name=="Configuring3" &&
-            dim.state("FAD_CONTROL").name=="Configuring2")
+        if (dim.state("MCP").name!="Configuring3" ||
+            dim.state("FAD_CONTROL").name!="Configuring2")
+            throw e;
+
+        console.out("");
+        console.out("Waiting for fadctrl to get configured timed out... checking for in-run FAD loss.");
+
+        var con  = sub_connections.get();
+        var stat = con.obj['status'];
+
+        console.out("Sending MCP/RESET");
+        dim.send("MCP/RESET");
+
+        dim.wait("FTM_CONTROL", "Idle",      3000);
+        dim.wait("FAD_CONTROL", "Connected", 3000);
+        dim.wait("MCP",         "Idle",      3000);
+
+        var reset = [ ];
+
+        for (var i=0; i<40; i++)
+            if (stat[i]!=0x43)
+            {
+                console.out("  FAD %2d".$(i)+" not in Configured state.");
+                reset.push(parseInt(i/10));
+            }
+
+        reset = reset.filter(function(elem,pos){return reset.indexOf(elem)==pos;});
+
+        if (reset.length>0)
         {
             console.out("");
-            console.out("Waiting for fadctrl to get configured timed out... checking for FAD loss.");
+            console.out("  FADs belong to crate(s): "+reset);
             console.out("");
-
-            var con  = sub_connections.get();
-            var stat = con.obj['status'];
-
-            var reset = [ ];
-
-            for (var i=0; i<40; i++)
-                if (stat[i]!=0x43)
-                {
-                    console.out("  FAD %2d".$(i)+" not in Configured state.");
-                    reset.push(parseInt(i/10));
-                }
-
-            reset = reset.filter(function(elem,pos){return reset.indexOf(elem)==pos;});
-
-            if (reset.length>0)
+        }
+
+        console.out("");
+        console.out("Trying automatic reconnect...");
+
+        for (var i=0; i<40; i++)
+            if (stat[i]!=0x43)
             {
-                console.out("");
-                console.out("  FADs belong to crate(s): "+reset);
-                console.out("");
+                console.out("   ...disconnect ", i);
+                dim.send("FAD_CONTROL/DISCONNECT", i);
             }
-        }
-
-        console.out("Sending MCP/RESET");
-        dim.send("MCP/RESET");
-
-        // If it works, we can decide here what to do...
+
+        console.out("   ...waiting for 5s");
+        v8.sleep(5000);
+
+        for (var i=0; i<40; i++)
+            if (stat[i]!=0x43)
+            {
+                console.out("   ...reconnect ", i);
+                dim.send("FAD_CONTROL/CONNECT", i);
+            }
+
+        console.out("   ...waiting for 1s");
+        v8.sleep(1000);
+        console.out("");
 
         throw e;
@@ -272,4 +344,35 @@
 
     dim.wait("MCP", "Idle", time>0 ? time*1250 : undefined); // run time plus 25%
+
+    if (incomplete)
+    {
+        console.out("");
+        console.out("Trying automatic reconnect...");
+
+        for (var i=0; i<40; i++)
+            if (incomplete&(1<<i))
+            {
+                console.out("   ...disconnect ", i);
+                dim.send("FAD_CONTROL/DISCONNECT", i);
+            }
+
+        console.out("   ...waiting for 5s");
+        v8.sleep(5000);
+
+        for (var i=0; i<40; i++)
+            if (incomplete&(1<<i))
+            {
+                console.out("   ...reconnect ", i);
+                dim.send("FAD_CONTROL/CONNECT", i);
+            }
+
+        console.out("   ...waiting for 1s");
+        v8.sleep(1000);
+        console.out("");
+
+        incomplete = 0;
+
+        throw new Error("In-run FAD loss detected.");
+    }
 
     //console.out("  Take run: end");
@@ -331,12 +434,12 @@
 function OpenLid()
 {
-    var horizon_parameter = "nautical";
-    while (Sun.horizon( horizon_parameter ).isUp)
+    /*
+    while (Sun.horizon(-13).isUp)
     {
         var now = new Date();
-        var minutes_until_sunset = (Sun.horizon( horizon_parameter ).set - now)/60000;
+        var minutes_until_sunset = (Sun.horizon(-13).set - now)/60000;
         console.out(now.toUTCString()+": Sun above FACT-horizon, lid cannot be opened: sleeping 1min, remaining %.1fmin".$(minutes_until_sunset));
         v8.sleep(60000);
-    }
+    }*/
 
     var isClosed = dim.state("LID_CONTROL").name=="Closed";
@@ -596,4 +699,6 @@
     console.out("");
     console.out("Shutdown: end ["+(new Date()-now)/1000+"s]");
+
+    sub.close();
 }
 
@@ -625,4 +730,6 @@
 dim.send("FEEDBACK/START_CURRENT_CONTROL", 0.);
 
+v8.timeout(3000, function() { var n = dim.state("FEEDBACK").name; if (n=="CurrentCtrlIdle" || n=="CurrentControl") return true; });
+
 // ----------------------------------------------------------------
 // Connect to the DRS_RUNS service
@@ -632,6 +739,23 @@
 var sub_drsruns = new Subscription("FAD_CONTROL/DRS_RUNS");
 sub_drsruns.get(5000);
-
 // FIXME: Check if the last DRS calibration was complete?
+
+function getTimeSinceLastDrsCalib()
+{
+    // ----- Time since last DRS Calibration [min] ------
+    var runs = sub_drsruns.get(0);
+    var diff = (new Date()-runs.time)/60000;
+
+    // Warning: 'roi=300' is a number which is not intrisically fixed
+    //          but can change depending on the taste of the observers
+    var valid = runs.obj['run'][2]>0 && runs.obj['roi']==300;
+
+    if (valid)
+        console.out("  Last DRS calib: %.1fmin ago".$(diff));
+    else
+        console.out("  No valid drs calibration available");
+
+    return valid ? diff : null;
+}
 
 // ----------------------------------------------------------------
@@ -664,4 +788,5 @@
 var sub;
 var lastObs;
+var sun = Sun.horizon(-13);
 
 while (1)
@@ -673,6 +798,4 @@
         break;
 
-    // FIXME: Check missing whether a shutdown is needed...
-
     // we are still waiting for the first observation in the schedule
     if (idxObs==-1)
@@ -684,4 +807,16 @@
     }
 
+    // Check if we have to take action do to sun-rise
+    var was_up = sun.isUp;
+    sun = Sun.horizon(-13);
+    if (!was_up && sun.isUp)
+    {
+        console.out("Sun rise detected.... automatic shutdown initiated!");
+        // FIXME: State check?
+        Shutdown();
+        continue;
+    }
+
+    // Current and next observation target
     var obs     = observations[idxObs];
     var nextObs = observations[idxObs+1];
@@ -725,4 +860,14 @@
     {
         v8.sleep(1000);
+        continue;
+    }
+
+    // Check if sun is still up... only DATA and RATESCAN must be suppressed
+    if ((obs[sub].task=="DATA" || obs[sub].task=="RATESCAN") && sun.isUp)
+    {
+        var now = new Date();
+        var remaining = (sun.set - now)/60000;
+        console.out(now.toUTCString()+" - "+obs[sub].task+": Sun above FACT-horizon: sleeping 1min, remaining %.1fmin".$(remaining));
+        v8.sleep(60000);
         continue;
     }
@@ -805,8 +950,11 @@
         console.out("  SINGLE-PE", "");
 
-        // FIXME: Check whether a DRS calib is necessary.
-
         // The lid must be closes
         CloseLid();
+
+        // Check if DRS calibration is necessary
+        var diff = getTimeSinceLastDrsCalib();
+        if (diff>30 || diff==null)
+            doDrsCalibration("singlepe");  // will turn voltage off
 
         // The voltage must be on
@@ -886,15 +1034,5 @@
 
         // ----- Time since last DRS Calibration [min] ------
-        var runs = sub_drsruns.get(0);
-        var diff = (new Date()-runs.time)/60000;
-
-        // Warning: 'roi=300' is a number which is not intrisically fixed
-        //          but can change depending on the taste of the observers
-        var valid = runs.obj['run'][2]>0 && runs.obj['roi']==300;
-
-        if (valid)
-            console.out("  Last DRS calib: %.1fmin ago".$(diff));
-        else
-            console.out("  No valid drs calibration available");
+        var diff = getTimeSinceLastDrsCalib();
 
         // Changine pointing position and take calibration...
@@ -910,5 +1048,5 @@
         //  ...when more than 15min of observation are left
         //  ...no drs calibration was done yet
-        var drscal = (run%4==0 && (remaining>15 && diff>70)) || !valid;
+        var drscal = (run%4==0 && (remaining>15 && diff>70)) || diff==null;
 
         if (point)
