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

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