source: trunk/FACT++/scripts/Main.js@ 18164

Last change on this file since 18164 was 18114, checked in by tbretz, 10 years ago
Added SLEEP task which is a shutdown without locking the drive and disconnecting the bias crate; restructured RATESCAN2 to switch voltage off before closing the lid or switching the voltage to the breakdown voltage in case of voltage on to avoid moving through full moon with full bias voltage as in data taking. Ramping voltage back to nominal after movement.
File size: 45.9 KB
Line 
1/**
2 * @fileOverview This file has functions related to documenting JavaScript.
3 * @author <a href="mailto:thomas.bretz@epfl.ch">Thomas Bretz</a>
4 */
5'use strict';
6
7dim.log("Start: "+__FILE__+" ["+__DATE__+"]");
8
9// This should be set in dimctrl.rc as JavaScript.schedule-database.
10// It is sent together with the script to the dimserver.
11// If started directly, it has to be set after the command:
12//
13// .js scripts/Main.js schedule-database=...
14//
15if (!$['schedule-database'])
16 throw new Error("Environment 'schedule-database' not set!");
17
18//dimctrl.defineState(37, "TimeOutBeforeTakingData", "MCP took more than 5minutes to start TakingData");
19
20// ================================================================
21// Code related to the schedule
22// ================================================================
23
24//this is just the class implementation of 'Observation'
25include('scripts/Observation_class.js');
26include('scripts/getSchedule.js');
27
28var observations = [ ];
29
30// Get the observation scheduled for 'now' from the table and
31// return its index
32function getObservation(now)
33{
34 if (now==undefined)
35 now = new Date();
36
37 if (isNaN(now.valueOf()))
38 throw new Error("Date argument in getObservation invalid.");
39
40 observations = getSchedule();
41
42 for (var i=0; i<observations.length; i++)
43 if (now<observations[i].start)
44 return i-1;
45
46 return observations.length-1;
47}
48
49// ================================================================
50// Code to check whether observation is allowed
51// ================================================================
52/*
53function currentEst(source)
54{
55 var moon = new Moon();
56 if (!moon.isUp)
57 return 7.7;
58
59 var dist = Sky.dist(moon, source);
60
61 var alt = 90-moon.toLocal().zd;
62
63 var lc = dist*alt*pow(Moon.disk(), 6)/360/360;
64
65 var cur = 7.7+4942*lc;
66
67 return cur;
68}
69
70function thresholdEst(source) // relative threshold (ratio)
71{
72 // Assumption:
73 // atmosphere is 70km, shower taks place after 60km, earth radius 6400km
74 // just using the cosine law
75 // This fits very well with MC results: See Roger Firpo, p.45
76 // "Study of the MAGIC telescope sensitivity for Large Zenith Angle observations"
77
78 var c = Math.cos(Math.Pi-source.zd);
79 var ratio = (10*sqrt(409600*c*c+9009) + 6400*c - 60)/10;
80
81 // assumption: Energy threshold increases linearily with current
82 // assumption: Energy threshold increases linearily with distance
83
84 return ratio*currentEst(source)/7.7;
85}
86*/
87
88// ================================================================
89// Code to perform the DRS calib sequence
90// ================================================================
91
92var irq;
93
94function doDrsCalibration(where)
95{
96 dim.log("Starting DRS calibration ["+where+"]");
97
98 service_feedback.voltageOff();
99
100 var tm = new Date();
101
102 while (!irq)
103 {
104 dim.send("FAD_CONTROL/START_DRS_CALIBRATION");
105 if (irq || !takeRun("drs-pedestal", 1000)) // 40 / 20s (50Hz)
106 continue;
107
108 if (irq || !takeRun("drs-gain", 1000)) // 40 / 20s (50Hz)
109 continue;
110
111 if (irq || !takeRun("drs-pedestal", 1000)) // 40 / 20s (50Hz)
112 continue;
113
114 break;
115 }
116
117 dim.send("FAD_CONTROL/SET_FILE_FORMAT", 6);
118
119 while (!irq && !takeRun("drs-pedestal", 1000)); // 40 / 20s (50Hz)
120 while (!irq && !takeRun("drs-time", 1000)); // 40 / 20s (50Hz)
121
122 while (!irq)
123 {
124 dim.send("FAD_CONTROL/RESET_SECONDARY_DRS_BASELINE");
125 if (takeRun("pedestal", 1000)) // 40 / 10s (80Hz)
126 break;
127 }
128
129 dim.send("FAD_CONTROL/SET_FILE_FORMAT", 6);
130
131 while (!irq && !takeRun("pedestal", 1000)); // 40 / 10s (80Hz)
132 // -----------
133 // 4'40 / 2'00
134
135 if (irq)
136 dim.log("DRS calibration interrupted [%.1fs]".$((new Date()-tm)/1000));
137 else
138 dim.log("DRS calibration done [%.1fs]".$((new Date()-tm)/1000));
139}
140
141// ================================================================
142// Code related to the lid
143// ================================================================
144
145function OpenLid()
146{
147 /*
148 while (Sun.horizon(-13).isUp)
149 {
150 var now = new Date();
151 var minutes_until_sunset = (Sun.horizon(-13).set - now)/60000;
152 console.out(now.toUTCString()+": Sun above FACT-horizon, lid cannot be opened: sleeping 1min, remaining %.1fmin".$(minutes_until_sunset));
153 v8.sleep(60000);
154 }*/
155
156 var isClosed = dim.state("LID_CONTROL").name=="Closed";
157
158 var tm = new Date();
159
160 // Wait for lid to be open
161 if (isClosed)
162 {
163 dim.log("Opening lid");
164 dim.send("LID_CONTROL/OPEN");
165 }
166 dim.wait("LID_CONTROL", "Open", 30000);
167
168 if (isClosed)
169 dim.log("Lid open [%.1fs]".$((new Date()-tm)/1000));
170}
171
172function CloseLid()
173{
174 var isOpen = dim.state("LID_CONTROL").name=="Open";
175
176 var tm = new Date();
177
178 // Wait for lid to be open
179 if (isOpen)
180 {
181 if (dim.state("FTM_CONTROL").name=="TriggerOn")
182 {
183 dim.send("FTM_CONTROL/STOP_TRIGGER");
184 dim.wait("FTM_CONTROL", "Valid", 3000);
185 }
186
187 dim.log("Closing lid.");
188 dim.send("LID_CONTROL/CLOSE");
189 }
190 dim.wait("LID_CONTROL", "Closed", 30000);
191
192 if (isOpen)
193 dim.log("Lid closed [%.1fs]".$((new Date()-tm)/1000));
194}
195
196// ================================================================
197// Interrupt data taking in case of high currents
198// ================================================================
199dim.onchange['FEEDBACK'] = function(state)
200{
201 if ((state.name=="Critical" || state.name=="OnStandby") &&
202 (this.prev!="Critical" && this.prev!="OnStandby"))
203 {
204 console.out("Feedback state changed from "+this.prev+" to "+state.name+" [Main.js]");
205 irq = "RESCHEDULE";
206 }
207 this.prev=state.name;
208}
209
210// ================================================================
211// Code related to switching bias voltage on and off
212// ================================================================
213
214var service_feedback = new Subscription("FEEDBACK/CALIBRATED_CURRENTS");
215
216service_feedback.onchange = function(evt)
217{
218 if (!evt.data)
219 return;
220
221 if (this.ok==undefined)
222 return;
223
224 var Unom = evt.obj['U_nom'];
225 var Uov = evt.obj['U_ov'];
226 if (!Uov)
227 return;
228
229 var cnt = 0;
230 var avg = 0;
231 for (var i=0; i<320; i++)
232 {
233 var dU = Uov[i]-Unom;
234
235 // 0.022 corresponds to 1 DAC count (90V/4096)
236 if (Math.abs(dU)>0.033)
237 cnt++;
238
239 avg += dU;
240 }
241 avg /= 320;
242
243 this.ok = cnt<3;// || (this.last!=undefined && Math.abs(this.last-avg)<0.002);
244
245 console.out(" DeltaUov=%.3f (%.3f) [N(>0.033V)=%d]".$(avg, avg-this.last, cnt));
246
247 this.last = avg;
248}
249
250service_feedback.voltageOff = function()
251{
252 var state = dim.state("BIAS_CONTROL").name;
253
254 if (state=="Disconnected")
255 {
256 console.out(" Voltage off: bias crate disconnected!");
257 return;
258 }
259
260 // check of feedback has to be switched on
261 var isOn = state=="VoltageOn" || state=="Ramping";
262 if (isOn)
263 {
264 dim.log("Switching voltage off.");
265
266 if (dim.state("FTM_CONTROL").name=="TriggerOn")
267 {
268 dim.send("FTM_CONTROL/STOP_TRIGGER");
269 dim.wait("FTM_CONTROL", "Valid", 3000);
270 }
271
272 // Supress the possibility that the bias control is
273 // ramping and will reject the command to switch the
274 // voltage off
275 //dim.send("FEEDBACK/STOP");
276 //dim.wait("FEEDBACK", "Calibrated", 3000);
277
278 // Make sure we are not in Ramping anymore
279 //dim.wait("BIAS_CONTROL", "VoltageOn", 3000);
280
281 // Switch voltage off
282 dim.send("BIAS_CONTROL/SET_ZERO_VOLTAGE");
283 }
284
285 dim.wait("BIAS_CONTROL", "VoltageOff", 60000); // FIXME: 30000?
286 dim.wait("FEEDBACK", "Calibrated", 3000);
287
288 // FEEDBACK stays in CurrentCtrl when Voltage is off but output enabled
289 // dim.wait("FEEDBACK", "CurrentCtrlIdle", 1000);
290
291 if (isOn)
292 dim.log("Voltage off.");
293}
294
295// DN: The name of the method voltageOn() in the context of the method
296// voltageOff() is a little bit misleading, since when voltageOff() returns
297// the caller can be sure the voltage is off, but when voltageOn() return
298// this is not the case, in the sense, that the caller can now take data.
299// instead the caller of voltageOn() *must* call waitForVoltageOn() afterwards
300// in order to safely take good-quality data.
301// This could lead to nasty bugs in the sense, that the second call might
302// be forgotten by somebody
303//
304// so I suggest to rename voltageOn() --> prepareVoltageOn()
305// waitForVoltageOn() stays as it is
306// and one creates a third method called:voltageOn() like this
307/* service_feedback.voltageOn = function()
308 * {
309 * this.prepareVoltageOn();
310 * this.waitForVoltageOn();
311 * }
312 *
313 * */
314// For convenience.
315
316service_feedback.voltageOn = function(ov)
317{
318 if (isNaN(ov))
319 ov = 1.1;
320
321 if (this.ov!=ov && dim.state("FEEDBACK").name=="InProgress") // FIXME: Warning, OnStandby, Critical if (ov<this.ov)
322 {
323 dim.log("Stoping feedback.");
324 if (dim.state("FTM_CONTROL").name=="TriggerOn")
325 {
326 dim.send("FTM_CONTROL/STOP_TRIGGER");
327 dim.wait("FTM_CONTROL", "Valid", 3000);
328 }
329
330 dim.send("FEEDBACK/STOP");
331 dim.wait("FEEDBACK", "Calibrated", 3000);
332
333 // Make sure we are not in Ramping anymore
334 dim.wait("BIAS_CONTROL", "VoltageOn", 3000);
335 }
336
337 var isOff = dim.state("FEEDBACK").name=="Calibrated";
338 if (isOff)
339 {
340 dim.log("Switching voltage to Uov="+ov+"V.");
341
342 dim.send("FEEDBACK/START", ov);
343
344 // FIXME: We could miss "InProgress" if it immediately changes to "Warning"
345 // Maybe a dim.timeout state>8 ?
346 dim.wait("FEEDBACK", "InProgress", 45000);
347
348 this.ov = ov;
349 }
350
351 // Wait until voltage on
352 dim.wait("BIAS_CONTROL", "VoltageOn", 60000); // FIXME: 30000?
353}
354
355service_feedback.waitForVoltageOn = function()
356{
357 // Avoid output if condition is already fulfilled
358 dim.log("Waiting for voltage to be stable.");
359
360 function func()
361 {
362 if (irq || this.ok==true)
363 return true;
364 }
365
366 var now = new Date();
367
368 this.last = undefined;
369 this.ok = false;
370 v8.timeout(4*60000, func, this); // FIMXE: Remove 4!
371 this.ok = undefined;
372
373 if (irq)
374 dim.log("Waiting for stable voltage interrupted.");
375 else
376 dim.log("Voltage stable within limits");
377}
378
379// ================================================================
380// Function to shutdown the system
381// ================================================================
382
383function Shutdown(type)
384{
385 if (!type)
386 type = "default";
387
388 dim.log("Starting shutdown ["+type+"].");
389
390 var now1 = new Date();
391
392 var bias = dim.state("BIAS_CONTROL").name;
393 if (bias=="VoltageOn" || bias=="Ramping")
394 service_feedback.voltageOn(0);
395
396 CloseLid();
397
398 var now2 = new Date();
399
400 if (type=="sleep")
401 dim.send("DRIVE_CONTROL/MOVE_TO", 101, 0);
402 else
403 dim.send("DRIVE_CONTROL/PARK");
404
405 console.out("","Waiting for telescope to park. This may take a while.");
406
407 // FIXME: This might not work is the drive is already close to park position
408 if (type!="sleep")
409 dim.wait("DRIVE_CONTROL", "Locked", 3000);
410
411 var sub = new Subscription("DRIVE_CONTROL/POINTING_POSITION");
412 sub.get(5000); // FIXME: Proper error message in case of failure
413
414 function func()
415 {
416 var report = sub.get();
417
418 var zd = report.obj['Zd'];
419 var az = report.obj['Az'];
420
421 if (zd>100 && Math.abs(az)<1)
422 return true;
423
424 return undefined;
425 }
426
427 try { v8.timeout(150000, func); }
428 catch (e)
429 {
430 var p = sub.get();
431 dim.log('Park position not reached? Telescope at Zd='+p.obj['Zd']+' Az='+p.obj['Az']);
432 }
433 /*
434 // Check if DRS calibration is necessary
435 var diff = getTimeSinceLastDrsCalib();
436 if (diff>30 || diff==null)
437 {
438 doDrsCalibration("singlepe"); // will turn voltage off
439 if (irq)
440 break;
441 }*/
442
443 if (type=="singlepe")
444 {
445 dim.log("Taking single-pe run.");
446
447 // The voltage must be on
448 service_feedback.voltageOn();
449 service_feedback.waitForVoltageOn();
450
451 // Before we can switch to 3000 we have to make the right DRS calibration
452 dim.log("Taking single p.e. run.");
453 while (!irq && !takeRun("single-pe", 10000));
454 }
455
456 // It is unclear what comes next, so we better switch off the voltage
457 service_feedback.voltageOff();
458
459 dim.log("Finishing shutdown.");
460
461 var now3 = new Date();
462
463 dim.send("FTM_CONTROL/STOP_TRIGGER");
464 dim.wait("FTM_CONTROL", "Valid", 3000);
465
466 if (bias!="Disconnected")
467 dim.wait("FEEDBACK", "Calibrated", 3000);
468
469 if (type!="sleep")
470 {
471 dim.send("BIAS_CONTROL/DISCONNECT");
472 dim.wait("BIAS_CONTROL", "Disconnected", 3000);
473
474 }
475
476 var report = sub.get();
477
478 console.out("");
479 console.out("Shutdown procedure ["+type+"] seems to be finished...");
480 console.out(" "+new Date().toUTCString());
481 console.out(" Telescope at Zd=%.1fdeg Az=%.1fdeg".$(report.obj['Zd'], report.obj['Az']));
482 console.out(" Please check on the web cam that the park position was reached");
483 console.out(" and the telescope is not moving anymore.");
484 console.out(" Please check visually that the lid is really closed and");
485 console.out(" that the biasctrl really switched the voltage off.", "");
486 console.out(" DRIVE_CONTROL: "+dim.state("DRIVE_CONTROL").name);
487 console.out(" FEEDBACK: "+dim.state("FEEDBACK").name);
488 console.out(" FTM_CONTROL: "+dim.state("FTM_CONTROL").name);
489 console.out(" BIAS_CONTROL: "+dim.state("BIAS_CONTROL").name);
490 console.out("");
491 dim.log("Shutdown: end ["+(now2-now1)/1000+"s, "+(now3-now2)/1000+"s, "+(new Date()-now3)/1000+"s]");
492 console.out("");
493
494 sub.close();
495}
496
497
498// ================================================================
499// Function to set the system to sleep-mode
500// ================================================================
501// FIXME: do not repeat code from shutdown-function
502/*
503function GoToSleep()
504{
505 CloseLid();
506
507 var isArmed = dim.state("DRIVE_CONTROL").name=="Armed";
508 if (!isArmed)
509 {
510 dim.log("Drive not ready to move. -> send STOP");
511 dim.send("DRIVE_CONTROL/STOP");
512 dim.wait("DRIVE_CONTROL", "Armed", 5000);
513 }
514
515 dim.send("DRIVE_CONTROL/MOVE_TO 101 0");//park position
516 var sub = new Subscription("DRIVE_CONTROL/POINTING_POSITION");
517 sub.get(5000); // FIXME: Proper error message in case of failure
518
519 function func()
520 {
521 var report = sub.get();
522
523 var zd = report.obj['Zd'];
524 var az = report.obj['Az'];
525
526 if (zd>100 && Math.abs(az)<1)
527 return true;
528
529 return undefined;
530 }
531
532 try { v8.timeout(150000, func); }
533 catch (e)
534 {
535 var p = sub.get();
536 dim.log('Park position not reached? Telescope at Zd='+p.obj['Zd']+' Az='+p.obj['Az']);
537 }
538 var p2 = sub.get();
539 dim.log('Telescope at Zd=%.1fdeg Az=%.1fdeg'.$(p2.obj['Zd'], p2.obj['Az']));
540 sub.close();
541}
542*/
543
544// ================================================================
545// Check datalogger subscriptions
546// ================================================================
547
548var datalogger_subscriptions = new Subscription("DATA_LOGGER/SUBSCRIPTIONS");
549datalogger_subscriptions.get(3000, false);
550
551datalogger_subscriptions.check = function()
552{
553 var obj = this.get();
554 if (!obj.data)
555 throw new Error("DATA_LOGGER/SUBSCRIPTIONS not available.");
556
557 var expected =
558 [
559 "AGILENT_CONTROL_24V/DATA",
560 "AGILENT_CONTROL_50V/DATA",
561 "AGILENT_CONTROL_80V/DATA",
562 "BIAS_CONTROL/CURRENT",
563 "BIAS_CONTROL/DAC",
564 "BIAS_CONTROL/NOMINAL",
565 "BIAS_CONTROL/VOLTAGE",
566 "DRIVE_CONTROL/POINTING_POSITION",
567 "DRIVE_CONTROL/SOURCE_POSITION",
568 "DRIVE_CONTROL/STATUS",
569 "DRIVE_CONTROL/TRACKING_POSITION",
570 "FAD_CONTROL/CONNECTIONS",
571 "FAD_CONTROL/DAC",
572 "FAD_CONTROL/DNA",
573 "FAD_CONTROL/DRS_RUNS",
574 "FAD_CONTROL/EVENTS",
575 "FAD_CONTROL/FEEDBACK_DATA",
576 "FAD_CONTROL/FILE_FORMAT",
577 "FAD_CONTROL/FIRMWARE_VERSION",
578 "FAD_CONTROL/INCOMPLETE",
579 "FAD_CONTROL/PRESCALER",
580 "FAD_CONTROL/REFERENCE_CLOCK",
581 "FAD_CONTROL/REGION_OF_INTEREST",
582 "FAD_CONTROL/RUNS",
583 "FAD_CONTROL/RUN_NUMBER",
584 "FAD_CONTROL/START_RUN",
585 "FAD_CONTROL/STATISTICS1",
586 "FAD_CONTROL/STATS",
587 "FAD_CONTROL/STATUS",
588 "FAD_CONTROL/TEMPERATURE",
589 "FEEDBACK/CALIBRATED_CURRENTS",
590 "FEEDBACK/CALIBRATION",
591 "FEEDBACK/CALIBRATION_R8",
592 "FEEDBACK/CALIBRATION_STEPS",
593/* "FEEDBACK/REFERENCE",*/
594 "FSC_CONTROL/CURRENT",
595 "FSC_CONTROL/HUMIDITY",
596 "FSC_CONTROL/TEMPERATURE",
597 "FSC_CONTROL/VOLTAGE",
598 "FTM_CONTROL/COUNTER",
599 "FTM_CONTROL/DYNAMIC_DATA",
600 "FTM_CONTROL/ERROR",
601 "FTM_CONTROL/FTU_LIST",
602 "FTM_CONTROL/PASSPORT",
603 "FTM_CONTROL/STATIC_DATA",
604 "FTM_CONTROL/TRIGGER_RATES",
605 "GPS_CONTROL/NEMA",
606 "SQM_CONTROL/DATA",
607 "LID_CONTROL/DATA",
608 "MAGIC_LIDAR/DATA",
609 "MAGIC_WEATHER/DATA",
610 "MCP/CONFIGURATION",
611 "PWR_CONTROL/DATA",
612 "RATE_CONTROL/THRESHOLD",
613 "RATE_SCAN/DATA",
614 "RATE_SCAN/PROCESS_DATA",
615 "TEMPERATURE/DATA",
616 "TIME_CHECK/OFFSET",
617 "TNG_WEATHER/DATA",
618 "TNG_WEATHER/DUST",
619 ];
620
621 function map(entry)
622 {
623 if (entry.length==0)
624 return undefined;
625
626 var rc = entry.split(',');
627 if (rc.length!=2)
628 throw new Error("Subscription list entry '"+entry+"' has wrong number of elements.");
629 return rc;
630 }
631
632 var list = obj.data.split('\n').map(map);
633 function check(name)
634 {
635 if (list.every(function(el){return el==undefined || el[0]!=name;}))
636 throw new Error("Subscription to '"+name+"' not available.");
637 }
638
639 expected.forEach(check);
640}
641
642
643
644// ================================================================
645// Crosscheck all states
646// ================================================================
647
648// ----------------------------------------------------------------
649// Do a standard startup to bring the system in into a well
650// defined state
651// ----------------------------------------------------------------
652include('scripts/Startup.js');
653
654// ================================================================
655// Code to monitor clock conditioner
656// ================================================================
657
658var sub_counter = new Subscription("FTM_CONTROL/COUNTER");
659sub_counter.onchange = function(evt)
660{
661 if (evt.qos>0 && evt.qos!=2 && evt.qos&0x100==0)
662 throw new Error("FTM reports: clock conditioner not locked.");
663}
664
665// ================================================================
666// Code related to monitoring the fad system
667// ================================================================
668
669// This code is here, because scripts/Startup.js needs the
670// same subscriptions... to be revised.
671var sub_incomplete = new Subscription("FAD_CONTROL/INCOMPLETE");
672var sub_connections = new Subscription("FAD_CONTROL/CONNECTIONS");
673var sub_startrun = new Subscription("FAD_CONTROL/START_RUN");
674sub_startrun.get(5000);
675
676include('scripts/takeRun.js');
677
678// ----------------------------------------------------------------
679// Check that everything we need is availabel to receive commands
680// (FIXME: Should that go to the general CheckState?)
681// ----------------------------------------------------------------
682//console.out("Checking send.");
683checkSend(["MCP", "DRIVE_CONTROL", "LID_CONTROL", "FAD_CONTROL", "FEEDBACK"]);
684//console.out("Checking send: done");
685
686// ----------------------------------------------------------------
687// Bring feedback into the correct operational state
688// ----------------------------------------------------------------
689//console.out("Feedback init: start.");
690service_feedback.get(5000);
691
692// ----------------------------------------------------------------
693// Connect to the DRS_RUNS service
694// ----------------------------------------------------------------
695//console.out("Drs runs init: start.");
696
697var sub_drsruns = new Subscription("FAD_CONTROL/DRS_RUNS");
698sub_drsruns.get(5000);
699// FIXME: Check if the last DRS calibration was complete?
700
701function getTimeSinceLastDrsCalib()
702{
703 // ----- Time since last DRS Calibration [min] ------
704 var runs = sub_drsruns.get(0);
705 var diff = (new Date()-runs.time)/60000;
706
707 // Warning: 'roi=300' is a number which is not intrisically fixed
708 // but can change depending on the taste of the observers
709 var valid = runs.obj['run'][2]>0 && runs.obj['roi']==300;
710
711 if (valid)
712 dim.log("Last DRS calibration was %.1fmin ago".$(diff));
713 else
714 dim.log("No valid DRS calibration available.");
715
716 return valid ? diff : null;
717}
718
719// ----------------------------------------------------------------
720// Install interrupt handler
721// ----------------------------------------------------------------
722function handleIrq(cmd, args, time, user)
723{
724 console.out("Interrupt received:");
725 console.out(" IRQ: "+cmd);
726 console.out(" Time: "+time);
727 console.out(" User: "+user);
728
729 irq = cmd ? cmd : "stop";
730
731 // This will end a run in progress as if it where correctly stopped
732 if (dim.state("MCP").name=="TakingData")
733 dim.send("MCP/STOP");
734
735 // This will stop a rate scan in progress
736 if (dim.state("RATE_SCAN").name=="InProgress")
737 dim.send("RATE_SCAN/STOP");
738}
739
740dimctrl.setInterruptHandler(handleIrq);
741
742// ----------------------------------------------------------------
743// Make sure we will write files
744// ----------------------------------------------------------------
745dim.send("FAD_CONTROL/SET_FILE_FORMAT", 6);
746
747// ----------------------------------------------------------------
748// Print some information for the user about the
749// expected first oberservation
750// ----------------------------------------------------------------
751var test = getObservation();
752if (test!=undefined)
753{
754 var n = new Date();
755 if (observations.length>0 && test==-1)
756 dim.log("First observation scheduled for "+observations[0].start.toUTCString()+" [id="+observations[0].id+"]");
757 if (test>=0 && test<observations.length)
758 dim.log("First observation should start immediately ["+observations[test].start.toUTCString()+", id="+observations[test].id+"]");
759 if (observations.length>0 && observations[0].start>n+12*3600*1000)
760 dim.log("No observations scheduled for the next 12 hours!");
761 if (observations.length==0)
762 dim.log("No observations scheduled!");
763}
764
765// ----------------------------------------------------------------
766// Start main loop
767// ----------------------------------------------------------------
768dim.log("Entering main loop.");
769console.out("");
770
771var run = -2; // getObservation never called
772var sub;
773var lastId;
774var nextId;
775var sun = Sun.horizon(-12);
776var system_on; // undefined
777
778function processIrq()
779{
780 if (!irq)
781 return false;
782
783 if (irq.toUpperCase()=="RESCHEDULE")
784 {
785 irq = undefined;
786 return false;
787 }
788
789 if (irq.toUpperCase()=="OFF")
790 {
791 service_feedback.voltageOff();
792 dim.send("FAD_CONTROL/CLOSE_OPEN_FILES");
793 return true;
794 }
795
796 /*
797 if (irq.toUpperCase()=="STOP")
798 {
799 dim.send("FAD_CONTROL/CLOSE_OPEN_FILES");
800 dim.send("MCP/STOP");
801 return true;
802 }*/
803
804 if (irq.toUpperCase()=="SHUTDOWN")
805 {
806 Shutdown();
807 return true;
808 }
809
810 dim.log("IRQ "+irq+" unhandled... stopping script.");
811 return true;
812}
813
814while (!processIrq())
815{
816 // Check if observation position is still valid
817 // If source position has changed, set run=0
818 var idxObs = getObservation();
819 if (idxObs===undefined)
820 break;
821
822 // we are still waiting for the first observation in the schedule
823 if (idxObs==-1)
824 {
825 // flag that the first observation will be in the future
826 run = -1;
827 v8.sleep(1000);
828 continue;
829 }
830
831 // Check if we have to take action do to sun-rise
832 var was_up = sun.isUp;
833 sun = Sun.horizon(-12);
834 if (!was_up && sun.isUp)
835 {
836 console.out("");
837 dim.log("Sun rise detected.... automatic shutdown initiated!");
838 // FIXME: State check?
839 Shutdown();
840 system_on = false;
841 continue;
842 }
843
844 // Current and next observation target
845 var obs = observations[idxObs];
846 var nextObs = observations[idxObs+1];
847
848 // Check if observation target has changed
849 if (lastId!=obs.id) // !Object.isEqual(obs, nextObs)
850 {
851 dim.log("Starting new observation ["+obs.start.toUTCString()+", id="+obs.id+"]");
852
853 // This is the first source, but we do not come from
854 // a scheduled 'START', so we have to check if the
855 // telescop is operational already
856 sub = 0;
857 if (run<0)
858 {
859 //Startup(); // -> Bias On/Off?, Lid open/closed?
860 //CloseLid();
861 }
862
863 // The first observation had a start-time in the past...
864 // In this particular case start with the last entry
865 // in the list of measurements
866 if (run==-2)
867 sub = obs.length-1;
868
869 run = 0;
870 lastId = obs.id;
871 }
872
873 //dim.log("DEBUG: Next observation scheduled for "+nextObs.start.toUTCString()+" [id="+nextObs.id+"]");
874 if (nextObs && nextId!=nextObs.id)
875 {
876 dim.log("Next observation scheduled for "+nextObs.start.toUTCString()+" [id="+nextObs.id+"]");
877 console.out("");
878 nextId = nextObs.id;
879 }
880
881 if (!nextObs && nextId)
882 {
883 dim.log("No further observation scheduled.");
884 console.out("");
885 nextId = undefined;
886 }
887
888 //if (nextObs==undefined && obs[obs.length-1].task!="SHUTDOWN")
889 // throw Error("Last scheduled measurement must be a shutdown.");
890
891 // We are done with all measurement slots for this
892 // observation... wait for next observation
893 if (sub>=obs.length)
894 {
895 v8.sleep(1000);
896 continue;
897 }
898
899 if (system_on===false && obs[sub].task!="STARTUP")
900 {
901 v8.sleep(1000);
902 continue;
903 }
904
905 // Check if sun is still up... only DATA and */
906 if ((obs[sub].task=="DATA" || obs[sub].task=="RATESCAN" || obs[sub].task=="RATESCAN2" ) && sun.isUp)
907 {
908 var now = new Date();
909 var remaining = (sun.set - now)/60000;
910 console.out(now.toUTCString()+" - "+obs[sub].task+": Sun above FACT-horizon: sleeping 1min, remaining %.1fmin".$(remaining));
911 v8.sleep(60000);
912 continue;
913 }
914
915
916 if (obs[sub].task!="IDLE" && (obs[sub].task!="DATA" && run>0))
917 dim.log("New task ["+obs[sub]+"]");
918
919 // FIXME: Maybe print a warning if Drive is on during day time!
920
921 // It is not ideal that we allow the drive to be on during day time, but
922 // otherwise it is difficult to allow e.g. the STARTUP at the beginning of the night
923 var power_states = sun.isUp || !system_on ? [ "DriveOff", "SystemOn" ] : [ "SystemOn" ];
924 var drive_states = sun.isUp || !system_on ? undefined : [ "Armed", "Tracking", "OnTrack" ];
925
926 // A scheduled task was found, lets check if all servers are
927 // still only and in reasonable states. If this is not the case,
928 // something unexpected must have happend and the script is aborted.
929 //console.out(" Checking states [general]");
930 var table =
931 [
932 [ "TNG_WEATHER" ],
933 [ "MAGIC_WEATHER" ],
934 [ "CHAT" ],
935 [ "SMART_FACT" ],
936 [ "TEMPERATURE" ],
937 [ "DATA_LOGGER", [ "NightlyFileOpen", "WaitForRun", "Logging" ] ],
938 [ "FSC_CONTROL", [ "Connected" ] ],
939 [ "MCP", [ "Idle" ] ],
940 [ "TIME_CHECK", [ "Valid" ] ],
941 [ "PWR_CONTROL", power_states/*[ "SystemOn" ]*/ ],
942 [ "AGILENT_CONTROL_24V", [ "VoltageOn" ] ],
943 [ "AGILENT_CONTROL_50V", [ "VoltageOn" ] ],
944 [ "AGILENT_CONTROL_80V", [ "VoltageOn" ] ],
945 [ "BIAS_CONTROL", [ "VoltageOff", "VoltageOn", "Ramping" ] ],
946 [ "FEEDBACK", [ "Calibrated", "InProgress", "OnStandby", "Warning", "Critical" ] ],
947 [ "LID_CONTROL", [ "Open", "Closed" ] ],
948 [ "DRIVE_CONTROL", drive_states/*[ "Armed", "Tracking", "OnTrack" ]*/ ],
949 [ "FTM_CONTROL", [ "Valid", "TriggerOn" ] ],
950 [ "FAD_CONTROL", [ "Connected", "RunInProgress" ] ],
951 [ "RATE_SCAN", [ "Connected" ] ],
952 [ "RATE_CONTROL", [ "Connected", "GlobalThresholdSet", "InProgress" ] ],
953 [ "GPS_CONTROL", [ "Locked" ] ],
954 [ "SQM_CONTROL", [ "Disconnected", "Connected", "Valid" ] ],
955 ];
956
957
958 if (!checkStates(table))
959 {
960 throw new Error("Something unexpected has happened. One of the servers "+
961 "is in a state in which it should not be. Please,"+
962 "try to find out what happened...");
963 }
964
965 datalogger_subscriptions.check();
966
967 // If this is an observation which needs the voltage to be swicthed on
968 // skip that if the voltage is not stable
969 /*
970 if (obs[sub].task=="DATA" || obs[sub].task=="RATESCAN")
971 {
972 var state = dim.state("FEEDBACK").name;
973 if (state=="Warning" || state=="Critical" || state=="OnStandby")
974 {
975 v8.sleep(1000);
976 continue;
977 }
978 }*/
979
980
981 // Check if obs.task is one of the one-time-tasks
982 switch (obs[sub].task)
983 {
984 case "IDLE":
985 v8.sleep(5000);
986 continue;
987
988 case "SLEEP":
989 Shutdown("sleep"); //GoToSleep();
990
991 sub++;
992 dim.log("Task finished [SLEEP].");
993 console.out("");
994 continue;
995
996 case "STARTUP":
997 CloseLid();
998
999 doDrsCalibration("startup"); // will switch the voltage off
1000
1001 if (irq)
1002 break;
1003
1004 service_feedback.voltageOn();
1005 service_feedback.waitForVoltageOn();
1006
1007 // Before we can switch to 3000 we have to make the right DRS calibration
1008 dim.log("Taking single p.e. run.");
1009 while (!irq && !takeRun("single-pe", 10000));
1010
1011 // It is unclear what comes next, so we better switch off the voltage
1012 service_feedback.voltageOff();
1013
1014 system_on = true;
1015 dim.log("Task finished [STARTUP]");
1016 console.out("");
1017 break;
1018
1019 case "SHUTDOWN":
1020 Shutdown("singlepe");
1021 system_on = false;
1022
1023 // FIXME: Avoid new observations after a shutdown until
1024 // the next startup (set run back to -2?)
1025 sub++;
1026 dim.log("Task finished [SHUTDOWN]");
1027 console.out("");
1028 //console.out(" Waiting for next startup.", "");
1029 continue;
1030
1031 case "DRSCALIB":
1032 doDrsCalibration("drscalib"); // will switch the voltage off
1033 dim.log("Task finished [DRSCALIB]");
1034 console.out("");
1035 break;
1036
1037 case "SINGLEPE":
1038 // The lid must be closes
1039 CloseLid();
1040
1041 // Check if DRS calibration is necessary
1042 var diff = getTimeSinceLastDrsCalib();
1043 if (diff>30 || diff==null)
1044 {
1045 doDrsCalibration("singlepe"); // will turn voltage off
1046 if (irq)
1047 break;
1048 }
1049
1050 // The voltage must be on
1051 service_feedback.voltageOn();
1052 service_feedback.waitForVoltageOn();
1053
1054 // Before we can switch to 3000 we have to make the right DRS calibration
1055 dim.log("Taking single p.e. run.");
1056 while (!irq && !takeRun("single-pe", 10000));
1057
1058 // It is unclear what comes next, so we better switch off the voltage
1059 service_feedback.voltageOff();
1060 dim.log("Task finished [SINGLE-PE]");
1061 console.out("");
1062 break;
1063
1064 case "OVTEST":
1065 var locked = dim.state("DRIVE_CONTROL").name=="Locked";
1066 if (!locked)
1067 dim.send("DRIVE_CONTROL/PARK");
1068
1069 dim.send("FEEDBACK/STOP");
1070
1071 // The lid must be closed
1072 CloseLid();
1073
1074 if (!locked)
1075 {
1076 //console.out("Waiting for telescope to park. This may take a while.");
1077 dim.wait("DRIVE_CONTROL", "Locked", 3000);
1078 dim.send("DRIVE_CONTROL/UNLOCK");
1079 }
1080
1081 // Check if DRS calibration is necessary
1082 var diff = getTimeSinceLastDrsCalib();
1083 if (diff>30 || diff==null)
1084 {
1085 doDrsCalibration("ovtest"); // will turn voltage off
1086 if (irq)
1087 break;
1088 }
1089
1090 // The voltage must be on
1091 service_feedback.voltageOn(0.4);
1092 service_feedback.waitForVoltageOn();
1093
1094 dim.log("Taking single p.e. run (0.4V)");
1095 while (!irq && !takeRun("single-pe", 10000));
1096
1097 for (var i=5; i<18 && !irq; i++)
1098 {
1099 dim.send("FEEDBACK/STOP");
1100 dim.wait("FEEDBACK", "Calibrated", 3000);
1101 dim.wait("BIAS_CONTROL", "VoltageOn", 3000);
1102 dim.send("FEEDBACK/START", i*0.1);
1103 dim.wait("FEEDBACK", "InProgress", 45000);
1104 dim.wait("BIAS_CONTROL", "VoltageOn", 60000); // FIXME: 30000?
1105 service_feedback.waitForVoltageOn();
1106 dim.log("Taking single p.e. run ("+(i*0.1)+"V)");
1107 while (!irq && !takeRun("single-pe", 10000));
1108 }
1109
1110 // It is unclear what comes next, so we better switch off the voltage
1111 service_feedback.voltageOff();
1112 dim.log("Task finished [OVTEST]");
1113 console.out("");
1114 break;
1115
1116 case "RATESCAN":
1117 var tm1 = new Date();
1118
1119 // This is a workaround to make sure that we really catch
1120 // the new OnTrack state later and not the old one
1121 dim.send("DRIVE_CONTROL/STOP");
1122 dim.wait("DRIVE_CONTROL", "Armed", 15000);
1123
1124 // The lid must be open
1125 OpenLid();
1126
1127 // Switch the voltage to a reduced level (Ubd)
1128 service_feedback.voltageOn(0);
1129
1130 if (obs[sub].source != undefined)
1131 {
1132 dim.log("Pointing telescope to '"+obs[sub].source+"'.");
1133 dim.send("DRIVE_CONTROL/TRACK_ON", obs[sub].source);
1134 }
1135 else
1136 {
1137 dim.log("Pointing telescope to ra="+obs[sub].ra+" dec="+obs[sub].dec);
1138 dim.send("DRIVE_CONTROL/TRACK", obs[sub].ra, obs[sub].dec);
1139 }
1140
1141 dim.wait("DRIVE_CONTROL", "OnTrack", 150000); // 110s for turning and 30s for stabilizing
1142
1143 // Now tracking stable, switch voltage to nominal level and wait
1144 // for stability.
1145 service_feedback.voltageOn();
1146 service_feedback.waitForVoltageOn();
1147
1148 if (!irq)
1149 {
1150 var tm2 = new Date();
1151
1152 dim.log("Starting ratescan.");
1153
1154 // Start rate scan
1155 dim.send("RATE_SCAN/START_THRESHOLD_SCAN", 50, 1000, -10, "default");
1156
1157 // Lets wait if the ratescan really starts... this might take a few
1158 // seconds because RATE_SCAN configures the ftm and is waiting for
1159 // it to be configured.
1160 dim.wait("RATE_SCAN", "InProgress", 10000);
1161 dim.wait("RATE_SCAN", "Connected", 2700000);
1162
1163 // Here one could implement a watchdog for the feedback as well, but what is the difference
1164 // whether finally one has to find out if the feedback was in the correct state
1165 // or the ratescan was interrupted?
1166
1167 // this line is actually some kind of hack.
1168 // after the Ratescan, no data is written to disk. I don't know why, but it happens all the time
1169 // So I decided to put this line here as a kind of patchwork....
1170 //dim.send("FAD_CONTROL/SET_FILE_FORMAT", 6);
1171
1172 dim.log("Ratescan done [%.1fs, %.1fs]".$((tm2-tm1)/1000, (new Date()-tm2)/1000));
1173 }
1174
1175 dim.log("Task finished [RATESCAN]");
1176 console.out("");
1177 break; // case "RATESCAN"
1178
1179 case "RATESCAN2":
1180 var tm1 = new Date();
1181
1182 // This is a workaround to make sure that we really catch
1183 // the new OnTrack state later and not the old one
1184 dim.send("DRIVE_CONTROL/STOP");
1185 dim.wait("DRIVE_CONTROL", "Armed", 15000);
1186
1187 if (obs[sub].rstype=="dark-bias-off")
1188 service_feedback.voltageOff();
1189 else
1190 {
1191 // Switch the voltage to a reduced level (Ubd)
1192 var bias = dim.state("BIAS_CONTROL").name;
1193 if (bias=="VoltageOn" || bias=="Ramping")
1194 service_feedback.voltageOn(0);
1195 }
1196
1197 // Open the lid if required
1198 if (!obs[sub].lidclosed)
1199 OpenLid();
1200 else
1201 CloseLid();
1202
1203 // track source/position or move to position
1204 if (obs[sub].lidclosed)
1205 {
1206 dim.log("Moving telescope to zd="+obs[sub].zd+" az="+obs[sub].az);
1207 dim.send("DRIVE_CONTROL/MOVE_TO", obs[sub].zd, obs[sub].az);
1208 v8.sleep(3000);
1209 dim.wait("DRIVE_CONTROL", "Armed", 150000); // 110s for turning and 30s for stabilizing
1210 }
1211 else
1212 {
1213 if (obs[sub].source != undefined)
1214 {
1215 dim.log("Pointing telescope to '"+obs[sub].source+"'.");
1216 dim.send("DRIVE_CONTROL/TRACK_ON", obs[sub].source);
1217 }
1218 else
1219 {
1220 dim.log("Pointing telescope to ra="+obs[sub].ra+" dec="+obs[sub].dec);
1221 dim.send("DRIVE_CONTROL/TRACK", obs[sub].ra, obs[sub].dec);
1222 }
1223
1224 dim.wait("DRIVE_CONTROL", "OnTrack", 150000); // 110s for turning and 30s for stabilizing
1225 }
1226
1227 // Now tracking stable, switch voltage to nominal level and wait
1228 // for stability.
1229 if (obs[sub].rstype!="dark-bias-off")
1230 {
1231 service_feedback.voltageOn();
1232 service_feedback.waitForVoltageOn();
1233 }
1234
1235 if (!irq)
1236 {
1237 var tm2 = new Date();
1238
1239 dim.log("Starting ratescan 2/1 ["+obs[sub].rstype+"]");
1240
1241 // Start rate scan
1242 dim.send("RATE_SCAN/START_THRESHOLD_SCAN", 50, 300, 20, obs[sub].rstype);
1243
1244 // Lets wait if the ratescan really starts... this might take a few
1245 // seconds because RATE_SCAN configures the ftm and is waiting for
1246 // it to be configured.
1247 dim.wait("RATE_SCAN", "InProgress", 10000);
1248 //FIXME: discuss what best value is here
1249 dim.wait("RATE_SCAN", "Connected", 2700000);//45min
1250 //dim.wait("RATE_SCAN", "Connected", 1200000);//3.3h
1251
1252 // Here one could implement a watchdog for the feedback as well, but what is the difference
1253 // whether finally one has to find out if the feedback was in the correct state
1254 // or the ratescan was interrupted?
1255
1256 // this line is actually some kind of hack.
1257 // after the Ratescan, no data is written to disk. I don't know why, but it happens all the time
1258 // So I decided to put this line here as a kind of patchwork....
1259 //dim.send("FAD_CONTROL/SET_FILE_FORMAT", 6);
1260
1261 dim.log("Ratescan 2/1 done [%.1fs, %.1fs]".$((tm2-tm1)/1000, (new Date()-tm2)/1000));
1262 }
1263
1264 if (!irq)
1265 {
1266 var tm2 = new Date();
1267
1268 dim.log("Starting ratescan 2/2 ["+obs[sub].rstype+"]");
1269
1270 // Start rate scan
1271 dim.send("RATE_SCAN/START_THRESHOLD_SCAN", 300, 1000, 100, obs[sub].rstype);
1272
1273 // Lets wait if the ratescan really starts... this might take a few
1274 // seconds because RATE_SCAN configures the ftm and is waiting for
1275 // it to be configured.
1276 dim.wait("RATE_SCAN", "InProgress", 10000);
1277 dim.wait("RATE_SCAN", "Connected", 2700000);
1278
1279 // Here one could implement a watchdog for the feedback as well, but what is the difference
1280 // whether finally one has to find out if the feedback was in the correct state
1281 // or the ratescan was interrupted?
1282
1283 // this line is actually some kind of hack.
1284 // after the Ratescan, no data is written to disk. I don't know why, but it happens all the time
1285 // So I decided to put this line here as a kind of patchwork....
1286 //dim.send("FAD_CONTROL/SET_FILE_FORMAT", 6);
1287
1288 dim.log("Ratescan 2/2 done [%.1fs, %.1fs]".$((tm2-tm1)/1000, (new Date()-tm2)/1000));
1289 }
1290
1291 dim.log("Task finished [RATESCAN2]");
1292 console.out("");
1293 break; // case "RATESCAN2"
1294
1295 case "DATA":
1296
1297 // ========================== case "DATA" ============================
1298 /*
1299 if (Sun.horizon("FACT").isUp)
1300 {
1301 console.out(" SHUTDOWN","");
1302 Shutdown();
1303 console.out(" Exit forced due to broken schedule", "");
1304 exit();
1305 }
1306 */
1307
1308 // Calculate remaining time for this observation in minutes
1309 var remaining = nextObs==undefined ? 0 : (nextObs.start-new Date())/60000;
1310 //dim.log("DEBUG: remaining: "+remaining+" nextObs="+nextObs+" start="+nextObs.start);
1311
1312 // ------------------------------------------------------------
1313
1314 dim.log("Run count "+run+" [remaining "+parseInt(remaining)+"min]");
1315
1316 // ----- Time since last DRS Calibration [min] ------
1317 var diff = getTimeSinceLastDrsCalib();
1318
1319 // Changine pointing position and take calibration...
1320 // ...every four runs (every ~20min)
1321 // ...if at least ten minutes of observation time are left
1322 // ...if this is the first run on the source
1323 var point = (run%4==0 && remaining>10) || run==0;
1324
1325 // Take DRS Calib...
1326 // ...every four runs (every ~20min)
1327 // ...at last every two hours
1328 // ...when DRS temperature has changed by more than 2deg (?)
1329 // ...when more than 15min of observation are left
1330 // ...no drs calibration was done yet
1331 var drscal = (run%4==0 && (remaining>15 && diff>70)) || diff==null;
1332
1333 if (point)
1334 {
1335 // Switch the voltage to a reduced voltage level
1336 service_feedback.voltageOn(0);
1337
1338 // Change wobble position every four runs,
1339 // start with alternating wobble positions each day
1340 var wobble = (parseInt(run/4) + parseInt(new Date()/1000/3600/24-0.5))%2+1;
1341
1342 //console.out(" Move telescope to '"+source+"' "+offset+" "+wobble);
1343 dim.log("Pointing telescope to '"+obs[sub].source+"' [wobble="+wobble+"]");
1344
1345 // This is a workaround to make sure that we really catch
1346 // the new OnTrack state later and not the old one
1347 dim.send("DRIVE_CONTROL/STOP");
1348 dim.wait("DRIVE_CONTROL", "Armed", 15000);
1349
1350 dim.send("DRIVE_CONTROL/TRACK_WOBBLE", wobble, obs[sub].source);
1351
1352 // Do we have to check if the telescope is really moving?
1353 // We can cross-check the SOURCE service later
1354 }
1355
1356 if (drscal)
1357 {
1358 doDrsCalibration("data"); // will turn voltage off
1359
1360 // Now we switch on the voltage and a significant amount of
1361 // time has been passed, so do the check again.
1362 sun = Sun.horizon(-12);
1363 if (!was_up && sun.isUp)
1364 {
1365 dim.log("Sun rise detected....");
1366 continue;
1367 }
1368 }
1369
1370 if (irq)
1371 continue;
1372
1373 OpenLid();
1374
1375 // This is now th right time to wait for th drive to be stable
1376 dim.wait("DRIVE_CONTROL", "OnTrack", 150000); // 110s for turning and 30s for stabilizing
1377
1378 // Now check the voltage... (do not start a lot of stuff just to do nothing)
1379 var state = dim.state("FEEDBACK").name;
1380 if (state=="Warning" || state=="Critical" || state=="OnStandby")
1381 {
1382 v8.sleep(60000);
1383 continue;
1384 }
1385
1386 // Now we are 'OnTrack', so we can ramp to nominal voltage
1387 // and wait for the feedback to get stable
1388 service_feedback.voltageOn();
1389 service_feedback.waitForVoltageOn();
1390
1391 // If pointing had changed, do calibration
1392 if (!irq && point)
1393 {
1394 dim.log("Starting calibration.");
1395
1396 // Calibration (2% of 20')
1397 while (!irq)
1398 {
1399 if (irq || !takeRun("pedestal", 1000)) // 80 Hz -> 10s
1400 continue;
1401 if (irq || !takeRun("light-pulser-ext", 1000)) // 80 Hz -> 10s
1402 continue;
1403 break;
1404 }
1405 }
1406
1407 //console.out(" Taking data: start [5min]");
1408
1409 // FIXME: What do we do if during calibration something has happened
1410 // e.g. drive went to ERROR? Maybe we have to check all states again?
1411
1412 var twilight = Sun.horizon(-16).isUp;
1413
1414 if (twilight)
1415 {
1416 for (var i=0; i<5 && !irq; i++)
1417 takeRun("data", -1, 60); // Take data (1min)
1418 }
1419 else
1420 {
1421 var len = 300;
1422 while (!irq && len>15)
1423 {
1424 var time = new Date();
1425 if (takeRun("data", -1, len)) // Take data (5min)
1426 break;
1427
1428 len -= parseInt((new Date()-time)/1000);
1429 }
1430 }
1431
1432 //console.out(" Taking data: done");
1433 run++;
1434
1435 continue; // case "DATA"
1436 }
1437
1438 if (nextObs!=undefined && sub==obs.length-1)
1439 dim.log("Next observation will start at "+nextObs.start.toUTCString()+" [id="+nextObs.id+"]");
1440
1441 sub++;
1442}
1443
1444sub_drsruns.close();
1445
1446dim.log("Left main loop [irq="+irq+"]");
1447
1448// ================================================================
1449// Comments and ToDo goes here
1450// ================================================================
1451
1452// error handline : http://www.sitepoint.com/exceptional-exception-handling-in-javascript/
1453// classes: http://www.phpied.com/3-ways-to-define-a-javascript-class/
Note: See TracBrowser for help on using the repository browser.