source: trunk/FACT++/src/fscctrl.cc@ 12555

Last change on this file since 12555 was 12510, checked in by tbretz, 13 years ago
Removed + and - from fits column names.
File size: 26.8 KB
Line 
1#include <functional>
2
3#include "Dim.h"
4#include "Event.h"
5#include "Shell.h"
6#include "StateMachineDim.h"
7#include "Connection.h"
8#include "Configuration.h"
9#include "Console.h"
10#include "Converter.h"
11
12#include "tools.h"
13
14namespace ba = boost::asio;
15namespace bs = boost::system;
16namespace dummy = ba::placeholders;
17
18using namespace std;
19
20// ------------------------------------------------------------------------
21
22class ConnectionFSC : public Connection
23{
24 boost::asio::streambuf fBuffer;
25
26 bool fIsVerbose;
27 bool fDump;
28
29 ofstream fDumpStream;
30
31protected:
32
33 virtual void UpdateTemp(float, const vector<float> &)
34 {
35 }
36
37 virtual void UpdateHum(float, const vector<float>&)
38 {
39 }
40
41 virtual void UpdateVolt(float, const vector<float>&)
42 {
43 }
44
45 virtual void UpdateCur(float, const vector<float>&)
46 {
47 }
48
49 /*
50 virtual void UpdateError()
51 {
52 if (!fIsVerbose)
53 return;
54
55 Out() << endl << kRed << "Error received:" << endl;
56 Out() << fError;
57 if (fIsHexOutput)
58 Out() << Converter::GetHex<uint16_t>(fError, 16) << endl;
59 }
60*/
61
62 void Dump(const string &str)
63 {
64 if (!fDumpStream.is_open())
65 {
66 fDumpStream.open("socket_dump-fsc.txt", ios::app);
67 if (!fDumpStream)
68 {
69 //ostringstream str;
70 //str << "Open file " << name << ": " << strerror(errno) << " (errno=" << errno << ")";
71 //Error(str);
72
73 return;
74 }
75 }
76
77 fDumpStream << str << endl;
78 }
79
80private:
81 //
82 // From: http://de.wikipedia.org/wiki/Pt100
83 //
84 double GetTempPT1000(double R) const
85 {
86 const double R0 = 1000; // 1kOhm
87
88 const double a = 3.85e-3;
89
90 return (R/R0 - 1)/a;
91 }
92
93
94 void HandleReceivedData(const bs::error_code& err, size_t bytes_received, int /*type*/)
95 {
96 // Do not schedule a new read if the connection failed.
97 if (bytes_received==0 || err)
98 {
99 if (err==ba::error::eof)
100 Warn("Connection closed by remote host (FTM).");
101
102 // 107: Transport endpoint is not connected (bs::error_code(107, bs::system_category))
103 // 125: Operation canceled
104 if (err && err!=ba::error::eof && // Connection closed by remote host
105 err!=ba::error::basic_errors::not_connected && // Connection closed by remote host
106 err!=ba::error::basic_errors::operation_aborted) // Connection closed by us
107 {
108 ostringstream str;
109 str << "Reading from " << URL() << ": " << err.message() << " (" << err << ")";// << endl;
110 Error(str);
111 }
112 PostClose(err!=ba::error::basic_errors::operation_aborted);
113 return;
114 }
115
116 if (fIsVerbose)
117 Out() << kBold << "Received (" << bytes_received << " bytes):" << endl;
118
119 /*
120 "status: 00000538 \n"
121 "time_s: 764.755 \n"
122 "VOLTAGES \n"
123 " \n"
124 "enable:11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 00001111 \n"
125 " done:11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 00001111 \n"
126 "values:0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 \n"
127 "RESISTANCES \n"
128 " \n"
129 "enable:11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 \n"
130 " done:11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 \n"
131 "values: \n"
132 "1000.16 3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 \n"
133 "3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 \n"
134 "1197.07 3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 \n"
135 " 558.59 677.92 817.26 989.39 1200.35 1503.06 1799.90 2204.18 \n"
136 "3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 \n"
137 "3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 \n"
138 "3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 \n"
139 "3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 3199.99 \n"
140 "end.\n";
141 */
142/*
143 const unsigned int TIME_OFF = 3;
144 const unsigned int VOLT_OFF = 30;
145 const unsigned int CURR_OFF = 70;
146 const unsigned int HUMI_OFF = 110;
147 const unsigned int TEMP_OFF = 134;
148 */
149
150 if (fDump)
151 {
152 ostringstream msg;
153 msg << "--- " << Time().GetAsStr() << " --- received " << bytes_received << " bytes.";
154 Dump(msg.str());
155 }
156
157
158 istream is(&fBuffer);
159
160 int state = 0;
161 bool values = false;
162
163 vector<int> volt;
164 vector<float> resist;
165 int status=-1;
166 float time=0;
167
168 string buffer;
169 while (getline(is, buffer, '\n'))
170 {
171 if (fIsVerbose)
172 Out() << buffer << endl;
173 if (fDump)
174 Dump(buffer);
175
176 buffer = Tools::Trim(buffer);
177
178 if (buffer.empty())
179 continue;
180
181 if (buffer.substr(0, 4)=="end.")
182 break;
183
184 if (buffer.substr(0, 8)=="status: ")
185 {
186 status = stoi(buffer.substr(8));
187 continue;
188 }
189
190 if (buffer.substr(0, 8)=="time_s: ")
191 {
192 time = stof(buffer.substr(8));
193 continue;
194 }
195
196 if (buffer.substr(0, 8)=="VOLTAGES")
197 {
198 state = 1;
199 continue;
200 }
201
202 if (buffer.substr(0, 11)=="RESISTANCES")
203 {
204 state = 2;
205 continue;
206 }
207
208 if (state==1 && buffer.substr(0, 7)=="values:")
209 {
210 istringstream in(buffer.substr(7));
211 while (1)
212 {
213 int v;
214 in >> v;
215 if (!in)
216 break;
217
218 volt.push_back(v);
219 }
220 continue;
221 }
222
223 if (state==2 && buffer.substr(0, 7)=="values:")
224 {
225 values = true;
226 continue;
227 }
228
229 if (state==2 && !values)
230 continue;
231
232 istringstream in(buffer);
233 while (1)
234 {
235 float f;
236 in >> f;
237 if (!in)
238 break;
239
240 resist.push_back(f);
241 }
242 }
243
244 if (volt.size()!=84 || resist.size()!=64)
245 {
246 ostringstream out;
247
248 out << "Corrupted data received (" << volt.size() << " voltages and ";
249 out << resist.size() << " resistances received; 84 and 64 expected)";
250 Warn(out);
251 StartRead();
252 return;
253 }
254
255 int mapv[] =
256 {
257 0, 16, 24, 8,
258 1, 17, 25, 9,
259 2, 18, 26, 10,
260 //
261 3, 19, 27, 11,
262 4, 20, 28, 12,
263 5, 21, 29, 13,
264 //
265 32, 36, 33, 34, 37, 38,
266 //
267 -1
268 };
269
270
271 int mapc[] =
272 {
273 40, 56, 64, 48,
274 41, 57, 65, 49,
275 42, 58, 66, 50,
276 //
277 43, 59, 67, 51,
278 44, 60, 68, 52,
279 45, 61, 69, 53,
280 //
281 72, 76, 73, 74, 77, 78,
282 //
283 -1
284 };
285
286
287 int maprh[] =
288 {
289 80, 81, 82, 83, -1
290 };
291
292 int offrh[] =
293 {
294 821, 822, 816, 822,
295 };
296
297 int mapt[] =
298 {
299 // sensor compartment temperatures
300 0, 1, 2, 3, 4, 5, 6, 56, 57, 58, 59, 60,
301 61, 62, 32, 33, 34, 35, 36, 63, 37, 38, 39, 24,
302 25, 26, 27, 28, 29, 30, 31,
303 // crate temperatures (0-3, back/front)
304 12, 13, 52, 53, 44, 46, 20, 21,
305 //crate power supply temperatures (0-3)
306 8, 9, 48, 49, 40, 41, 16, 17,
307 // aux power supplies (FTM-side top/bot, FSC-side top/bot)
308 45, 50, 19, 42,
309 // backpanel (FTM-side top/bot, FSC-side top/bot)
310 11, 51, 18, 43,
311 // switch boxes (top front/back, bottom front/back)
312 15, 14, 47, 10,
313 //
314 -1
315 };
316
317 vector<float> voltages;
318 vector<float> currents;
319 vector<float> humidities;
320 vector<float> temperatures;
321
322 for (int *pv=mapv; *pv>=0; pv++)
323 voltages.push_back(volt[*pv]*0.001);
324
325 for (int *pc=mapc; *pc>=0; pc++)
326 currents.push_back(volt[*pc]*0.005);
327
328 for (int idx=0; idx<4; idx++)
329 {
330 voltages[idx +8] *= -1;
331 voltages[idx+20] *= -1;
332 currents[idx +8] *= -1;
333 currents[idx+20] *= -1;
334 }
335 voltages[12] *= 2;
336 voltages[13] *= 2;
337 voltages[14] *= 2;
338 voltages[15] *= 2;
339
340 voltages[24] *= 2;
341 voltages[25] *= 2;
342
343 voltages[27] *= -1;
344 voltages[29] *= -1;
345
346 currents[27] *= -1;
347 currents[29] *= -1;
348
349 int idx=0;
350 for (int *ph=maprh; *ph>=0; ph++, idx++)
351 humidities.push_back((volt[*ph]-offrh[idx])*0.0313);
352
353 for (int *pt=mapt; *pt>=0; pt++)
354 temperatures.push_back(resist[*pt]>800&&resist[*pt]<2000 ? GetTempPT1000(resist[*pt]) : 0);
355
356 // 0 = 3-(3+0)%4
357 // 3 = 3-(3+1)%4
358 // 2 = 3-(3+2)%4
359 // 1 = 3-(3+3)%4
360
361 /*
362 index unit offset scale crate for board:
363 0 mV 0 1 0 FAD 3.3V
364 24 mV 0 1 1 FAD 3.3V
365 16 mV 0 1 2 FAD 3.3V
366 8 mV 0 1 3 FAD 3.3V
367
368 1 mV 0 1 0 FAD 3.3V
369 25 mV 0 1 1 FAD 3.3V
370 17 mV 0 1 2 FAD 3.3V
371 9 mV 0 1 3 FAD 3.3V
372
373 2 mV 0 -1 0 FAD -2.0V
374 26 mV 0 -1 1 FAD -2.0V
375 18 mV 0 -1 2 FAD -2.0V
376 10 mV 0 -1 3 FAD -2.0V
377
378 --
379
380 3 mV 0 1 0 FPA 5.0V
381 27 mV 0 1 1 FPA 5.0V
382 19 mV 0 1 2 FPA 5.0V
383 11 mV 0 1 3 FPA 5.0V
384
385 4 mV 0 1 0 FPA 3.3V
386 28 mV 0 1 1 FPA 3.3V
387 20 mV 0 1 2 FPA 3.3V
388 12 mV 0 1 3 FPA 3.3V
389
390 5 mV 0 -1 0 FPA -3.3V
391 29 mV 0 -1 1 FPA -3.3V
392 21 mV 0 -1 2 FPA -3.3V
393 13 mV 0 -1 3 FPA -3.3V
394
395 --
396
397 32 mV 0 1 bottom ETH 5V
398 36 mV 0 1 top ETH 5V
399
400 33 mV 0 1 bottom FTM 3.3V
401 34 mV 0 -1 bottom FTM -3.3V
402
403 37 mV 0 1 top FFC 3.3V
404 38 mV 0 -1 top FLP -3.3V
405
406 -----
407
408 40 mA 0 5 0 FAD
409 64 mA 0 5 1 FAD
410 56 mA 0 5 2 FAD
411 48 mA 0 5 3 FAD
412
413 41 mA 0 5 0 FAD
414 65 mA 0 5 1 FAD
415 57 mA 0 5 2 FAD
416 49 mA 0 5 3 FAD
417
418 42 mA 0 -5 0 FAD
419 66 mA 0 -5 1 FAD
420 58 mA 0 -5 2 FAD
421 50 mA 0 -5 3 FAD
422
423 --
424
425 43 mA 0 5 0 FPA
426 67 mA 0 5 1 FPA
427 59 mA 0 5 2 FPA
428 51 mA 0 5 3 FPA
429
430 44 mA 0 5 0 FPA
431 68 mA 0 5 1 FPA
432 60 mA 0 5 2 FPA
433 52 mA 0 5 3 FPA
434
435 45 mA 0 -5 0 FPA
436 69 mA 0 -5 1 FPA
437 61 mA 0 -5 2 FPA
438 53 mA 0 -5 3 FPA
439
440 ---
441
442 72 mA 0 5 bottom ETH
443 76 mA 0 5 top ETH
444
445 73 mA 0 5 bottom FTM
446 74 mA 0 -5 bottom FTM
447
448 77 mA 0 5 top FFC
449 78 mA 0 -5 top FLP
450
451 ----
452
453 80 % RH -821 0.0313 FSP000
454 81 % RH -822 0.0313 FSP221
455 82 % RH -816 0.0313 Sector0
456 83 % RH -822 0.0313 Sector2
457 */
458
459 // TEMPERATURES
460 // 31 x Sensor plate
461 // 8 x Crate
462 // 12 x PS
463 // 4 x Backpanel
464 // 4 x Switchbox
465
466
467
468 /*
469 0 ohms FSP 000
470 1 ohms FSP 010
471 2 ohms FSP 023
472 3 ohms FSP 043
473 4 ohms FSP 072
474 5 ohms FSP 080
475 6 ohms FSP 092
476 56 ohms FSP 103
477 57 ohms FSP 111
478 58 ohms FSP 121
479 59 ohms FSP 152
480 60 ohms FSP 163
481 61 ohms FSP 171
482 62 ohms FSP 192
483 32 ohms FSP 200
484 33 ohms FSP 210
485 34 ohms FSP 223
486 35 ohms FSP 233
487 36 ohms FSP 243
488 63 ohms FSP 252
489 37 ohms FSP 280
490 38 ohms FSP 283
491 39 ohms FSP 293
492 24 ohms FSP 311
493 25 ohms FSP 321
494 26 ohms FSP 343
495 27 ohms FSP 352
496 28 ohms FSP 363
497 29 ohms FSP 371
498 30 ohms FSP 381
499 31 ohms FSP 392
500 8 ohms Crate0 ?
501 9 ohms Crate0 ?
502 48 ohms Crate1 ?
503 49 ohms Crate1 ?
504 40 ohms Crate2 ?
505 41 ohms Crate2 ?
506 16 ohms Crate3 ?
507 17 ohms Crate3 ?
508 10 ohms PS Crate 0
509 11 ohms PS Crate 0
510 50 ohms PS Crate 1
511 51 ohms PS Crate 1
512 42 ohms PS Crate 2
513 43 ohms PS Crate 2
514 18 ohms PS Crate 3
515 19 ohms PS Crate 3
516 12 ohms PS Aux0
517 52 ohms PS Aux0
518 20 ohms PS Aux1
519 44 ohms PS Aux1
520 13 ohms Backpanel ?
521 21 ohms Backpanel ?
522 45 ohms Backpanel ?
523 53 ohms Backpanel ?
524 14 ohms Switchbox0 ?
525 15 ohms Switchbox0 ?
526 46 ohms Switchbox1 ?
527 47 ohms Switchbox1 ?
528 7 ohms nc nc
529 22 ohms nc nc
530 23 ohms nc nc
531 54 ohms nc nc
532 55 ohms nc nc
533 */
534
535 for (size_t i=0; i<resist.size(); i++)
536 if (resist[i]>800 && resist[i]<2000)
537 cout << setw(2) << i << " - " << setw(4) << (int)resist[i] << ": " << setprecision(1) << fixed << GetTempPT1000(resist[i]) << endl;
538 else
539 cout << setw(2) << i << " - " << setw(4) << (int)resist[i] << ": " << "----" << endl;
540
541 UpdateTemp(time, temperatures);
542 UpdateVolt(time, voltages);
543 UpdateCur( time, currents);
544 UpdateHum( time, humidities);
545
546 StartRead();
547 }
548
549 void StartRead()
550 {
551 ba::async_read_until(*this, fBuffer, "end.\n",
552 boost::bind(&ConnectionFSC::HandleReceivedData, this,
553 dummy::error, dummy::bytes_transferred, 0));
554
555 // FIXME: Add timeout here
556 }
557
558 // This is called when a connection was established
559 void ConnectionEstablished()
560 {
561 PostMessage("m", 1);
562
563 fBuffer.prepare(10000);
564 StartRead();
565 }
566
567/*
568 void HandleReadTimeout(const bs::error_code &error)
569 {
570 if (error==ba::error::basic_errors::operation_aborted)
571 return;
572
573 if (error)
574 {
575 ostringstream str;
576 str << "Read timeout of " << URL() << ": " << error.message() << " (" << error << ")";// << endl;
577 Error(str);
578
579 PostClose();
580 return;
581
582 }
583
584 if (!is_open())
585 {
586 // For example: Here we could schedule a new accept if we
587 // would not want to allow two connections at the same time.
588 return;
589 }
590
591 // Check whether the deadline has passed. We compare the deadline
592 // against the current time since a new asynchronous operation
593 // may have moved the deadline before this actor had a chance
594 // to run.
595 if (fInTimeout.expires_at() > ba::deadline_timer::traits_type::now())
596 return;
597
598 Error("Timeout reading data from "+URL());
599
600 PostClose();
601 }
602*/
603
604public:
605 ConnectionFSC(ba::io_service& ioservice, MessageImp &imp) : Connection(ioservice, imp()),
606 fIsVerbose(true), fDump(false)
607 {
608 SetLogStream(&imp);
609 }
610
611 void SetVerbose(bool b)
612 {
613 fIsVerbose = b;
614 }
615
616 void SetDumpStream(bool b)
617 {
618 fDump = b;
619 }
620};
621
622// ------------------------------------------------------------------------
623
624#include "DimDescriptionService.h"
625
626class ConnectionDimFSC : public ConnectionFSC
627{
628private:
629
630 DimDescribedService fDimTemp;
631 DimDescribedService fDimHum;
632 DimDescribedService fDimVolt;
633 DimDescribedService fDimCurrent;
634
635 void Update(DimDescribedService &svc, vector<float> data, float time) const
636 {
637 data.insert(data.begin(), time);
638 svc.Update(data);
639 }
640
641 void UpdateTemp(float time, const vector<float> &temp)
642 {
643 Update(fDimTemp, temp, time);
644 }
645
646 void UpdateHum(float time, const vector<float> &hum)
647 {
648 Update(fDimHum, hum, time);
649 }
650
651 void UpdateVolt(float time, const vector<float> &volt)
652 {
653 Update(fDimVolt, volt, time);
654 }
655
656 void UpdateCur(float time, const vector<float> &curr)
657 {
658 Update(fDimCurrent, curr, time);
659 }
660
661public:
662 ConnectionDimFSC(ba::io_service& ioservice, MessageImp &imp) :
663 ConnectionFSC(ioservice, imp),
664 fDimTemp ("FSC_CONTROL/TEMPERATURE", "F:1;F:31;F:8;F:8;F:4;F:4;F:4",
665 "|t[s]:FSC uptime"
666 "|T_sens[deg C]:Sensor compartment temperatures"
667 "|T_crate[deg C]:Temperatures crate 0 (back/front), 1 (back/front), 2 (back/front), 3 (back/front)"
668 "|T_ps[deg C]:Temperatures power supplies crate 0 (back/front), 1 (back/front), 2 (back/front), 3 (back/front)"
669 "|T_aux[deg C]:Auxiliary power supply temperatures FTM (top/bottom), FSC (top/bottom)"
670 "|T_back[deg C]:FTM backpanel temperatures FTM (top/bottom), FSC (top/bottom)"
671 "|T_eth[deg C]:Ethernet switches temperatures top (front/back), bottom (front/back)"),
672 fDimHum ("FSC_CONTROL/HUMIDITY", "F:1;F:4",
673 "|t[s]:FSC uptime"
674 "|H[%]:Humidity sensors readout"),
675 fDimVolt ("FSC_CONTROL/VOLTAGE",
676 "F:1;F:4;F:4;F:4;F:4;F:4;F:4;F:2;F:2;F:1;F:1",
677 "|t[s]:FSC uptime"
678 "|FAD_Ud[V]:FAD digital (crate 0-3)"
679 "|FAD_Up[V]:FAD positive (crate 0-3)"
680 "|FAD_Un[V]:FAD negative (crate 0-3)"
681 "|FPA_Ud[V]:FPA digital (crate 0-3)"
682 "|FPA_Up[V]:FPA positive (crate 0-3)"
683 "|FPA_Un[V]:FPA negative (crate 0-3)"
684 "|ETH_U[V]:Ethernet switch (pos/neg)"
685 "|FTM_U[V]:FTM - trigger master (pos/neg)"
686 "|FFC_U[V]:FFC"
687 "|FLP_U[V]:FLP - light pulser"),
688 fDimCurrent("FSC_CONTROL/CURRENT", "F:1;F:4;F:4;F:4;F:4;F:4;F:4;F:2;F:2;F:1;F:1",
689 "|t[s]:FSC uptime"
690 "|FAD_Id[A]:FAD digital (crate 0-3)"
691 "|FAD_Ip[A]:FAD positive (crate 0-3)"
692 "|FAD_In[A]:FAD negative (crate 0-3)"
693 "|FPA_Id[A]:FPA digital (crate 0-3)"
694 "|FPA_Ip[A]:FPA positive (crate 0-3)"
695 "|FPA_In[A]:FPA negative (crate 0-3)"
696 "|ETH_I[A]:Ethernet switch (pos/neg)"
697 "|FTM_I[A]:FTM - trigger master (pos/neg)"
698 "|FFC_I[A]:FFC"
699 "|FLP_I[A]:FLP - light pulser")
700 {
701 }
702
703 // A B [C] [D] E [F] G H [I] J K [L] M N O P Q R [S] T U V W [X] Y Z
704};
705
706// ------------------------------------------------------------------------
707
708template <class T, class S>
709class StateMachineFSC : public T, public ba::io_service, public ba::io_service::work
710{
711 int Wrap(boost::function<void()> f)
712 {
713 f();
714 return T::GetCurrentState();
715 }
716
717 function<int(const EventImp &)> Wrapper(function<void()> func)
718 {
719 return bind(&StateMachineFSC::Wrap, this, func);
720 }
721
722private:
723 S fFSC;
724
725 enum states_t
726 {
727 kStateDisconnected = 1,
728 kStateConnected = 2,
729 };
730
731 int Disconnect()
732 {
733 // Close all connections
734 fFSC.PostClose(false);
735
736 /*
737 // Now wait until all connection have been closed and
738 // all pending handlers have been processed
739 poll();
740 */
741
742 return T::GetCurrentState();
743 }
744
745 int Reconnect(const EventImp &evt)
746 {
747 // Close all connections to supress the warning in SetEndpoint
748 fFSC.PostClose(false);
749
750 // Now wait until all connection have been closed and
751 // all pending handlers have been processed
752 poll();
753
754 if (evt.GetBool())
755 fFSC.SetEndpoint(evt.GetString());
756
757 // Now we can reopen the connection
758 fFSC.PostClose(true);
759
760 return T::GetCurrentState();
761 }
762
763 int Execute()
764 {
765 // Dispatch (execute) at most one handler from the queue. In contrary
766 // to run_one(), it doesn't wait until a handler is available
767 // which can be dispatched, so poll_one() might return with 0
768 // handlers dispatched. The handlers are always dispatched/executed
769 // synchronously, i.e. within the call to poll_one()
770 poll_one();
771
772 return fFSC.IsConnected() ? kStateConnected : kStateDisconnected;
773 }
774
775 bool CheckEventSize(size_t has, const char *name, size_t size)
776 {
777 if (has==size)
778 return true;
779
780 ostringstream msg;
781 msg << name << " - Received event has " << has << " bytes, but expected " << size << ".";
782 T::Fatal(msg);
783 return false;
784 }
785
786 int SetVerbosity(const EventImp &evt)
787 {
788 if (!CheckEventSize(evt.GetSize(), "SetVerbosity", 1))
789 return T::kSM_FatalError;
790
791 fFSC.SetVerbose(evt.GetBool());
792
793 return T::GetCurrentState();
794 }
795
796 int SetDumpStream(const EventImp &evt)
797 {
798 if (!CheckEventSize(evt.GetSize(), "SetDumpStream", 1))
799 return T::kSM_FatalError;
800
801 fFSC.SetDumpStream(evt.GetBool());
802
803 return T::GetCurrentState();
804 }
805
806public:
807 StateMachineFSC(ostream &out=cout) :
808 T(out, "FSC_CONTROL"), ba::io_service::work(static_cast<ba::io_service&>(*this)),
809 fFSC(*this, *this)
810 {
811 // ba::io_service::work is a kind of keep_alive for the loop.
812 // It prevents the io_service to go to stopped state, which
813 // would prevent any consecutive calls to run()
814 // or poll() to do nothing. reset() could also revoke to the
815 // previous state but this might introduce some overhead of
816 // deletion and creation of threads and more.
817
818 // State names
819 AddStateName(kStateDisconnected, "Disconnected",
820 "FSC board not connected via ethernet.");
821
822 AddStateName(kStateConnected, "Connected",
823 "Ethernet connection to FSC established.");
824
825 // Verbosity commands
826 T::AddEvent("SET_VERBOSE", "B:1")
827 (bind(&StateMachineFSC::SetVerbosity, this, placeholders::_1))
828 ("set verbosity state"
829 "|verbosity[bool]:disable or enable verbosity for received data (yes/no), except dynamic data");
830
831 T::AddEvent("DUMP_STREAM", "B:1")
832 (bind(&StateMachineFSC::SetDumpStream, this, placeholders::_1))
833 (""
834 "");
835
836 // Conenction commands
837 AddEvent("DISCONNECT", kStateConnected)
838 (bind(&StateMachineFSC::Disconnect, this))
839 ("disconnect from ethernet");
840
841 AddEvent("RECONNECT", "O", kStateDisconnected, kStateConnected)
842 (bind(&StateMachineFSC::Reconnect, this, placeholders::_1))
843 ("(Re)connect ethernet connection to FTM, a new address can be given"
844 "|[host][string]:new ethernet address in the form <host:port>");
845
846 fFSC.StartConnect();
847 }
848
849 void SetEndpoint(const string &url)
850 {
851 fFSC.SetEndpoint(url);
852 }
853
854 int EvalOptions(Configuration &conf)
855 {
856 SetEndpoint(conf.Get<string>("addr"));
857
858 fFSC.SetVerbose(!conf.Get<bool>("quiet"));
859
860 return -1;
861 }
862};
863
864// ------------------------------------------------------------------------
865
866#include "Main.h"
867
868template<class T, class S, class R>
869int RunShell(Configuration &conf)
870{
871 return Main::execute<T, StateMachineFSC<S, R>>(conf);
872}
873
874void SetupConfiguration(Configuration &conf)
875{
876 po::options_description control("FTM control options");
877 control.add_options()
878 ("no-dim", po_bool(), "Disable dim services")
879 ("addr,a", var<string>("localhost:5000"), "Network address of FTM")
880 ("quiet,q", po_bool(), "Disable printing contents of all received messages (except dynamic data) in clear text.")
881 ;
882
883 conf.AddOptions(control);
884}
885
886/*
887 Extract usage clause(s) [if any] for SYNOPSIS.
888 Translators: "Usage" and "or" here are patterns (regular expressions) which
889 are used to match the usage synopsis in program output. An example from cp
890 (GNU coreutils) which contains both strings:
891 Usage: cp [OPTION]... [-T] SOURCE DEST
892 or: cp [OPTION]... SOURCE... DIRECTORY
893 or: cp [OPTION]... -t DIRECTORY SOURCE...
894 */
895void PrintUsage()
896{
897 cout <<
898 "The ftmctrl controls the FSC (FACT Slow Control) board.\n"
899 "\n"
900 "The default is that the program is started without user intercation. "
901 "All actions are supposed to arrive as DimCommands. Using the -c "
902 "option, a local shell can be initialized. With h or help a short "
903 "help message about the usuage can be brought to the screen.\n"
904 "\n"
905 "Usage: fscctrl [-c type] [OPTIONS]\n"
906 " or: fscctrl [OPTIONS]\n";
907 cout << endl;
908}
909
910void PrintHelp()
911{
912 Main::PrintHelp<StateMachineFSC<StateMachine, ConnectionFSC>>();
913
914 /* Additional help text which is printed after the configuration
915 options goes here */
916
917 /*
918 cout << "bla bla bla" << endl << endl;
919 cout << endl;
920 cout << "Environment:" << endl;
921 cout << "environment" << endl;
922 cout << endl;
923 cout << "Examples:" << endl;
924 cout << "test exam" << endl;
925 cout << endl;
926 cout << "Files:" << endl;
927 cout << "files" << endl;
928 cout << endl;
929 */
930}
931
932int main(int argc, const char* argv[])
933{
934 Configuration conf(argv[0]);
935 conf.SetPrintUsage(PrintUsage);
936 Main::SetupConfiguration(conf);
937 SetupConfiguration(conf);
938
939 if (!conf.DoParse(argc, argv, PrintHelp))
940 return -1;
941
942 //try
943 {
944 // No console access at all
945 if (!conf.Has("console"))
946 {
947 if (conf.Get<bool>("no-dim"))
948 return RunShell<LocalStream, StateMachine, ConnectionFSC>(conf);
949 else
950 return RunShell<LocalStream, StateMachineDim, ConnectionDimFSC>(conf);
951 }
952 // Cosole access w/ and w/o Dim
953 if (conf.Get<bool>("no-dim"))
954 {
955 if (conf.Get<int>("console")==0)
956 return RunShell<LocalShell, StateMachine, ConnectionFSC>(conf);
957 else
958 return RunShell<LocalConsole, StateMachine, ConnectionFSC>(conf);
959 }
960 else
961 {
962 if (conf.Get<int>("console")==0)
963 return RunShell<LocalShell, StateMachineDim, ConnectionDimFSC>(conf);
964 else
965 return RunShell<LocalConsole, StateMachineDim, ConnectionDimFSC>(conf);
966 }
967 }
968 /*catch (std::exception& e)
969 {
970 cerr << "Exception: " << e.what() << endl;
971 return -1;
972 }*/
973
974 return 0;
975}
Note: See TracBrowser for help on using the repository browser.