source: branches/fscctrl_safety_limits/src/fscctrl.cc@ 18341

Last change on this file since 18341 was 18341, checked in by dneise, 9 years ago
Starting with Current limits: * define limits in config-file, or config-DB * add new state 'OverCurrent' * add some functionality to make SET_VERBOSE look different. (maybe not meant to stay forever)
File size: 40.0 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 bool fIsAutoReconnect;
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
40protected:
41 vector<Interpolator2D::vec> fPositionsSensors;
42 vector<Interpolator2D::vec> fPositionsBias;
43 FSC::SecurityCurrentLimits fSecurityCurrentLimits;
44 bool fSecurityLimitsExceeded;
45
46 virtual void UpdateTemp(float, const vector<float> &)
47 {
48 }
49
50 virtual void UpdateHum(float, const vector<float>&)
51 {
52 }
53
54 virtual void UpdateVolt(float, const vector<float>&)
55 {
56 }
57
58 virtual void UpdateCur(float, const vector<float>&)
59 {
60 }
61
62private:
63 //
64 // From: http://de.wikipedia.org/wiki/Pt100
65 //
66 double GetTempPT1000(double R) const
67 {
68 // This is precise within the range 5degC and 25degC
69 // by 3e-3 degC. At 0degC and 30degC it overestimates the
70 // temperature by 0.025 degC. At -10degC it is ~0.9degC
71 // and at 40degC ~0.05degC.
72 const double x = R/1000;
73 return -193.804 + 96.0651*x + 134.673*x*x - 36.9091*x*x*x;
74
75 //for a reasonable range:
76 // R=970 -> -7.6 degC
77 // R=1300 -> 77.6 degC
78
79 //const double R0 = 1000; // 1kOhm
80 //const double a = 3.893e-3;
81 //return (R/R0 - 1)/a;
82 }
83
84 bool CheckChecksum()
85 {
86 const uint16_t volt_checksum = Tools::Fletcher16(fMsg.adc_values, kNumVoltageChannels);
87 const uint16_t resi_checksum = Tools::Fletcher16(fMsg.ad7719_values, kNumResistanceChannels);
88
89 const bool volt_ok = volt_checksum == fMsg.adc_values_checksum;
90 const bool resi_ok = resi_checksum == fMsg.ad7719_values_checksum;
91
92 if (volt_ok && resi_ok)
93 return true;
94
95 fNumConsecutiveErrors++;
96
97 ostringstream out;
98 out << "Checksum error (V:";
99 out << hex << setfill('0');
100
101 if (volt_ok)
102 out << "----|----";
103 else
104 {
105 out << setw(4) << volt_checksum;
106 out << "|";
107 out << setw(4) << fMsg.adc_values_checksum;
108 }
109
110 out << ", R:";
111
112 if (resi_ok)
113 out << "----|----";
114 else
115 {
116 out << setw(4) << resi_checksum;
117 out << "|";
118 out << setw(4) << fMsg.ad7719_values_checksum;
119 }
120
121 out << ", " << dec;
122 out << "Nok=" << fNumConsecutiveMessages << ", ";
123 out << "Nerr=" << fNumConsecutiveErrors << ")";
124
125 Warn(out);
126
127 fNumConsecutiveMessages = 0;
128
129 return false;
130 }
131
132 bool ProcessMessage()
133 {
134 if (fIsVerbose)
135 Out() << "Received one_message of FSC::BinaryOutput_t ... will now process it" << endl;
136
137 if (!CheckChecksum())
138 return false;
139
140 // That looks a bit odd because it copies the values twice for no reason.
141 // This is historical and keeps the following code consistent with the
142 // previous code which was reading ascii data from the fsc
143 vector<float> volt( fMsg.adc_values, fMsg.adc_values + kNumVoltageChannels);
144 vector<float> resist(fMsg.ad7719_values, fMsg.ad7719_values + kNumResistanceChannels);
145
146 const float time = fMsg.time_sec + fMsg.time_ms/1000.;
147
148 // We want to convert the pure ADC values from the FSC board to mV and kOhm respectively
149 // So we do:
150 for (unsigned int i=0; i<volt.size(); i++)
151 volt[i] /= 10;
152
153 for (unsigned int i=0; i<resist.size(); i++)
154 resist[i] *= (6.25 * 1024) / (1 << 25);
155
156 int mapv[] =
157 {
158 0, 16, 24, 8,
159 1, 17, 25, 9,
160 2, 18, 26, 10,
161 //
162 3, 19, 27, 11,
163 4, 20, 28, 12,
164 5, 21, 29, 13,
165 //
166 32, 36, 33, 34, 37, 38,
167 //
168 -1
169 };
170
171 int mapc[] =
172 {
173 40, 56, 64, 48,
174 41, 57, 65, 49,
175 42, 58, 66, 50,
176 //
177 43, 59, 67, 51,
178 44, 60, 68, 52,
179 45, 61, 69, 53,
180 //
181 72, 76, 73, 74, 77, 78,
182 //
183 -1
184 };
185
186
187 int maprh[] =
188 {
189 80, 81, 82, 83, -1
190 };
191
192 int offrh[] =
193 {
194 821, 822, 816, 822,
195 };
196
197 int mapt[] =
198 {
199 // sensor compartment temperatures
200 0, 1, 2, 3, 4, 5, 6, 56, 57, 58, 59, 60,
201 61, 62, 32, 33, 34, 35, 36, 63, 37, 38, 39, 24,
202 25, 26, 27, 28, 29, 30, 31,
203 // crate temperatures (0-3, back/front)
204 12, 13, 52, 53, 44, 46, 20, 21,
205 //crate power supply temperatures (0-3)
206 8, 9, 48, 49, 40, 41, 16, 17,
207 // aux power supplies (FTM-side top/bot, FSC-side top/bot)
208 45, 50, 19, 42,
209 // backpanel (FTM-side top/bot, FSC-side top/bot)
210 11, 51, 18, 43,
211 // switch boxes (top front/back, bottom front/back)
212 15, 14, 47, 10,
213 //
214 -1
215 };
216
217 vector<float> voltages;
218 vector<float> currents;
219 vector<float> humidities;
220 vector<float> temperatures;
221
222 for (int *pv=mapv; *pv>=0; pv++)
223 voltages.push_back(volt[*pv]*0.001);
224
225 for (int *pc=mapc; *pc>=0; pc++)
226 currents.push_back(volt[*pc]*0.005);
227
228 for (int idx=0; idx<4; idx++)
229 {
230 voltages[idx +8] *= -1;
231 voltages[idx+20] *= -1;
232 currents[idx +8] *= -1;
233 currents[idx+20] *= -1;
234 }
235 voltages[12] *= 2;
236 voltages[13] *= 2;
237 voltages[14] *= 2;
238 voltages[15] *= 2;
239
240 voltages[24] *= 2;
241 voltages[25] *= 2;
242
243 voltages[27] *= -1;
244 voltages[29] *= -1;
245
246 currents[27] *= -1;
247 currents[29] *= -1;
248
249 int idx=0;
250 for (int *ph=maprh; *ph>=0; ph++, idx++)
251 humidities.push_back((volt[*ph]-offrh[idx])*0.0313);
252
253 //1019=4.8
254 //1005=1.3
255 //970=-7.6
256 //1300=76
257 for (int *pt=mapt; *pt>=0; pt++)
258 //temperatures.push_back(resist[*pt]>800&&resist[*pt]<2000 ? GetTempPT1000(resist[*pt]) : 0);
259 temperatures.push_back(resist[*pt]>970&&resist[*pt]<1300 ? GetTempPT1000(resist[*pt]) : 0);
260 //temperatures.push_back(resist[*pt]>1019&&resist[*pt]<1300 ? GetTempPT1000(resist[*pt]) : 0);
261
262 // 0 = 3-(3+0)%4
263 // 3 = 3-(3+1)%4
264 // 2 = 3-(3+2)%4
265 // 1 = 3-(3+3)%4
266
267 /*
268 index unit offset scale crate for board:
269 0 mV 0 1 0 FAD 3.3V
270 24 mV 0 1 1 FAD 3.3V
271 16 mV 0 1 2 FAD 3.3V
272 8 mV 0 1 3 FAD 3.3V
273
274 1 mV 0 1 0 FAD 3.3V
275 25 mV 0 1 1 FAD 3.3V
276 17 mV 0 1 2 FAD 3.3V
277 9 mV 0 1 3 FAD 3.3V
278
279 2 mV 0 -1 0 FAD -2.0V
280 26 mV 0 -1 1 FAD -2.0V
281 18 mV 0 -1 2 FAD -2.0V
282 10 mV 0 -1 3 FAD -2.0V
283
284 --
285
286 3 mV 0 1 0 FPA 5.0V
287 27 mV 0 1 1 FPA 5.0V
288 19 mV 0 1 2 FPA 5.0V
289 11 mV 0 1 3 FPA 5.0V
290
291 4 mV 0 1 0 FPA 3.3V
292 28 mV 0 1 1 FPA 3.3V
293 20 mV 0 1 2 FPA 3.3V
294 12 mV 0 1 3 FPA 3.3V
295
296 5 mV 0 -1 0 FPA -3.3V
297 29 mV 0 -1 1 FPA -3.3V
298 21 mV 0 -1 2 FPA -3.3V
299 13 mV 0 -1 3 FPA -3.3V
300
301 --
302
303 32 mV 0 1 bottom ETH 5V
304 36 mV 0 1 top ETH 5V
305
306 33 mV 0 1 bottom FTM 3.3V
307 34 mV 0 -1 bottom FTM -3.3V
308
309 37 mV 0 1 top FFC 3.3V
310 38 mV 0 -1 top FLP -3.3V
311
312 -----
313
314 40 mA 0 5 0 FAD
315 64 mA 0 5 1 FAD
316 56 mA 0 5 2 FAD
317 48 mA 0 5 3 FAD
318
319 41 mA 0 5 0 FAD
320 65 mA 0 5 1 FAD
321 57 mA 0 5 2 FAD
322 49 mA 0 5 3 FAD
323
324 42 mA 0 -5 0 FAD
325 66 mA 0 -5 1 FAD
326 58 mA 0 -5 2 FAD
327 50 mA 0 -5 3 FAD
328
329 --
330
331 43 mA 0 5 0 FPA
332 67 mA 0 5 1 FPA
333 59 mA 0 5 2 FPA
334 51 mA 0 5 3 FPA
335
336 44 mA 0 5 0 FPA
337 68 mA 0 5 1 FPA
338 60 mA 0 5 2 FPA
339 52 mA 0 5 3 FPA
340
341 45 mA 0 -5 0 FPA
342 69 mA 0 -5 1 FPA
343 61 mA 0 -5 2 FPA
344 53 mA 0 -5 3 FPA
345
346 ---
347
348 72 mA 0 5 bottom ETH
349 76 mA 0 5 top ETH
350
351 73 mA 0 5 bottom FTM
352 74 mA 0 -5 bottom FTM
353
354 77 mA 0 5 top FFC
355 78 mA 0 -5 top FLP
356
357 ----
358
359 80 % RH -821 0.0313 FSP000
360 81 % RH -822 0.0313 FSP221
361 82 % RH -816 0.0313 Sector0
362 83 % RH -822 0.0313 Sector2
363 */
364
365 // TEMPERATURES
366 // 31 x Sensor plate
367 // 8 x Crate
368 // 12 x PS
369 // 4 x Backpanel
370 // 4 x Switchbox
371
372
373
374 /*
375 0 ohms FSP 000
376 1 ohms FSP 010
377 2 ohms FSP 023
378 3 ohms FSP 043
379 4 ohms FSP 072
380 5 ohms FSP 080
381 6 ohms FSP 092
382 56 ohms FSP 103
383 57 ohms FSP 111
384 58 ohms FSP 121
385 59 ohms FSP 152
386 60 ohms FSP 163
387 61 ohms FSP 171
388 62 ohms FSP 192
389 32 ohms FSP 200
390 33 ohms FSP 210
391 34 ohms FSP 223
392 35 ohms FSP 233
393 36 ohms FSP 243
394 63 ohms FSP 252
395 37 ohms FSP 280
396 38 ohms FSP 283
397 39 ohms FSP 293
398 24 ohms FSP 311
399 25 ohms FSP 321
400 26 ohms FSP 343
401 27 ohms FSP 352
402 28 ohms FSP 363
403 29 ohms FSP 371
404 30 ohms FSP 381
405 31 ohms FSP 392
406 8 ohms Crate0 ?
407 9 ohms Crate0 ?
408 48 ohms Crate1 ?
409 49 ohms Crate1 ?
410 40 ohms Crate2 ?
411 41 ohms Crate2 ?
412 16 ohms Crate3 ?
413 17 ohms Crate3 ?
414 10 ohms PS Crate 0
415 11 ohms PS Crate 0
416 50 ohms PS Crate 1
417 51 ohms PS Crate 1
418 42 ohms PS Crate 2
419 43 ohms PS Crate 2
420 18 ohms PS Crate 3
421 19 ohms PS Crate 3
422 12 ohms PS Aux0
423 52 ohms PS Aux0
424 20 ohms PS Aux1
425 44 ohms PS Aux1
426 13 ohms Backpanel ?
427 21 ohms Backpanel ?
428 45 ohms Backpanel ?
429 53 ohms Backpanel ?
430 14 ohms Switchbox0 ?
431 15 ohms Switchbox0 ?
432 46 ohms Switchbox1 ?
433 47 ohms Switchbox1 ?
434 7 ohms nc nc
435 22 ohms nc nc
436 23 ohms nc nc
437 54 ohms nc nc
438 55 ohms nc nc
439 */
440
441 CheckCurrentLimits(currents);
442 if (fIsVerbose)
443 {
444 /*
445 for (size_t i=0; i<resist.size(); i++)
446 //if (resist[i]>800 && resist[i]<2000)
447 if (resist[i]>970 && resist[i]<1300)
448 //if (resist[i]>1019 && resist[i]<1300)
449 Out() << setw(2) << i << " - " << setw(4) << (int)resist[i] << ": " << setprecision(1) << fixed << GetTempPT1000(resist[i]) << endl;
450 else
451 Out() << setw(2) << i << " - " << setw(4) << (int)resist[i] << ": " << "----" << endl;
452 */
453 PrintTemperaturesNicely(temperatures);
454 PrintVoltagesNicely(voltages, currents);
455 Out() << "\n" << "fSecurityLimitsExceeded:" << fSecurityLimitsExceeded << endl;
456 }
457
458 UpdateTemp(time, temperatures);
459 UpdateVolt(time, voltages);
460 UpdateCur( time, currents);
461 UpdateHum( time, humidities);
462
463 fNumConsecutiveErrors = 0;
464 fNumConsecutiveMessages++;
465
466
467 return true;
468 }
469
470 void PrintTemperaturesNicely(const vector<float> &t)
471 {
472 /*
473 "FSC_CONTROL/TEMPERATURE", "F:1;F:31;F:8;F:8;F:4;F:4;F:4",
474 "|t[s]:FSC uptime"
475 "|T_sens[deg C]:Sensor compartment temperatures"
476 "|T_crate[deg C]:Temperatures crate 0 (back/front), 1 (b/f), 2 (b/f), 3 (b/f)"
477 "|T_ps[deg C]:Temp power supplies crate 0 (back/front), 1, 2, 3"
478 "|T_aux[deg C]:Auxiliary power supply temperatures FTM (top/bottom), FSC (t/b)"
479 "|T_back[deg C]:FTM backpanel temperatures FTM (top/bottom), FSC (top/bottom)"
480 "|T_eth[deg C]:Ethernet switches temperatures top (front/back), bottom (f/b)"),
481 // sensor compartment temperatures
482 0, 1, 2, 3, 4, 5, 6, 56, 57, 58, 59, 60,
483 61, 62, 32, 33, 34, 35, 36, 63, 37, 38, 39, 24,
484 25, 26, 27, 28, 29, 30, 31,
485 // crate temperatures (0-3, back/front)
486 12, 13, 52, 53, 44, 46, 20, 21,
487 //crate power supply temperatures (0-3)
488 8, 9, 48, 49, 40, 41, 16, 17,
489 // aux power supplies (FTM-side top/bot, FSC-side top/bot)
490 45, 50, 19, 42,
491 // backpanel (FTM-side top/bot, FSC-side top/bot)
492 11, 51, 18, 43,
493 // switch boxes (top front/back, bottom front/back)
494 15, 14, 47, 10,
495 */
496 //Out() << "0 1 2 3 4 5 6 7 " << endl;
497 //Out() << "01234567890123456789012345678901234567890123456789012345678901234567890123456789" << endl;
498 Out() << ". - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . -." << endl;
499 Out() << "T_sens:";
500 for (int i=0; i<31; i++){
501 if (i%16==0){
502 Out() << "\n";
503 }
504 Out() << setw(4) << setprecision(1) << fixed << t[i] << " ";
505 }
506 Out() << endl;
507 Out() << ". - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . -." << endl;
508
509 Out() << "T_crate: (B:back, F:front)" << endl;
510 Out() << "0: B| F|1: B| F|2: B| F|3: B| F|" << endl;
511 for (int i=31; i<31+8; i++){
512 Out() << setw(4) << setprecision(1) << fixed << t[i] << "|";
513 }
514 Out() << endl;
515 Out() << ". - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . -." << endl;
516
517 Out() << "T_ps: crate power supplies (B:back, F:front)" << endl;
518 Out() << "0: B| F|1: B| F|2: B| F|3: B| F|" << endl;
519 for (int i=31+8; i<31+8+8; i++){
520 Out() << setw(4) << setprecision(1) << fixed << t[i] << "|";
521 }
522 Out() << endl;
523 Out() << ". - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . -." << endl;
524 Out() << "T_aux: auxiliary power supplies" << endl;
525 Out() << "FTM top| bot|FSC top| bot|" << endl;
526 for (int i=31+8+8; i<31+8+8+4; i++){
527 Out() << setw(7) << setprecision(1) << fixed << t[i] << "|";
528 }
529 Out() << endl;
530 Out() << ". - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . -." << endl;
531 Out() << "T_back: backpanel temperatures" << endl;
532 Out() << "FTM top| bot|FSC top| bot|" << endl;
533 for (int i=31+8+8+4; i<31+8+8+4+4; i++){
534 Out() << setw(7) << setprecision(1) << fixed << t[i] << "|";
535 }
536 Out() << endl;
537 Out() << ". - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . -." << endl;
538 Out() << "T_ethernet: switch boxes" << endl;
539 Out() << "top front| back|bot front| back|" << endl;
540 for (int i=31+8+8+4; i<31+8+8+4+4; i++){
541 Out() << setw(9) << setprecision(1) << fixed << t[i] << "|";
542 }
543 Out() << endl;
544 Out() << ". - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . -." << endl;
545 }
546
547 void PrintVoltagesNicely(const vector<float> &v, const vector<float> &c)
548 {
549 /*
550
551 F:4;F:4;F:4;F:4;F:4;F:4;F:2;F:2;F:1;F:1",
552
553 "|FAD_Ud[V]:FAD digital (crate 0-3)"
554 "|FAD_Up[V]:FAD positive (crate 0-3)"
555 "|FAD_Un[V]:FAD negative (crate 0-3)"
556 "|FPA_Ud[V]:FPA digital (crate 0-3)"
557 "|FPA_Up[V]:FPA positive (crate 0-3)"
558 "|FPA_Un[V]:FPA negative (crate 0-3)"
559
560 "|ETH_U[V]:Ethernet switch (pos/neg)"
561 "|FTM_U[V]:FTM - trigger master (pos/neg)"
562 "|FFC_U[V]:FFC"
563 "|FLP_U[V]:FLP - light pulser"),
564 */
565 const char* const voltage_names[] = {
566 "FAD_d | ",
567 "FAD_p | ",
568 "FAD_n | ",
569 "FPA_d | ",
570 "FPA_p | ",
571 "FPA_n | ",
572 "Etherne| ",
573 "FTM | ",
574 "FFC | ",
575 "FLP | ",
576 };
577 const int length_per_group[] = {
578 4, 4, 4, 4, 4, 4, 2, 2, 1, 1,
579 };
580
581 Out() << ". - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . -." << endl;
582
583 Out() << " | Voltages | Currents" << endl;
584 Out() << "-------| 0 | 1 | 2 | 3 | | 0 | 1 | 2 | 3 |" << endl;
585
586 int pos=0;
587 for (int i=0; i<10; i++)
588 {
589 Out() << voltage_names[i];
590 for (int j=0; j<length_per_group[i]; j++)
591 {
592 Out() << setw(6) << setprecision(2) << fixed << v[pos++] << "| ";
593 }
594 pos -= length_per_group[i];
595 for (int j=0; j<4-length_per_group[i]; j++)
596 {
597 Out() << " ";
598 }
599 Out() << "|";
600 for (int j=0; j<length_per_group[i]; j++)
601 {
602 Out() << setw(6) << setprecision(2) << fixed << c[pos++] << "| ";
603 }
604 Out() << endl;
605 }
606
607 Out() << ". - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . -." << endl;
608
609
610 }
611
612 bool CheckCurrentLimits(const vector<float> &currents)
613 {
614 /*
615 F:4;F:4;F:4;F:4;F:4;F:4;F:2;F:2;F:1;F:1",
616 "|FAD_Id[A]:FAD digital (crate 0-3)"
617 "|FAD_Ip[A]:FAD positive (crate 0-3)"
618 "|FAD_In[A]:FAD negative (crate 0-3)"
619 "|FPA_Id[A]:FPA digital (crate 0-3)"
620 "|FPA_Ip[A]:FPA positive (crate 0-3)"
621 "|FPA_In[A]:FPA negative (crate 0-3)"
622 "|ETH_I[A]:Ethernet switch (pos/neg)"
623 "|FTM_I[A]:FTM - trigger master (pos/neg)"
624 "|FFC_I[A]:FFC"
625 "|FLP_I[A]:FLP - light pulser")
626 */
627 fSecurityLimitsExceeded = false;
628
629 const double current_limits[] = {
630 fSecurityCurrentLimits.FAD_digital,
631 fSecurityCurrentLimits.FAD_positive,
632 fSecurityCurrentLimits.FAD_negative,
633 fSecurityCurrentLimits.FPA_digital,
634 fSecurityCurrentLimits.FPA_positive,
635 fSecurityCurrentLimits.FPA_negative,
636 fSecurityCurrentLimits.ethernet_switch,
637 INFINITY,
638 fSecurityCurrentLimits.FFC,
639 fSecurityCurrentLimits.FLP,
640 };
641
642 const int channels_per_group[] = {
643 4, 4, 4, 4, 4, 4, 2, 2, 1, 1,
644 };
645
646 const int groups = 10;
647
648 const char* const group_names[] = {
649 "FAD_digital",
650 "FAD_positive",
651 "FAD_negative",
652 "FPA_digital",
653 "FPA_positive",
654 "FPA_negative",
655 "ethernet_switch",
656 "",
657 "FFC",
658 "FLP",
659 };
660
661 const char* const channel_names[][4] = {
662 {"crate 0", "crate 1", "crate 2", "crate 3"},
663 {"crate 0", "crate 1", "crate 2", "crate 3"},
664 {"crate 0", "crate 1", "crate 2", "crate 3"},
665 {"crate 0", "crate 1", "crate 2", "crate 3"},
666 {"crate 0", "crate 1", "crate 2", "crate 3"},
667 {"crate 0", "crate 1", "crate 2", "crate 3"},
668 {"FTM side", "FSC side"},
669 {""},
670 {"-"},
671 {"-"},
672 };
673
674
675 int offset=0;
676 for (int g=0; g<groups; g++){
677 for (int c=0; c<channels_per_group[g]; c++)
678 {
679 int id = offset+c;
680 if (abs(currents[id]) > abs(current_limits[g])){
681 Out() << "current limit exeeded!! ";
682 Out() << "group: "<< group_names[g];
683 Out() << " channel: "<< channel_names[g][c];
684 Out() << " value: "<< currents[id];
685 Out() << " limit: "<< current_limits[g];
686 Out() << endl;
687 fSecurityLimitsExceeded = true;
688 }
689
690 }
691 offset += channels_per_group[g];
692 }
693 return fSecurityLimitsExceeded;
694 }
695
696
697
698 void StartRead()
699 {
700 ba::async_read(*this, ba::buffer(&fMsg, sizeof(FSC::BinaryOutput_t)),
701 boost::bind(&ConnectionFSC::HandleRead, this,
702 dummy::error, dummy::bytes_transferred));
703
704 AsyncWait(fInTimeout, 35000, &Connection::HandleReadTimeout); // 30s
705 }
706
707 void HandleRead(const boost::system::error_code& err, size_t bytes_received)
708 {
709 // Do not schedule a new read if the connection failed.
710 if (bytes_received==0 || err)
711 {
712 if (err==ba::error::eof)
713 return;
714
715 // 107: Transport endpoint is not connected (bs::error_code(107, bs::system_category))
716 // 125: Operation canceled
717 if (err && err!=ba::error::eof && // Connection closed by remote host
718 err!=ba::error::basic_errors::not_connected && // Connection closed by remote host
719 err!=ba::error::basic_errors::operation_aborted) // Connection closed by us
720 {
721 ostringstream str;
722 str << "Reading from " << URL() << ": " << err.message() << " (" << err << ")";// << endl;
723 Error(str);
724 }
725 PostClose(err!=ba::error::basic_errors::operation_aborted);
726 return;
727 }
728
729 if (!ProcessMessage())
730 {
731 fIsAutoReconnect = true;
732 fReconnectTimeout.expires_from_now(boost::posix_time::seconds(10));
733 fReconnectTimeout.async_wait(boost::bind(&ConnectionFSC::HandleReconnectTimeout,
734 this, dummy::error));
735 PostClose(true);
736 return;
737 }
738
739 StartRead();
740 }
741
742 void ConnectionEstablished()
743 {
744 fNumConsecutiveErrors = 0;
745 fNumConsecutiveMessages = 0;
746 fIsAutoReconnect = false;
747
748 StartRead();
749 }
750
751 void HandleReconnectTimeout(const bs::error_code &)
752 {
753 fIsAutoReconnect = false;
754 }
755
756 void HandleReadTimeout(const bs::error_code &error)
757 {
758 if (error==ba::error::basic_errors::operation_aborted)
759 return;
760
761 if (error)
762 {
763 ostringstream str;
764 str << "Read timeout of " << URL() << ": " << error.message() << " (" << error << ")";// << endl;
765 Error(str);
766
767 PostClose();
768 return;
769
770 }
771
772 if (!is_open())
773 {
774 // For example: Here we could schedule a new accept if we
775 // would not want to allow two connections at the same time.
776 return;
777 }
778
779 // Check whether the deadline has passed. We compare the deadline
780 // against the current time since a new asynchronous operation
781 // may have moved the deadline before this actor had a chance
782 // to run.
783 if (fInTimeout.expires_at() > ba::deadline_timer::traits_type::now())
784 return;
785
786 Error("Timeout reading data from "+URL());
787
788 PostClose();
789 }
790
791public:
792 ConnectionFSC(ba::io_service& ioservice, MessageImp &imp) : Connection(ioservice, imp()),
793 fIsVerbose(false), fIsAutoReconnect(false), fReconnectTimeout(ioservice)
794 {
795 SetLogStream(&imp);
796 }
797
798 void SetVerbose(bool b)
799 {
800 fIsVerbose = b;
801 }
802
803 void SetPositionsSensors(const vector<Interpolator2D::vec> &vec)
804 {
805 fPositionsSensors = vec;
806 }
807
808 void SetSecurityCurrentLimits(const FSC::SecurityCurrentLimits &lim)
809 {
810 fSecurityCurrentLimits = lim;
811 }
812
813 void SetPositionsBias(const vector<Interpolator2D::vec> &vec)
814 {
815 fPositionsBias = vec;
816 }
817
818 bool IsSecurityLimitExceeded() const
819 {
820 return fSecurityLimitsExceeded;
821 }
822
823 bool IsOpen() const
824 {
825 return IsConnected() || fIsAutoReconnect;
826 }
827};
828
829// ------------------------------------------------------------------------
830
831#include "DimDescriptionService.h"
832
833class ConnectionDimFSC : public ConnectionFSC
834{
835private:
836
837 vector<double> fLastRms;
838
839 DimDescribedService fDimTemp;
840 DimDescribedService fDimTemp2;
841 DimDescribedService fDimHum;
842 DimDescribedService fDimVolt;
843 DimDescribedService fDimCurrent;
844
845 void Update(DimDescribedService &svc, vector<float> data, float time) const
846 {
847 data.insert(data.begin(), time);
848 svc.Update(data);
849 }
850
851 void UpdateTemp(float time, const vector<float> &temp)
852 {
853 Update(fDimTemp, temp, time);
854
855 vector<double> T;
856 vector<Interpolator2D::vec> xy;
857
858 T.reserve(31);
859 xy.reserve(31);
860
861 double avg = 0;
862 double rms = 0;
863
864 // Create a list of all valid sensors
865 for (int i=0; i<31; i++)
866 if (temp[i]!=0)
867 {
868 T.emplace_back(temp[i]);
869 xy.emplace_back(fPositionsSensors[i]);
870
871 avg += temp[i];
872 rms += temp[i]*temp[i];
873 }
874
875 if (T.size()==0)
876 {
877 Warn("No valid sensor temperatures.");
878 return;
879 }
880
881 avg /= T.size();
882 rms /= T.size();
883 rms -= avg*avg;
884 rms = rms<0 ? 0 : sqrt(rms);
885
886 // Clean broken reports
887 const double cut_val = 0.015;
888 const bool reject = rms>4 || (fabs(fLastRms[0]-fLastRms[1])<=cut_val && fabs(rms-fLastRms[0])>cut_val);
889
890 fLastRms[1] = fLastRms[0];
891 fLastRms[0] = rms;
892
893 if (reject)
894 {
895 Warn("Suspicious temperature values rejecte for BIAS_TEMP.");
896 return;
897 }
898
899 // Create interpolator for the corresponding sensor positions
900 Interpolator2D inter(xy);
901
902 // Calculate weights for the output positions
903 if (!inter.SetOutputGrid(fPositionsBias))
904 {
905 Warn("Temperature values rejecte for BIAS_TEMP (calculation of weights failed).");
906 return;
907 }
908
909 // Interpolate the data
910 T = inter.Interpolate(T);
911
912 avg = 0;
913 rms = 0;
914 for (int i=0; i<320; i++)
915 {
916 avg += T[i];
917 rms += T[i]*T[i];
918 }
919
920 avg /= 320;
921 rms /= 320;
922 rms -= avg*avg;
923 rms = rms<0 ? 0 : sqrt(rms);
924
925 vector<float> out;
926 out.reserve(322);
927 out.assign(T.cbegin(), T.cend());
928 out.emplace_back(avg);
929 out.emplace_back(rms);
930
931 // Update the Dim service with the interpolated positions
932 Update(fDimTemp2, out, time);
933 }
934
935 void UpdateHum(float time, const vector<float> &hum)
936 {
937 Update(fDimHum, hum, time);
938 }
939
940 void UpdateVolt(float time, const vector<float> &volt)
941 {
942 Update(fDimVolt, volt, time);
943 }
944
945 void UpdateCur(float time, const vector<float> &curr)
946 {
947 Update(fDimCurrent, curr, time);
948 }
949
950public:
951 ConnectionDimFSC(ba::io_service& ioservice, MessageImp &imp) :
952 ConnectionFSC(ioservice, imp), fLastRms(2),
953 fDimTemp ("FSC_CONTROL/TEMPERATURE", "F:1;F:31;F:8;F:8;F:4;F:4;F:4",
954 "|t[s]:FSC uptime"
955 "|T_sens[deg C]:Sensor compartment temperatures"
956 "|T_crate[deg C]:Temperatures crate 0 (back/front), 1 (b/f), 2 (b/f), 3 (b/f)"
957 "|T_ps[deg C]:Temp power supplies crate 0 (back/front), 1, 2, 3"
958 "|T_aux[deg C]:Auxiliary power supply temperatures FTM (top/bottom), FSC (t/b)"
959 "|T_back[deg C]:FTM backpanel temperatures FTM (top/bottom), FSC (top/bottom)"
960 "|T_eth[deg C]:Ethernet switches temperatures top (front/back), bottom (f/b)"),
961 fDimTemp2 ("FSC_CONTROL/BIAS_TEMP", "F:1;F:320;F:1;F:1",
962 "|t[s]:FSC uptime"
963 "|T[deg C]:Interpolated temperatures at bias patch positions"
964 "|T_avg[deg C]:Average temperature calculated from all patches"
965 "|T_rms[deg C]:Temperature RMS calculated from all patches"),
966 fDimHum ("FSC_CONTROL/HUMIDITY", "F:1;F:4",
967 "|t[s]:FSC uptime"
968 "|H[%]:Humidity sensors readout"),
969 fDimVolt ("FSC_CONTROL/VOLTAGE",
970 "F:1;F:4;F:4;F:4;F:4;F:4;F:4;F:2;F:2;F:1;F:1",
971 "|t[s]:FSC uptime"
972 "|FAD_Ud[V]:FAD digital (crate 0-3)"
973 "|FAD_Up[V]:FAD positive (crate 0-3)"
974 "|FAD_Un[V]:FAD negative (crate 0-3)"
975 "|FPA_Ud[V]:FPA digital (crate 0-3)"
976 "|FPA_Up[V]:FPA positive (crate 0-3)"
977 "|FPA_Un[V]:FPA negative (crate 0-3)"
978 "|ETH_U[V]:Ethernet switch (pos/neg)"
979 "|FTM_U[V]:FTM - trigger master (pos/neg)"
980 "|FFC_U[V]:FFC"
981 "|FLP_U[V]:FLP - light pulser"),
982 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",
983 "|t[s]:FSC uptime"
984 "|FAD_Id[A]:FAD digital (crate 0-3)"
985 "|FAD_Ip[A]:FAD positive (crate 0-3)"
986 "|FAD_In[A]:FAD negative (crate 0-3)"
987 "|FPA_Id[A]:FPA digital (crate 0-3)"
988 "|FPA_Ip[A]:FPA positive (crate 0-3)"
989 "|FPA_In[A]:FPA negative (crate 0-3)"
990 "|ETH_I[A]:Ethernet switch (pos/neg)"
991 "|FTM_I[A]:FTM - trigger master (pos/neg)"
992 "|FFC_I[A]:FFC"
993 "|FLP_I[A]:FLP - light pulser")
994 {
995 fLastRms[0] = 1.5;
996 }
997
998 // 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
999};
1000
1001// ------------------------------------------------------------------------
1002
1003template <class T, class S>
1004class StateMachineFSC : public StateMachineAsio<T>
1005{
1006private:
1007 S fFSC;
1008
1009 int Disconnect()
1010 {
1011 // Close all connections
1012 fFSC.PostClose(false);
1013
1014 return T::GetCurrentState();
1015 }
1016
1017 int Reconnect(const EventImp &evt)
1018 {
1019 // Close all connections to supress the warning in SetEndpoint
1020 fFSC.PostClose(false);
1021
1022 // Now wait until all connection have been closed and
1023 // all pending handlers have been processed
1024 ba::io_service::poll();
1025
1026 if (evt.GetBool())
1027 fFSC.SetEndpoint(evt.GetString());
1028
1029 // Now we can reopen the connection
1030 fFSC.PostClose(true);
1031
1032 return T::GetCurrentState();
1033 }
1034
1035 int Execute()
1036 {
1037 if (fFSC.IsSecurityLimitExceeded())
1038 {
1039 return State::kOverCurrent;
1040 }
1041 else if(fFSC.IsOpen())
1042 {
1043 return State::kConnected;
1044 }
1045 else
1046 {
1047 return State::kDisconnected;
1048 }
1049
1050 //return fFSC.IsOpen() ? State::kConnected : State::kDisconnected;
1051 }
1052
1053 bool CheckEventSize(size_t has, const char *name, size_t size)
1054 {
1055 if (has==size)
1056 return true;
1057
1058 ostringstream msg;
1059 msg << name << " - Received event has " << has << " bytes, but expected " << size << ".";
1060 T::Fatal(msg);
1061 return false;
1062 }
1063
1064 int SetVerbosity(const EventImp &evt)
1065 {
1066 if (!CheckEventSize(evt.GetSize(), "SetVerbosity", 1))
1067 return T::kSM_FatalError;
1068
1069 fFSC.SetVerbose(evt.GetBool());
1070
1071 return T::GetCurrentState();
1072 }
1073
1074public:
1075 StateMachineFSC(ostream &out=cout) :
1076 StateMachineAsio<T>(out, "FSC_CONTROL"), fFSC(*this, *this)
1077 {
1078 // State names
1079 T::AddStateName(State::kDisconnected, "Disconnected",
1080 "FSC board not connected via ethernet.");
1081
1082 T::AddStateName(State::kConnected, "Connected",
1083 "Ethernet connection to FSC established.");
1084
1085 T::AddStateName(State::kHighCurrent, "HighPowerConsumption",
1086 "FSC board measures high power consumption, c.f. FSC current limits in config-file or config-DB.");
1087
1088 T::AddStateName(State::kOverCurrent, "OverCurrent",
1089 "FSC board measures *too* power consumption, c.f. FSC current limits in config-file or config-DB.");
1090
1091 // Verbosity commands
1092 T::AddEvent("SET_VERBOSE", "B:1")
1093 (bind(&StateMachineFSC::SetVerbosity, this, placeholders::_1))
1094 ("set verbosity state"
1095 "|verbosity[bool]:disable or enable verbosity for received data (yes/no), except dynamic data");
1096
1097 // Conenction commands
1098 T::AddEvent("DISCONNECT", State::kConnected)
1099 (bind(&StateMachineFSC::Disconnect, this))
1100 ("disconnect from ethernet");
1101
1102 T::AddEvent("RECONNECT", "O", State::kDisconnected, State::kConnected)
1103 (bind(&StateMachineFSC::Reconnect, this, placeholders::_1))
1104 ("(Re)connect ethernet connection to FSC, a new address can be given"
1105 "|[host][string]:new ethernet address in the form <host:port>");
1106
1107 fFSC.StartConnect();
1108 }
1109
1110 void SetEndpoint(const string &url)
1111 {
1112 fFSC.SetEndpoint(url);
1113 }
1114
1115 int EvalOptions(Configuration &conf)
1116 {
1117 fFSC.SetVerbose(!conf.Get<bool>("quiet"));
1118
1119 const string fname1 = conf.Get<string>("sensor-pos-file");
1120 const auto v1 = Interpolator2D::ReadGrid(fname1);
1121 if (v1.size() != 31)
1122 {
1123 T::Error("Reading sensor positions from "+fname1+"failed ("+to_string(v1.size())+")");
1124 return 1;
1125 }
1126
1127 const string fname2 = conf.Get<string>("patch-pos-file");
1128 const auto v2 = Interpolator2D::ReadGrid(fname2);
1129 if (v2.size() != 320)
1130 {
1131 T::Error("Reading bias patch positions from "+fname2+"failed ("+to_string(v2.size())+")");
1132 return 1;
1133 }
1134
1135 fFSC.SetPositionsSensors(v1);
1136 fFSC.SetPositionsBias(v2);
1137
1138 FSC::SecurityCurrentLimits lim;
1139 lim.ethernet_switch = conf.Get<double>("ethernet_switch");
1140 lim.FFC = conf.Get<double>("FFC");
1141 lim.FLP = conf.Get<double>("FLP");
1142 lim.FAD_digital = conf.Get<double>("FAD_digital");
1143 lim.FAD_negative = conf.Get<double>("FAD_negative");
1144 lim.FAD_positive = conf.Get<double>("FAD_positive");
1145 lim.FPA_digital = conf.Get<double>("FPA_digital");
1146 lim.FPA_negative = conf.Get<double>("FPA_negative");
1147 lim.FPA_positive = conf.Get<double>("FPA_positive");
1148 fFSC.SetSecurityCurrentLimits(lim);
1149
1150 SetEndpoint(conf.Get<string>("addr"));
1151
1152 return -1;
1153 }
1154};
1155
1156// ------------------------------------------------------------------------
1157
1158#include "Main.h"
1159
1160template<class T, class S, class R>
1161int RunShell(Configuration &conf)
1162{
1163 return Main::execute<T, StateMachineFSC<S, R>>(conf);
1164}
1165
1166void SetupConfiguration(Configuration &conf)
1167{
1168 po::options_description control("FTM control options");
1169 control.add_options()
1170 ("no-dim", po_bool(), "Disable dim services")
1171 ("addr,a", var<string>("localhost:5000"), "Network address of FSC")
1172 ("sensor-pos-file", var<string>()->required(), "File with the positions of the 31 temperature sensors")
1173 ("patch-pos-file", var<string>()->required(), "File with the positions of the 320 bias patches")
1174 ("quiet,q", po_bool(true), "Disable printing contents of all received messages (except dynamic data) in clear text.")
1175 ;
1176
1177 po::options_description current_limits("Security current limits");
1178 current_limits.add_options()
1179 ("ethernet_switch", var<double>()->required(), "(signed) floating point number, the max/min current, for pos/neg currents in A.")
1180 ("FFC", var<double>()->required(), "(signed) floating point number, the max/min current, for pos/neg currents in A.")
1181 ("FLP", var<double>()->required(), "(signed) floating point number, the max/min current, for pos/neg currents in A.")
1182 ("FAD_digital", var<double>()->required(), "(signed) floating point number, the max/min current, for pos/neg currents in A.")
1183 ("FAD_negative", var<double>()->required(), "(signed) floating point number, the max/min current, for pos/neg currents in A.")
1184 ("FAD_positive", var<double>()->required(), "(signed) floating point number, the max/min current, for pos/neg currents in A.")
1185 ("FPA_digital", var<double>()->required(), "(signed) floating point number, the max/min current, for pos/neg currents in A.")
1186 ("FPA_negative", var<double>()->required(), "(signed) floating point number, the max/min current, for pos/neg currents in A.")
1187 ("FPA_positive", var<double>()->required(), "(signed) floating point number, the max/min current, for pos/neg currents in A.")
1188 ;
1189
1190 conf.AddOptions(control);
1191 conf.AddOptions(current_limits);
1192}
1193
1194/*
1195 Extract usage clause(s) [if any] for SYNOPSIS.
1196 Translators: "Usage" and "or" here are patterns (regular expressions) which
1197 are used to match the usage synopsis in program output. An example from cp
1198 (GNU coreutils) which contains both strings:
1199 Usage: cp [OPTION]... [-T] SOURCE DEST
1200 or: cp [OPTION]... SOURCE... DIRECTORY
1201 or: cp [OPTION]... -t DIRECTORY SOURCE...
1202 */
1203void PrintUsage()
1204{
1205 cout <<
1206 "The fscctrl controls the FSC (FACT Slow Control) board.\n"
1207 "\n"
1208 "The default is that the program is started without user intercation. "
1209 "All actions are supposed to arrive as DimCommands. Using the -c "
1210 "option, a local shell can be initialized. With h or help a short "
1211 "help message about the usuage can be brought to the screen.\n"
1212 "\n"
1213 "Usage: fscctrl [-c type] [OPTIONS]\n"
1214 " or: fscctrl [OPTIONS]\n";
1215 cout << endl;
1216}
1217
1218void PrintHelp()
1219{
1220 Main::PrintHelp<StateMachineFSC<StateMachine, ConnectionFSC>>();
1221
1222 /* Additional help text which is printed after the configuration
1223 options goes here */
1224
1225 /*
1226 cout << "bla bla bla" << endl << endl;
1227 cout << endl;
1228 cout << "Environment:" << endl;
1229 cout << "environment" << endl;
1230 cout << endl;
1231 cout << "Examples:" << endl;
1232 cout << "test exam" << endl;
1233 cout << endl;
1234 cout << "Files:" << endl;
1235 cout << "files" << endl;
1236 cout << endl;
1237 */
1238}
1239
1240int main(int argc, const char* argv[])
1241{
1242 Configuration conf(argv[0]);
1243 conf.SetPrintUsage(PrintUsage);
1244 Main::SetupConfiguration(conf);
1245 SetupConfiguration(conf);
1246
1247 if (!conf.DoParse(argc, argv, PrintHelp))
1248 return 127;
1249
1250 //try
1251 {
1252 // No console access at all
1253 if (!conf.Has("console"))
1254 {
1255 if (conf.Get<bool>("no-dim"))
1256 return RunShell<LocalStream, StateMachine, ConnectionFSC>(conf);
1257 else
1258 return RunShell<LocalStream, StateMachineDim, ConnectionDimFSC>(conf);
1259 }
1260 // Cosole access w/ and w/o Dim
1261 if (conf.Get<bool>("no-dim"))
1262 {
1263 if (conf.Get<int>("console")==0)
1264 return RunShell<LocalShell, StateMachine, ConnectionFSC>(conf);
1265 else
1266 return RunShell<LocalConsole, StateMachine, ConnectionFSC>(conf);
1267 }
1268 else
1269 {
1270 if (conf.Get<int>("console")==0)
1271 return RunShell<LocalShell, StateMachineDim, ConnectionDimFSC>(conf);
1272 else
1273 return RunShell<LocalConsole, StateMachineDim, ConnectionDimFSC>(conf);
1274 }
1275 }
1276 /*catch (std::exception& e)
1277 {
1278 cerr << "Exception: " << e.what() << endl;
1279 return -1;
1280 }*/
1281
1282 return 0;
1283}
Note: See TracBrowser for help on using the repository browser.