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

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