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

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