Index: /trunk/FACT++/scripts/Main.js
===================================================================
--- /trunk/FACT++/scripts/Main.js	(revision 15269)
+++ /trunk/FACT++/scripts/Main.js	(revision 15270)
@@ -5,4 +5,10 @@
 'use strict';
 
+//dimctrl.defineState(37, "TimeOutBeforeTakingData", "MCP took more than 5minutes to start TakingData");
+
+// ================================================================
+//  Code related to the schedule
+// ================================================================
+
 //this is just the class implementation of 'Observation'
 include('scripts/Observation_class.js');
@@ -25,35 +31,25 @@
 }
 
-// ----------------------------------------------------------------
-// ================================================================
-// ----------------------------------------------------------------
-
-//dimctrl.defineState(37, "TimeOutBeforeTakingData", "MCP took more than 5minutes to start TakingData");
-
-
-// error handline : http://www.sitepoint.com/exceptional-exception-handling-in-javascript/
-// classes: http://www.phpied.com/3-ways-to-define-a-javascript-class/
-//
-// Arguments: TakeFirstDrsCalib
-// To be determined: How to stop the script without foreceful interruption?
-
-//
-// SCRIPTS:
-//
-//  - Startup, e.g. do not open LID
-//
-//  - Bring telescop to state 'operational', e.g. open lid,
-//    when first run != START is detected in the loop
-//
-//  - Take data
-//
-//  - Shutdown
-//
-// ----> Does smartfact display alarm messages already?
-// ----> How to display errors in smartfact? Is that necessary at all?
-//       (red output? maybe just <red>...</red>?
-//
-// ----------------------------------------------------------------
-
+// Get the observation scheduled for 'now' from the table and
+// return its index
+function getObservation(now)
+{
+    if (now==undefined)
+        now = new Date();
+
+    if (isNaN(now.valueOf()))
+        throw new Error("Date argument in getObservation invalid.");
+
+    for (var i=0; i<observations.length; i++)
+        if (now<observations[i].start)
+            return i-1;
+
+    return observations.length-1;
+}
+
+// ================================================================
+//  Code to check whether observation is allowed
+// ================================================================
+/*
 function currentEst(source)
 {
@@ -89,16 +85,13 @@
     return ratio*currentEst(source)/7.7;
 }
-
-// Ratio in rate would be (estimate, not precise calculation)
-// pow(ratio, -0.7)
-
-// ----------------------------------------------------------------
-
-//DN: the name of the Subscription object 'service_con' is not really 
-// telling that its a subscription to FAD_CONTROL/CONNECTIONS
-// fad_connections sound ok for be, since 
-// fad_connections.onchange() is pretty clear
-// fad_connections.reconnect() is not really good, but at least it has FAD in it.
-var service_con = new Subscription("FAD_CONTROL/CONNECTIONS");
+*/
+
+// ----------------------------------------------------------------
+
+// ================================================================
+//  Code related to monitoring the fad system
+// ================================================================
+
+var sub_connections = new Subscription("FAD_CONTROL/CONNECTIONS");
 
 /**
@@ -107,5 +100,5 @@
  *
  */
-service_con.onchange = function(evt)
+sub_connections.onchange = function(evt)
 {
     return;
@@ -144,8 +137,8 @@
  *
  * @example
- *      if (!service_con.reconnect())
+ *      if (!sub_connections.reconnect())
  *          exit();
  */
-service_con.reconnect = function()
+sub_connections.reconnect = function()
 {
     // this.reset is a list containing the IDs of FADs, 
@@ -171,4 +164,8 @@
     return true;
 }
+
+// ================================================================
+//  Code related to taking data
+// ================================================================
 
 var startrun = new Subscription("FAD_CONTROL/START_RUN");
@@ -244,5 +241,5 @@
             console.out("");
 
-            var con  = service_con.get();
+            var con  = sub_connections.get();
             var stat = con.obj['status'];
 
@@ -280,8 +277,8 @@
     // DN: currently reconnect() never returns false 
     //     .. but it can fail of course.
-    if (!service_con.reconnect())
-        exit();
-
-    return true;//service_con.reconnect();
+    //if (!sub_connections.reconnect())
+    //    exit();
+
+    return true;//sub_connections.reconnect();
 }
 
