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

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