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

Last change on this file since 13006 was 12954, checked in by tbretz, 13 years ago
Added include of LocalControl.h
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 for (size_t i=0; i<resist.size(); i++)
537 if (resist[i]>800 && resist[i]<2000)
538 cout << setw(2) << i << " - " << setw(4) << (int)resist[i] << ": " << setprecision(1) << fixed << GetTempPT1000(resist[i]) << endl;
539 else
540 cout << setw(2) << i << " - " << setw(4) << (int)resist[i] << ": " << "----" << endl;
541
542 UpdateTemp(time, temperatures);
543 UpdateVolt(time, voltages);
544 UpdateCur( time, currents);
545 UpdateHum( time, humidities);
546
547 StartRead();
548 }
549
550 void StartRead()
551 {
552 ba::async_read_until(*this, fBuffer, "end.\n",
553 boost::bind(&ConnectionFSC::HandleReceivedData, this,
554 dummy::error, dummy::bytes_transferred, 0));
555
556 // FIXME: Add timeout here
557 }
558
559 // This is called when a connection was established
560 void ConnectionEstablished()
561 {
562 PostMessage("m", 1);
563
564 fBuffer.prepare(10000);
565 StartRead();
566 }
567
568/*
569 void HandleReadTimeout(const bs::error_code &error)
570 {
571 if (error==ba::error::basic_errors::operation_aborted)
572 return;
573
574 if (error)
575 {
576 ostringstream str;
577 str << "Read timeout of " << URL() << ": " << error.message() << " (" << error << ")";// << endl;
578 Error(str);
579
580 PostClose();
581 return;
582
583 }
584
585 if (!is_open())
586 {
587 // For example: Here we could schedule a new accept if we
588 // would not want to allow two connections at the same time.
589 return;
590 }
591
592 // Check whether the deadline has passed. We compare the deadline
593 // against the current time since a new asynchronous operation
594 // may have moved the deadline before this actor had a chance
595 // to run.
596 if (fInTimeout.expires_at() > ba::deadline_timer::traits_type::now())
597 return;
598
599 Error("Timeout reading data from "+URL());
600
601 PostClose();
602 }
603*/
604
605public:
606 ConnectionFSC(ba::io_service& ioservice, MessageImp &imp) : Connection(ioservice, imp()),
607 fIsVerbose(true), fDump(false)
608 {
609 SetLogStream(&imp);
610 }
611
612 void SetVerbose(bool b)
613 {
614 fIsVerbose = b;
615 }
616
617 void SetDumpStream(bool b)
618 {
619 fDump = b;
620 }
621};
622
623// ------------------------------------------------------------------------
624
625#include "DimDescriptionService.h"
626
627class ConnectionDimFSC : public ConnectionFSC
628{
629private:
630
631 DimDescribedService fDimTemp;
632 DimDescribedService fDimHum;
633 DimDescribedService fDimVolt;
634 DimDescribedService fDimCurrent;
635
636 void Update(DimDescribedService &svc, vector<float> data, float time) const
637 {
638 data.insert(data.begin(), time);
639 svc.Update(data);
640 }
641
642 void UpdateTemp(float time, const vector<float> &temp)
643 {
644 Update(fDimTemp, temp, time);
645 }
646
647 void UpdateHum(float time, const vector<float> &hum)
648 {
649 Update(fDimHum, hum, time);
650 }
651
652 void UpdateVolt(float time, const vector<float> &volt)
653 {
654 Update(fDimVolt, volt, time);
655 }
656
657 void UpdateCur(float time, const vector<float> &curr)
658 {
659 Update(fDimCurrent, curr, time);
660 }
661
662public:
663 ConnectionDimFSC(ba::io_service& ioservice, MessageImp &imp) :
664 ConnectionFSC(ioservice, imp),
665 fDimTemp ("FSC_CONTROL/TEMPERATURE", "F:1;F:31;F:8;F:8;F:4;F:4;F:4",
666 "|t[s]:FSC uptime"
667 "|T_sens[deg C]:Sensor compartment temperatures"
668 "|T_crate[deg C]:Temperatures crate 0 (back/front), 1 (back/front), 2 (back/front), 3 (back/front)"
669 "|T_ps[deg C]:Temperatures power supplies crate 0 (back/front), 1 (back/front), 2 (back/front), 3 (back/front)"
670 "|T_aux[deg C]:Auxiliary power supply temperatures FTM (top/bottom), FSC (top/bottom)"
671 "|T_back[deg C]:FTM backpanel temperatures FTM (top/bottom), FSC (top/bottom)"
672 "|T_eth[deg C]:Ethernet switches temperatures top (front/back), bottom (front/back)"),
673 fDimHum ("FSC_CONTROL/HUMIDITY", "F:1;F:4",
674 "|t[s]:FSC uptime"
675 "|H[%]:Humidity sensors readout"),
676 fDimVolt ("FSC_CONTROL/VOLTAGE",
677 "F:1;F:4;F:4;F:4;F:4;F:4;F:4;F:2;F:2;F:1;F:1",
678 "|t[s]:FSC uptime"
679 "|FAD_Ud[V]:FAD digital (crate 0-3)"
680 "|FAD_Up[V]:FAD positive (crate 0-3)"
681 "|FAD_Un[V]:FAD negative (crate 0-3)"
682 "|FPA_Ud[V]:FPA digital (crate 0-3)"
683 "|FPA_Up[V]:FPA positive (crate 0-3)"
684 "|FPA_Un[V]:FPA negative (crate 0-3)"
685 "|ETH_U[V]:Ethernet switch (pos/neg)"
686 "|FTM_U[V]:FTM - trigger master (pos/neg)"
687 "|FFC_U[V]:FFC"
688 "|FLP_U[V]:FLP - light pulser"),
689 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",
690 "|t[s]:FSC uptime"
691 "|FAD_Id[A]:FAD digital (crate 0-3)"
692 "|FAD_Ip[A]:FAD positive (crate 0-3)"
693 "|FAD_In[A]:FAD negative (crate 0-3)"
694 "|FPA_Id[A]:FPA digital (crate 0-3)"
695 "|FPA_Ip[A]:FPA positive (crate 0-3)"
696 "|FPA_In[A]:FPA negative (crate 0-3)"
697 "|ETH_I[A]:Ethernet switch (pos/neg)"
698 "|FTM_I[A]:FTM - trigger master (pos/neg)"
699 "|FFC_I[A]:FFC"
700 "|FLP_I[A]:FLP - light pulser")
701 {
702 }
703
704 // 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
705};
706
707// ------------------------------------------------------------------------
708
709template <class T, class S>
710class StateMachineFSC : public T, public ba::io_service, public ba::io_service::work
711{
712 int Wrap(boost::function<void()> f)
713 {
714 f();
715 return T::GetCurrentState();
716 }
717
718 function<int(const EventImp &)> Wrapper(function<void()> func)
719 {
720 return bind(&StateMachineFSC::Wrap, this, func);
721 }
722
723private:
724 S fFSC;
725
726 enum states_t
727 {
728 kStateDisconnected = 1,
729 kStateConnected = 2,
730 };
731
732 int Disconnect()
733 {
734 // Close all connections
735 fFSC.PostClose(false);
736
737 /*
738 // Now wait until all connection have been closed and
739 // all pending handlers have been processed
740 poll();
741 */
742
743 return T::GetCurrentState();
744 }
745
746 int Reconnect(const EventImp &evt)
747 {
748 // Close all connections to supress the warning in SetEndpoint
749 fFSC.PostClose(false);
750
751 // Now wait until all connection have been closed and
752 // all pending handlers have been processed
753 poll();
754
755 if (evt.GetBool())
756 fFSC.SetEndpoint(evt.GetString());
757
758 // Now we can reopen the connection
759 fFSC.PostClose(true);
760
761 return T::GetCurrentState();
762 }
763
764 int Execute()
765 {
766 // Dispatch (execute) at most one handler from the queue. In contrary
767 // to run_one(), it doesn't wait until a handler is available
768 // which can be dispatched, so poll_one() might return with 0
769 // handlers dispatched. The handlers are always dispatched/executed
770 // synchronously, i.e. within the call to poll_one()
771 poll_one();
772
773 return fFSC.IsConnected() ? kStateConnected : kStateDisconnected;
774 }
775
776 bool CheckEventSize(size_t has, const char *name, size_t size)
777 {
778 if (has==size)
779 return true;
780
781 ostringstream msg;
782 msg << name << " - Received event has " << has << " bytes, but expected " << size << ".";
783 T::Fatal(msg);
784 return false;
785 }
786
787 int SetVerbosity(const EventImp &evt)
788 {
789 if (!CheckEventSize(evt.GetSize(), "SetVerbosity", 1))
790 return T::kSM_FatalError;
791
792 fFSC.SetVerbose(evt.GetBool());
793
794 return T::GetCurrentState();
795 }
796
797 int SetDumpStream(const EventImp &evt)
798 {
799 if (!CheckEventSize(evt.GetSize(), "SetDumpStream", 1))
800 return T::kSM_FatalError;
801
802 fFSC.SetDumpStream(evt.GetBool());
803
804 return T::GetCurrentState();
805 }
806
807public:
808 StateMachineFSC(ostream &out=cout) :
809 T(out, "FSC_CONTROL"), ba::io_service::work(static_cast<ba::io_service&>(*this)),
810 fFSC(*this, *this)
811 {
812 // ba::io_service::work is a kind of keep_alive for the loop.
813 // It prevents the io_service to go to stopped state, which
814 // would prevent any consecutive calls to run()
815 // or poll() to do nothing. reset() could also revoke to the
816 // previous state but this might introduce some overhead of
817 // deletion and creation of threads and more.
818
819 // State names
820 AddStateName(kStateDisconnected, "Disconnected",
821 "FSC board not connected via ethernet.");
822
823 AddStateName(kStateConnected, "Connected",
824 "Ethernet connection to FSC established.");
825
826 // Verbosity commands
827 T::AddEvent("SET_VERBOSE", "B:1")
828 (bind(&StateMachineFSC::SetVerbosity, this, placeholders::_1))
829 ("set verbosity state"
830 "|verbosity[bool]:disable or enable verbosity for received data (yes/no), except dynamic data");
831
832 T::AddEvent("DUMP_STREAM", "B:1")
833 (bind(&StateMachineFSC::SetDumpStream, this, placeholders::_1))
834 (""
835 "");
836
837 // Conenction commands
838 AddEvent("DISCONNECT", kStateConnected)
839 (bind(&StateMachineFSC::Disconnect, this))
840 ("disconnect from ethernet");
841
842 AddEvent("RECONNECT", "O", kStateDisconnected, kStateConnected)
843 (bind(&StateMachineFSC::Reconnect, this, placeholders::_1))
844 ("(Re)connect ethernet connection to FTM, a new address can be given"
845 "|[host][string]:new ethernet address in the form <host:port>");
846
847 fFSC.StartConnect();
848 }
849
850 void SetEndpoint(const string &url)
851 {
852 fFSC.SetEndpoint(url);
853 }
854
855 int EvalOptions(Configuration &conf)
856 {
857 SetEndpoint(conf.Get<string>("addr"));
858
859 fFSC.SetVerbose(!conf.Get<bool>("quiet"));
860
861 return -1;
862 }
863};
864
865// ------------------------------------------------------------------------
866
867#include "Main.h"
868
869template<class T, class S, class R>
870int RunShell(Configuration &conf)
871{
872 return Main::execute<T, StateMachineFSC<S, R>>(conf);
873}
874
875void SetupConfiguration(Configuration &conf)
876{
877 po::options_description control("FTM control options");
878 control.add_options()
879 ("no-dim", po_bool(), "Disable dim services")
880 ("addr,a", var<string>("localhost:5000"), "Network address of FTM")
881 ("quiet,q", po_bool(), "Disable printing contents of all received messages (except dynamic data) in clear text.")
882 ;
883
884 conf.AddOptions(control);
885}
886
887/*
888 Extract usage clause(s) [if any] for SYNOPSIS.
889 Translators: "Usage" and "or" here are patterns (regular expressions) which
890 are used to match the usage synopsis in program output. An example from cp
891 (GNU coreutils) which contains both strings:
892 Usage: cp [OPTION]... [-T] SOURCE DEST
893 or: cp [OPTION]... SOURCE... DIRECTORY
894 or: cp [OPTION]... -t DIRECTORY SOURCE...
895 */
896void PrintUsage()
897{
898 cout <<
899 "The ftmctrl controls the FSC (FACT Slow Control) board.\n"
900 "\n"
901 "The default is that the program is started without user intercation. "
902 "All actions are supposed to arrive as DimCommands. Using the -c "
903 "option, a local shell can be initialized. With h or help a short "
904 "help message about the usuage can be brought to the screen.\n"
905 "\n"
906 "Usage: fscctrl [-c type] [OPTIONS]\n"
907 " or: fscctrl [OPTIONS]\n";
908 cout << endl;
909}
910
911void PrintHelp()
912{
913 Main::PrintHelp<StateMachineFSC<StateMachine, ConnectionFSC>>();
914
915 /* Additional help text which is printed after the configuration
916 options goes here */
917
918 /*
919 cout << "bla bla bla" << endl << endl;
920 cout << endl;
921 cout << "Environment:" << endl;
922 cout << "environment" << endl;
923 cout << endl;
924 cout << "Examples:" << endl;
925 cout << "test exam" << endl;
926 cout << endl;
927 cout << "Files:" << endl;
928 cout << "files" << endl;
929 cout << endl;
930 */
931}
932
933int main(int argc, const char* argv[])
934{
935 Configuration conf(argv[0]);
936 conf.SetPrintUsage(PrintUsage);
937 Main::SetupConfiguration(conf);
938 SetupConfiguration(conf);
939
940 if (!conf.DoParse(argc, argv, PrintHelp))
941 return -1;
942
943 //try
944 {
945 // No console access at all
946 if (!conf.Has("console"))
947 {
948 if (conf.Get<bool>("no-dim"))
949 return RunShell<LocalStream, StateMachine, ConnectionFSC>(conf);
950 else
951 return RunShell<LocalStream, StateMachineDim, ConnectionDimFSC>(conf);
952 }
953 // Cosole access w/ and w/o Dim
954 if (conf.Get<bool>("no-dim"))
955 {
956 if (conf.Get<int>("console")==0)
957 return RunShell<LocalShell, StateMachine, ConnectionFSC>(conf);
958 else
959 return RunShell<LocalConsole, StateMachine, ConnectionFSC>(conf);
960 }
961 else
962 {
963 if (conf.Get<int>("console")==0)
964 return RunShell<LocalShell, StateMachineDim, ConnectionDimFSC>(conf);
965 else
966 return RunShell<LocalConsole, StateMachineDim, ConnectionDimFSC>(conf);
967 }
968 }
969 /*catch (std::exception& e)
970 {
971 cerr << "Exception: " << e.what() << endl;
972 return -1;
973 }*/
974
975 return 0;
976}
Note: See TracBrowser for help on using the repository browser.