@@ -328,5 +325,7 @@
 }
 
-// ----------------------------------------------------------------
+// ================================================================
+//  Code related to the lid
+// ================================================================
 
 function OpenLid()
@@ -375,5 +374,7 @@
 }
 
-// ----------------------------------------------------------------
+// ================================================================
+//  Code related to switching bias voltage on and off
+// ================================================================
 
 var service_feedback = new Subscription("FEEDBACK/DEVIATION");
@@ -541,53 +542,6 @@
 
 // ================================================================
-// Crosscheck all states
-// ================================================================
-
-include('scripts/Startup.js');//Startup();
-
-// ----------------------------------------------------------------
-
-console.out("Checking send.");
-checkSend(["MCP", "DRIVE_CONTROL", "LID_CONTROL", "FAD_CONTROL", "FEEDBACK"]);
-console.out("Checking send: done");
-
-// ----------------------------------------------------------------
-
-console.out("Feedback init: start.");
-service_feedback.get(5000);
-
-dim.send("FEEDBACK/ENABLE_OUTPUT", true);
-dim.send("FEEDBACK/START_CURRENT_CONTROL", 0.);
-
-console.out("Feedback init: end.");
-
-// ----------------------------------------------------------------
-// Bring the system into a well defined state
-// ----------------------------------------------------------------
-
-console.out("Drs runs init: start.");
-
-// FIMXE: Double subscription is not allowed!
-//        also Startup needs DRS_RUNS
-var service_drs = new Subscription("FAD_CONTROL/DRS_RUNS");
-service_drs.get(5000);
-
-console.out("Drs runs init: end.");
-
-// FIXME: Check if the last DRS calibration was complete?
-// ----------------------------------------------------------------
-
-// We have to stup a few things here which might not by set by Startup.js
-dim.send("FAD_CONTROL/SET_FILE_FORMAT", 2);
-
-// ----------------------------------------------------------------
-
-console.out("Start main loop.");
-
-function Startup()
-{
-    /**** dummy ****/
-    console.out("  => [STARTUP] called.");
-}
+//  Function to shutdown the system
+// ================================================================
 
 function Shutdown()
@@ -644,30 +598,50 @@
 }
 
-// Get the observation scheduled for 'now' from the table and
-// return its index
-function getObservation(now)
-{
-    if (now==undefined)
-        now = new Date();
-
-    if (isNaN(now.valueOf()))
-        throw new Error("Date argument in getObservation invalid.");
-
-    for (var i=0; i<observations.length; i++)
-        if (now<observations[i].start)
-            return i-1;
-
-    return observations.length-1;
-}
-
-
-// DN: using so called magic numbers to encode certain 
-//      states of the logic is considered pretty bad coding as far as I understand.
-//      the reader at this point has no idea why run is -2 ... this is the first time she
-//      reads about this variable and there is not a word of explanation found.
-var run = -2; // getObservation never called
-var sub;
-var lastObs;
-
+// ================================================================
+// Crosscheck all states
+// ================================================================
+
+// ----------------------------------------------------------------
+// Do a standard startup to bring the system in into a well
+// defined state
+// ----------------------------------------------------------------
+include('scripts/Startup.js');
+
+// ----------------------------------------------------------------
+// Check that everything we need is availabel to receive commands
+// (FIXME: Should that go to the general CheckState?)
+// ----------------------------------------------------------------
+console.out("Checking send.");
+checkSend(["MCP", "DRIVE_CONTROL", "LID_CONTROL", "FAD_CONTROL", "FEEDBACK"]);
+console.out("Checking send: done");
+
+// ----------------------------------------------------------------
+// Bring feedback into the correct operational state
+// ----------------------------------------------------------------
+console.out("Feedback init: start.");
+service_feedback.get(5000);
+
+dim.send("FEEDBACK/ENABLE_OUTPUT", true);
+dim.send("FEEDBACK/START_CURRENT_CONTROL", 0.);
+
+// ----------------------------------------------------------------
+// Connect to the DRS_RUNS service
+// ----------------------------------------------------------------
+console.out("Drs runs init: start.");
+
+var sub_drsruns = new Subscription("FAD_CONTROL/DRS_RUNS");
+sub_drsruns.get(5000);
+
+// FIXME: Check if the last DRS calibration was complete?
+
+// ----------------------------------------------------------------
+// Make sure we will write files
+// ----------------------------------------------------------------
+dim.send("FAD_CONTROL/SET_FILE_FORMAT", 2);
+
+// ----------------------------------------------------------------
+// Print some information for the user about the
+// expected first oberservation
+// ----------------------------------------------------------------
 var test = getObservation();
 if (test!=undefined)
