Index: trunk/FACT++/scripts/Main.js
===================================================================
--- trunk/FACT++/scripts/Main.js	(revision 15097)
+++ trunk/FACT++/scripts/Main.js	(revision 15098)
@@ -6,5 +6,5 @@
 
 //this is just the class implementation of 'Observation'
-include('scripts/Observation_class.js');  
+include('scripts/Observation_class.js');
 
 dimctrl.defineState(37, "TimeOutBeforeTakingData", "MCP took more than 5minutes to start TakingData");
@@ -12,10 +12,8 @@
 
 // error handline : http://www.sitepoint.com/exceptional-exception-handling-in-javascript/
-// clases: http://www.phpied.com/3-ways-to-define-a-javascript-class/
+// 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?
-
-// adapt states of drivectrl
 
 //
@@ -82,4 +80,5 @@
 // fad_connections.reconnect() is not really good, but at least it has FAD in it.
 var service_con = new Subscription("FAD_CONTROL/CONNECTIONS");
+
 /**
  * call-back function of FAD_CONTROL/CONNECTIONS
@@ -102,5 +101,5 @@
         return;
 
-    dim.alarm("FAD board loss detected...");
+    //m.alarm("FAD board loss detected...");
     dim.send("MCP/RESET");
     dim.send("FAD_CONTROL/CLOSE_OPEN_FILES");
@@ -157,10 +156,7 @@
         time = -1;
 
-    console.out("  Take run N="+count+" T="+time+"s ["+type+"]");
-    // change rats for cal runs1!!!
+    console.out("  Take run: N="+count+" T="+time+"s ["+type+"]");
 
     dim.send("MCP/START", time?time:-1, count?count:-1, type);
-
-    
 
     // What could be a reasonable timeout here?
@@ -263,30 +259,38 @@
     while (Sun.horizon( horizon_parameter ).isUp)
     {
-       var minutes_until_sunset = (Sun.horizon( horizon_parameter ).set - new Date())/60000;
-       console.out("Open Lid - Info: ");
-       console.out("    Sun is above FACT-horizon, lid cannot be opened.");
-       console.out("    sleeping " + minutes_until_sunset + "minutes ...");
-       v8.sleep(60000);
-    }
-
-    console.out("Open lid: start");
+        var now = new Date();
+        var minutes_until_sunset = (Sun.horizon( horizon_parameter ).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";
 
     // Wait for lid to be open
-    if (dim.state("LID_CONTROL").name=="Closed")
+    if (isClosed)
+    {
+        console.out("  Open lid: start");
         dim.send("LID_CONTROL/OPEN");
+    }
     dim.wait("LID_CONTROL", "Open", 30000);
-    console.out("Open lid: done");
+
+    if (isClosed)
+        console.out("  Open lid: done");
 }
 
 function CloseLid()
 {
-    console.out("Close lid: start");
+    var isOpen = dim.state("LID_CONTROL").name=="Open";
 
     // Wait for lid to be open
-    if (dim.state("LID_CONTROL").name=="Open")
+    if (isOpen)
+    {
+        console.out("  Close lid: start");
         dim.send("LID_CONTROL/CLOSE");
+    }
     dim.wait("LID_CONTROL", "Closed", 30000);
 
-    console.out("Close lid: end");
+    if (isOpen)
+        console.out("  Close lid: end");
 }
 
@@ -303,12 +307,34 @@
 service_feedback.voltageOff = function()
 {
-    console.out("  Voltage off: start");
-
-    var isOn = dim.state("BIAS_CONTROL").name=="VoltageOn";
-
+    var state = dim.state("BIAS_CONTROL").name;
+
+    // check of feedback has to be switched on
+    var isOn = state=="VoltageOn" || state=="Ramping";
     if (isOn)
     {
+        console.out("  Voltage off: start");
+
+        // Supress the possibility that the bias control is
+        // ramping and will reject the command to switch the
+        // voltage off
+        var isControl = dim.state("FEEDBACK").name=="CurrentControl";
+        if (isControl)
+        {
+            console.out("  Suspending feedback.");
+            dim.send("FEEDBACK/ENABLE_OUTPUT", false);
+            dim.wait("FEEDBACK", "CurrentCtrlIdle", 3000);
+        }
+
+        // Switch voltage off
         console.out("  Voltage on: switch off");
         dim.send("BIAS_CONTROL/SET_ZERO_VOLTAGE");
+
+        // If the feedback was enabled, re-enable it
+        if (isControl)
+        {
+            console.out("  Resuming feedback.");
+            dim.send("FEEDBACK/ENABLE_OUTPUT", true);
+            dim.wait("FEEDBACK", "CurrentControl", 3000);
+        }
     }
 
@@ -318,5 +344,6 @@
     // dim.wait("FEEDBACK", "CurrentCtrlIdle", 1000);
 
-    console.out("  Voltage off: end");
+    if (isOn)
+        console.out("  Voltage off: end");
 }
 
@@ -347,12 +374,9 @@
     //    throw new Error("Sun is above FACT-horizon, voltage cannot be switched on.");
 
-    console.out("  Voltage on: start");
-
     var isOff = dim.state("BIAS_CONTROL").name=="VoltageOff";
-
     if (isOff)
     {
         console.out("  Voltage on: switch on");
-	// console.out(JSON.stringify(dim.state("BIAS_CONTROL")));
+        //console.out(JSON.stringify(dim.state("BIAS_CONTROL")));
 
         dim.send("BIAS_CONTROL/SET_GLOBAL_DAC", 1);
@@ -371,9 +395,5 @@
         console.out("  Voltage on: cnt="+this.cnt);
     }
-
-    console.out("  Voltage on: end");
-}
-
-
+}
 
 service_feedback.waitForVoltageOn = function()
@@ -390,8 +410,17 @@
     // So we want one recent temperature update
     //  and three recent current updates
-    console.out("  Voltage wait: start");
+
+    // Avoid output if condition is already fulfilled
+    if (this.cnt && this.get().counter>this.cnt+2)
+        return;
+
+    // FIXME: timeout missing
+    console.out("  Feedback wait: start");
+
+    var now = new Date();
     while (this.cnt==undefined || this.get().counter<=this.cnt+2)
         v8.sleep();
-    console.out("  Voltage wait: end [cnt="+this.get().counter+"]");
+
+    console.out("  Feedback wait: end [cnt=%d, %.2fs]".$(this.get().counter, (new Date()-now)/1000));
 }
 
@@ -460,11 +489,11 @@
 // this file just contains the definition of
 // the variable observations, which builds our nightly schedule, hence the filename
-include('scripts/schedule.js');  
-    
+include('scripts/schedule.js');
+
 // make Observation objects from user input and check if 'date' is increasing.
 for (var i=0; i<observations.length; i++)
 {
     observations[i] = new Observation(observations[i]);
-    
+
     // check if the start date given by the user is increasing.
     if (i>0 && observations[i].start <= observations[i-1].start)
@@ -474,6 +503,4 @@
     }
 }
-
-
 
 // ----------------------------------------------------------------
@@ -486,5 +513,5 @@
 //        also Startup needs DRS_RUNS
 var service_drs = new Subscription("FAD_CONTROL/DRS_RUNS");
-service_drs.get(5000, false);
+service_drs.get(5000);
 
 console.out("Drs runs init: end.");
@@ -511,9 +538,38 @@
     //console.out("  => [SHUTDOWN] called.");
     console.out("Shutdown: start");
+
+    dim.send("FTM_CONTROL/STOP_TRIGGER");
     service_feedback.voltageOff();
     CloseLid(); 
     dim.send("DRIVE_CONTROL/PARK");
+
+    console.out("Waiting for telescope to park. This may take a while.");
+
+    // FIXME: This might not work is the drive is already close to park position
     dim.wait("DRIVE_CONTROL", "Moving", 3000);
-    dim.wait("DRIVE_CONTROL", "Armed", 120000); 
+    dim.wait("DRIVE_CONTROL", "Armed", 120000);
+
+    // dim.wait("DRIVE_CONTROL", "Locked", 3000);
+
+    var sub = new Subscription("DRIVE_CONTROL/POINTING_POSITION");
+    sub.get(5000);  // FIXME: Proper error message in case of failure
+
+    function func()
+    {
+        var report = sub.get();
+
+        var zd = report.obj['Zd'];
+        var az = report.obj['Az'];
+
+        if (zd>100 && Math.abs(az)<1)
+            return true;
+
+        return undefined;
+    }
+
+    v8.timeout(150000, func);
+
+    // FIXME: Add a check for the position here!
+
     console.out("Shutdown: end");
 }
@@ -525,5 +581,5 @@
     if (now==undefined)
         now = new Date();
-    
+
     if (isNaN(now.valueOf()))
         throw new Error("Date argument in getObservation invalid.");
@@ -541,17 +597,17 @@
 //      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;
+var run = -2; // getObservation never called
+var sub;
 var lastObs;
 
 var test = getObservation();
-if (test!=undefined && test<observations.length)
-{
-    var t = observations[test].start;
+if (test!=undefined)
+{
     var n = new Date();
-    if (t>n)
-        console.out(n.toUTCString()+": First observation scheduled for "+t.toUTCString());
-    else
+    if (test==-1)
+        console.out(n.toUTCString()+": First observation scheduled for "+observations[0].start.toUTCString());
+    if (test>=0 && test<observations.length)
         console.out(n.toUTCString()+": First observation should start immediately.");
-    if (t>n+12*3600*1000)
+    if (observations[0].start>n+12*3600*1000)
         console.out(n.toUTCString()+": No observations scheduled for the next 12 hours!");
 }
@@ -565,6 +621,9 @@
         exit();
 
+    // we are still waiting for the first observation in the schedule
     if (idxObs==-1)
     {
+        // flag that the first observation will be in the future
+        run = -1; 
         v8.sleep(1000);
         continue;
@@ -575,10 +634,11 @@
 
     // Check if observation target has changed
-    if (lastObs!=idxObs)
+    if (lastObs!=idxObs) // !Object.isEqual(obs, nextObs)
     {
         console.out("--- "+idxObs+" ---");
-        console.out("Current time:        "+new Date());
-        console.out("Current observation: "+obs);
-        console.out("Next    observation: "+nextObs);
+        console.out("Current time:        "+new Date().toUTCString());
+        console.out("Current observation: "+obs.start.toUTCString());
+        if (nextObs!=undefined)
+            console.out("Next    observation: "+nextObs.start.toUTCString());
         console.out("");
 
@@ -586,5 +646,6 @@
         // a scheduled 'START', so we have to check if the
         // telescop is operational already
-        if (run==-2)
+        sub = 0;
+        if (run<0)
         {
             Startup();   // -> Bias On/Off?, Lid open/closed?
@@ -592,17 +653,29 @@
         }
 
+        // The first observation had a start-time in the past...
+        // In this particular case start with the last entry
+        // in the list of measurements
+        if (run==-2)
+            sub = obs.length-1;
+
         run = 0;
     }
     lastObs = idxObs;
 
-    // We have performed startup or shutdown... wait for next observation
-    if (run==-1)
+    if (nextObs==undefined && obs[obs.length-1].task!="SHUTDOWN")
+        throw Error("Last scheduled measurement must be a shutdown.");
+
+    // We are done with all measurement slots for this
+    // observation... wait for next observation
+    if (sub>=obs.length)
     {
         v8.sleep(1000);
         continue;
     }
+// add time
+    console.out("\n"+(new Date()).toUTCString()+": Current measurement: "+obs[sub]);
 
     // Check if obs.task is one of the one-time-tasks
-    switch (obs.task)
+    switch (obs[sub].task)
     {
     case "STARTUP":
@@ -627,5 +700,5 @@
 
         console.out("  Waiting for first scheduled observation.","");
-        run = -1;
+        sub++;
         continue;
 
@@ -635,5 +708,10 @@
 
         console.out("  Waiting for next startup.", "");
-        run = -1;
+        sub++;
+        continue;
+
+    case "IDLE":
+        // FIXME: Checks missing whether a shutdown is needed...
+        v8.sleep(1000);
         continue;
 
@@ -641,18 +719,24 @@
         console.out("  RATESCAN  ");
 
+        if (dim.state("FTM_CONTROL").name=="TriggerOn")
+        {
+            dim.send("FTM_CONTROL/STOP_TRIGGER");
+            dim.wait("FTM_CONTROL", "Idle", 3000);
+        }
+
         dim.send("DRIVE_CONTROL/STOP");
         dim.wait("DRIVE_CONTROL", "Armed", 5000);
 
+        OpenLid();
+
+        service_feedback.voltageOn();
+
         if (obs.source != undefined)
-            dim.send("DRIVE_CONTROL/TRACK_ON", obs.source);
+            dim.send("DRIVE_CONTROL/TRACK_ON", obs[sub].source);
         else
-            dim.send("DRIVE_CONTROL/TRACK", obs.ra, obs.dec);
-
-        //OpenLid();    
-        dim.wait("DRIVE_CONTROL", "OnTrack", 300000);
-
-        OpenLid();
-
-        service_feedback.voltageOn();
+            dim.send("DRIVE_CONTROL/TRACK", obs[sub].ra, obs[sub].dec);
+
+        dim.wait("DRIVE_CONTROL", "OnTrack", 150000); // 110s for turning and 30s for stabilizing
+
         service_feedback.waitForVoltageOn();
 
@@ -702,7 +786,9 @@
 
         console.out("Ratescan done.");
-        run = -1;
+        sub++;
         continue;
     }
+
+    // ========================== case "DATA" ============================
 /*
     if (Sun.horizon("FACT").isUp)
@@ -715,5 +801,5 @@
 */
     // Calculate remaining time for this observation in minutes
