Index: /branches/FACT++_scripts_refactoring/Startup.js
===================================================================
--- /branches/FACT++_scripts_refactoring/Startup.js	(revision 18262)
+++ /branches/FACT++_scripts_refactoring/Startup.js	(revision 18263)
@@ -3,4 +3,6 @@
 include("scripts/CheckFTU.js");
 include("scripts/CheckUnderflow.js");
+include("scripts/CheckStates.js");
+include("scripts/Handler_Function_class");
 // To de done:
 //  - CheckLID status (should be open or closed)
@@ -11,200 +13,134 @@
 // =================================================================
 
-/*
-var table =
-[
- [ "AGILENT_CONTROL" ],
- [ "BIAS_CONTROL"    ],
- [ "CHAT"            ],
- [ "DATA_LOGGER"     ],
- [ "DRIVE_CONTROL"   ],
- [ "FEEDBACK"        ],
- [ "FAD_CONTROL"     ],
- [ "FSC_CONTROL"     ],
- [ "FTM_CONTROL"     ],
- [ "LID_CONTROL"     ],
- [ "MAGIC_WEATHER"   ],
- [ "MCP"             ],
- [ "PWR_CONTROL"     ],
- [ "RATE_CONTROL"    ],
- [ "RATE_SCAN"       ],
- [ "SMART_FACT"      ],
- [ "TIME_CHECK"      ],
- [ "TNG_WEATHER"     ],
-];
-
-if (dim.state("DRIVE_CONTROL").name=="Locked")
-{
-    throw new Error("Drivectrl still locked... needs UNLOCK first.");
-    //while (!dim.send("DRIVE_CONTROL"))
-    //    v8.sleep();
-    //dim.send("DRIVE_CONTROL/UNLOCK");
-    //dim.wait("DRIVE_CONTROL", "Armed", 1000);
-}
-
-*/
-
-console.out("");
-dim.alarm();
-
-var loop;
-include("scripts/Handler.js");
-include("scripts/CheckStates.js");
-
-// -----------------------------------------------------------------
-// Make sure camera electronics is switched on and has power
-// -----------------------------------------------------------------
-
-include("scripts/handleAgilentPowerOn24V.js");
-include("scripts/handleAgilentPowerOn50V.js");
-include("scripts/handleAgilentPowerOn80V.js");
-include("scripts/handlePwrCameraOn.js");
-
-checkSend(["AGILENT_CONTROL_24V","AGILENT_CONTROL_50V","AGILENT_CONTROL_80V","PWR_CONTROL"]);
-
-loop = new Handler("PowerOn");
-//loop.add(handleAgilentPowerOn24V);
-//loop.add(handleAgilentPowerOn50V);
-//loop.add(handleAgilentPowerOn80V);
-loop.add(handlePwrCameraOn);
-loop.run();
-console.out("");
-
-// If power was switched on: wait for a few seconds
-
-// -----------------------------------------------------------------
-// Now take care that the bias control, the ftm and the fsc are
-// properly connected and are in a reasonable state (e.g. the
-// trigger is switched off)
-// -----------------------------------------------------------------
-
-include("scripts/handleBiasVoltageOff.js");
-include("scripts/handleFtmIdle.js");
-include("scripts/handleFscConnected.js");
-include("scripts/handleFeedbackConnected.js");
-include("scripts/handleRatectrlConnected.js");
-include("scripts/handleLidClosed.js");
-include("scripts/handleFadConnected.js");
-
-checkSend(["BIAS_CONTROL","FAD_CONTROL","FTM_CONTROL", "FSC_CONTROL", "FEEDBACK", "RATE_CONTROL", "MCP"]);
-
-dim.send("MCP/RESET");
-
-loop = new Handler("SystemSetup");
-loop.add(handleBiasVoltageOff);
-loop.add(handleFtmIdle);
-loop.add(handleFscConnected);
-loop.add(handleFadConnected);
-loop.add(handleFeedbackConnected); // Feedback needs FAD to be Connected
-loop.add(handleRatectrlConnected);
-loop.add(handleLidClosed);
-loop.run();
-
-console.out("biasctrl:    "+dim.state("BIAS_CONTROL").name);
-console.out("ftmctrl:     "+dim.state("FTM_CONTROL").name);
-console.out("fscctrl:     "+dim.state("FSC_CONTROL").name);
-console.out("feedback:    "+dim.state("FEEDBACK").name);
-console.out("ratecontrol: "+dim.state("RATE_CONTROL").name);
-console.out("fadctrl:     "+dim.state("FAD_CONTROL").name);
-console.out("mcp:         "+dim.state("MCP").name);
-console.out("");
-
-console.out("Enable all FTU");
-dim.send("FTM_CONTROL/ENABLE_FTU", -1, true);
-
-// -----------------------------------------------------------------
-// Now we check the FTU connection
-// -----------------------------------------------------------------
-CheckFTU.checkFTU();
-
-
-// -----------------------------------------------------------------
-// Now we check the clock conditioner
-// -----------------------------------------------------------------
-
-var sub_counter = new Subscription("FTM_CONTROL/COUNTER");
-var counter = sub_counter.get(3000, false).counter;
-dim.send("FTM_CONTROL/REQUEST_STATIC_DATA");
-v8.timeout(3000, function() { if (sub_counter.get(0, false).counter>counter) return true; });
-if (sub_counter.get(0, false).qos&0x100==0)
-    throw new Error("Clock conditioner not locked.");
-sub_counter.close();
-
-// -----------------------------------------------------------------
-// Now we can safely try to connect the FAD boards.
-// -----------------------------------------------------------------
-/*
- include("scripts/handleFadConnected.js");
-
-// If FADs already connected
-
-checkSend(["FAD_CONTROL"]);
-
-loop = new Handler("ConnectFad");
-loop.add(handleFadConnected);
-loop.run();
-
-var failed = false;
-dim.onchange["FAD_CONTROL"] = function(arg)
-{
-    if (this.rc && arg.name!="Connected")
-        failed = true;
-}
-
-console.out("FADs connected.");
-console.out("");
-
-console.out(dim.state("FAD_CONTROL").name);
-console.out(dim.state("MCP").name);
-*/
-
-// ================================================================
-// Underflow check
-// ================================================================
-// Is it necessary to check for the so called 'underflow-problem'?
-// (This is necessary after each power cycle)
-// ----------------------------------------------------------------
-CheckUnderflow.checkUnderflow();
-
-// Now it is time to check the connection of the FADs
-// it might hav thrown an exception already anyway
-
-
-// ================================================================
-// Power on drive system if power is off (do it hre to make sure not
-// everything is switchd on at the same time)
-// ================================================================
-
-//console.out("PWR: "+(dim.state("PWR_CONTROL").index&16));
-
-if ((dim.state("PWR_CONTROL").index&16)==0)
-{
-    console.out("Drive cabinet not powered... Switching on.");
-    dim.send("PWR_CONTROL/TOGGLE_DRIVE");
-    v8.timeout(5000, function() { if (dim.state("PWR_CONTROL").index&16) return true; });
-}
-
-include("scripts/handleDriveArmed.js");
-
-checkSend(["DRIVE_CONTROL"]);
-
-loop = new Handler("ArmDrive");
-loop.add(handleDriveArmed);
-loop.run();
-
-
-// ================================================================
-// Bias crate calibration
-// ================================================================
-// Bias crate calibration if necessary (it is aftr 4pm (local tome)
-// and the last calibration was more than eight hours ago.
-// -----------------------------------------------------------------
-
-// At this point we know that:
-//  1) The lid is closed
-//  2) The feedback is stopped
-//  3) The voltage is off
-function makeCurrentCalibration()
-{
+/**
+ *var table =
+ *[
+ * [ "AGILENT_CONTROL" ],
+ * [ "BIAS_CONTROL"    ],
+ * [ "CHAT"            ],
+ * [ "DATA_LOGGER"     ],
+ * [ "DRIVE_CONTROL"   ],
+ * [ "FEEDBACK"        ],
+ * [ "FAD_CONTROL"     ],
+ * [ "FSC_CONTROL"     ],
+ * [ "FTM_CONTROL"     ],
+ * [ "LID_CONTROL"     ],
+ * [ "MAGIC_WEATHER"   ],
+ * [ "MCP"             ],
+ * [ "PWR_CONTROL"     ],
+ * [ "RATE_CONTROL"    ],
+ * [ "RATE_SCAN"       ],
+ * [ "SMART_FACT"      ],
+ * [ "TIME_CHECK"      ],
+ * [ "TNG_WEATHER"     ],
+ *];
+ *
+ *if (dim.state("DRIVE_CONTROL").name=="Locked")
+ *{
+ *    throw new Error("Drivectrl still locked... needs UNLOCK first.");
+ *    //while (!dim.send("DRIVE_CONTROL"))
+ *    //    v8.sleep();
+ *    //dim.send("DRIVE_CONTROL/UNLOCK");
+ *    //dim.wait("DRIVE_CONTROL", "Armed", 1000);
+ *}
+ *
+ */
+var switch_camera_on = function(){
+    console.out("");
+    dim.alarm(); // I believe this *resets* any prior alarm.
+
+    CheckStates.checkSend(["PWR_CONTROL"], undefined, true);
+
+    var camera_on_handler = new Handler_Function_class.Handler("PowerOn");
+    camera_on_handler.add(Handler_Function_class.power_camera_on);
+    camera_on_handler.run();
+    console.out("");
+    // If power was switched on: wait for a few seconds
+};
+
+var set_up_systems = function(){
+    // -----------------------------------------------------------------
+    // Now take care that the bias control, the ftm and the fsc are
+    // properly connected and are in a reasonable state (e.g. the
+    // trigger is switched off)
+    // -----------------------------------------------------------------
+
+
+    CheckStates.checkSend(
+        ["BIAS_CONTROL",
+         "FAD_CONTROL",
+         "FTM_CONTROL", 
+         "FSC_CONTROL", 
+         "FEEDBACK", 
+         "RATE_CONTROL", 
+         "MCP"],
+        undefined,
+        true);
+
+    dim.send("MCP/RESET");
+
+    var set_up_handler = new Handler_Function_class.Handler("SystemSetup");
+    set_up_handler.add(Handler_Function_class.bias_voltage_off);
+    set_up_handler.add(Handler_Function_class.make_ftm_idle);
+    set_up_handler.add(Handler_Function_class.connect_fsc);
+    set_up_handler.add(Handler_Function_class.connect_fad);
+    set_up_handler.add(Handler_Function_class.connect_feedback); // Feedback needs FAD to be Connected
+    set_up_handler.add(Handler_Function_class.connect_ratecontrol);
+    set_up_handler.add(Handler_Function_class.close_lid);
+    set_up_handler.run();
+
+    console.out("biasctrl:    "+dim.state("BIAS_CONTROL").name);
+    console.out("ftmctrl:     "+dim.state("FTM_CONTROL").name);
+    console.out("fscctrl:     "+dim.state("FSC_CONTROL").name);
+    console.out("feedback:    "+dim.state("FEEDBACK").name);
+    console.out("ratecontrol: "+dim.state("RATE_CONTROL").name);
+    console.out("fadctrl:     "+dim.state("FAD_CONTROL").name);
+    console.out("mcp:         "+dim.state("MCP").name);
+    console.out("");
+
+    console.out("Enable all FTU");
+    dim.send("FTM_CONTROL/ENABLE_FTU", -1, true);
+};
+
+var check_clock_conditioner = function(){
+    var sub_counter = new Subscription("FTM_CONTROL/COUNTER");
+    var counter = sub_counter.get(3000, false).counter;
+    dim.send("FTM_CONTROL/REQUEST_STATIC_DATA");
+    v8.timeout(3000, 
+        function() { 
+            if (sub_counter.get(0, false).counter>counter) 
+                return true; 
+        });
+    if (sub_counter.get(0, false).qos & 0x100 == 0)
+        throw new Error("Clock conditioner not locked.");
+    sub_counter.close();
+};
+
+var power_on_drive = function(){
+    if ((dim.state("PWR_CONTROL").index & 16) == 0)
+    {
+        console.out("Drive cabinet not powered... Switching on.");
+        dim.send("PWR_CONTROL/TOGGLE_DRIVE");
+        v8.timeout(5000, 
+            function() { 
+                if (dim.state("PWR_CONTROL").index&16) 
+                    return true; 
+            });
+    }
+
+    checkSend(["DRIVE_CONTROL"]);
+
+    var arm_drive_handler = new Handler("ArmDrive");
+    arm_drive_handler.add(Handler_Function_class.arm_drive);
+    arm_drive_handler.run();
+};
+
+var makeCurrentCalibration = function(){
+    // At this point we know that:
+    //  1) The lid is closed
+    //  2) The feedback is stopped
+    //  3) The voltage is off
+
+
     dim.send("BIAS_CONTROL/SET_ZERO_VOLTAGE");
     dim.wait("BIAS_CONTROL", "VoltageOff", 30000); // waS: 15000
@@ -223,96 +159,120 @@
     console.out("Wait for voltage to be off");
     dim.wait("BIAS_CONTROL", "VoltageOff", 30000); // was: 15000
-}
-
-// Check age of calibration
-var service_calibration = new Subscription("FEEDBACK/CALIBRATION");
-
-var data_calibration = service_calibration.get(3000, false);
-
-var age = data_calibration.time;
-var now = new Date();
-
-var diff = (now-age)/3600000;
-
-var fb_state = dim.state("FEEDBACK").index;
-
-// !data_calibration.data: FEEDBACK might just be freshly
-// started and will not yet serve this service.
-if (fb_state<5 || (diff>8 && now.getHours()>16))
-{
-    if (fb_state<5)
-        console.out("No BIAS crate calibration available: New calibration needed.");
-    else
-        console.out("Last BIAS crate calibration taken at "+age.toUTCString()+": New calibration needed.");
-
-    makeCurrentCalibration();
-}
-
-service_calibration.close();
-
-// ================================================================
-// Setup GPS control and wait for the satellites to be locked
-// ================================================================
-
-checkSend(["GPS_CONTROL"]);
-
-if (dim.state("GPS_CONTROL").name=="Disconnected")
-    dim.send("GPS_CONTROL/RECONNECT");
-
-// Wait for being connectes
-v8.timeout(5000, function() { if (dim.state("GPS_CONTROL").name!="Disconnected") return true; });
-
-// Wait for status available
-v8.timeout(5000, function() { if (dim.state("GPS_CONTROL").name!="Connected") return true; });
-
-if (dim.state("GPS_CONTROL").name=="Disabled")
-    dim.send("GPS_CONTROL/ENABLE");
-
-// Wait for gps to be enabled and locked
-dim.wait("GPS_CONTROL", "Locked", 15000);
-
-// ================================================================
-// Crosscheck all states
-// ================================================================
-
-// FIXME: Check if there is a startup scheduled, if not do not force
-// drive to be switched on
-
-var table =
-[
- [ "TNG_WEATHER"   ],
- [ "MAGIC_WEATHER" ],
- [ "CHAT"          ],
- [ "SMART_FACT"    ],
- [ "TEMPERATURE"   ],
- [ "EVENT_SERVER",        [ "Running", "Standby" ] ],
- [ "DATA_LOGGER",         [ "NightlyFileOpen", "WaitForRun", "Logging" ] ],
- [ "FSC_CONTROL",         [ "Connected"                       ] ],
- [ "MCP",                 [ "Idle"                            ] ],
- [ "TIME_CHECK",          [ "Valid"                           ] ],
- [ "PWR_CONTROL",         [ "SystemOn"                        ] ],
- [ "AGILENT_CONTROL_24V", [ "VoltageOn"                       ] ],
- [ "AGILENT_CONTROL_50V", [ "VoltageOn"                       ] ],
- [ "AGILENT_CONTROL_80V", [ "VoltageOn"                       ] ],
- [ "BIAS_CONTROL",        [ "VoltageOff"                      ] ],
- [ "FEEDBACK",            [ "Calibrated"                      ] ],
- [ "RATE_SCAN",           [ "Connected"                       ] ],
- [ "RATE_CONTROL",        [ "Connected"                       ] ],
- [ "DRIVE_CONTROL",       [ "Armed", "Tracking", "OnTrack", "Locked" ] ],
- [ "LID_CONTROL",         [ "Open", "Closed"                  ] ],
- [ "FTM_CONTROL",         [ "Valid", "TriggerOn"              ] ],
- [ "FAD_CONTROL",         [ "Connected", "WritingData"        ] ],
- [ "GPS_CONTROL",         [ "Locked" ] ],
- [ "SQM_CONTROL",         [ "Valid" ] ],
- [ "PFMINI_CONTROL",      [ "Receiving" ] ],
-];
-
-
-
-if (!checkStates(table))
-{
-    throw new Error("Something unexpected has happened. Although the startup-"+
-                    "procedure has finished, not all servers are in the state "+
-                    "in which they ought to be. Please, try to find out what "+
-                    "happened...");
-}
+};
+
+var perform_current_calibration_if_needed = function(){
+    // ================================================================
+    // Bias crate calibration
+    // ================================================================
+    // Bias crate calibration if necessary (it is aftr 4pm (local tome)
+    // and the last calibration was more than eight hours ago.
+    // -----------------------------------------------------------------
+
+    // Check age of calibration
+    var service_calibration = new Subscription("FEEDBACK/CALIBRATION");
+
+    var data_calibration = service_calibration.get(3000, false);
+
+    var age = data_calibration.time;
+    var now = new Date();
+
+    var diff = (now-age)/3600000;
+
+    var fb_state = dim.state("FEEDBACK").index;
+
+    // !data_calibration.data: FEEDBACK might just be freshly
+    // started and will not yet serve this service.
+    if (fb_state<5 || (diff>8 && now.getHours()>16))
+    {
+        if (fb_state<5)
+            console.out("No BIAS crate calibration available: New calibration needed.");
+        else
+            console.out("Last BIAS crate calibration taken at "+age.toUTCString()+": New calibration needed.");
+
+        makeCurrentCalibration();
+    }
+
+    service_calibration.close();
+};
+
+var set_up_gps_control = function(){
+    // ================================================================
+    // Setup GPS control and wait for the satellites to be locked
+    // ================================================================
+
+    checkSend(["GPS_CONTROL"]);
+
+    if (dim.state("GPS_CONTROL").name=="Disconnected")
+        dim.send("GPS_CONTROL/RECONNECT");
+
+    // Wait for being connectes
+    v8.timeout(5000, function() { if (dim.state("GPS_CONTROL").name!="Disconnected") return true; });
+
+    // Wait for status available
+    v8.timeout(5000, function() { if (dim.state("GPS_CONTROL").name!="Connected") return true; });
+
+    if (dim.state("GPS_CONTROL").name=="Disabled")
+        dim.send("GPS_CONTROL/ENABLE");
+
+    // Wait for gps to be enabled and locked
+    dim.wait("GPS_CONTROL", "Locked", 15000);
+};
+
+var crosscheck_all_states = function(){
+    // ================================================================
+    // Crosscheck all states
+    // ================================================================
+
+    // FIXME: Check if there is a startup scheduled, if not do not force
+    // drive to be switched on
+    var table =
+    [
+     [ "TNG_WEATHER"   ],
+     [ "MAGIC_WEATHER" ],
+     [ "CHAT"          ],
+     [ "SMART_FACT"    ],
+     [ "TEMPERATURE"   ],
+     [ "EVENT_SERVER",        [ "Running", "Standby" ] ],
+     [ "DATA_LOGGER",         [ "NightlyFileOpen", "WaitForRun", "Logging" ] ],
+     [ "FSC_CONTROL",         [ "Connected"                       ] ],
+     [ "MCP",                 [ "Idle"                            ] ],
+     [ "TIME_CHECK",          [ "Valid"                           ] ],
+     [ "PWR_CONTROL",         [ "SystemOn"                        ] ],
+     [ "AGILENT_CONTROL_24V", [ "VoltageOn"                       ] ],
+     [ "AGILENT_CONTROL_50V", [ "VoltageOn"                       ] ],
+     [ "AGILENT_CONTROL_80V", [ "VoltageOn"                       ] ],
+     [ "BIAS_CONTROL",        [ "VoltageOff"                      ] ],
+     [ "FEEDBACK",            [ "Calibrated"                      ] ],
+     [ "RATE_SCAN",           [ "Connected"                       ] ],
+     [ "RATE_CONTROL",        [ "Connected"                       ] ],
+     [ "DRIVE_CONTROL",       [ "Armed", "Tracking", "OnTrack", "Locked" ] ],
+     [ "LID_CONTROL",         [ "Open", "Closed"                  ] ],
+     [ "FTM_CONTROL",         [ "Valid", "TriggerOn"              ] ],
+     [ "FAD_CONTROL",         [ "Connected", "WritingData"        ] ],
+     [ "GPS_CONTROL",         [ "Locked" ] ],
+     [ "SQM_CONTROL",         [ "Valid" ] ],
+     [ "PFMINI_CONTROL",      [ "Receiving" ] ],
+    ];
+
+    if (!checkStates(table))
+    {
+        throw new Error("Something unexpected has happened. Although the startup-"+
+                        "procedure has finished, not all servers are in the state "+
+                        "in which they ought to be. Please, try to find out what "+
+                        "happened...");
+    }
+};
+
+var perform_the_entire_startup = function(){
+    switch_camera_on();
+    set_up_systems();
+    CheckFTU.checkFTU();
+    check_clock_conditioner();
+    CheckUnderflow.checkUnderflow();
+    power_on_drive();
+    perform_current_calibration_if_needed();
+    set_up_gps_control();
+    crosscheck_all_states();
+};
+
+perform_the_entire_startup();
