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

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