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

Last change on this file since 13612 was 13609, checked in by tbretz, 13 years ago
Fixed the display of the camera display; fixed the display of the MCP/CONFIGURATIOn service and added a time counter for started runs.
File size: 34.4 KB
Line 
1#include "Dim.h"
2#include "Event.h"
3#include "Shell.h"
4#include "StateMachineDim.h"
5#include "Connection.h"
6#include "Configuration.h"
7#include "Console.h"
8#include "Converter.h"
9#include "DimServiceInfoList.h"
10#include "PixelMap.h"
11
12#include "tools.h"
13#include "DimData.h"
14
15#include "LocalControl.h"
16
17#include "HeadersFAD.h"
18#include "HeadersBIAS.h"
19#include "HeadersFTM.h"
20
21namespace ba = boost::asio;
22namespace bs = boost::system;
23namespace dummy = ba::placeholders;
24
25using namespace std;
26
27// ------------------------------------------------------------------------
28
29#include "DimDescriptionService.h"
30
31// ------------------------------------------------------------------------
32
33const static string kHtmlWhite = "#ffffff";
34const static string kHtmlYellow = "#fffff0";
35const static string kHtmlRed = "#fff8f0";
36const static string kHtmlGreen = "#f0fff0";
37const static string kHtmlBlue = "#f0f0ff";
38
39class StateMachineSmartFACT : public StateMachineDim, public DimInfoHandler
40{
41private:
42 enum states_t
43 {
44 kStateDimNetworkNA = 1,
45 kStateRunning,
46 };
47
48 // ------------------------- Internal variables -----------------------
49
50 PixelMap fPixelMap;
51
52 Time fLastUpdate;
53
54 // ----------------------------- Data storage -------------------------
55
56 uint32_t fMcpConfigurationState;
57 int64_t fMcpConfigurationMaxTime;
58 int64_t fMcpConfigurationMaxEvents;
59 string fMcpConfigurationName;
60 Time fMcpConfigurationRunStart;
61
62 enum weather_t { kWeatherBegin=0, kTemp = kWeatherBegin, kDew, kHum, kPress, kWind, kGusts, kDir, kWeatherEnd = kDir };
63 deque<float> fMagicWeatherHist[kWeatherEnd+1];
64
65 vector<float> fFeedbackCalibration;
66 vector<float> fBiasControlVoltageVec;
67
68 float fBiasControlVoltageMed;
69 float fBiasControlCurrentMed;
70 float fBiasControlCurrentMax;
71
72 deque<float> fBiasControlCurrentHist;
73 deque<float> fFscControlTemperatureHist;
74
75 float fFscControlTemperatureAvg;
76 float fFscControlHumidityAvg;
77
78 float fDriveControlPointingZd;
79 string fDriveControlPointingAz;
80 float fDriveControlTrackingDev;
81 string fDriveControlSourceName;
82
83 float fFtmControlTriggerRateCam;
84 deque<float> fFtmControlTriggerRateHist;
85
86 // ------------- Initialize variables before the Dim stuff ------------
87
88 DimServiceInfoList fNetwork;
89
90 class DimState : public DimInfoHandler
91 {
92 public:
93 DimState(const string &n, const string s="STATE") :
94 server(n), info(make_pair(Time(), -2)),
95 dim((n+"/"+s).c_str(), (void*)NULL, 0, this) { }
96
97 string server;
98 pair<Time, int> info;
99
100 DimStampedInfo dim;
101
102 void infoHandler()
103 {
104 DimInfo *curr = getInfo(); // get current DimInfo address
105 if (!curr || curr != &dim)
106 return;
107
108 const bool disconnected = dim.getSize()==0;
109
110 // Make sure getTimestamp is called _before_ getTimestampMillisecs
111 const int tsec = dim.getTimestamp();
112 const int tms = dim.getTimestampMillisecs();
113
114 info = make_pair(Time(tsec, tms*1000),
115 disconnected ? -2 : dim.getQuality());
116 }
117
118 const Time &time() const { return info.first; }
119 const int &state() const { return info.second; }
120
121 const string &name() const { return server; }
122 };
123
124 class DimVersion : public DimState
125 {
126 public:
127 DimVersion() : DimState("DIS_DNS", "VERSION_NUMBER") { }
128
129 void infoHandler()
130 {
131 DimInfo *curr = getInfo(); // get current DimInfo address
132 if (!curr || curr != &dim)
133 return;
134
135 DimState::infoHandler();
136
137 info.second = dim.getSize()==4 ? dim.getInt() : 0;
138 }
139
140 string version() const
141 {
142 if (info.second==0)
143 return "Offline";
144
145 ostringstream msg;
146 msg << "V" << info.second/100 << 'r' << info.second%100;
147 return msg.str();
148 }
149 };
150
151
152 DimVersion fDim;
153 DimState fDimMcp;
154 DimState fDimDataLogger;
155 DimState fDimDriveControl;
156 DimState fDimMagicWeather;
157 DimState fDimFeedback;
158 DimState fDimBiasControl;
159 DimState fDimFtmControl;
160 DimState fDimFadControl;
161 DimState fDimFscControl;
162 DimState fDimRateControl;
163 DimState fDimRateScan;
164 DimState fDimChatServer;
165
166 DimStampedInfo fDimMcpConfiguration;
167
168 DimStampedInfo fDimDriveControlPointing;
169 DimStampedInfo fDimDriveControlTracking;
170 DimStampedInfo fDimDriveControlSource;
171
172 DimStampedInfo fDimFscControlTemperature;
173 DimStampedInfo fDimFscControlHumidity;
174
175 DimStampedInfo fDimMagicWeatherData;
176
177 DimStampedInfo fDimFeedbackCalibration;
178
179 DimStampedInfo fDimBiasControlVoltage;
180 DimStampedInfo fDimBiasControlCurrent;
181
182 DimStampedInfo fDimFtmControlTriggerRates;
183
184 DimStampedInfo *fDimFadControlEventData;
185
186 // -------------------------------------------------------------------
187
188 const State GetState(const DimState &s) const
189 {
190 return fNetwork.GetState(s.name(), s.state());
191 }
192
193 bool HandleService(DimInfo *curr, const DimInfo &service, void (StateMachineSmartFACT::*handle)(const DimData &))
194 {
195 if (curr!=&service)
196 return false;
197
198 (this->*handle)(DimData(curr));
199 return true;
200 }
201
202
203 bool CheckDataSize(const DimData &d, const char *name, size_t size, bool min=false)
204 {
205 if ((!min && d.data.size()==size) || (min && d.data.size()>size))
206 return true;
207
208 ostringstream msg;
209 msg << name << " - Received service has " << d.data.size() << " bytes, but expected ";
210 if (min)
211 msg << "more than ";
212 msg << size << ".";
213 Warn(msg);
214 return false;
215 }
216
217
218 // -------------------------------------------------------------------
219
220 template<class T>
221 void WriteBinary(const string &fname, const T &t, double scale, double offset=0)
222 {
223 vector<uint8_t> val(t.size(), 0);
224 for (uint64_t i=0; i<t.size(); i++)
225 {
226 float range = nearbyint(128*(t[i]+offset)/scale); // [-2V; 2V]
227 if (range>127)
228 range=127;
229 if (range<0)
230 range=0;
231 val[i] = (uint8_t)range;
232 }
233
234 const char *ptr = reinterpret_cast<char*>(val.data());
235
236 ofstream fout("www/"+fname+".bin");
237 fout.write(ptr, val.size()*sizeof(uint8_t));
238 }
239
240 // -------------------------------------------------------------------
241
242 void HandleMcpConfiguration(const DimData &d)
243 {
244 if (!CheckDataSize(d, "Mcp:Configuration", 16, true))
245 return;
246
247 fMcpConfigurationState = d.qos;
248 fMcpConfigurationMaxTime = d.get<uint64_t>();
249 fMcpConfigurationMaxEvents = d.get<uint64_t>(8);
250 fMcpConfigurationName = d.ptr<char>(16);
251
252 if (d.qos==12)
253 fMcpConfigurationRunStart = Time();
254 }
255
256 void WriteWeather(const DimData &d, const string &name, int i, float min, float max)
257 {
258 const auto fmin = min_element(fMagicWeatherHist[i].begin(), fMagicWeatherHist[i].end());
259 const auto fmax = max_element(fMagicWeatherHist[i].begin(), fMagicWeatherHist[i].end());
260 const float favg = accumulate (fMagicWeatherHist[i].begin(), fMagicWeatherHist[i].end(), 0.)/fMagicWeatherHist[i].size();
261
262 ostringstream out;
263 out << setprecision(3);
264 out << uint64_t(d.time.UnixTime()*1000) << '\n';
265
266 out << "#ffffff\t" << fMagicWeatherHist[i].back() << '\n';
267 out << "#ffffff\t" << *fmin << '\n';
268 out << "#ffffff\t" << favg << '\n';
269 out << "#ffffff\t" << *fmax << '\n';
270
271 ofstream("www/"+name+".txt") << out.str();
272
273 WriteBinary("magicweather-"+name+"-hist", fMagicWeatherHist[i], max-min, -min);
274 }
275
276 void HandleMagicWeatherData(const DimData &d)
277 {
278 if (!CheckDataSize(d, "MagicWeather:Data", 7*4+2))
279 return;
280
281 // Store a history of the last 300 entries
282 for (int i=kWeatherBegin; i<=kWeatherEnd; i++)
283 {
284 fMagicWeatherHist[i].push_back(d.ptr<float>(2)[i]);
285 if (fMagicWeatherHist[i].size()>300)
286 fMagicWeatherHist[i].pop_front();
287 }
288
289 ostringstream out;
290 out << uint64_t(d.time.UnixTime()*1000) << '\n';
291
292 for (int i=0; i<7; i++)
293 out << "#ffffff\t" << fMagicWeatherHist[i].back() << '\n';
294
295 ofstream("www/magicweather.txt") << out.str();
296
297 WriteWeather(d, "temp", kTemp, -5, 35);
298 WriteWeather(d, "dew", kDew, -5, 35);
299 WriteWeather(d, "hum", kHum, 0, 100);
300 WriteWeather(d, "wind", kWind, 0, 100);
301 WriteWeather(d, "gusts", kGusts, 0, 100);
302 WriteWeather(d, "press", kPress, 700, 1000);
303 }
304
305 void HandleDriveControlPointing(const DimData &d)
306 {
307 if (!CheckDataSize(d, "DriveControl:Pointing", 16))
308 return;
309
310 fDriveControlPointingZd = d.get<double>();
311
312 const double az = d.get<double>(8);
313
314 static const char *dir[] =
315 {
316 "N", "NNE", "NE", "ENE",
317 "E", "ESE", "SE", "SSE",
318 "S", "SSW", "SW", "WSW",
319 "W", "WNW", "NW", "NNW"
320 };
321
322 const uint16_t i = uint16_t(floor(fmod(az+360+11.25, 360)/22));
323 fDriveControlPointingAz = dir[i];
324
325 ostringstream out;
326 out << uint64_t(d.time.UnixTime()*1000) << '\n';
327
328 out << setprecision(5);
329 out << fDriveControlPointingZd << '\n';
330 out << az << '\n';
331
332 ofstream fout("www/drive-pointing.txt");
333 fout << out.str();
334 }
335
336 void HandleDriveControlTracking(const DimData &d)
337 {
338 if (!CheckDataSize(d, "DriveControl:Tracking", 56))
339 return;
340
341 const double zd = d.get<double>(4*8) * M_PI / 180;
342 const double dzd = d.get<double>(6*8) * M_PI / 180;
343 const double daz = d.get<double>(7*8) * M_PI / 180;
344
345 // Correct:
346 // const double d = cos(del) - sin(zd+dzd)*sin(zd)*(1.-cos(daz));
347
348 // Simplified:
349 const double dev = cos(dzd) - sin(zd+dzd)*sin(zd)*(1.-cos(daz));
350 fDriveControlTrackingDev = acos(dev) * 180 / M_PI * 3600;
351 if (fDriveControlTrackingDev<0.01)
352 fDriveControlTrackingDev=0;
353 }
354
355 void HandleDriveControlSource(const DimData &d)
356 {
357 if (!CheckDataSize(d, "DriveControl:Source", 7*4+2, true))
358 return;
359
360 const double *ptr = d.ptr<double>();
361
362 const double ra = ptr[0]; // Ra[h]
363 const double dec = ptr[1]; // Dec[deg]
364 const double woff = ptr[4]; // Wobble offset [deg]
365 const double wang = ptr[5]; // Wobble angle [deg]
366
367 fDriveControlSourceName = d.ptr<char>(6*8);
368
369 ostringstream out;
370 out << uint64_t(d.time.UnixTime()*1000) << '\n';
371
372 out << "#ffffff\t" << fDriveControlSourceName << '\n';
373 out << setprecision(5);
374 out << "#ffffff\t" << ra << '\n';
375 out << "#ffffff\t" << dec << '\n';
376 out << setprecision(3);
377 out << "#ffffff\t" << woff << '\n';
378 out << "#ffffff\t" << wang << '\n';
379
380 ofstream fout("www/drive.txt");
381 fout << out.str();
382 }
383
384 void HandleFeedbackCalibration(const DimData &d)
385 {
386 if (!CheckDataSize(d, "Feedback:Calibration", 3*4*416))
387 {
388 fFeedbackCalibration.clear();
389 return;
390 }
391
392 const float *ptr = d.ptr<float>();
393 fFeedbackCalibration.assign(ptr+2*416, ptr+3*416);
394 }
395
396 void HandleBiasControlVoltage(const DimData &d)
397 {
398 if (!CheckDataSize(d, "BiasControl:Voltage", 1664))
399 {
400 fBiasControlVoltageVec.clear();
401 return;
402 }
403
404 fBiasControlVoltageVec.assign(d.ptr<float>(), d.ptr<float>()+320);
405
406 vector<float> v(fBiasControlVoltageVec);
407 sort(v.begin(), v.end());
408
409 fBiasControlVoltageMed = (v[159]+v[160])/2;
410
411 //const char *ptr = d.ptr<char>();
412 //ofstream fout("www/biascontrol-voltage.bin");
413 //fout.write(ptr, 320*sizeof(float));
414
415 vector<float> val(320, 0);
416 for (int i=0; i<320; i++)
417 {
418 const int idx = (fPixelMap.hv(i).hw()/9)*2+fPixelMap.hv(i).group();
419 val[i] = v[i];
420 }
421
422 WriteBinary("biascontrol-voltage", val, 75);
423 }
424
425 void HandleBiasControlCurrent(const DimData &d)
426 {
427 if (!CheckDataSize(d, "BiasControl:Current", 832))
428 return;
429
430 // Convert dac counts to uA
431 vector<float> v(320);
432 for (int i=0; i<320; i++)
433 v[i] = d.ptr<uint16_t>()[i] * 5000./4096;
434
435 // Calibrate the data (subtract offset)
436 if (fFeedbackCalibration.size()>0 && fBiasControlVoltageVec.size()>0)
437 for (int i=0; i<320; i++)
438 v[i] -= fBiasControlVoltageVec[i]/fFeedbackCalibration[i]*1e6;
439
440 // Get the maximum of each patch
441 vector<float> val(320, 0);
442 for (int i=0; i<320; i++)
443 {
444 const int idx = (fPixelMap.hv(i).hw()/9)*2+fPixelMap.hv(i).group();
445 val[idx] = v[i];//max(v[i*2], v[i*2+1]);
446 }
447
448 // Write the 160 patch values to a file
449 WriteBinary("biascontrol-current", val, 1000);
450
451 // Now sort them to determine the median
452 sort(v.begin(), v.end());
453
454 // Exclude the three crazy channels
455 fBiasControlCurrentMed = (v[159]+v[160])/2;
456 fBiasControlCurrentMax = v[316];
457
458 // Store a history of the last 60 entries
459 fBiasControlCurrentHist.push_back(fBiasControlCurrentMed);
460 if (fBiasControlCurrentHist.size()>60)
461 fBiasControlCurrentHist.pop_front();
462
463 // write the history to a file
464 WriteBinary("biascontrol-current-hist", fBiasControlCurrentHist, 1000);
465 }
466
467 void HandleFtmControlTriggerRates(const DimData &d)
468 {
469 if (!CheckDataSize(d, "FtmControl:TriggerRates", 24+160+640+8))
470 return;
471
472 fFtmControlTriggerRateCam = d.get<float>(20);
473
474 const float *brates = d.ptr<float>(24); // Board rate
475 const float *prates = d.ptr<float>(24+160); // Patch rate
476
477 // Store a history of the last 60 entries
478 fFtmControlTriggerRateHist.push_back(fFtmControlTriggerRateCam);
479 if (fFtmControlTriggerRateHist.size()>60)
480 fFtmControlTriggerRateHist.pop_front();
481
482 // FIXME: Add statistics for all kind of rates
483
484 WriteBinary("ftmcontrol-triggerrate-hist",
485 fFtmControlTriggerRateHist, 100);
486 WriteBinary("ftmcontrol-boardrates",
487 vector<float>(brates, brates+40), 10);
488 WriteBinary("ftmcontrol-patchrates",
489 vector<float>(prates, prates+160), 10);
490
491 ostringstream out;
492 out << setprecision(3);
493 out << uint64_t(d.time.UnixTime()*1000) << '\n';
494 out << "#ffffff\t" << fFtmControlTriggerRateCam << '\n';
495
496 ofstream fout("www/trigger.txt");
497 fout << out.str();
498 }
499
500 void HandleFadControlEventData(const DimData &d)
501 {
502 if (!CheckDataSize(d, "FadControl:EventData", 23040))
503 return;
504
505 //const float *avg = d.ptr<float>();
506 //const float *rms = d.ptr<float>(1440*sizeof(float));
507 const float *dat = d.ptr<float>(1440*sizeof(float)*2);
508 //const float *pos = d.ptr<float>(1440*sizeof(float)*3);
509
510 vector<float> max(320, -2000);
511 for (int i=0; i<1440; i++)
512 {
513 if (i%9==8)
514 continue;
515
516 const int idx = (fPixelMap.hw(i).hw()/9)*2+fPixelMap.hw(i).group();
517 if (dat[i]>max[idx])
518 max[idx]=dat[i];
519 }
520
521 switch (d.qos)
522 {
523 case 0: WriteBinary("fadcontrol-eventdata", max, 2000, 1000); break;
524 case 1: WriteBinary("fadcontrol-eventdata", max, 2000, 0); break;
525 default: WriteBinary("fadcontrol-eventdata", max, 250, 0); break;
526 }
527 }
528
529 void HandleFscControlTemperature(const DimData &d)
530 {
531 if (!CheckDataSize(d, "FscControl:Temperature", 240))
532 return;
533
534 const float *ptr = d.ptr<float>(4);
535
536 double avg = 0;
537 double rms = 0;
538 double min = 99;
539 double max = -99;
540
541 int num = 0;
542 for (const float *t=ptr; t<ptr+31; t++)
543 {
544 if (*t==0)
545 continue;
546
547 if (*t>max)
548 max = *t;
549
550 if (*t<min)
551 min = *t;
552
553 avg += *t;
554 rms += *t * *t;
555
556 num++;
557 }
558
559 avg /= num;
560 rms = sqrt(rms/num-avg*avg);
561
562 fFscControlTemperatureAvg = avg;
563
564 fFscControlTemperatureHist.push_back(avg);
565 if (fFscControlTemperatureHist.size()>300)
566 fFscControlTemperatureHist.pop_front();
567
568 const auto beg = fFscControlTemperatureHist.begin();
569 const auto end = fFscControlTemperatureHist.end();
570
571 const auto fmin = min_element(beg, end);
572 const auto fmax = max_element(beg, end);
573 const float favg = accumulate (beg, end, 0)/fFscControlTemperatureHist.size();
574
575 ostringstream out;
576 out << setprecision(3);
577 out << uint64_t(d.time.UnixTime()*1000) << '\n';
578 out << "#ffffff\t" << min << '\n';
579 out << "#ffffff\t" << avg << '\n';
580 out << "#ffffff\t" << max << '\n';
581 out << "#ffffff\t" << *fmin << '\n';
582 out << "#ffffff\t" << favg << '\n';
583 out << "#ffffff\t" << *fmax << '\n';
584
585 ofstream("www/fsc.txt") << out.str();
586
587 WriteBinary("fsccontrol-temperature-hist",
588 fFscControlTemperatureHist, 30);
589
590 }
591
592 void HandleFscControlHumidity(const DimData &d)
593 {
594 if (!CheckDataSize(d, "FscControl:Humidity", 5*4))
595 return;
596
597 const float *ptr = d.ptr<float>(4);
598
599 double avg = 0;
600 int num = 0;
601
602 for (const float *t=ptr; t<ptr+4; t++)
603 if (*t>0)
604 {
605 avg += *t;
606 num++;
607 }
608
609 fFscControlHumidityAvg = avg/num;
610 }
611
612
613 // -------------------------------------------------------------------
614
615 void infoHandler()
616 {
617 DimInfo *curr = getInfo(); // get current DimInfo address
618 if (!curr)
619 return;
620
621 if (HandleService(curr, fDimMcpConfiguration, &StateMachineSmartFACT::HandleMcpConfiguration))
622 return;
623 if (HandleService(curr, fDimMagicWeatherData, &StateMachineSmartFACT::HandleMagicWeatherData))
624 return;
625 if (HandleService(curr, fDimDriveControlPointing, &StateMachineSmartFACT::HandleDriveControlPointing))
626 return;
627 if (HandleService(curr, fDimDriveControlTracking, &StateMachineSmartFACT::HandleDriveControlTracking))
628 return;
629 if (HandleService(curr, fDimDriveControlSource, &StateMachineSmartFACT::HandleDriveControlSource))
630 return;
631 if (HandleService(curr, fDimFeedbackCalibration, &StateMachineSmartFACT::HandleFeedbackCalibration))
632 return;
633 if (HandleService(curr, fDimBiasControlVoltage, &StateMachineSmartFACT::HandleBiasControlVoltage))
634 return;
635 if (HandleService(curr, fDimBiasControlCurrent, &StateMachineSmartFACT::HandleBiasControlCurrent))
636 return;
637 if (HandleService(curr, fDimFtmControlTriggerRates, &StateMachineSmartFACT::HandleFtmControlTriggerRates))
638 return;
639 if (HandleService(curr, *fDimFadControlEventData, &StateMachineSmartFACT::HandleFadControlEventData))
640 return;
641 if (HandleService(curr, fDimFscControlTemperature, &StateMachineSmartFACT::HandleFscControlTemperature))
642 return;
643 if (HandleService(curr, fDimFscControlHumidity, &StateMachineSmartFACT::HandleFscControlHumidity))
644 return;
645 }
646
647 bool CheckEventSize(size_t has, const char *name, size_t size)
648 {
649 if (has==size)
650 return true;
651
652 ostringstream msg;
653 msg << name << " - Received event has " << has << " bytes, but expected " << size << ".";
654 Fatal(msg);
655 return false;
656 }
657
658 void PrintState(const DimState &state) const
659 {
660 const State rc = GetState(state);
661
662 Out() << state.time().GetAsStr("%H:%M:%S.%f").substr(0, 12) << " - ";
663 Out() << kBold << state.name() << ": ";
664 if (rc.index==-2)
665 {
666 Out() << kReset << "Offline" << endl;
667 return;
668 }
669 Out() << rc.name << "[" << rc.index << "]";
670 Out() << kReset << " - " << kBlue << rc.comment << endl;
671 }
672
673 int Print() const
674 {
675 Out() << fDim.time().GetAsStr("%H:%M:%S.%f").substr(0, 12) << " - ";
676 Out() << kBold << "DIM_DNS: " << fDim.version() << endl;
677
678 PrintState(fDimMcp);
679 PrintState(fDimDataLogger);
680 PrintState(fDimDriveControl);
681 PrintState(fDimFadControl);
682 PrintState(fDimFtmControl);
683 PrintState(fDimBiasControl);
684 PrintState(fDimFeedback);
685 PrintState(fDimRateControl);
686 PrintState(fDimFscControl);
687 PrintState(fDimMagicWeather);
688 PrintState(fDimRateScan);
689 PrintState(fDimChatServer);
690
691 return GetCurrentState();
692 }
693
694 string GetStateHtml(const DimState &state, int green) const
695 {
696 const State rc = GetState(state);
697
698 //ostringstream msg;
699 //msg << kHtmlWhite << '\t' << rc.name << " [" << rc.index << "]\n";
700 //return msg.str();
701
702 if (rc.index<1)
703 return kHtmlWhite + "\t---\n";
704
705
706 return (rc.index<green?kHtmlYellow:kHtmlGreen) + '\t' + rc.name + '\n';
707 }
708
709 int Execute()
710 {
711 // Dispatch (execute) at most one handler from the queue. In contrary
712 // to run_one(), it doesn't wait until a handler is available
713 // which can be dispatched, so poll_one() might return with 0
714 // handlers dispatched. The handlers are always dispatched/executed
715 // synchronously, i.e. within the call to poll_one()
716 //poll_one();
717
718 if (fDim.state()==0)
719 return kStateDimNetworkNA;
720
721 Time now;
722 if (now-fLastUpdate<boost::posix_time::seconds(1))
723 return kStateRunning;
724
725 fLastUpdate=now;
726
727 ostringstream out;
728 out << uint64_t(nearbyint(now.UnixTime()*1000)) << '\n';
729 out << setprecision(3);
730
731 // -------------- System status --------------
732 if (fDimMcp.state()>=5) // Idle
733 {
734 string col = kHtmlBlue;
735 if (fMcpConfigurationState!= 5 &&
736 fMcpConfigurationState!=11 &&
737 fMcpConfigurationState!=12) // 9 e.g. Configuring3
738 col = kHtmlYellow;
739 else
740 if (fDimFadControl.state()==FAD::kWritingData)
741 col = kHtmlGreen;
742
743 out << col << '\t' << fMcpConfigurationName;
744
745 if (fMcpConfigurationMaxEvents>0 || fMcpConfigurationState==12)
746 out << " [";
747 if (fMcpConfigurationMaxEvents>0)
748 out << fMcpConfigurationMaxEvents;
749 if (fMcpConfigurationMaxEvents>0 || fMcpConfigurationState==12)
750 out << '/';
751 if (fMcpConfigurationMaxTime>0)
752 {
753 if (fMcpConfigurationState==12)
754 out << fMcpConfigurationMaxTime-(Time()-fMcpConfigurationRunStart).total_seconds() << 's';
755 else
756 out << fMcpConfigurationMaxTime << 's';
757 }
758 else
759 {
760 if (fMcpConfigurationState==12)
761 {
762 ostringstream d;
763 d << Time()-fMcpConfigurationRunStart;
764 out << d.str().substr(3, 5);
765 }
766 }
767
768 if (fMcpConfigurationMaxEvents>0 || fMcpConfigurationState==12)
769 out << ']';
770
771
772 }
773 else
774 out << kHtmlWhite;
775 out << '\n';
776
777 // ------------------ Drive -----------------
778 if (fDimDriveControl.state()>=5) // Armed, Moving, Tracking
779 {
780 const State rc = GetState(fDimDriveControl);
781 string col = kHtmlGreen;
782 if (rc.index==6) // Moving
783 col = kHtmlBlue;
784 if (rc.index==5) // Armed
785 col = kHtmlWhite;
786 out << col << '\t';
787 out << rc.name << '\t';
788 out << fDriveControlPointingZd << '\t';
789 out << fDriveControlPointingAz << '\t';
790 if (fDimDriveControl.state()==7)
791 {
792 out << setprecision(2);
793 out << fDriveControlTrackingDev << '\t';
794 out << setprecision(3);
795 out << fDriveControlSourceName << '\n';
796 }
797 else
798 out << "\t\n";
799 }
800 else
801 out << kHtmlWhite << '\n';
802
803 // ------------------- FSC ------------------
804 if (fDimFscControl.state()>1)
805 {
806 out << kHtmlGreen << '\t' << fFscControlTemperatureAvg << '\n';
807 }
808 else
809 out << kHtmlWhite << '\n';
810
811 // --------------- MagicWeather -------------
812 if (fDimMagicWeather.state()==3)
813 {
814 /*
815 const float diff = fMagicWeatherHist[kTemp].back()-fMagicWeatherHist[kDew].back();
816 string col1 = kHtmlRed;
817 if (diff>0.3)
818 col1 = kHtmlYellow;
819 if (diff>0.7)
820 col1 = kHtmlGreen;
821 */
822
823 const float wind = fMagicWeatherHist[kGusts].back();
824 const float hum = fMagicWeatherHist[kHum].back();
825 string col = kHtmlGreen;
826 if (wind>35 || hum>95)
827 col = kHtmlYellow;
828 if (wind>50 || hum>98)
829 col = kHtmlRed;
830
831 out << col << '\t';
832 out << fMagicWeatherHist[kHum].back() << '\t';
833 out << fMagicWeatherHist[kGusts].back() << '\n';
834 }
835 else
836 out << kHtmlWhite << "\n";
837
838 // --------------- FtmControl -------------
839 if (fDimFtmControl.state()>=FTM::kIdle)
840 {
841 string col = kHtmlGreen;
842 if (fFtmControlTriggerRateCam<15)
843 col = kHtmlYellow;
844 if (fFtmControlTriggerRateCam>100)
845 col = kHtmlRed;
846
847 out << col << '\t' << fFtmControlTriggerRateCam << '\n';
848 }
849 else
850 out << kHtmlWhite << '\n';
851
852 // --------------- BiasControl -------------
853 if (fDimBiasControl.state()==5 || // Ramping
854 fDimBiasControl.state()==7 || // On
855 fDimBiasControl.state()==9) // Off
856 {
857 string col = fBiasControlVoltageMed>3?kHtmlGreen:kHtmlWhite;
858 if (fBiasControlCurrentMax>280)
859 col = kHtmlYellow;
860 if (fBiasControlCurrentMax>350)
861 col = kHtmlRed;
862
863 if (fFeedbackCalibration.size()==0)
864 col = kHtmlBlue;
865
866 if (fDimFeedback.state()==13)
867 {
868 out << kHtmlBlue << '\t';
869 out << "***\t";
870 out << "***\t";
871 out << "---\n";
872 }
873 else
874 {
875 out << col << '\t';
876 out << fBiasControlCurrentMed << '\t';
877 out << fBiasControlCurrentMax << '\t';
878 out << fBiasControlVoltageMed << '\n';
879 }
880 }
881 else
882 out << kHtmlWhite << '\n';
883
884
885 // ------------------------------------------
886
887 ofstream("www/fact.txt") << out.str();
888
889 // ==========================================
890
891 out.str("");
892 out << uint64_t(nearbyint(now.UnixTime()*1000)) << '\n';
893
894 if (fDim.state()==0)
895 out << kHtmlWhite << "\tOffline\n\n\n\n\n\n\n\n\n\n\n\n";
896 else
897 {
898 out << kHtmlGreen << '\t' << fDim.version() << '\n';
899
900 out << GetStateHtml(fDimMcp, 4);
901 out << GetStateHtml(fDimDataLogger, 1);
902 out << GetStateHtml(fDimDriveControl, 2);
903 out << GetStateHtml(fDimFadControl, FAD::kConnected);
904 out << GetStateHtml(fDimFtmControl, FTM::kConnected);
905 out << GetStateHtml(fDimBiasControl, BIAS::kConnected);
906 out << GetStateHtml(fDimFeedback, 4);
907 out << GetStateHtml(fDimRateControl, 4);
908 out << GetStateHtml(fDimFscControl, 2);
909 out << GetStateHtml(fDimMagicWeather, 2);
910 out << GetStateHtml(fDimRateScan, 4);
911 out << GetStateHtml(fDimChatServer, 1);
912 }
913
914 ofstream("www/status.txt") << out.str();
915
916 return kStateRunning;
917 }
918
919public:
920 StateMachineSmartFACT(ostream &out=cout) : StateMachineDim(out, "SMART_FACT"),
921 //---
922 fDimMcp ("MCP"),
923 fDimDataLogger ("DATA_LOGGER"),
924 fDimDriveControl ("DRIVE_CONTROL"),
925 fDimMagicWeather ("MAGIC_WEATHER"),
926 fDimFeedback ("FEEDBACK"),
927 fDimBiasControl ("BIAS_CONTROL"),
928 fDimFtmControl ("FTM_CONTROL"),
929 fDimFadControl ("FAD_CONTROL"),
930 fDimFscControl ("FSC_CONTROL"),
931 fDimRateControl ("RATE_CONTROL"),
932 fDimRateScan ("RATE_SCAN"),
933 fDimChatServer ("CHAT_SERVER"),
934 //---
935 fDimMcpConfiguration ("MCP/CONFIGURATION", (void*)NULL, 0, this),
936 //---
937 fDimDriveControlPointing ("DRIVE_CONTROL/POINTING_POSITION", (void*)NULL, 0, this),
938 fDimDriveControlTracking ("DRIVE_CONTROL/TRACKING_POSITION", (void*)NULL, 0, this),
939 fDimDriveControlSource ("DRIVE_CONTROL/SOURCE_POSITION", (void*)NULL, 0, this),
940 //---
941 fDimFscControlTemperature ("FSC_CONTROL/TEMPERATURE", (void*)NULL, 0, this),
942 fDimFscControlHumidity ("FSC_CONTROL/HUMIDITY", (void*)NULL, 0, this),
943 //---
944 fDimMagicWeatherData ("MAGIC_WEATHER/DATA", (void*)NULL, 0, this),
945 //---
946 fDimFeedbackCalibration ("FEEDBACK/CALIBRATION", (void*)NULL, 0, this),
947 //---
948 fDimBiasControlVoltage ("BIAS_CONTROL/VOLTAGE", (void*)NULL, 0, this),
949 fDimBiasControlCurrent ("BIAS_CONTROL/CURRENT", (void*)NULL, 0, this),
950 //---
951 fDimFtmControlTriggerRates("FTM_CONTROL/TRIGGER_RATES", (void*)NULL, 0, this),
952 //-
953 fMcpConfigurationMaxEvents(0),
954 fMcpConfigurationMaxTime(0),
955 fDimFadControlEventData(0)
956 {
957 // State names
958 AddStateName(kStateDimNetworkNA, "DimNetworkNotAvailable",
959 "The Dim DNS is not reachable.");
960
961 AddStateName(kStateRunning, "Running", "");
962
963 // Verbosity commands
964// AddEvent("SET_VERBOSE", "B:1")
965// (bind(&StateMachineMCP::SetVerbosity, this, placeholders::_1))
966// ("set verbosity state"
967// "|verbosity[bool]:disable or enable verbosity for received data (yes/no), except dynamic data");
968
969 AddEvent("PRINT")
970 (bind(&StateMachineSmartFACT::Print, this))
971 ("");
972 }
973 ~StateMachineSmartFACT()
974 {
975 delete fDimFadControlEventData;
976 }
977 int EvalOptions(Configuration &conf)
978 {
979 if (!fPixelMap.Read(conf.Get<string>("pixel-map-file")))
980 {
981 Error("Reading mapping table from "+conf.Get<string>("pixel-map-file")+" failed.");
982 return 1;
983 }
984
985 // Pixel map is needed to deal with this service
986 fDimFadControlEventData=new DimStampedInfo("FAD_CONTROL/EVENT_DATA", (void*)NULL, 0, this);
987
988 return -1;
989 }
990};
991
992// ------------------------------------------------------------------------
993
994#include "Main.h"
995
996template<class T>
997int RunShell(Configuration &conf)
998{
999 return Main::execute<T, StateMachineSmartFACT>(conf);
1000}
1001
1002void SetupConfiguration(Configuration &conf)
1003{
1004 po::options_description control("Smart FACT");
1005 control.add_options()
1006 ("pixel-map-file", var<string>("FACTmapV5a.txt"), "Pixel mapping file. Used here to get the default reference voltage.")
1007 ;
1008
1009 conf.AddOptions(control);
1010}
1011
1012/*
1013 Extract usage clause(s) [if any] for SYNOPSIS.
1014 Translators: "Usage" and "or" here are patterns (regular expressions) which
1015 are used to match the usage synopsis in program output. An example from cp
1016 (GNU coreutils) which contains both strings:
1017 Usage: cp [OPTION]... [-T] SOURCE DEST
1018 or: cp [OPTION]... SOURCE... DIRECTORY
1019 or: cp [OPTION]... -t DIRECTORY SOURCE...
1020 */
1021void PrintUsage()
1022{
1023 cout <<
1024 "SmartFACT is a tool writing the files needed for the SmartFACT web interface.\n"
1025 "\n"
1026 "The default is that the program is started without user intercation. "
1027 "All actions are supposed to arrive as DimCommands. Using the -c "
1028 "option, a local shell can be initialized. With h or help a short "
1029 "help message about the usuage can be brought to the screen.\n"
1030 "\n"
1031 "Usage: smartfact [-c type] [OPTIONS]\n"
1032 " or: smartfact [OPTIONS]\n";
1033 cout << endl;
1034}
1035
1036void PrintHelp()
1037{
1038 Main::PrintHelp<StateMachineSmartFACT>();
1039
1040 /* Additional help text which is printed after the configuration
1041 options goes here */
1042
1043 /*
1044 cout << "bla bla bla" << endl << endl;
1045 cout << endl;
1046 cout << "Environment:" << endl;
1047 cout << "environment" << endl;
1048 cout << endl;
1049 cout << "Examples:" << endl;
1050 cout << "test exam" << endl;
1051 cout << endl;
1052 cout << "Files:" << endl;
1053 cout << "files" << endl;
1054 cout << endl;
1055 */
1056}
1057
1058int main(int argc, const char* argv[])
1059{
1060 Configuration conf(argv[0]);
1061 conf.SetPrintUsage(PrintUsage);
1062 Main::SetupConfiguration(conf);
1063 SetupConfiguration(conf);
1064
1065 if (!conf.DoParse(argc, argv, PrintHelp))
1066 return -1;
1067
1068 //try
1069 {
1070 // No console access at all
1071 if (!conf.Has("console"))
1072 {
1073// if (conf.Get<bool>("no-dim"))
1074// return RunShell<LocalStream, StateMachine, ConnectionFSC>(conf);
1075// else
1076 return RunShell<LocalStream>(conf);
1077 }
1078 // Cosole access w/ and w/o Dim
1079/* if (conf.Get<bool>("no-dim"))
1080 {
1081 if (conf.Get<int>("console")==0)
1082 return RunShell<LocalShell, StateMachine, ConnectionFSC>(conf);
1083 else
1084 return RunShell<LocalConsole, StateMachine, ConnectionFSC>(conf);
1085 }
1086 else
1087*/ {
1088 if (conf.Get<int>("console")==0)
1089 return RunShell<LocalShell>(conf);
1090 else
1091 return RunShell<LocalConsole>(conf);
1092 }
1093 }
1094 /*catch (std::exception& e)
1095 {
1096 cerr << "Exception: " << e.what() << endl;
1097 return -1;
1098 }*/
1099
1100 return 0;
1101}
Note: See TracBrowser for help on using the repository browser.