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

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