-    var remaining = (nextObs.start-new Date())/60000;
+    var remaining = nextObs==undefined ? 0 : (nextObs.start-new Date())/60000;
 
     // ------------------------------------------------------------
@@ -755,17 +841,15 @@
     }
 
-    console.out("  Checking states: end.");
-
     // ------------------------------------------------------------
 
-    console.out("  Run #"+run+"  ("+parseInt(remaining)+"min)");
+    console.out("  Run #"+run+"  (remaining "+parseInt(remaining)+"min)");
 
     // ----- Time since last DRS Calibration [min] ------
-    var runs = service_drs.get(0, false);
+    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.data[1][2]>0 && runs.data[0]==300;
+    var valid = runs.obj['run'][2]>0 && runs.obj['roi']==300;
 
     if (valid)
@@ -795,5 +879,5 @@
 
         //console.out("  Move telescope to '"+source+"' "+offset+" "+wobble);
-        console.out("  Move telescope to '"+obs.source+"' ["+wobble+"]");
+        console.out("  Move telescope to '"+obs[sub].source+"' ["+wobble+"]");
 
         //var offset = observations[obs][2];
@@ -802,5 +886,5 @@
         //dim.send("DRIVE_CONTROL/TRACK_SOURCE", offset, wobble, source);
 
-        dim.send("DRIVE_CONTROL/TRACK_WOBBLE", wobble+1, obs.source);
+        dim.send("DRIVE_CONTROL/TRACK_WOBBLE", wobble+1, obs[sub].source);
 
         // Do we have to check if the telescope is really moving?
@@ -856,7 +940,5 @@
     }
 
-    //v8.sleep(360000);
     console.out("  Taking data: done");
-
     run++;
 }
