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

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