source: trunk/FACT++/src/smartfact.cc@ 13907

Last change on this file since 13907 was 13907, checked in by tbretz, 12 years ago
Removed some stray debug messages; do not display 'no-file' in scriptlog
File size: 67.0 KB
Line 
1#ifdef HAVE_LIBNOVA
2#include <libnova/solar.h>
3#include <libnova/lunar.h>
4#include <libnova/rise_set.h>
5#endif
6
7#include "Dim.h"
8#include "Event.h"
9#include "Shell.h"
10#include "StateMachineDim.h"
11#include "Connection.h"
12#include "Configuration.h"
13#include "Console.h"
14#include "Converter.h"
15#include "PixelMap.h"
16
17#include "tools.h"
18
19#include "LocalControl.h"
20
21#include "HeadersFAD.h"
22#include "HeadersBIAS.h"
23#include "HeadersFTM.h"
24
25#include <boost/filesystem.hpp>
26
27using namespace std;
28
29// ------------------------------------------------------------------------
30
31#include "DimDescriptionService.h"
32#include "DimState.h"
33
34// ------------------------------------------------------------------------
35
36const static string kHtmlWhite = "#ffffff";
37const static string kHtmlYellow = "#fffff0";
38const static string kHtmlRed = "#fff8f0";
39const static string kHtmlGreen = "#f0fff0";
40const static string kHtmlBlue = "#f0f0ff";
41
42// ========================================================================
43// ========================================================================
44// ========================================================================
45
46class Astro
47{
48public:
49 Time time;
50
51 Time fSunRiseDayTime;
52 Time fSunRiseCivil;
53 Time fSunRiseAstronomical;
54 Time fSunRiseDarkTime;
55
56 Time fSunSetDayTime;
57 Time fSunSetCivil;
58 Time fSunSetAstronomical;
59 Time fSunSetDarkTime;
60
61 int state;
62 string description;
63 string color;
64
65 bool isday;
66
67public:
68 Astro(double lon, double lat, const Time &t=Time()) : time(t)
69 {
70#ifdef HAVE_LIBNOVA
71 ln_lnlat_posn observer;
72 observer.lng = lon;
73 observer.lat = lat;
74
75 // get Julian day from local time
76 const double JD = time.JD();
77
78 ln_rst_time sun_day;
79 ln_rst_time sun_civil;
80 ln_rst_time sun_astronomical;
81 ln_rst_time sun_dark;
82
83 // Warning: return code of 1 means circumpolar and is not checked!
84 //ln_get_lunar_rst (JD-0.5, &observer, &moon);
85 ln_get_solar_rst (JD-0.5, &observer, &sun_day);
86 ln_get_solar_rst_horizon(JD-0.5, &observer, - 6, &sun_civil);
87 ln_get_solar_rst_horizon(JD-0.5, &observer, -12, &sun_astronomical);
88 ln_get_solar_rst_horizon(JD-0.5, &observer, -18, &sun_dark);
89
90 fSunSetDayTime = Time(sun_day.set);
91 fSunSetCivil = Time(sun_civil.set);
92 fSunSetAstronomical = Time(sun_astronomical.set);
93 fSunSetDarkTime = Time(sun_dark.set);
94
95 fSunRiseDayTime = Time(sun_day.rise);
96 fSunRiseCivil = Time(sun_civil.rise);
97 fSunRiseAstronomical = Time(sun_astronomical.rise);
98 fSunRiseDarkTime = Time(sun_dark.rise);
99
100 const bool is_day = JD>sun_day.rise;
101 const bool is_night = JD>sun_dark.set;
102
103 //ln_get_lunar_rst (JD+0.5, &observer, &moon);
104 ln_get_solar_rst (JD+0.5, &observer, &sun_day);
105 ln_get_solar_rst_horizon(JD+0.5, &observer, - 6, &sun_civil);
106 ln_get_solar_rst_horizon(JD+0.5, &observer, -12, &sun_astronomical);
107 ln_get_solar_rst_horizon(JD+0.5, &observer, -18, &sun_dark);
108
109 if (is_day)
110 {
111 fSunRiseDayTime = Time(sun_day.rise);
112 fSunRiseCivil = Time(sun_civil.rise);
113 fSunRiseAstronomical = Time(sun_astronomical.rise);
114 fSunRiseDarkTime = Time(sun_dark.rise);
115 }
116
117 if (is_night)
118 {
119 fSunSetDayTime = Time(sun_day.set);
120 fSunSetCivil = Time(sun_civil.set);
121 fSunSetAstronomical = Time(sun_astronomical.set);
122 fSunSetDarkTime = Time(sun_dark.set);
123 }
124
125 // case 0: midnight to sun-rise | !is_day && !is_night | rise/set
126 // case 1: sun-rise to sun-set | is_day && !is_night | set /rise
127 // case 2: sun-set to midnight | is_day && is_night | rise/set
128 /*
129 if (is_day^is_night)
130 {
131 cout << "SunSet: " << fSunSetDayTime << endl;
132 cout << "SunRise: " << fSunRiseDayTime << endl;
133 }
134 else
135 {
136 cout << "SunRise: " << fSunRiseDayTime << endl;
137 cout << "SunSet: " << fSunSetDayTime << endl;
138 }*/
139
140 isday = is_day^is_night;
141
142 state = isday ? 4 : 0;
143 if (time>fSunSetDayTime) state++;
144 if (time>fSunSetCivil) state++;
145 if (time>fSunSetAstronomical) state++;
146 if (time>fSunSetDarkTime) state++;
147
148 if (time>fSunRiseDarkTime) state++;
149 if (time>fSunRiseAstronomical) state++;
150 if (time>fSunRiseCivil) state++;
151 if (time>fSunRiseDayTime) state++;
152
153 string name[] =
154 {
155 "dark time",
156 "astron. twilight",
157 "civil twilight",
158 "sunrise",
159 "day time",
160 "sunset",
161 "civil twilight",
162 "astron. twilight",
163 "dark time"
164 };
165
166 description = state[name];
167
168 string arr;
169 ostringstream out;
170 if (isday)
171 {
172 out << fSunSetDarkTime-time;
173 arr = "&darr;";
174 }
175 else
176 {
177 out << fSunRiseDayTime-time;
178 arr = "&uarr;";
179 }
180
181 description += " ["+out.str().substr(0, 5)+arr+"]";
182
183 switch (state)
184 {
185 case 0: case 1: color = kHtmlGreen; break;
186 case 2: case 3: color = kHtmlYellow; break;
187 case 4: color = kHtmlRed; break;
188 case 5: case 6: color = kHtmlYellow; break;
189 case 7: case 8: color = kHtmlGreen; break;
190 }
191#endif
192 }
193};
194
195class Moon
196{
197public:
198 double ra;
199 double dec;
200
201 double disk;
202
203 bool visible;
204
205 Time fMoonRise;
206 Time fMoonTransit;
207 Time fMoonSet;
208
209 string description;
210 string color;
211
212 Time time;
213
214 Moon(double lon, double lat, const Time &t=Time()) : time(t)
215 {
216#ifdef HAVE_LIBNOVA
217 const double JD = time.JD();
218
219 ln_lnlat_posn observer;
220 observer.lng = lon;
221 observer.lat = lat;
222
223 ln_rst_time moon;
224 ln_get_lunar_rst(JD-0.5, &observer, &moon);
225
226 fMoonRise = Time(moon.rise);
227 fMoonTransit = Time(moon.transit);
228 fMoonSet = Time(moon.set);
229
230 visible =
231 (JD>moon.rise && JD<moon.set && moon.rise<moon.set) ||
232 ((JD<moon.set || JD>moon.rise) && moon.rise>moon.set);
233
234 const bool is_up = JD>moon.rise;
235 const bool is_sinking = JD>moon.transit;
236 const bool is_dn = JD>moon.set;
237
238 ln_get_lunar_rst(JD+0.5, &observer, &moon);
239 if (is_up)
240 fMoonRise = Time(moon.rise);
241 if (is_sinking)
242 fMoonTransit = Time(moon.transit);
243 if (is_dn)
244 fMoonSet = Time(moon.set);
245
246 ln_equ_posn pos;
247 ln_get_lunar_equ_coords(JD, &pos);
248
249 ra = pos.ra/15;
250 dec = pos.dec;
251
252 disk = ln_get_lunar_disk(JD)*100;
253
254 if (!visible || disk<25)
255 color = kHtmlGreen;
256 else
257 color = disk>75 ? kHtmlRed : kHtmlYellow;
258
259 string arr;
260 ostringstream dt;
261 if (fMoonSet<fMoonRise)
262 {
263 dt << fMoonSet-time;
264 arr = "&darr;";
265 }
266 else
267 {
268 dt << fMoonRise-time;
269 arr = "&uarr;";
270 }
271
272 ostringstream out;
273 out << setprecision(2);
274 out << (visible?"visible ":"") << (disk<0.1?0:disk) << "% [" << dt.str().substr(0,5) << arr << "]";
275
276 description = out.str();
277#endif
278 }
279
280 double Angle(double r, double d)
281 {
282 const double theta0 = M_PI/2-d*M_PI/180;
283 const double phi0 = r*M_PI/12;
284
285 const double theta1 = M_PI/2-dec*M_PI/180;
286 const double phi1 = ra*M_PI/12;
287
288 const double x0 = sin(theta0) * cos(phi0);
289 const double y0 = sin(theta0) * sin(phi0);
290 const double z0 = cos(theta0);
291
292 const double x1 = sin(theta1) * cos(phi1);
293 const double y1 = sin(theta1) * sin(phi1);
294 const double z1 = cos(theta1);
295
296 double arg = x0*x1 + y0*y1 + z0*z1;
297 if(arg > 1.0) arg = 1.0;
298 if(arg < -1.0) arg = -1.0;
299
300 return acos(arg) * 180/M_PI;
301 }
302};
303
304// ========================================================================
305// ========================================================================
306// ========================================================================
307
308class StateMachineSmartFACT : public StateMachineDim
309{
310private:
311 const Time fRunTime;
312
313 enum states_t
314 {
315 kStateDimNetworkNA = 1,
316 kStateRunning,
317 };
318
319 // ------------------------- Internal variables -----------------------
320
321 PixelMap fPixelMap;
322
323 Time fLastUpdate;
324
325 string fPath;
326
327 // ----------------------------- Data storage -------------------------
328
329 deque<string> fControlMessageHist;
330 int32_t fControlScriptDepth;
331
332 uint32_t fMcpConfigurationState; // For consistency
333 int64_t fMcpConfigurationMaxTime;
334 int64_t fMcpConfigurationMaxEvents;
335 string fMcpConfigurationName;
336 Time fMcpConfigurationRunStart;
337
338 enum weather_t { kWeatherBegin=0, kTemp = kWeatherBegin, kDew, kHum, kPress, kWind, kGusts, kDir, kWeatherEnd = kDir+1 };
339 deque<float> fMagicWeatherHist[kWeatherEnd];
340
341 deque<float> fTngWeatherDustHist;
342 Time fTngWeatherDustTime;
343
344 vector<float> fFeedbackCalibration;
345
346 float fFeedbackTempOffset;
347 float fFeedbackUserOffset;
348
349 vector<float> fBiasControlVoltageVec;
350
351 float fBiasControlVoltageMed;
352 float fBiasControlCurrentMed;
353 float fBiasControlCurrentMax;
354
355 deque<float> fBiasControlCurrentHist;
356 deque<float> fFscControlTemperatureHist;
357
358 float fFscControlHumidityAvg;
359
360 float fDriveControlPointingZd;
361 string fDriveControlPointingAz;
362 string fDriveControlSourceName;
363
364 deque<float> fDriveControlTrackingDevHist;
365
366 int64_t fFadControlNumEvents;
367
368 float fFtmControlTriggerRateCam;
369 deque<float> fFtmControlTriggerRateHist;
370
371 float fFtmPatchThresholdMed;
372 float fFtmBoardThresholdMed;
373
374 bool fFtmControlFtuOk;
375
376 uint64_t fRateScanDataId;
377 uint8_t fRateScanBoard;
378 deque<float> fRateScanDataHist[41];
379
380 int fHasError;
381
382 // ------------- Initialize variables before the Dim stuff ------------
383
384 DimVersion fDimDNS;
385 DimControl fDimControl;
386 DimDescribedState fDimMcp;
387 DimDescribedState fDimDataLogger;
388 DimDescribedState fDimDriveControl;
389 DimDescribedState fDimMagicWeather;
390 DimDescribedState fDimTngWeather;
391 DimDescribedState fDimFeedback;
392 DimDescribedState fDimBiasControl;
393 DimDescribedState fDimFtmControl;
394 DimDescribedState fDimFadControl;
395 DimDescribedState fDimFscControl;
396 DimDescribedState fDimRateControl;
397 DimDescribedState fDimRateScan;
398 DimDescribedState fDimChatServer;
399
400 // -------------------------------------------------------------------
401
402 bool CheckDataSize(const EventImp &d, const char *name, size_t size, bool min=false)
403 {
404 if ((!min && d.GetSize()==size) || (min && d.GetSize()>size))
405 return true;
406
407 ostringstream msg;
408 msg << name << " - Received service has " << d.GetSize() << " bytes, but expected ";
409 if (min)
410 msg << "more than ";
411 msg << size << ".";
412 Warn(msg);
413 return false;
414 }
415
416 // -------------------------------------------------------------------
417
418 template<class T>
419 void WriteBinary(const EventImp &d, const string &fname, const T &t, double scale, double offset=0)
420 {
421 const Statistics stat(t);
422
423 vector<uint8_t> val(t.size(), 0);
424 for (uint64_t i=0; i<t.size(); i++)
425 {
426 float range = nearbyint(128*(t[i]-offset)/scale); // [-2V; 2V]
427 if (range>127)
428 range=127;
429 if (range<0)
430 range=0;
431 val[i] = (uint8_t)range;
432 }
433
434 const char *ptr = reinterpret_cast<char*>(val.data());
435
436 ostringstream out;
437 out << d.GetJavaDate() << '\n';
438 out << offset << '\n';
439 out << offset+scale << '\n';
440 out << setprecision(3);
441 out << stat.min << '\n';
442 out << stat.med << '\n';
443 out << stat.max << '\n';
444 out.write(ptr, val.size()*sizeof(uint8_t));
445
446 ofstream(fPath+"/"+fname+".bin") << out.str();
447 }
448
449 // -------------------------------------------------------------------
450
451 struct Statistics
452 {
453 float min;
454 float max;
455 float med;
456 float avg;
457 //float rms;
458
459 template<class T>
460 Statistics(const T &t, size_t offset_min=0, size_t offset_max=0)
461 : min(0), max(0), med(0), avg(0)
462 {
463 if (t.size()==0)
464 return;
465
466 T copy(t);
467 sort(copy.begin(), copy.end());
468
469 if (offset_min>t.size())
470 offset_min = 0;
471 if (offset_max>t.size())
472 offset_max = 0;
473
474 min = copy[offset_min];
475 max = copy[copy.size()-1-offset_max];
476 avg = accumulate (t.begin(), t.end(), 0.)/t.size();
477
478 const size_t p = t.size()/2;
479
480 med = copy[p];
481 }
482 };
483
484 void HandleControlMessageImp(const EventImp &d)
485 {
486 if (d.GetSize()==0)
487 return;
488
489 const string time = d.GetTimeAsStr("%H:%M:%S ");
490
491 string str = " ";
492 for (auto it=fControlMessageHist.rbegin(); it!=fControlMessageHist.rend(); it++)
493 {
494 str = it->substr(0, time.length());
495 if (str!="--:--:-- ")
496 break;
497 }
498
499 ostringstream tst;
500 tst << d.GetQoS();
501
502 string msg;
503 msg += str==time ? "--:--:-- " : time;
504 msg += "<->"+string(d.Ptr<char>())+"</->";
505
506 fControlMessageHist.push_back(msg);
507
508 ostringstream out;
509 out << setprecision(3);
510 out << d.GetJavaDate() << '\n';
511 out << "#ffffff\t";
512
513 for (auto it=fControlMessageHist.begin(); it!=fControlMessageHist.end(); it++)
514 out << *it << "<br/>";
515
516 out << '\n';
517
518 ofstream(fPath+"/scriptlog.data") << out.str();
519 }
520
521 int HandleDimControlMessage(const EventImp &d)
522 {
523 if (d.GetQoS()==90)
524 HandleControlMessageImp(d);
525
526 return GetCurrentState();
527 }
528
529 void HandleControlStateChange(const EventImp &d)
530 {
531 DimControl ctrl;
532 ctrl.Handler(d);
533
534 if (d.GetQoS()==-2 && ctrl.scriptdepth==0)
535 fControlMessageHist.clear();
536
537 if (d.GetQoS()>=0)
538 return;
539
540#if BOOST_VERSION < 104600
541 const string file = boost::filesystem::path(ctrl.file).filename();
542#else
543 const string file = boost::filesystem::path(ctrl.file).filename().string();
544#endif
545
546 HandleControlMessageImp(Event(d, ctrl.shortmsg.data(), ctrl.shortmsg.length()+1));
547 if (!file.empty())
548 HandleControlMessageImp(Event(d, file.data(), file.length()+1));
549 }
550
551 int HandleMcpConfiguration(const EventImp &d)
552 {
553 if (!CheckDataSize(d, "Mcp:Configuration", 16, true))
554 {
555 fMcpConfigurationState = -256;
556 fMcpConfigurationMaxTime = 0;
557 fMcpConfigurationMaxEvents = 0;
558 fMcpConfigurationName = "";
559 fMcpConfigurationRunStart = Time(Time::none);
560 return GetCurrentState();
561 }
562
563 fMcpConfigurationState = d.GetQoS();
564 fMcpConfigurationMaxTime = d.Get<uint64_t>();
565 fMcpConfigurationMaxEvents = d.Get<uint64_t>(8);
566 fMcpConfigurationName = d.Ptr<char>(16);
567
568 if (d.GetQoS()==12)
569 fMcpConfigurationRunStart = Time();
570
571 return GetCurrentState();
572 }
573
574 void WriteWeather(const EventImp &d, const string &name, int i, float min, float max)
575 {
576 const Statistics stat(fMagicWeatherHist[i]);
577
578 ostringstream out;
579 out << setprecision(3);
580 out << d.GetJavaDate() << '\n';
581
582 out << "#ffffff\t" << fMagicWeatherHist[i].back() << '\n';
583 out << "#ffffff\t" << stat.min << '\n';
584 out << "#ffffff\t" << stat.avg << '\n';
585 out << "#ffffff\t" << stat.max << '\n';
586
587 ofstream(fPath+"/"+name+".data") << out.str();
588
589 WriteBinary(d, "magicweather-"+name+"-hist", fMagicWeatherHist[i], max-min, min);
590 }
591
592 int HandleMagicWeatherData(const EventImp &d)
593 {
594 if (!CheckDataSize(d, "MagicWeather:Data", 7*4+2))
595 return GetCurrentState();
596
597 // Store a history of the last 300 entries
598 for (int i=kWeatherBegin; i<kWeatherEnd; i++)
599 {
600 fMagicWeatherHist[i].push_back(d.Ptr<float>(2)[i]);
601 if (fMagicWeatherHist[i].size()>300)
602 fMagicWeatherHist[i].pop_front();
603 }
604
605 static const char *dir[] =
606 {
607 "N", "NNE", "NE", "ENE",
608 "E", "ESE", "SE", "SSE",
609 "S", "SSW", "SW", "WSW",
610 "W", "WNW", "NW", "NNW"
611 };
612
613
614 const uint16_t idx = uint16_t(floor(fMagicWeatherHist[kDir].back()/22.5+16.5))%16;
615 //const uint16_t idx = uint16_t(floor(fmod(fMagicWeatherHist[kDir].back()/22.5+360+11.25, 360)/22.5))%16;
616
617 Astro astro(-(17.+53./60+26.525/3600), 28.+45./60+42.462/3600);
618 Moon moon (-(17.+53./60+26.525/3600), 28.+45./60+42.462/3600);
619
620 ostringstream out;
621 out << d.GetJavaDate() << '\n';
622 out << astro.color << '\t' << astro.description << '\n';
623 out << setprecision(2);
624 out << (astro.isday?kHtmlWhite:moon.color) << '\t' << moon.description << '\n';
625 out << setprecision(3);
626 for (int i=0; i<6; i++)
627 out << "#ffffff\t" << fMagicWeatherHist[i].back() << '\n';
628 out << "#ffffff\t" << dir[idx] << '\n';
629 out << "#ffffff\t";
630 if (fTngWeatherDustHist.size()>0)
631 out << fTngWeatherDustHist.back() << '\t' << fTngWeatherDustTime.GetAsStr("%H:%M") << '\n';
632 else
633 out << "\t\n";
634
635 ofstream(fPath+"/weather.data") << out.str();
636
637 out.str("");
638 out << astro.time.JavaDate() << '\n';
639 out << kHtmlWhite << '\t' << astro.fSunRiseDarkTime.GetAsStr("%H:%M") << '\n';
640 out << kHtmlWhite << '\t' << astro.fSunRiseAstronomical.GetAsStr("%H:%M") << '\n';
641 out << kHtmlWhite << '\t' << astro.fSunRiseCivil.GetAsStr("%H:%M") << '\n';
642 out << kHtmlWhite << '\t' << astro.fSunRiseDayTime.GetAsStr("%H:%M") << '\n';
643
644 out << kHtmlWhite << '\t' << astro.fSunSetDayTime.GetAsStr("%H:%M") << '\n';
645 out << kHtmlWhite << '\t' << astro.fSunSetCivil.GetAsStr("%H:%M") << '\n';
646 out << kHtmlWhite << '\t' << astro.fSunSetAstronomical.GetAsStr("%H:%M") << '\n';
647 out << kHtmlWhite << '\t' << astro.fSunSetDarkTime.GetAsStr("%H:%M") << '\n';
648
649 out << kHtmlWhite << '\t' << moon.fMoonRise.GetAsStr("%H:%M") << '\n';
650 out << kHtmlWhite << '\t' << moon.fMoonTransit.GetAsStr("%H:%M") << '\n';
651 out << kHtmlWhite << '\t' << moon.fMoonSet.GetAsStr("%H:%M") << '\n';
652 out << kHtmlWhite << '\t';
653
654 ofstream(fPath+"/astro.data") << out.str();
655
656 WriteWeather(d, "temp", kTemp, -5, 35);
657 WriteWeather(d, "dew", kDew, -5, 35);
658 WriteWeather(d, "hum", kHum, 0, 100);
659 WriteWeather(d, "wind", kWind, 0, 100);
660 WriteWeather(d, "gusts", kGusts, 0, 100);
661 WriteWeather(d, "press", kPress, 700, 1000);
662
663 return GetCurrentState();
664 }
665
666 int HandleTngWeatherDust(const EventImp &d)
667 {
668 if (!CheckDataSize(d, "TngWeather:Dust", 4))
669 return GetCurrentState();
670
671 fTngWeatherDustTime = d.GetTime();
672
673 fTngWeatherDustHist.push_back(d.GetFloat());
674 if (fTngWeatherDustHist.size()>300)
675 fTngWeatherDustHist.pop_front();
676
677 const Statistics stat(fTngWeatherDustHist);
678
679 const double scale = stat.max>0 ? pow(10, ceil(log10(stat.max))) : 0;
680
681 WriteBinary(d, "tng-dust-hist", fTngWeatherDustHist, scale);
682
683 ostringstream out;
684 out << d.GetJavaDate() << '\n';
685
686 ofstream(fPath+"/tngdust.data") << out.str();
687
688 return GetCurrentState();
689 }
690
691 int HandleDrivePointing(const EventImp &d)
692 {
693 if (!CheckDataSize(d, "DriveControl:Pointing", 16))
694 return GetCurrentState();
695
696 fDriveControlPointingZd = d.Get<double>();
697
698 const double az = d.Get<double>(8);
699
700 static const char *dir[] =
701 {
702 "N", "NNE", "NE", "ENE",
703 "E", "ESE", "SE", "SSE",
704 "S", "SSW", "SW", "WSW",
705 "W", "WNW", "NW", "NNW"
706 };
707
708 const uint16_t idx = uint16_t(floor(az/22.5+16.5))%16;
709 fDriveControlPointingAz = dir[idx];
710
711 ostringstream out;
712 out << d.GetJavaDate() << '\n';
713
714 out << setprecision(5);
715 out << fDriveControlPointingZd << '\n';
716 out << az << '\n';
717
718 ofstream(fPath+"/drive-pointing.data") << out.str();
719
720 return GetCurrentState();
721 }
722
723 int HandleDriveTracking(const EventImp &d)
724 {
725 if (!CheckDataSize(d, "DriveControl:Tracking", 56))
726 return GetCurrentState();
727
728 const double Ra = d.Get<double>(0*8);
729 const double Dec = d.Get<double>(1*8);
730 const double Zd = d.Get<double>(3*8);
731 const double Az = d.Get<double>(4*8);
732
733 const double zd = Zd * M_PI / 180;
734 const double dzd = d.Get<double>(5*8) * M_PI / 180;
735 const double daz = d.Get<double>(6*8) * M_PI / 180;
736
737 // Correct:
738 // const double d = cos(del) - sin(zd+dzd)*sin(zd)*(1.-cos(daz));
739
740 // Simplified:
741 double dev = cos(dzd) - sin(zd+dzd)*sin(zd)*(1.-cos(daz));
742 dev = acos(dev) * 180 / M_PI * 3600;
743
744 fDriveControlTrackingDevHist.push_back(dev);
745 if (fDriveControlTrackingDevHist.size()>300)
746 fDriveControlTrackingDevHist.pop_front();
747
748 WriteBinary(d, "control-deviation-hist", fDriveControlTrackingDevHist, 120);
749
750 ostringstream out;
751 out << d.GetJavaDate() << '\n';
752
753 out << kHtmlWhite << '\t' << fDriveControlSourceName << '\n';
754 out << setprecision(5);
755 out << kHtmlWhite << '\t' << Ra << '\n';
756 out << kHtmlWhite << '\t' << Dec << '\n';
757 out << setprecision(3);
758 out << kHtmlWhite << '\t' << Zd << '\n';
759 out << kHtmlWhite << '\t' << Az << '\n';
760 out << kHtmlWhite << '\t' << dev << '\n';
761
762 Moon moon(-(17.+53./60+26.525/3600), 28.+45./60+42.462/3600);
763 if (moon.visible)
764 {
765 const double angle = moon.Angle(Ra, Dec);
766
767 string col = kHtmlGreen;
768 if (angle<35 || angle>145)
769 col = kHtmlYellow;
770 if (angle<25 || angle>155)
771 col = kHtmlRed;
772 out << col << '\t' << setprecision(3) << angle << '\n';
773 }
774 else
775 out << kHtmlWhite << "\t&mdash; \n";
776
777 ofstream(fPath+"/tracking.data") << out.str();
778
779 return GetCurrentState();
780 }
781
782 int HandleDriveSource(const EventImp &d)
783 {
784 if (!CheckDataSize(d, "DriveControl:Source", 7*4+2, true))
785 return GetCurrentState();
786
787 const double *ptr = d.Ptr<double>();
788
789 const double ra = ptr[0]; // Ra[h]
790 const double dec = ptr[1]; // Dec[deg]
791 const double woff = ptr[4]; // Wobble offset [deg]
792 const double wang = ptr[5]; // Wobble angle [deg]
793
794 fDriveControlSourceName = d.Ptr<char>(6*8);
795
796 ostringstream out;
797 out << d.GetJavaDate() << '\n';
798
799 out << "#ffffff\t" << fDriveControlSourceName << '\n';
800 out << setprecision(5);
801 out << "#ffffff\t" << ra << '\n';
802 out << "#ffffff\t" << dec << '\n';
803 out << setprecision(3);
804 out << "#ffffff\t" << woff << '\n';
805 out << "#ffffff\t" << wang << '\n';
806
807 ofstream(fPath+"/source.data") << out.str();
808
809 return GetCurrentState();
810 }
811
812 int HandleFeedbackCalibration(const EventImp &d)
813 {
814 if (!CheckDataSize(d, "Feedback:Calibration", 3*4*416))
815 {
816 fFeedbackCalibration.clear();
817 return GetCurrentState();
818 }
819
820 const float *ptr = d.Ptr<float>();
821 fFeedbackCalibration.assign(ptr+2*416, ptr+3*416);
822
823 return GetCurrentState();
824 }
825
826 int HandleFeedbackDeviation(const EventImp &d)
827 {
828 if (!CheckDataSize(d, "Feedback:Deviation", (2*416+2)*4))
829 return GetCurrentState();
830
831 const float *ptr = d.Ptr<float>();
832 vector<float> dev(ptr+416, ptr+416+320);
833
834 fFeedbackTempOffset = ptr[2*416];
835 fFeedbackUserOffset = ptr[2*416+1];
836
837 for (int i=0; i<320; i++)
838 dev[i] -= fFeedbackTempOffset+fFeedbackUserOffset;
839
840 // Write the 160 patch values to a file
841 WriteBinary(d, "feedback-deviation", dev, 1);
842
843 const Statistics stat(dev, 3);
844
845 ostringstream out;
846 out << d.GetJavaDate() << '\n';
847 out << kHtmlWhite << '\t' << fFeedbackUserOffset << '\n';
848 out << setprecision(3);
849 out << kHtmlWhite << '\t' << fFeedbackTempOffset << '\n';
850 out << kHtmlWhite << '\t' << stat.min << '\n';
851 out << kHtmlWhite << '\t' << stat.med << '\n';
852 out << kHtmlWhite << '\t' << stat.avg << '\n';
853 out << kHtmlWhite << '\t' << stat.max << '\n';
854 ofstream(fPath+"/feedback.data") << out.str();
855
856 return GetCurrentState();
857 }
858
859 int HandleBiasVoltage(const EventImp &d)
860 {
861 if (!CheckDataSize(d, "BiasControl:Voltage", 1664))
862 {
863 fBiasControlVoltageVec.clear();
864 return GetCurrentState();
865 }
866
867 fBiasControlVoltageVec.assign(d.Ptr<float>(), d.Ptr<float>()+320);
868
869 const Statistics stat(fBiasControlVoltageVec);
870
871 fBiasControlVoltageMed = stat.med;
872
873 vector<float> val(320, 0);
874 for (int i=0; i<320; i++)
875 {
876 const int idx = (fPixelMap.hv(i).hw()/9)*2+fPixelMap.hv(i).group();
877 val[idx] = fBiasControlVoltageVec[i];
878 }
879
880 if (fDimBiasControl.state()==BIAS::kVoltageOn)
881 WriteBinary(d, "biascontrol-voltage", val, 10, 65);
882 else
883 WriteBinary(d, "biascontrol-voltage", val, 75);
884
885 ostringstream out;
886 out << setprecision(3);
887 out << d.GetJavaDate() << '\n';
888 out << kHtmlWhite << '\t' << stat.min << '\n';
889 out << kHtmlWhite << '\t' << stat.med << '\n';
890 out << kHtmlWhite << '\t' << stat.avg << '\n';
891 out << kHtmlWhite << '\t' << stat.max << '\n';
892 ofstream(fPath+"/voltage.data") << out.str();
893
894 return GetCurrentState();
895 }
896
897 int HandleBiasCurrent(const EventImp &d)
898 {
899 if (!CheckDataSize(d, "BiasControl:Current", 832))
900 return GetCurrentState();
901
902 // Convert dac counts to uA
903 vector<float> v(320);
904 for (int i=0; i<320; i++)
905 v[i] = d.Ptr<uint16_t>()[i] * 5000./4096;
906
907 const bool cal = fFeedbackCalibration.size()>0 && fBiasControlVoltageVec.size()>0;
908
909 double power_tot = 0;
910 double power_apd = 0;
911
912 // 3900 Ohm/n + 1000 Ohm + 1100 Ohm (with n=4 or n=5)
913 const double R[2] = { 3075, 2870 };
914
915 // Calibrate the data (subtract offset)
916 if (cal)
917 for (int i=0; i<320; i++)
918 {
919 // Measued current minus leakage current (bias crate calibration)
920 v[i] -= fBiasControlVoltageVec[i]/fFeedbackCalibration[i]*1e6;
921
922 // Total power participated in the camera at the G-APD
923 // and the serial resistors (total voltage minus voltage
924 // drop at resistors in bias crate)
925 power_tot += v[i]*(fBiasControlVoltageVec[i] - 1100e-6*v[i])*1e-6;
926
927 // Group index (0 or 1) of the of the pixel (4 or 5 pixel patch)
928 const int g = fPixelMap.hv(i).group();
929
930 // Current per G-APD
931 v[i] /= g ? 5 : 4;
932
933 // Power consumption per G-APD
934 if (i!=66 && i!=191 && i!=193)
935 power_apd += v[i]*(fBiasControlVoltageVec[i]-R[g]*v[i]*1e-6)*1e-6;
936 }
937
938 // Divide by number of summed channels, concert to mW
939 power_apd /= 317e-3; // [mW]
940
941 if (power_tot<1e-3)
942 power_tot = 0;
943 if (power_apd<1e-3)
944 power_apd = 0;
945
946 // Get the maximum of each patch
947 vector<float> val(320, 0);
948 for (int i=0; i<320; i++)
949 {
950 const int idx = (fPixelMap.hv(i).hw()/9)*2+fPixelMap.hv(i).group();
951 val[idx] = v[i];
952 }
953
954 // Write the 160 patch values to a file
955 WriteBinary(d, "biascontrol-current", val, 100);
956
957 const Statistics stat(v, 0, 3);
958
959 // Exclude the three crazy channels
960 fBiasControlCurrentMed = stat.med;
961 fBiasControlCurrentMax = stat.max;
962
963 // Store a history of the last 60 entries
964 fBiasControlCurrentHist.push_back(fBiasControlCurrentMed);
965 if (fBiasControlCurrentHist.size()>360)
966 fBiasControlCurrentHist.pop_front();
967
968 // write the history to a file
969 WriteBinary(d, "biascontrol-current-hist", fBiasControlCurrentHist, 100);
970
971 const string col0 = cal ? kHtmlGreen : kHtmlWhite;
972
973 string col1 = col0;
974 string col2 = col0;
975 string col3 = col0;
976 string col4 = col0;
977
978 if (cal && stat.min>65)
979 col1 = kYellow;
980 if (cal && stat.min>80)
981 col1 = kRed;
982
983 if (cal && stat.med>65)
984 col2 = kYellow;
985 if (cal && stat.med>80)
986 col2 = kRed;
987
988 if (cal && stat.avg>65)
989 col3 = kYellow;
990 if (cal && stat.avg>80)
991 col3 = kRed;
992
993 if (cal && stat.max>65)
994 col4 = kYellow;
995 if (cal && stat.max>80)
996 col4 = kRed;
997
998 ostringstream out;
999 out << setprecision(2);
1000 out << d.GetJavaDate() << '\n';
1001 out << col0 << '\t' << (cal?"yes":"no") << '\n';
1002 out << col1 << '\t' << stat.min << '\n';
1003 out << col2 << '\t' << stat.med << '\n';
1004 out << col3 << '\t' << stat.avg << '\n';
1005 out << col4 << '\t' << stat.max << '\n';
1006 out << kHtmlWhite << '\t' << power_tot << "W [" << power_apd << "mW]\n";
1007 ofstream(fPath+"/current.data") << out.str();
1008
1009 return GetCurrentState();
1010 }
1011
1012 int HandleFadEvents(const EventImp &d)
1013 {
1014 if (!CheckDataSize(d, "FadControl:Events", 4*4))
1015 {
1016 fFadControlNumEvents = -1;
1017 return GetCurrentState();
1018 }
1019
1020 fFadControlNumEvents = d.Get<uint32_t>();
1021
1022 return GetCurrentState();
1023 }
1024
1025 int HandleFadConnections(const EventImp &d)
1026 {
1027 if (!CheckDataSize(d, "FadControl:Connections", 41))
1028 {
1029 //fStatusEventBuilderLabel->setText("Offline");
1030 return GetCurrentState();
1031 }
1032
1033 string rc(40, '-'); // orange/red [45]
1034
1035 const uint8_t *ptr = d.Ptr<uint8_t>();
1036
1037 int c[4] = { '.', '.', '.', '.' };
1038
1039 for (int i=0; i<40; i++)
1040 {
1041 const uint8_t stat1 = ptr[i]&3;
1042 const uint8_t stat2 = ptr[i]>>3;
1043
1044 if (stat1==0 && stat2==0)
1045 rc[i] = '.'; // gray [46]
1046 else
1047 if (stat1>=2 && stat2==8)
1048 rc[i] = stat1==2?'+':'*'; // green [43] : check [42]
1049
1050 if (rc[i]<c[i/10])
1051 c[i/10] = rc[i];
1052 }
1053
1054 string col[4];
1055 for (int i=0; i<4; i++)
1056 switch (c[i])
1057 {
1058 case '.': col[i]=kHtmlWhite; break;
1059 case '-': col[i]=kHtmlRed; break;
1060 case '+': col[i]=kHtmlYellow; break;
1061 case '*': col[i]=kHtmlGreen; break;
1062 }
1063
1064 ostringstream out;
1065 out << setprecision(3);
1066 out << d.GetJavaDate() << '\n';
1067 out << col[0] << '\t' << rc.substr( 0, 10) << '\n';
1068 out << col[1] << '\t' << rc.substr(10, 10) << '\n';
1069 out << col[2] << '\t' << rc.substr(20, 10) << '\n';
1070 out << col[3] << '\t' << rc.substr(30, 10) << '\n';
1071 ofstream(fPath+"/fad.data") << out.str();
1072
1073 return GetCurrentState();
1074 }
1075
1076 int HandleFtmTriggerRates(const EventImp &d)
1077 {
1078 if (!CheckDataSize(d, "FtmControl:TriggerRates", 24+160+640+8))
1079 return GetCurrentState();
1080
1081 // New run started
1082 if (d.Get<float>(20)<0)
1083 return GetCurrentState();
1084
1085 fFtmControlTriggerRateCam = d.Get<float>(20);
1086
1087 const float *brates = d.Ptr<float>(24); // Board rate
1088 const float *prates = d.Ptr<float>(24+160); // Patch rate
1089
1090 // Store a history of the last 60 entries
1091 fFtmControlTriggerRateHist.push_back(fFtmControlTriggerRateCam);
1092 if (fFtmControlTriggerRateHist.size()>60)
1093 fFtmControlTriggerRateHist.pop_front();
1094
1095 // FIXME: Add statistics for all kind of rates
1096
1097 WriteBinary(d, "ftmcontrol-triggerrate-hist",
1098 fFtmControlTriggerRateHist, 100);
1099 WriteBinary(d, "ftmcontrol-boardrates",
1100 vector<float>(brates, brates+40), 10);
1101 WriteBinary(d, "ftmcontrol-patchrates",
1102 vector<float>(prates, prates+160), 10);
1103
1104 ostringstream out;
1105 out << setprecision(3);
1106 out << d.GetJavaDate() << '\n';
1107 out << "#ffffff\t" << fFtmControlTriggerRateCam << '\n';
1108
1109 ofstream(fPath+"/trigger.data") << out.str();
1110
1111 const Statistics bstat(vector<float>(brates, brates+40));
1112 const Statistics pstat(vector<float>(prates, prates+160));
1113
1114 out.str("");
1115 out << d.GetJavaDate() << '\n';
1116 out << kHtmlWhite << '\t' << bstat.min << '\n';
1117 out << kHtmlWhite << '\t' << bstat.med << '\n';
1118 out << kHtmlWhite << '\t' << bstat.avg << '\n';
1119 out << kHtmlWhite << '\t' << bstat.max << '\n';
1120 ofstream(fPath+"/boardrates.data") << out.str();
1121
1122 out.str("");
1123 out << d.GetJavaDate() << '\n';
1124 out << kHtmlWhite << '\t' << pstat.min << '\n';
1125 out << kHtmlWhite << '\t' << pstat.med << '\n';
1126 out << kHtmlWhite << '\t' << pstat.avg << '\n';
1127 out << kHtmlWhite << '\t' << pstat.max << '\n';
1128 ofstream(fPath+"/patchrates.data") << out.str();
1129
1130 return GetCurrentState();
1131 }
1132
1133 int HandleFtmStaticData(const EventImp &d)
1134 {
1135 if (!CheckDataSize(d, "FtmControl:StaticData", sizeof(FTM::DimStaticData)))
1136 return GetCurrentState();
1137
1138 const FTM::DimStaticData &dat = d.Ref<FTM::DimStaticData>();
1139
1140 vector<uint16_t> vecp(dat.fThreshold, dat.fThreshold+160);
1141 vector<uint16_t> vecb(dat.fMultiplicity, dat.fMultiplicity+40);
1142
1143 WriteBinary(d, "ftmcontrol-thresholds-patch", vecp, 1000);
1144 WriteBinary(d, "ftmcontrol-thresholds-board", vecb, 1000);
1145
1146 const Statistics statp(vecp);
1147 const Statistics statb(vecb);
1148
1149 fFtmPatchThresholdMed = statp.med;
1150 fFtmBoardThresholdMed = statb.med;
1151
1152 ostringstream out;
1153 out << d.GetJavaDate() << '\n';
1154 out << kHtmlWhite << '\t' << statb.min << '\n';
1155 out << kHtmlWhite << '\t' << statb.med << '\n';
1156 //out << kHtmlWhite << '\t' << statb.avg << '\n';
1157 out << kHtmlWhite << '\t' << statb.max << '\n';
1158 out << kHtmlWhite << '\t' << statp.min << '\n';
1159 out << kHtmlWhite << '\t' << statp.med << '\n';
1160 //out << kHtmlWhite << '\t' << statp.avg << '\n';
1161 out << kHtmlWhite << '\t' << statp.max << '\n';
1162 ofstream(fPath+"/thresholds.data") << out.str();
1163
1164 out.str("");
1165 out << d.GetJavaDate() << '\n';
1166 out << kHtmlWhite << '\t' << dat.fTriggerInterval << '\n';
1167 out << kHtmlWhite << '\t';
1168 if (dat.HasPedestal())
1169 out << dat.fTriggerSeqPed;
1170 else
1171 out << "&ndash;";
1172 out << ':';
1173 if (dat.HasLPext())
1174 out << dat.fTriggerSeqLPext;
1175 else
1176 out << "&ndash;";
1177 out << ':';
1178 if (dat.HasLPint())
1179 out << dat.fTriggerSeqLPint;
1180 else
1181 out << "&ndash;";
1182 out << '\n';
1183
1184 out << kHtmlWhite << '\t' << (dat.HasTrigger()?"on":"off") << " / " << (dat.HasExt1()?"on":"off") << " / " << (dat.HasExt2()?"on":"off") << '\n';
1185 out << kHtmlWhite << '\t' << (dat.HasVeto()?"on":"off") << " / " << (dat.HasClockConditioner()?"time cal":"marker") << '\n';
1186 out << kHtmlWhite << '\t' << dat.fMultiplicityPhysics << " / " << dat.fMultiplicityCalib << '\n';
1187 out << kHtmlWhite << '\t' << dat.fWindowPhysics << '\t' << dat.fWindowCalib << '\n';
1188 out << kHtmlWhite << '\t' << dat.fDelayTrigger << '\t' << dat.fDelayTimeMarker << '\n';
1189 out << kHtmlWhite << '\t' << dat.fDeadTime << '\n';
1190
1191 int64_t vp = dat.fPrescaling[0];
1192 for (int i=1; i<40; i++)
1193 if (vp!=dat.fPrescaling[i])
1194 vp = -1;
1195
1196 if (vp<0)
1197 out << kHtmlYellow << "\tdifferent\n";
1198 else
1199 out << kHtmlWhite << "\t" << 0.5*vp << "\n";
1200
1201 ofstream(fPath+"/ftm.data") << out.str();
1202
1203 // Active FTUs: IsActive(i)
1204 // Enabled Pix: IsEnabled(i)
1205
1206 return GetCurrentState();
1207 }
1208
1209 int HandleFtmFtuList(const EventImp &d)
1210 {
1211 if (!CheckDataSize(d, "FtmControl:FtuList", sizeof(FTM::DimFtuList)))
1212 return GetCurrentState();
1213
1214 const FTM::DimFtuList &sdata = d.Ref<FTM::DimFtuList>();
1215
1216 ostringstream out;
1217 out << d.GetJavaDate() << '\n';
1218
1219 int cnt = 0;
1220 for (int i=0; i<4; i++)
1221 {
1222 out << kHtmlWhite << '\t';
1223 for (int j=0; j<10; j++)
1224 if (sdata.IsActive(i*10+j))
1225 {
1226 if (sdata.fPing[i*10+j]==1)
1227 {
1228 out << '*';
1229 cnt++;
1230 }
1231 else
1232 out << sdata.fPing[i*10+j];
1233 }
1234 else
1235 out << '-';
1236 out << '\n';
1237 }
1238
1239 fFtmControlFtuOk = cnt==40;
1240
1241 ofstream(fPath+"/ftu.data") << out.str();
1242
1243 return GetCurrentState();
1244 }
1245
1246 int HandleFadEventData(const EventImp &d)
1247 {
1248 if (!CheckDataSize(d, "FadControl:EventData", 23040))
1249 return GetCurrentState();
1250
1251 //const float *avg = d.Ptr<float>();
1252 //const float *rms = d.Ptr<float>(1440*sizeof(float));
1253 const float *dat = d.Ptr<float>(1440*sizeof(float)*2);
1254 //const float *pos = d.Ptr<float>(1440*sizeof(float)*3);
1255
1256 vector<float> max(320, -2);
1257 for (int i=0; i<1440; i++)
1258 {
1259 if (i%9==8)
1260 continue;
1261
1262 const int idx = (fPixelMap.hw(i).hw()/9)*2+fPixelMap.hw(i).group();
1263 const double v = dat[i]/1000;
1264 if (v>max[idx])
1265 max[idx]=v;
1266 }
1267
1268 switch (d.GetQoS())
1269 {
1270 case 0: WriteBinary(d, "fadcontrol-eventdata", max, 2, -1); break;
1271 case 1: WriteBinary(d, "fadcontrol-eventdata", max, 2, 0); break;
1272 default: WriteBinary(d, "fadcontrol-eventdata", max, 0.25, 0); break;
1273 }
1274
1275 return GetCurrentState();
1276 }
1277
1278 int HandleFscTemperature(const EventImp &d)
1279 {
1280 if (!CheckDataSize(d, "FscControl:Temperature", 240))
1281 return GetCurrentState();
1282
1283 const float *ptr = d.Ptr<float>(4);
1284
1285 double avg = 0;
1286 double rms = 0;
1287 double min = 99;
1288 double max = -99;
1289
1290 int num = 0;
1291 for (const float *t=ptr; t<ptr+31; t++)
1292 {
1293 if (*t==0)
1294 continue;
1295
1296 if (*t>max)
1297 max = *t;
1298
1299 if (*t<min)
1300 min = *t;
1301
1302 avg += *t;
1303 rms += *t * *t;
1304
1305 num++;
1306 }
1307
1308 avg /= num;
1309 rms = sqrt(rms/num-avg*avg);
1310
1311 if (fMagicWeatherHist[kTemp].size()>0)
1312 {
1313 fFscControlTemperatureHist.push_back(avg-fMagicWeatherHist[kTemp].back());
1314 if (fFscControlTemperatureHist.size()>300)
1315 fFscControlTemperatureHist.pop_front();
1316 }
1317
1318 const Statistics stat(fFscControlTemperatureHist);
1319
1320 ostringstream out;
1321 out << setprecision(3);
1322 out << d.GetJavaDate() << '\n';
1323 out << "#ffffff\t" << fFscControlHumidityAvg << '\n';
1324 out << "#ffffff\t" << min << '\n';
1325 out << "#ffffff\t" << avg << '\n';
1326 out << "#ffffff\t" << max << '\n';
1327 out << "#ffffff\t" << stat.min << '\n';
1328 out << "#ffffff\t" << stat.avg << '\n';
1329 out << "#ffffff\t" << stat.max << '\n';
1330
1331 ofstream(fPath+"/fsc.data") << out.str();
1332
1333 WriteBinary(d, "fsccontrol-temperature-hist",
1334 fFscControlTemperatureHist, 10);
1335
1336 return GetCurrentState();
1337 }
1338
1339 int HandleFscHumidity(const EventImp &d)
1340 {
1341 if (!CheckDataSize(d, "FscControl:Humidity", 5*4))
1342 return GetCurrentState();
1343
1344 const float *ptr = d.Ptr<float>(4);
1345
1346 double avg = 0;
1347 int num = 0;
1348
1349 for (const float *t=ptr; t<ptr+4; t++)
1350 if (*t>0)
1351 {
1352 avg += *t;
1353 num++;
1354 }
1355
1356 fFscControlHumidityAvg = avg/num;
1357
1358 return GetCurrentState();
1359 }
1360
1361 int HandleRateScanData(const EventImp &d)
1362 {
1363 if (!CheckDataSize(d, "RateScan:Data", 824))
1364 return GetCurrentState();
1365
1366 const uint64_t id = d.Get<uint64_t>();
1367 const float *rate = d.Ptr<float>(20);
1368
1369 if (fRateScanDataId!=id)
1370 {
1371 for (int i=0; i<41; i++)
1372 fRateScanDataHist[i].clear();
1373 fRateScanDataId = id;
1374 }
1375 fRateScanDataHist[0].push_back(log10(rate[0]));
1376
1377 double max = 0;
1378 for (int i=1; i<41; i++)
1379 {
1380 fRateScanDataHist[i].push_back(log10(rate[i]));
1381 if (rate[i]>max)
1382 max = rate[i];
1383 }
1384
1385 // Cycle by time!
1386 fRateScanBoard ++;
1387 fRateScanBoard %= 40;
1388
1389 WriteBinary(d, "ratescan-hist", fRateScanDataHist[0], 10, -2);
1390 WriteBinary(d, "ratescan-board", fRateScanDataHist[fRateScanBoard+1], 10, -4);
1391
1392 ostringstream out;
1393 out << setprecision(3);
1394 out << d.GetJavaDate() << '\n';
1395 out << "#ffffff\t" << fFtmBoardThresholdMed << '\n';
1396 out << "#ffffff\t" << fFtmPatchThresholdMed << '\n';
1397 out << "#ffffff\t" << pow(10, fRateScanDataHist[0].back()) << '\n';
1398 out << "#ffffff\t" << max << '\n';
1399
1400 ofstream(fPath+"/ratescan.data") << out.str();
1401
1402 out.str("");
1403 out << d.GetJavaDate() << '\n';
1404 out << "#ffffff\t" << int(fRateScanBoard) << '\n';
1405 out << "#ffffff\t" << pow(10, fRateScanDataHist[fRateScanBoard+1].back()) << '\n';
1406
1407 ofstream(fPath+"/ratescan_board.data") << out.str();
1408
1409 return GetCurrentState();
1410 }
1411
1412 // -------------------------------------------------------------------
1413
1414 void HandleDoTest(const EventImp &d)
1415 {
1416 ostringstream out;
1417 out << d.GetJavaDate() << '\t' << fHasError << '\n';
1418 switch (d.GetQoS())
1419 {
1420 case -3: out << kHtmlWhite << "\tNot running\n"; break;
1421 case -2: out << kHtmlBlue << "\tLoading\n"; break;
1422 case -1: out << kHtmlBlue << "\tStarted\n"; break;
1423 default: out << kHtmlGreen << "\tRunning [" << d.GetQoS() << "]\n"; break;
1424 }
1425
1426 ofstream(fPath+"/dotest.data") << out.str();
1427 }
1428
1429 // -------------------------------------------------------------------
1430
1431 bool CheckEventSize(size_t has, const char *name, size_t size)
1432 {
1433 if (has==size)
1434 return true;
1435
1436 ostringstream msg;
1437 msg << name << " - Received event has " << has << " bytes, but expected " << size << ".";
1438 Fatal(msg);
1439 return false;
1440 }
1441
1442 int Print() const
1443 {
1444 Out() << fDimDNS << endl;
1445 Out() << fDimMcp << endl;
1446 Out() << fDimControl << endl;
1447 Out() << fDimDataLogger << endl;
1448 Out() << fDimDriveControl << endl;
1449 Out() << fDimFadControl << endl;
1450 Out() << fDimFtmControl << endl;
1451 Out() << fDimBiasControl << endl;
1452 Out() << fDimFeedback << endl;
1453 Out() << fDimRateControl << endl;
1454 Out() << fDimFscControl << endl;
1455 Out() << fDimMagicWeather << endl;
1456 Out() << fDimTngWeather << endl;
1457 Out() << fDimRateScan << endl;
1458 Out() << fDimChatServer << endl;
1459
1460 return GetCurrentState();
1461 }
1462
1463 string GetStateHtml(const DimState &state, int green) const
1464 {
1465 if (!state.online())
1466 return kHtmlWhite+"\t&mdash;\n";
1467
1468 if (&state==&fDimControl)
1469 return kHtmlGreen +'\t'+(state.state()==-3?"Idle":fDimControl.shortmsg)+'\n';
1470
1471 const State rc = state.description();
1472
1473 // Sate not found in list, server online (-3: offline; -2: not found)
1474 if (rc.index==-2)
1475 {
1476 ostringstream out;
1477 out << kHtmlWhite << '\t' << state.state() << '\n';
1478 return out.str();
1479 }
1480
1481 //ostringstream msg;
1482 //msg << kHtmlWhite << '\t' << rc.name << " [" << rc.index << "]\n";
1483 //return msg.str();
1484
1485 if (rc.index<1)
1486 return kHtmlWhite + "\t&mdash;\n";
1487
1488
1489 return (rc.index<green?kHtmlYellow:kHtmlGreen) + '\t' + rc.name + '\n';
1490 }
1491
1492 int Execute()
1493 {
1494 // Dispatch (execute) at most one handler from the queue. In contrary
1495 // to run_one(), it doesn't wait until a handler is available
1496 // which can be dispatched, so poll_one() might return with 0
1497 // handlers dispatched. The handlers are always dispatched/executed
1498 // synchronously, i.e. within the call to poll_one()
1499 //poll_one();
1500
1501 Time now;
1502 if (now-fLastUpdate<boost::posix_time::seconds(1))
1503 return kStateRunning;
1504
1505 fLastUpdate=now;
1506
1507 // ==============================================================
1508
1509 ostringstream msg;
1510
1511 if (fHasError==2)
1512 msg << "SmartFACT backend initializing." << endl;
1513 if (!fDimDNS.online())
1514 msg << "DIM network not available.<br/>";
1515 if (fDimDriveControl.state()>0xff)
1516 msg << "Drive in ERROR state<br/>";
1517 if (fDimBiasControl.state()<BIAS::kRamping && (fDimMcp.state()==11 || fDimMcp.state()==12))
1518 msg << "BIAS not operating during data-taking<br/>";
1519 if (fDimBiasControl.state()==BIAS::kOverCurrent)
1520 msg << "BIAS channels in OverCurrent<br/>";
1521 if (fDimBiasControl.state()==BIAS::kNotReferenced)
1522 msg << "BIAS voltage not at reference<br/>";
1523 if (fBiasControlCurrentMed>75)
1524 msg << "Median current exceeds 75&micro;A/pix<br/>";
1525 if (fBiasControlCurrentMax>90)
1526 msg << "Maximum current exceeds 90&micro;A/pix<br/>";
1527 if (fMagicWeatherHist[kHum].size()>0 && fMagicWeatherHist[kHum].back()>98 && (fDimMcp.state()==11 || fDimMcp.state()==12))
1528 msg << "Outside humidity exceeds 98% during data-taking<br/>";
1529 if (fMagicWeatherHist[kGusts].size()>0 && fMagicWeatherHist[kGusts].back()>98 && fDimDriveControl.state()==7)
1530 msg << "Wind gusts exceed 50km/h during tracking<br/>";
1531 if (fFscControlTemperatureHist.size()>0 && fFscControlTemperatureHist.back()>7)
1532 msg << "Sensor temperature exceeds outside temperature by more than 7&deg;C<br/>";
1533 if (fFtmControlTriggerRateCam<0.01 && (fDimMcp.state()==11 || fDimMcp.state()==12))
1534 msg << "Trigger rate below 10mHz during data taking<br/>";
1535 if (fFscControlHumidityAvg>60)
1536 msg << "Average camera humidity exceed 60%<br/>";
1537 if (!fDimControl.online())
1538 msg << "dimctrl offline<br/>";
1539
1540 // FTM in Connected instead of Idle --> power cyclen
1541
1542 /* // Check offline and disconnected status?
1543 Out() << fDimMcp << endl;
1544 Out() << fDimControl << endl;
1545 Out() << fDimDataLogger << endl;
1546 Out() << fDimDriveControl << endl;
1547 Out() << fDimFadControl << endl;
1548 Out() << fDimFtmControl << endl;
1549 Out() << fDimBiasControl << endl;
1550 Out() << fDimFeedback << endl;
1551 Out() << fDimRateControl << endl;
1552 Out() << fDimFscControl << endl;
1553 Out() << fDimMagicWeather << endl;
1554 Out() << fDimRateScan << endl;
1555 Out() << fDimChatServer << endl;
1556 */
1557
1558 // FTU in error
1559 // FAD lost
1560
1561 // --------------------------------------------------------------
1562
1563 const bool haserror = msg.str().size()>0;
1564
1565 ostringstream out;
1566 out << now.JavaDate() << '\t' << haserror << '\t' << (fDimControl.state()>-3) << '\n';
1567 out << setprecision(3);
1568 out << kHtmlWhite << '\t' << msg.str() << '\n';
1569
1570 if (haserror || fHasError)
1571 ofstream(fPath+"/error.data") << out.str();
1572
1573 fHasError = haserror;
1574
1575 if (!fDimDNS.online())
1576 return kStateDimNetworkNA;
1577
1578 // ==============================================================
1579
1580 out.str("");
1581 out << now.JavaDate() << '\t' << fHasError << '\t' << (fDimControl.state()>-3) << '\n';
1582 out << setprecision(3);
1583
1584 // -------------- System status --------------
1585 if (fDimMcp.state()>=5) // Idle
1586 {
1587 string col = kHtmlBlue;
1588 if (fMcpConfigurationState!= 5 && // Idle
1589 fMcpConfigurationState!=11 && // Trigger On
1590 fMcpConfigurationState!=12) // Taking Data
1591 col = kHtmlYellow;
1592 else
1593 if (fDimFadControl.state()==FAD::kWritingData)
1594 col = kHtmlGreen;
1595
1596 out << col << '\t';
1597
1598 if (fDimRateControl.state()!=5 && fDimRateScan.state()!=6)
1599 {
1600 switch (fMcpConfigurationState)
1601 {
1602 // kStateIdle
1603 case 5: out << "Idle [" << fMcpConfigurationName << "]"; break;
1604 // Configuring1 - Configuring3
1605 case 7:
1606 case 8:
1607 case 9: out << "Configuring [" << fMcpConfigurationName << "]"; break;
1608 // Configured
1609 case 10: out << "Configured [" << fMcpConfigurationName << "]"; break;
1610 // TriggerOn / Taking Data
1611 case 11:
1612 case 12: out << fMcpConfigurationName; break;
1613 }
1614 }
1615 else
1616 if (fDimRateControl.state()==5/*kStateSettingGlobalThreshold*/)
1617 out << "Calibrating threshold";
1618 else
1619 if (fDimRateScan.state()==6/*kStateSettingGlobalThreshold*/)
1620 out << "Rate scan in progress";
1621
1622 if (fMcpConfigurationState>10 && fDimRateControl.state()!=5)
1623 {
1624 if (fMcpConfigurationMaxEvents>0 || fMcpConfigurationMaxTime>0 || fMcpConfigurationState==12)
1625 out << " [";
1626 if (fMcpConfigurationMaxEvents>0)
1627 {
1628 if (fFadControlNumEvents>0 && fMcpConfigurationState==12)
1629 out << fMcpConfigurationMaxEvents-fFadControlNumEvents;
1630 else
1631 out << fMcpConfigurationMaxEvents;
1632 }
1633 if (fMcpConfigurationMaxEvents>0 && (fMcpConfigurationMaxTime>0 || fMcpConfigurationState==12))
1634 out << '/';
1635 if (fMcpConfigurationMaxTime>0)
1636 {
1637 if (fMcpConfigurationState==12)
1638 {
1639
1640 const uint32_t dt = (Time()-fMcpConfigurationRunStart).total_seconds();
1641 if (dt>fMcpConfigurationMaxTime)
1642 out << "---";
1643 else
1644 out << fMcpConfigurationMaxTime-dt << 's';
1645 }
1646 else
1647 out << fMcpConfigurationMaxTime << 's';
1648 }
1649 else
1650 {
1651 if (fMcpConfigurationState==12)
1652 {
1653 ostringstream d;
1654 d << Time()-fMcpConfigurationRunStart;
1655 out << d.str().substr(3, 5);
1656 }
1657 }
1658
1659 if (fMcpConfigurationMaxEvents>0 || fMcpConfigurationMaxTime>0 || fMcpConfigurationState==12)
1660 out << ']';
1661 }
1662 }
1663 else
1664 out << kHtmlWhite;
1665 out << '\n';
1666
1667 // ------------------ Drive -----------------
1668 if (fDimDriveControl.state()>=5) // Armed, Moving, Tracking
1669 {
1670 const double dev = fDriveControlTrackingDevHist.size()>0 ? fDriveControlTrackingDevHist.back() : 0;
1671 const State rc = fDimDriveControl.description();
1672 string col = kHtmlGreen;
1673 if (rc.index==6) // Moving
1674 col = kHtmlBlue;
1675 if (rc.index==5) // Armed
1676 col = kHtmlWhite;
1677 if (rc.index==7) // Tracking
1678 {
1679 if (dev>60) // ~1.5mm
1680 col = kHtmlYellow;
1681 if (dev>100) // ~1/4 of a pixel ~ 2.5mm
1682 col = kHtmlRed;
1683 }
1684 out << col << '\t';
1685
1686 //out << rc.name << '\t';
1687 out << fDriveControlPointingZd << '\t';
1688 out << fDriveControlPointingAz << '\t';
1689 if (fDimDriveControl.state()==7)
1690 {
1691 out << fDriveControlSourceName << '\t';
1692 out << setprecision(2);
1693 out << dev << '\n';
1694 out << setprecision(3);
1695 }
1696 else
1697 out << "\t\n";
1698 }
1699 else
1700 out << kHtmlWhite << '\n';
1701
1702 // ------------------- FSC ------------------
1703 if (fDimFscControl.state()>1 && fFscControlTemperatureHist.size()>0)
1704 {
1705 out << kHtmlGreen << '\t' << fFscControlTemperatureHist.back() << '\n';
1706 }
1707 else
1708 out << kHtmlWhite << '\n';
1709
1710 // --------------- MagicWeather -------------
1711 if (fDimMagicWeather.state()==3 && fMagicWeatherHist[kWeatherBegin].size()>0)
1712 {
1713 /*
1714 const float diff = fMagicWeatherHist[kTemp].back()-fMagicWeatherHist[kDew].back();
1715 string col1 = kHtmlRed;
1716 if (diff>0.3)
1717 col1 = kHtmlYellow;
1718 if (diff>0.7)
1719 col1 = kHtmlGreen;
1720 */
1721
1722 const float wind = fMagicWeatherHist[kGusts].back();
1723 const float hum = fMagicWeatherHist[kHum].back();
1724 string col = kHtmlGreen;
1725 if (wind>35 || hum>95)
1726 col = kHtmlYellow;
1727 if (wind>50 || hum>98)
1728 col = kHtmlRed;
1729
1730 out << col << '\t';
1731 out << fMagicWeatherHist[kHum].back() << '\t';
1732 out << setprecision(2);
1733 out << fMagicWeatherHist[kGusts].back() << '\n';
1734 out << setprecision(3);
1735 }
1736 else
1737 out << kHtmlWhite << "\n";
1738
1739 // --------------- FtmControl -------------
1740 if (fDimFtmControl.state()==FTM::kTriggerOn)
1741 {
1742 string col = kHtmlGreen;
1743 if (fFtmControlTriggerRateCam<15)
1744 col = kHtmlYellow;
1745 if (fFtmControlTriggerRateCam>100)
1746 col = kHtmlRed;
1747
1748 out << col << '\t' << fFtmControlTriggerRateCam << '\n';
1749 }
1750 else
1751 out << kHtmlWhite << '\n';
1752
1753 // --------------- BiasControl -------------
1754 if (fDimBiasControl.state()==BIAS::kRamping ||
1755 fDimBiasControl.state()==BIAS::kOverCurrent ||
1756 fDimBiasControl.state()==BIAS::kVoltageOn ||
1757 fDimBiasControl.state()==BIAS::kVoltageOff)
1758 {
1759 const bool off = fDimBiasControl.state()==BIAS::kVoltageOff;
1760 const bool oc = fDimBiasControl.state()==BIAS::kOverCurrent;
1761
1762 string col = fBiasControlVoltageMed>3?kHtmlGreen:kHtmlWhite;
1763 if (fBiasControlCurrentMax>65)
1764 col = kHtmlYellow;
1765 if (fBiasControlCurrentMax>80)
1766 col = kHtmlRed;
1767
1768 // Bias in overcurrent => Red
1769 if (fDimBiasControl.state()==BIAS::kOverCurrent)
1770 col = kHtmlRed;
1771
1772 // MCP in ReadyForDatataking/Configuring/Configured/TriggerOn/TakingData
1773 // and Bias not in "data-taking state' => Red
1774 if (fMcpConfigurationState>5 &&
1775 fDimBiasControl.state()!=BIAS::kVoltageOn &&
1776 fDimBiasControl.state()!=BIAS::kVoltageOff)
1777 col = kHtmlRed;
1778
1779 const bool cal = fFeedbackCalibration.size();
1780
1781 // Feedback is currently calibrating => Blue
1782 if (fDimFeedback.state()==13)
1783 {
1784 out << kHtmlBlue << '\t';
1785 out << "***\t";
1786 out << "***\t";
1787 }
1788 else
1789 {
1790 out << setprecision(2);
1791 out << col << '\t';
1792 out << (off ? 0 : fBiasControlCurrentMed) << '\t';
1793 if (oc)
1794 out << "(OC) ";
1795 else
1796 {
1797 if (cal)
1798 out << (off ? 0 : fBiasControlCurrentMax);
1799 else
1800 out << "&mdash; ";
1801 }
1802 out << '\t';
1803 out << setprecision(3);
1804 }
1805 out << (off ? 0 : fBiasControlVoltageMed) << '\n';
1806 }
1807 else
1808 out << kHtmlWhite << '\n';
1809
1810 ofstream(fPath+"/fact.data") << out.str();
1811
1812 // ==============================================================
1813
1814 out.str("");
1815 out << now.JavaDate() << '\t' << fHasError << '\t' << (fDimControl.state()>-3) << '\n';
1816
1817 if (!fDimDNS.online())
1818 out << kHtmlWhite << "\tOffline\n\n\n\n\n\n\n\n\n\n\n\n\n";
1819 else
1820 {
1821 ostringstream dt;
1822 dt << (Time()-fRunTime);
1823
1824 out << kHtmlGreen << '\t' << fDimDNS.version() << '\n';
1825
1826 out << GetStateHtml(fDimControl, 0);
1827 out << GetStateHtml(fDimMcp, 4);
1828 out << GetStateHtml(fDimDataLogger, 1);
1829 out << GetStateHtml(fDimDriveControl, 2);
1830 out << GetStateHtml(fDimFadControl, FAD::kConnected);
1831 out << GetStateHtml(fDimFtmControl, FTM::kConnected);
1832 out << GetStateHtml(fDimBiasControl, BIAS::kConnected);
1833 out << GetStateHtml(fDimFeedback, 4);
1834 out << GetStateHtml(fDimRateControl, 4);
1835 out << GetStateHtml(fDimFscControl, 2);
1836 out << GetStateHtml(fDimMagicWeather, 2);
1837 out << GetStateHtml(fDimTngWeather, 2);
1838 out << GetStateHtml(fDimRateScan, 4);
1839 out << GetStateHtml(fDimChatServer, 1);
1840
1841 out << kHtmlGreen << '\t' << dt.str().substr(0, dt.str().length()-7) << '\n';
1842 }
1843
1844 ofstream(fPath+"/status.data") << out.str();
1845
1846 return kStateRunning;
1847 }
1848
1849
1850public:
1851 StateMachineSmartFACT(ostream &out=cout) : StateMachineDim(out, "SMART_FACT"),
1852 fPath("www/smartfact/data"),
1853 fControlScriptDepth(0),
1854 fMcpConfigurationMaxTime(0),
1855 fMcpConfigurationMaxEvents(0),
1856 fTngWeatherDustTime(Time::none),
1857 fBiasControlVoltageMed(0),
1858 fBiasControlCurrentMed(0),
1859 fBiasControlCurrentMax(0),
1860 fFscControlHumidityAvg(0),
1861 fFtmControlTriggerRateCam(0),
1862 fRateScanDataId(0),
1863 fRateScanBoard(0),
1864 fHasError(2),
1865 // ---
1866 fDimMcp ("MCP"),
1867 fDimDataLogger ("DATA_LOGGER"),
1868 fDimDriveControl("DRIVE_CONTROL"),
1869 fDimMagicWeather("MAGIC_WEATHER"),
1870 fDimTngWeather ("TNG_WEATHER"),
1871 fDimFeedback ("FEEDBACK"),
1872 fDimBiasControl ("BIAS_CONTROL"),
1873 fDimFtmControl ("FTM_CONTROL"),
1874 fDimFadControl ("FAD_CONTROL"),
1875 fDimFscControl ("FSC_CONTROL"),
1876 fDimRateControl ("RATE_CONTROL"),
1877 fDimRateScan ("RATE_SCAN"),
1878 fDimChatServer ("CHAT_SERVER")
1879 {
1880 fDimDNS.Subscribe(*this);
1881 fDimControl.Subscribe(*this);
1882 fDimMcp.Subscribe(*this);
1883 fDimDataLogger.Subscribe(*this);
1884 fDimDriveControl.Subscribe(*this);
1885 fDimMagicWeather.Subscribe(*this);
1886 fDimTngWeather.Subscribe(*this);
1887 fDimFeedback.Subscribe(*this);
1888 fDimBiasControl.Subscribe(*this);
1889 fDimFtmControl.Subscribe(*this);
1890 fDimFadControl.Subscribe(*this);
1891 fDimFscControl.Subscribe(*this);
1892 fDimRateControl.Subscribe(*this);
1893 fDimRateScan.Subscribe(*this);
1894 fDimChatServer.Subscribe(*this);
1895
1896 fDimControl.SetCallback(bind(&StateMachineSmartFACT::HandleControlStateChange, this, placeholders::_1));
1897 fDimControl.AddCallback("dotest.dim", bind(&StateMachineSmartFACT::HandleDoTest, this, placeholders::_1));
1898
1899 Subscribe("DIM_CONTROL/MESSAGE")
1900 (bind(&StateMachineSmartFACT::HandleDimControlMessage, this, placeholders::_1));
1901
1902 Subscribe("MCP/CONFIGURATION")
1903 (bind(&StateMachineSmartFACT::HandleMcpConfiguration, this, placeholders::_1));
1904
1905 Subscribe("DRIVE_CONTROL/POINTING_POSITION")
1906 (bind(&StateMachineSmartFACT::HandleDrivePointing, this, placeholders::_1));
1907 Subscribe("DRIVE_CONTROL/TRACKING_POSITION")
1908 (bind(&StateMachineSmartFACT::HandleDriveTracking, this, placeholders::_1));
1909 Subscribe("DRIVE_CONTROL/SOURCE_POSITION")
1910 (bind(&StateMachineSmartFACT::HandleDriveSource, this, placeholders::_1));
1911
1912 Subscribe("FSC_CONTROL/TEMPERATURE")
1913 (bind(&StateMachineSmartFACT::HandleFscTemperature, this, placeholders::_1));
1914 Subscribe("FSC_CONTROL/HUMIDITY")
1915 (bind(&StateMachineSmartFACT::HandleFscHumidity, this, placeholders::_1));
1916
1917 Subscribe("MAGIC_WEATHER/DATA")
1918 (bind(&StateMachineSmartFACT::HandleMagicWeatherData, this, placeholders::_1));
1919 Subscribe("TNG_WEATHER/DUST")
1920 (bind(&StateMachineSmartFACT::HandleTngWeatherDust, this, placeholders::_1));
1921
1922 Subscribe("FEEDBACK/DEVIATION")
1923 (bind(&StateMachineSmartFACT::HandleFeedbackDeviation, this, placeholders::_1));
1924 Subscribe("FEEDBACK/CALIBRATION")
1925 (bind(&StateMachineSmartFACT::HandleFeedbackCalibration, this, placeholders::_1));
1926
1927 Subscribe("BIAS_CONTROL/VOLTAGE")
1928 (bind(&StateMachineSmartFACT::HandleBiasVoltage, this, placeholders::_1));
1929 Subscribe("BIAS_CONTROL/CURRENT")
1930 (bind(&StateMachineSmartFACT::HandleBiasCurrent, this, placeholders::_1));
1931
1932 Subscribe("FAD_CONTROL/CONNECTIONS")
1933 (bind(&StateMachineSmartFACT::HandleFadConnections, this, placeholders::_1));
1934 Subscribe("FAD_CONTROL/EVENTS")
1935 (bind(&StateMachineSmartFACT::HandleFadEvents, this, placeholders::_1));
1936
1937 Subscribe("FTM_CONTROL/TRIGGER_RATES")
1938 (bind(&StateMachineSmartFACT::HandleFtmTriggerRates, this, placeholders::_1));
1939 Subscribe("FTM_CONTROL/STATIC_DATA")
1940 (bind(&StateMachineSmartFACT::HandleFtmStaticData, this, placeholders::_1));
1941 Subscribe("FTM_CONTROL/FTU_LIST")
1942 (bind(&StateMachineSmartFACT::HandleFtmFtuList, this, placeholders::_1));
1943
1944 Subscribe("RATE_SCAN/DATA")
1945 (bind(&StateMachineSmartFACT::HandleRateScanData, this, placeholders::_1));
1946
1947 Subscribe("FAD_CONTROL/EVENT_DATA")
1948 (bind(&StateMachineSmartFACT::HandleFadEventData, this, placeholders::_1));
1949
1950 // =================================================================
1951
1952 // State names
1953 AddStateName(kStateDimNetworkNA, "DimNetworkNotAvailable",
1954 "The Dim DNS is not reachable.");
1955
1956 AddStateName(kStateRunning, "Running", "");
1957
1958 // =================================================================
1959
1960 AddEvent("PRINT")
1961 (bind(&StateMachineSmartFACT::Print, this))
1962 ("Print a list of the states of all connected servers.");
1963
1964 }
1965 int EvalOptions(Configuration &conf)
1966 {
1967 if (!fPixelMap.Read(conf.Get<string>("pixel-map-file")))
1968 {
1969 Error("Reading mapping table from "+conf.Get<string>("pixel-map-file")+" failed.");
1970 return 1;
1971 }
1972
1973 fPath = conf.Get<string>("path");
1974
1975 return -1;
1976 }
1977};
1978
1979// ------------------------------------------------------------------------
1980
1981#include "Main.h"
1982
1983template<class T>
1984int RunShell(Configuration &conf)
1985{
1986 return Main::execute<T, StateMachineSmartFACT>(conf);
1987}
1988
1989void SetupConfiguration(Configuration &conf)
1990{
1991 po::options_description control("Smart FACT");
1992 control.add_options()
1993 ("pixel-map-file", var<string>("FACTmapV5a.txt"), "Pixel mapping file. Used here to get the default reference voltage")
1994 ("path", var<string>("www/smartfact/data"), "Output path for the data-files")
1995 ;
1996
1997 conf.AddOptions(control);
1998}
1999
2000/*
2001 Extract usage clause(s) [if any] for SYNOPSIS.
2002 Translators: "Usage" and "or" here are patterns (regular expressions) which
2003 are used to match the usage synopsis in program output. An example from cp
2004 (GNU coreutils) which contains both strings:
2005 Usage: cp [OPTION]... [-T] SOURCE DEST
2006 or: cp [OPTION]... SOURCE... DIRECTORY
2007 or: cp [OPTION]... -t DIRECTORY SOURCE...
2008 */
2009void PrintUsage()
2010{
2011 cout <<
2012 "SmartFACT is a tool writing the files needed for the SmartFACT web interface.\n"
2013 "\n"
2014 "The default is that the program is started without user intercation. "
2015 "All actions are supposed to arrive as DimCommands. Using the -c "
2016 "option, a local shell can be initialized. With h or help a short "
2017 "help message about the usuage can be brought to the screen.\n"
2018 "\n"
2019 "Usage: smartfact [-c type] [OPTIONS]\n"
2020 " or: smartfact [OPTIONS]\n";
2021 cout << endl;
2022}
2023
2024void PrintHelp()
2025{
2026 Main::PrintHelp<StateMachineSmartFACT>();
2027
2028 /* Additional help text which is printed after the configuration
2029 options goes here */
2030
2031 /*
2032 cout << "bla bla bla" << endl << endl;
2033 cout << endl;
2034 cout << "Environment:" << endl;
2035 cout << "environment" << endl;
2036 cout << endl;
2037 cout << "Examples:" << endl;
2038 cout << "test exam" << endl;
2039 cout << endl;
2040 cout << "Files:" << endl;
2041 cout << "files" << endl;
2042 cout << endl;
2043 */
2044}
2045
2046int main(int argc, const char* argv[])
2047{
2048 Configuration conf(argv[0]);
2049 conf.SetPrintUsage(PrintUsage);
2050 Main::SetupConfiguration(conf);
2051 SetupConfiguration(conf);
2052
2053 if (!conf.DoParse(argc, argv, PrintHelp))
2054 return -1;
2055
2056 //try
2057 {
2058 // No console access at all
2059 if (!conf.Has("console"))
2060 {
2061// if (conf.Get<bool>("no-dim"))
2062// return RunShell<LocalStream, StateMachine, ConnectionFSC>(conf);
2063// else
2064 return RunShell<LocalStream>(conf);
2065 }
2066 // Cosole access w/ and w/o Dim
2067/* if (conf.Get<bool>("no-dim"))
2068 {
2069 if (conf.Get<int>("console")==0)
2070 return RunShell<LocalShell, StateMachine, ConnectionFSC>(conf);
2071 else
2072 return RunShell<LocalConsole, StateMachine, ConnectionFSC>(conf);
2073 }
2074 else
2075*/ {
2076 if (conf.Get<int>("console")==0)
2077 return RunShell<LocalShell>(conf);
2078 else
2079 return RunShell<LocalConsole>(conf);
2080 }
2081 }
2082 /*catch (std::exception& e)
2083 {
2084 cerr << "Exception: " << e.what() << endl;
2085 return -1;
2086 }*/
2087
2088 return 0;
2089}
Note: See TracBrowser for help on using the repository browser.