FACT++  1.0
fscctrl.cc
Go to the documentation of this file.
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"
14 
15 #include "tools.h"
16 
17 #include "HeadersFSC.h"
18 
19 namespace ba = boost::asio;
20 namespace bs = boost::system;
21 namespace dummy = ba::placeholders;
22 
23 using namespace std;
24 using namespace FSC;
25 
26 // ------------------------------------------------------------------------
27 
28 class ConnectionFSC : public Connection
29 {
30  FSC::BinaryOutput_t fMsg; // A single message
31 
32  bool fIsVerbose;
34 
35  size_t fNumConsecutiveErrors; // Number of consecutive messages with errors
36  size_t fNumConsecutiveMessages; // Number of consecutive message which are ok
37 
38  boost::asio::deadline_timer fReconnectTimeout;
39 
40 protected:
41  vector<Interpolator2D::vec> fPositionsSensors;
42  vector<Interpolator2D::vec> fPositionsBias;
43 
44  virtual void UpdateTemp(float, const vector<float> &)
45  {
46  }
47 
48  virtual void UpdateHum(float, const vector<float>&)
49  {
50  }
51 
52  virtual void UpdateVolt(float, const vector<float>&)
53  {
54  }
55 
56  virtual void UpdateCur(float, const vector<float>&)
57  {
58  }
59 
60 private:
61  //
62  // From: http://de.wikipedia.org/wiki/Pt100
63  //
64  double GetTempPT1000(double R) const
65  {
66  // This is precise within the range 5degC and 25degC
67  // by 3e-3 degC. At 0degC and 30degC it overestimates the
68  // temperature by 0.025 degC. At -10degC it is ~0.9degC
69  // and at 40degC ~0.05degC.
70  const double x = R/1000;
71  return -193.804 + 96.0651*x + 134.673*x*x - 36.9091*x*x*x;
72 
73  //for a reasonable range:
74  // R=970 -> -7.6 degC
75  // R=1300 -> 77.6 degC
76 
77  //const double R0 = 1000; // 1kOhm
78  //const double a = 3.893e-3;
79  //return (R/R0 - 1)/a;
80  }
81 
83  {
84  const uint16_t volt_checksum = Tools::Fletcher16(fMsg.adc_values, kNumVoltageChannels);
85  const uint16_t resi_checksum = Tools::Fletcher16(fMsg.ad7719_values, kNumResistanceChannels);
86 
87  const bool volt_ok = volt_checksum == fMsg.adc_values_checksum;
88  const bool resi_ok = resi_checksum == fMsg.ad7719_values_checksum;
89 
90  if (volt_ok && resi_ok)
91  return true;
92 
93  fNumConsecutiveErrors++;
94 
95  ostringstream out;
96  out << "Checksum error (V:";
97  out << hex << setfill('0');
98 
99  if (volt_ok)
100  out << "----|----";
101  else
102  {
103  out << setw(4) << volt_checksum;
104  out << "|";
105  out << setw(4) << fMsg.adc_values_checksum;
106  }
107 
108  out << ", R:";
109 
110  if (resi_ok)
111  out << "----|----";
112  else
113  {
114  out << setw(4) << resi_checksum;
115  out << "|";
116  out << setw(4) << fMsg.ad7719_values_checksum;
117  }
118 
119  out << ", " << dec;
120  out << "Nok=" << fNumConsecutiveMessages << ", ";
121  out << "Nerr=" << fNumConsecutiveErrors << ")";
122 
123  Warn(out);
124 
125  fNumConsecutiveMessages = 0;
126 
127  return false;
128  }
129 
131  {
132  if (fIsVerbose)
133  Out() << "Received one_message of FSC::BinaryOutput_t ... will now process it" << endl;
134 
135  if (!CheckChecksum())
136  return false;
137 
138  // That looks a bit odd because it copies the values twice for no reason.
139  // This is historical and keeps the following code consistent with the
140  // previous code which was reading ascii data from the fsc
141  vector<float> volt(kNumVoltageChannels);
142  vector<float> resist(kNumResistanceChannels);
143 
144  const float time = fMsg.time_sec + fMsg.time_ms/1000.;
145 
146  // We want to convert the pure ADC values from the FSC board to mV and kOhm respectively
147  // So we do:
148  for (unsigned int i=0; i<volt.size(); i++)
149  volt[i] = fMsg.adc_values[i]*0.1;
150 
151  for (unsigned int i=0; i<resist.size(); i++)
152  resist[i] = fMsg.ad7719_values[i] * (6.25 * 1024) / (1 << 25);
153 
154  int mapv[] =
155  {
156  0, 16, 24, 8,
157  1, 17, 25, 9,
158  2, 18, 26, 10,
159  //
160  3, 19, 27, 11,
161  4, 20, 28, 12,
162  5, 21, 29, 13,
163  //
164  32, 36, 33, 34, 37, 38,
165  //
166  -1
167  };
168 
169  int mapc[] =
170  {
171  40, 56, 64, 48,
172  41, 57, 65, 49,
173  42, 58, 66, 50,
174  //
175  43, 59, 67, 51,
176  44, 60, 68, 52,
177  45, 61, 69, 53,
178  //
179  72, 76, 73, 74, 77, 78,
180  //
181  -1
182  };
183 
184 
185  int maprh[] =
186  {
187  80, 81, 82, 83, -1
188  };
189 
190  int offrh[] =
191  {
192  821, 822, 816, 822,
193  };
194 
195  int mapt[] =
196  {
197  // sensor compartment temperatures
198  0, 1, 2, 3, 4, 5, 6, 56, 57, 58, 59, 60,
199  61, 62, 32, 33, 34, 35, 36, 63, 37, 38, 39, 24,
200  25, 26, 27, 28, 29, 30, 31,
201  // crate temperatures (0-3, back/front)
202  12, 13, 52, 53, 44, 46, 20, 21,
203  //crate power supply temperatures (0-3)
204  8, 9, 48, 49, 40, 41, 16, 17,
205  // aux power supplies (FTM-side top/bot, FSC-side top/bot)
206  45, 50, 19, 42,
207  // backpanel (FTM-side top/bot, FSC-side top/bot)
208  11, 51, 18, 43,
209  // switch boxes (top front/back, bottom front/back)
210  15, 14, 47, 10,
211  //
212  -1
213  };
214 
215  vector<float> voltages;
216  vector<float> currents;
217  vector<float> humidities;
218  vector<float> temperatures;
219 
220  for (int *pv=mapv; *pv>=0; pv++)
221  voltages.push_back(volt[*pv]*0.001);
222 
223  for (int *pc=mapc; *pc>=0; pc++)
224  currents.push_back(volt[*pc]*0.005);
225 
226  for (int idx=0; idx<4; idx++)
227  {
228  voltages[idx +8] *= -1;
229  voltages[idx+20] *= -1;
230  currents[idx +8] *= -1;
231  currents[idx+20] *= -1;
232  }
233  voltages[12] *= 2;
234  voltages[13] *= 2;
235  voltages[14] *= 2;
236  voltages[15] *= 2;
237 
238  voltages[24] *= 2;
239  voltages[25] *= 2;
240 
241  voltages[27] *= -1;
242  voltages[29] *= -1;
243 
244  currents[27] *= -1;
245  currents[29] *= -1;
246 
247  int idx=0;
248  for (int *ph=maprh; *ph>=0; ph++, idx++)
249  humidities.push_back((volt[*ph]-offrh[idx])*0.0313);
250 
251  //1019=4.8
252  //1005=1.3
253  //970=-7.6
254  //1300=76
255  for (int *pt=mapt; *pt>=0; pt++)
256  //temperatures.push_back(resist[*pt]>800&&resist[*pt]<2000 ? GetTempPT1000(resist[*pt]) : 0);
257  temperatures.push_back(resist[*pt]>970&&resist[*pt]<1300 ? GetTempPT1000(resist[*pt]) : 0);
258  //temperatures.push_back(resist[*pt]>1019&&resist[*pt]<1300 ? GetTempPT1000(resist[*pt]) : 0);
259 
260  // 0 = 3-(3+0)%4
261  // 3 = 3-(3+1)%4
262  // 2 = 3-(3+2)%4
263  // 1 = 3-(3+3)%4
264 
265  /*
266  index unit offset scale crate for board:
267  0 mV 0 1 0 FAD 3.3V
268  24 mV 0 1 1 FAD 3.3V
269  16 mV 0 1 2 FAD 3.3V
270  8 mV 0 1 3 FAD 3.3V
271 
272  1 mV 0 1 0 FAD 3.3V
273  25 mV 0 1 1 FAD 3.3V
274  17 mV 0 1 2 FAD 3.3V
275  9 mV 0 1 3 FAD 3.3V
276 
277  2 mV 0 -1 0 FAD -2.0V
278  26 mV 0 -1 1 FAD -2.0V
279  18 mV 0 -1 2 FAD -2.0V
280  10 mV 0 -1 3 FAD -2.0V
281 
282  --
283 
284  3 mV 0 1 0 FPA 5.0V
285  27 mV 0 1 1 FPA 5.0V
286  19 mV 0 1 2 FPA 5.0V
287  11 mV 0 1 3 FPA 5.0V
288 
289  4 mV 0 1 0 FPA 3.3V
290  28 mV 0 1 1 FPA 3.3V
291  20 mV 0 1 2 FPA 3.3V
292  12 mV 0 1 3 FPA 3.3V
293 
294  5 mV 0 -1 0 FPA -3.3V
295  29 mV 0 -1 1 FPA -3.3V
296  21 mV 0 -1 2 FPA -3.3V
297  13 mV 0 -1 3 FPA -3.3V
298 
299  --
300 
301  32 mV 0 1 bottom ETH 5V
302  36 mV 0 1 top ETH 5V
303 
304  33 mV 0 1 bottom FTM 3.3V
305  34 mV 0 -1 bottom FTM -3.3V
306 
307  37 mV 0 1 top FFC 3.3V
308  38 mV 0 -1 top FLP -3.3V
309 
310  -----
311 
312  40 mA 0 5 0 FAD
313  64 mA 0 5 1 FAD
314  56 mA 0 5 2 FAD
315  48 mA 0 5 3 FAD
316 
317  41 mA 0 5 0 FAD
318  65 mA 0 5 1 FAD
319  57 mA 0 5 2 FAD
320  49 mA 0 5 3 FAD
321 
322  42 mA 0 -5 0 FAD
323  66 mA 0 -5 1 FAD
324  58 mA 0 -5 2 FAD
325  50 mA 0 -5 3 FAD
326 
327  --
328 
329  43 mA 0 5 0 FPA
330  67 mA 0 5 1 FPA
331  59 mA 0 5 2 FPA
332  51 mA 0 5 3 FPA
333 
334  44 mA 0 5 0 FPA
335  68 mA 0 5 1 FPA
336  60 mA 0 5 2 FPA
337  52 mA 0 5 3 FPA
338 
339  45 mA 0 -5 0 FPA
340  69 mA 0 -5 1 FPA
341  61 mA 0 -5 2 FPA
342  53 mA 0 -5 3 FPA
343 
344  ---
345 
346  72 mA 0 5 bottom ETH
347  76 mA 0 5 top ETH
348 
349  73 mA 0 5 bottom FTM
350  74 mA 0 -5 bottom FTM
351 
352  77 mA 0 5 top FFC
353  78 mA 0 -5 top FLP
354 
355  ----
356 
357  80 % RH -821 0.0313 FSP000
358  81 % RH -822 0.0313 FSP221
359  82 % RH -816 0.0313 Sector0
360  83 % RH -822 0.0313 Sector2
361  */
362 
363  // TEMPERATURES
364  // 31 x Sensor plate
365  // 8 x Crate
366  // 12 x PS
367  // 4 x Backpanel
368  // 4 x Switchbox
369 
370 
371 
372  /*
373  0 ohms FSP 000
374  1 ohms FSP 010
375  2 ohms FSP 023
376  3 ohms FSP 043
377  4 ohms FSP 072
378  5 ohms FSP 080
379  6 ohms FSP 092
380  56 ohms FSP 103
381  57 ohms FSP 111
382  58 ohms FSP 121
383  59 ohms FSP 152
384  60 ohms FSP 163
385  61 ohms FSP 171
386  62 ohms FSP 192
387  32 ohms FSP 200
388  33 ohms FSP 210
389  34 ohms FSP 223
390  35 ohms FSP 233
391  36 ohms FSP 243
392  63 ohms FSP 252
393  37 ohms FSP 280
394  38 ohms FSP 283
395  39 ohms FSP 293
396  24 ohms FSP 311
397  25 ohms FSP 321
398  26 ohms FSP 343
399  27 ohms FSP 352
400  28 ohms FSP 363
401  29 ohms FSP 371
402  30 ohms FSP 381
403  31 ohms FSP 392
404  8 ohms Crate0 ?
405  9 ohms Crate0 ?
406  48 ohms Crate1 ?
407  49 ohms Crate1 ?
408  40 ohms Crate2 ?
409  41 ohms Crate2 ?
410  16 ohms Crate3 ?
411  17 ohms Crate3 ?
412  10 ohms PS Crate 0
413  11 ohms PS Crate 0
414  50 ohms PS Crate 1
415  51 ohms PS Crate 1
416  42 ohms PS Crate 2
417  43 ohms PS Crate 2
418  18 ohms PS Crate 3
419  19 ohms PS Crate 3
420  12 ohms PS Aux0
421  52 ohms PS Aux0
422  20 ohms PS Aux1
423  44 ohms PS Aux1
424  13 ohms Backpanel ?
425  21 ohms Backpanel ?
426  45 ohms Backpanel ?
427  53 ohms Backpanel ?
428  14 ohms Switchbox0 ?
429  15 ohms Switchbox0 ?
430  46 ohms Switchbox1 ?
431  47 ohms Switchbox1 ?
432  7 ohms nc nc
433  22 ohms nc nc
434  23 ohms nc nc
435  54 ohms nc nc
436  55 ohms nc nc
437  */
438 
439  if (fIsVerbose)
440  {
441  for (size_t i=0; i<resist.size(); i++)
442  //if (resist[i]>800 && resist[i]<2000)
443  if (resist[i]>970 && resist[i]<1300)
444  //if (resist[i]>1019 && resist[i]<1300)
445  Out() << setw(2) << i << " - " << setw(4) << (int)resist[i] << ": " << setprecision(1) << fixed << GetTempPT1000(resist[i]) << endl;
446  else
447  Out() << setw(2) << i << " - " << setw(4) << (int)resist[i] << ": " << "----" << endl;
448  }
449 
450  UpdateTemp(time, temperatures);
451  UpdateVolt(time, voltages);
452  UpdateCur( time, currents);
453  UpdateHum( time, humidities);
454 
455  fNumConsecutiveErrors = 0;
456  fNumConsecutiveMessages++;
457 
458  return true;
459  }
460 
461  void StartRead()
462  {
463  ba::async_read(*this, ba::buffer(&fMsg, sizeof(FSC::BinaryOutput_t)),
464  boost::bind(&ConnectionFSC::HandleRead, this,
465  dummy::error, dummy::bytes_transferred));
466 
467  AsyncWait(fInTimeout, 35000, &Connection::HandleReadTimeout); // 30s
468  }
469 
470  void HandleRead(const boost::system::error_code& err, size_t bytes_received)
471  {
472  // Do not schedule a new read if the connection failed.
473  if (bytes_received==0 || err)
474  {
475  if (err==ba::error::eof)
476  return;
477 
478  // 107: Transport endpoint is not connected (bs::error_code(107, bs::system_category))
479  // 125: Operation canceled
480  if (err && err!=ba::error::eof && // Connection closed by remote host
481  err!=ba::error::basic_errors::not_connected && // Connection closed by remote host
482  err!=ba::error::basic_errors::operation_aborted) // Connection closed by us
483  {
484  ostringstream str;
485  str << "Reading from " << URL() << ": " << err.message() << " (" << err << ")";// << endl;
486  Error(str);
487  }
488  PostClose(err!=ba::error::basic_errors::operation_aborted);
489  return;
490  }
491 
492  if (!ProcessMessage())
493  {
494  fIsAutoReconnect = true;
495  fReconnectTimeout.expires_from_now(boost::posix_time::seconds(10));
496  fReconnectTimeout.async_wait(boost::bind(&ConnectionFSC::HandleReconnectTimeout,
497  this, dummy::error));
498  PostClose(true);
499  return;
500  }
501 
502  StartRead();
503  }
504 
506  {
507  fNumConsecutiveErrors = 0;
508  fNumConsecutiveMessages = 0;
509  fIsAutoReconnect = false;
510 
511  StartRead();
512  }
513 
514  void HandleReconnectTimeout(const bs::error_code &)
515  {
516  fIsAutoReconnect = false;
517  }
518 
519  void HandleReadTimeout(const bs::error_code &error)
520  {
521  if (error==ba::error::basic_errors::operation_aborted)
522  return;
523 
524  if (error)
525  {
526  ostringstream str;
527  str << "Read timeout of " << URL() << ": " << error.message() << " (" << error << ")";// << endl;
528  Error(str);
529 
530  PostClose();
531  return;
532 
533  }
534 
535  if (!is_open())
536  {
537  // For example: Here we could schedule a new accept if we
538  // would not want to allow two connections at the same time.
539  return;
540  }
541 
542  // Check whether the deadline has passed. We compare the deadline
543  // against the current time since a new asynchronous operation
544  // may have moved the deadline before this actor had a chance
545  // to run.
546  if (fInTimeout.expires_at() > ba::deadline_timer::traits_type::now())
547  return;
548 
549  Error("Timeout reading data from "+URL());
550 
551  PostClose();
552  }
553 
554 public:
555  ConnectionFSC(ba::io_service& ioservice, MessageImp &imp) : Connection(ioservice, imp()),
556  fIsVerbose(false), fIsAutoReconnect(false), fReconnectTimeout(ioservice)
557  {
558  SetLogStream(&imp);
559  }
560 
561  void SetVerbose(bool b)
562  {
563  fIsVerbose = b;
564  }
565 
566  void SetPositionsSensors(const vector<Interpolator2D::vec> &vec)
567  {
568  fPositionsSensors = vec;
569  }
570 
571  void SetPositionsBias(const vector<Interpolator2D::vec> &vec)
572  {
573  fPositionsBias = vec;
574  }
575 
576  bool IsOpen() const
577  {
578  return IsConnected() || fIsAutoReconnect;
579  }
580 };
581 
582 // ------------------------------------------------------------------------
583 
584 #include "DimDescriptionService.h"
585 
587 {
588 private:
589 
590  vector<double> fLastRms;
591 
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 
703 public:
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 
756 template <class T, class S>
758 {
759 private:
760  S fFSC;
761 
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.IsOpen() ? 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 
814 public:
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 
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 
882 template<class T, class S, class R>
884 {
885  return Main::execute<T, StateMachineFSC<S, R>>(conf);
886 }
887 
889 {
890  po::options_description control("FSC 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  */
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 
926 void 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 
948 int main(int argc, const char* argv[])
949 {
950  Configuration conf(argv[0]);
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 }
std::vector< double > Interpolate(const std::vector< double > &z) const
void HandleReconnectTimeout(const bs::error_code &)
Definition: fscctrl.cc:514
bool SetOutputGrid(std::size_t n, double *x, double *y)
Definition: HeadersFSC.h:4
void SetupConfiguration(Configuration &conf)
Definition: fscctrl.cc:888
void SetVerbose(bool b)
Definition: fscctrl.cc:561
ConnectionFSC(ba::io_service &ioservice, MessageImp &imp)
Definition: fscctrl.cc:555
uint32_t ad7719_values[kNumResistanceChannels]
Definition: HeadersFSC.h:30
bool CheckChecksum()
Definition: fscctrl.cc:82
A general base-class describing events issues in a state machine.
Definition: EventImp.h:11
int Disconnect()
Definition: fscctrl.cc:762
size_t fNumConsecutiveMessages
Definition: fscctrl.cc:36
void SetupConfiguration(Configuration &conf)
Definition: Main.h:25
int Reconnect(const EventImp &evt)
Definition: fscctrl.cc:770
virtual void UpdateTemp(float, const vector< float > &)
Definition: fscctrl.cc:44
int i
Definition: db_dim_client.c:21
The base implementation of a distributed messaging system.
Definition: MessageImp.h:10
void UpdateCur(float time, const vector< float > &curr)
Definition: fscctrl.cc:698
void PrintHelp()
Definition: fscctrl.cc:926
char str[80]
Definition: test_client.c:7
void SetPrintUsage(const std::function< void(void)> &func)
T Get(const std::string &var)
DimDescribedService fDimTemp
Definition: fscctrl.cc:592
bool fIsVerbose
Definition: fscctrl.cc:32
boost::asio::deadline_timer fReconnectTimeout
Definition: fscctrl.cc:38
FSC::BinaryOutput_t fMsg
Definition: fscctrl.cc:30
STL namespace.
vector< Interpolator2D::vec > fPositionsBias
Definition: fscctrl.cc:42
void UpdateHum(float time, const vector< float > &hum)
Definition: fscctrl.cc:688
void HandleRead(const boost::system::error_code &err, size_t bytes_received)
Definition: fscctrl.cc:470
DimDescribedService fDimCurrent
Definition: fscctrl.cc:596
virtual void UpdateCur(float, const vector< float > &)
Definition: fscctrl.cc:56
int main(int argc, const char *argv[])
Definition: fscctrl.cc:948
bool ProcessMessage()
Definition: fscctrl.cc:130
uint16_t Fletcher16(const T *t, size_t cnt)
Definition: tools.h:22
std::string GetString() const
Definition: EventImp.cc:194
float temp
Definition: HeadersPFmini.h:56
int SetVerbosity(const EventImp &evt)
Definition: fscctrl.cc:804
Extra- and interpolate in 2D.
int RunShell(Configuration &conf)
Definition: fscctrl.cc:883
void StartRead()
Definition: fscctrl.cc:461
virtual void UpdateHum(float, const vector< float > &)
Definition: fscctrl.cc:48
ConnectionDimFSC(ba::io_service &ioservice, MessageImp &imp)
Definition: fscctrl.cc:704
double GetTempPT1000(double R) const
Definition: fscctrl.cc:64
bool CheckEventSize(size_t has, const char *name, size_t size)
Definition: fscctrl.cc:793
void SetPositionsBias(const vector< Interpolator2D::vec > &vec)
Definition: fscctrl.cc:571
bool Has(const std::string &var)
void SetEndpoint(const string &url)
Definition: fscctrl.cc:844
vector< double > fLastRms
Definition: fscctrl.cc:590
void AddOptions(const po::options_description &opt, bool visible=true)
Definition: Configuration.h:92
size_t fNumConsecutiveErrors
Definition: fscctrl.cc:35
bool fIsAutoReconnect
Definition: fscctrl.cc:33
bool IsOpen() const
Definition: fscctrl.cc:576
Warning because the service this data corrsponds to might have been last updated longer ago than Local time
Definition: smartfact.txt:92
float hum
Definition: HeadersPFmini.h:55
Commandline parsing, resource file parsing and database access.
Definition: Configuration.h:9
int buffer[BUFFSIZE]
Definition: db_dim_client.c:14
uint16_t adc_values[kNumVoltageChannels]
Definition: HeadersFSC.h:38
void HandleReadTimeout(const bs::error_code &error)
Definition: fscctrl.cc:519
int size
Definition: db_dim_server.c:17
float data[4 *1440]
DimDescribedService fDimHum
Definition: fscctrl.cc:594
StateMachineFSC(ostream &out=cout)
Definition: fscctrl.cc:815
vector< Interpolator2D::vec > fPositionsSensors
Definition: fscctrl.cc:41
void ConnectionEstablished()
Definition: fscctrl.cc:505
virtual void HandleReadTimeout(const boost::system::error_code &)
Definition: Connection.h:138
bool GetBool() const
Definition: EventImp.h:90
void SetPositionsSensors(const vector< Interpolator2D::vec > &vec)
Definition: fscctrl.cc:566
void UpdateTemp(float time, const vector< float > &temp)
Definition: fscctrl.cc:604
Error()
Definition: HeadersFTM.h:197
uint16_t adc_values_checksum
Definition: HeadersFSC.h:39
static std::vector< Interpolator2D::vec > ReadGrid(const std::string &filename)
po::typed_value< bool > * po_bool(bool def=false)
void UpdateVolt(float time, const vector< float > &volt)
Definition: fscctrl.cc:693
void PrintUsage()
Definition: fscctrl.cc:911
void Update(DimDescribedService &svc, vector< float > data, float time) const
Definition: fscctrl.cc:598
DimDescribedService fDimVolt
Definition: fscctrl.cc:595
bool DoParse(int argc, const char **argv, const std::function< void()> &func=std::function< void()>())
virtual void UpdateVolt(float, const vector< float > &)
Definition: fscctrl.cc:52
uint16_t ad7719_values_checksum
Definition: HeadersFSC.h:31
int EvalOptions(Configuration &conf)
Definition: fscctrl.cc:849
DimDescribedService fDimTemp2
Definition: fscctrl.cc:593
virtual size_t GetSize() const
Definition: EventImp.h:55