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

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