@@ -682,4 +656,13 @@
 }
 
+// ----------------------------------------------------------------
+// Start main loop
+// ----------------------------------------------------------------
+console.out("Start main loop.");
+
+var run = -2; // getObservation never called
+var sub;
+var lastObs;
+
 while (1)
 {
@@ -688,5 +671,5 @@
     var idxObs = getObservation();
     if (idxObs===undefined)
-        exit();
+        break;
 
     // FIXME: Check missing whether a shutdown is needed...
@@ -785,5 +768,4 @@
     case "STARTUP":
         console.out("  STARTUP", "");
-        Startup();  // BiasOn/Off?, Lid open/close?
         CloseLid();
 
@@ -797,13 +779,7 @@
         while (!takeRun("pedestal", 5000));
 
+        // It is unclear what comes next, so we better switch off the voltage
         service_feedback.voltageOff();
-
-        //dim.send("RATE_CONTROL/STOP"); // get out of GlobalThresholdSet
-        //dim.wait("RATE_CONTROL", "Connected", 3000);
-
-        if (nextObs!=undefined && sub==obs.length-1)
-            console.out("  Waiting for next observation scheduled for "+nextObs.start.toUTCString(),"");
-        sub++;
-        continue;
+        break;
 
     case "SHUTDOWN":
@@ -811,4 +787,6 @@
         Shutdown();
 
+        // FIXME: Avoid new observations after a shutdown until
+        //        the next startup (set run back to -2?)
         console.out("  Waiting for next startup.", "");
         sub++;
@@ -821,12 +799,6 @@
     case "DRSCALIB":
         console.out("  DRSCALIB", "");
-
         doDrsCalibration("drscalib");  // will switch the voltage off
-
-        if (nextObs!=undefined && sub==obs.length-1)
-            console.out("  Waiting for next observation scheduled for "+nextObs.start.toUTCString(),"");
-
-        sub++;
-        continue;
+        break;
 
     case "SINGLEPE":
@@ -847,11 +819,6 @@
 
         // It is unclear what comes next, so we better switch off the voltage
-        // service_feedback.voltageOff();
-
-        if (nextObs!=undefined && sub==obs.length-1)
-            console.out("  Waiting for next observation scheduled for "+nextObs.start.toUTCString(),"");
-
-        sub++;
-        continue;
+        service_feedback.voltageOff();
+        break;
 
     case "RATESCAN":
@@ -897,130 +864,138 @@
 
         console.out("  Ratescan done [%.1fs, %.1fs]".$((tm2-tm1)/1000, (new Date()-tm2)/1000));
-
-        if (nextObs!=undefined && sub==obs.length-1)
-            console.out("  Waiting for next observation scheduled for "+nextObs.start.toUTCString(),"");
-
-        sub++;
-        continue;
-    }
-
-    // ========================== case "DATA" ============================
-/*
-    if (Sun.horizon("FACT").isUp)
-    {
-        console.out("  SHUTDOWN","");
-        Shutdown();
-        console.out("  Exit forced due to broken schedule", "");
-        exit();
-    }
-*/
-    // Calculate remaining time for this observation in minutes
-    var remaining = nextObs==undefined ? 0 : (nextObs.start-new Date())/60000;
-
-    // ------------------------------------------------------------
-
-    // Checking for 'Ramping' in the BIAS_CONTROL is not ideal, but at the moment
-    // it is not possible to distinguish between a real ramping and the short
-    // ramping which takes place whenever the feedback updated the voltages.
-
-    // ------------------------------------------------------------
-
-    console.out("  Run #"+run+"  (remaining "+parseInt(remaining)+"min)");
-
-    // ----- Time since last DRS Calibration [min] ------
-    var runs = service_drs.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");
-
-    // Changine pointing position and take calibration...
-    //  ...every four runs (every ~20min)
-    //  ...if at least ten minutes of observation time are left
-    //  ...if this is the first run on the source
-    var point  = (run%4==0 && remaining>10) || run==0;
-
-    // Take DRS Calib...
-    //  ...every four runs (every ~20min)
-    //  ...at last  every two hours
-    //  ...when DRS temperature has changed by more than 2deg (?)
-    //  ...when more than 15min of observation are left
-    //  ...no drs calibration was done yet
-    var drscal = (run%4==0 && (remaining>15 && diff>70)) || !valid;
-
-    if (point)
-    {
-        // Change wobble position every four runs,
-        // start with alternating wobble positions each day
-        var wobble = (parseInt(run/4) + parseInt(new Date()/1000/3600/24-0.5))%2+1;
-
-        //console.out("  Move telescope to '"+source+"' "+offset+" "+wobble);
-        console.out("  Move telescope to '"+obs[sub].source+"' ["+wobble+"]");
-
-        //var offset = observations[obs][2];
-        //var wobble = observations[obs][3 + parseInt(run/4)%2];
-
-        //dim.send("DRIVE_CONTROL/TRACK_SOURCE", offset, wobble, source);
-
-        dim.send("DRIVE_CONTROL/TRACK_WOBBLE", wobble, obs[sub].source);
-
-        // Do we have to check if the telescope is really moving?
-        // We can cross-check the SOURCE service later
-    }
-
-    if (drscal)
-        doDrsCalibration("data");  // will turn voltage off
-
-    OpenLid();
-
-    // voltage must be switched on after the lid is open for the
-    // feedback to adapt the voltage properly to the night-sky
-    // background light level.
-    service_feedback.voltageOn();
-
-    // This is now th right time to wait for th drive to be stable
-    dim.wait("DRIVE_CONTROL", "OnTrack", 150000); // 110s for turning and 30s for stabilizing
-
-    // Now we have to be prepared for data-taking:
-    // make sure voltage is on
-    service_feedback.waitForVoltageOn();
-
-    // If pointing had changed, do calibration
-    if (point)
-    {
-        console.out("  Calibration.");
-
-        // Calibration (2% of 20')
-        while (1)
+        break; // case "RATESCAN"
+
+    case "DATA":
+
+        // ========================== case "DATA" ============================
+    /*
+        if (Sun.horizon("FACT").isUp)
         {
-            if (!takeRun("pedestal",         1000))  // 80 Hz  -> 10s
-                continue;
-            if (!takeRun("light-pulser-ext", 1000))  // 80 Hz  -> 10s
-                continue;
-            break;
+            console.out("  SHUTDOWN","");
+            Shutdown();
+            console.out("  Exit forced due to broken schedule", "");
+            exit();
         }
-    }
-
-    console.out("  Taking data: start [5min]");
-
-    var len = 300;
-    while (len>0)
-    {
-        var time = new Date();
-        if (takeRun("data", -1, len)) // Take data (5min)
-            break;
-
-        len -= parseInt((new Date()-time)/1000);
-    }
-
-    console.out("  Taking data: done");
-    run++;
-}
-
-service_drs.close();
+    */
+        // Calculate remaining time for this observation in minutes
+        var remaining = nextObs==undefined ? 0 : (nextObs.start-new Date())/60000;
+
+        // ------------------------------------------------------------
+
+        console.out("  Run #"+run+"  (remaining "+parseInt(remaining)+"min)");
+
+        // ----- 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");
+
+        // Changine pointing position and take calibration...
+        //  ...every four runs (every ~20min)
+        //  ...if at least ten minutes of observation time are left
+        //  ...if this is the first run on the source
+        var point  = (run%4==0 && remaining>10) || run==0;
+
+        // Take DRS Calib...
+        //  ...every four runs (every ~20min)
+        //  ...at last  every two hours
+        //  ...when DRS temperature has changed by more than 2deg (?)
+        //  ...when more than 15min of observation are left
+        //  ...no drs calibration was done yet
+        var drscal = (run%4==0 && (remaining>15 && diff>70)) || !valid;
+
+        if (point)
+        {
+            // Change wobble position every four runs,
+            // start with alternating wobble positions each day
+            var wobble = (parseInt(run/4) + parseInt(new Date()/1000/3600/24-0.5))%2+1;
+
+            //console.out("  Move telescope to '"+source+"' "+offset+" "+wobble);
+            console.out("  Move telescope to '"+obs[sub].source+"' ["+wobble+"]");
+
+            //var offset = observations[obs][2];
+            //var wobble = observations[obs][3 + parseInt(run/4)%2];
+
+            //dim.send("DRIVE_CONTROL/TRACK_SOURCE", offset, wobble, source);
+
+            dim.send("DRIVE_CONTROL/TRACK_WOBBLE", wobble, obs[sub].source);
+
+            // Do we have to check if the telescope is really moving?
+            // We can cross-check the SOURCE service later
+        }
+
+        if (drscal)
+            doDrsCalibration("data");  // will turn voltage off
+
+        OpenLid();
+
+        // voltage must be switched on after the lid is open for the
+        // feedback to adapt the voltage properly to the night-sky
+        // background light level.
+        service_feedback.voltageOn();
+
+        // This is now th right time to wait for th drive to be stable
+        dim.wait("DRIVE_CONTROL", "OnTrack", 150000); // 110s for turning and 30s for stabilizing
+
+        // Now we have to be prepared for data-taking:
+        // make sure voltage is on
+        service_feedback.waitForVoltageOn();
+
+        // If pointing had changed, do calibration
+        if (point)
+        {
+            console.out("  Calibration.");
+
+            // Calibration (2% of 20')
+            while (1)
+            {
+                if (!takeRun("pedestal",         1000))  // 80 Hz  -> 10s
+                    continue;
+                if (!takeRun("light-pulser-ext", 1000))  // 80 Hz  -> 10s
+                    continue;
+                break;
+            }
+        }
+
+        console.out("  Taking data: start [5min]");
+
+        var len = 300;
+        while (len>0)
+        {
+            var time = new Date();
+            if (takeRun("data", -1, len)) // Take data (5min)
+                break;
+
+            len -= parseInt((new Date()-time)/1000);
+        }
+
+        console.out("  Taking data: done");
+        run++;
+
+        continue; // case "DATA"
+    }
+
+    if (nextObs!=undefined && sub==obs.length-1)
+        console.out("  Waiting for next observation scheduled for "+nextObs.start.toUTCString(),"");
+
+    sub++;
+}
+
+sub_drsruns.close();
+
+// ================================================================
+// Comments and ToDo goes here
+// ================================================================
+
+// error handline : http://www.sitepoint.com/exceptional-exception-handling-in-javascript/
+// classes: http://www.phpied.com/3-ways-to-define-a-javascript-class/
+//
+// Arguments: TakeFirstDrsCalib
+// To be determined: How to stop the script without foreceful interruption?
