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

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