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

Last change on this file since 17170 was 17170, checked in by tbretz, 11 years ago
Implemented a new service providing bias patch wise temperatures; in addition the provided tempertures are filtered to remove faulty FSC reports.
File size: 29.1 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<pair<double,double>> fPositionsSensors;
40 vector<pair<double,double>> 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.85e-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 UpdateHum( time, humidities);
554 UpdateTemp(time, temperatures);
555 UpdateVolt(time, voltages);
556 UpdateCur( time, currents);
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<pair<double,double>> &vec)
634 {
635 fPositionsSensors = vec;
636 }
637
638 void SetPositionsBias(const vector<pair<double,double>> &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].first, fPositionsSensors[i].second);
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 - avg*avg);
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 // Update the Dim service with the interpolated positions
728 Update(fDimTemp2, vector<float>(T.cbegin(), T.cend()), time);
729 }
730
731 void UpdateHum(float time, const vector<float> &hum)
732 {
733 Update(fDimHum, hum, time);
734 }
735
736 void UpdateVolt(float time, const vector<float> &volt)
737 {
738 Update(fDimVolt, volt, time);
739 }
740
741 void UpdateCur(float time, const vector<float> &curr)
742 {
743 Update(fDimCurrent, curr, time);
744 }
745
746public:
747 ConnectionDimFSC(ba::io_service& ioservice, MessageImp &imp) :
748 ConnectionFSC(ioservice, imp), fLastRms(2),
749 fDimTemp ("FSC_CONTROL/TEMPERATURE", "F:1;F:31;F:8;F:8;F:4;F:4;F:4",
750 "|t[s]:FSC uptime"
751 "|T_sens[deg C]:Sensor compartment temperatures"
752 "|T_crate[deg C]:Temperatures crate 0 (back/front), 1 (b/f), 2 (b/f), 3 (b/f)"
753 "|T_ps[deg C]:Temp power supplies crate 0 (back/front), 1, 2, 3"
754 "|T_aux[deg C]:Auxiliary power supply temperatures FTM (top/bottom), FSC (t/b)"
755 "|T_back[deg C]:FTM backpanel temperatures FTM (top/bottom), FSC (top/bottom)"
756 "|T_eth[deg C]:Ethernet switches temperatures top (front/back), bottom (f/b)"),
757 fDimTemp2 ("FSC_CONTROL/BIAS_TEMP", "F:1;F:320",
758 "|t[s]:FSC uptime"
759 "|T[deg C]:Interpolated temperatures at bias patch positions"),
760 fDimHum ("FSC_CONTROL/HUMIDITY", "F:1;F:4",
761 "|t[s]:FSC uptime"
762 "|H[%]:Humidity sensors readout"),
763 fDimVolt ("FSC_CONTROL/VOLTAGE",
764 "F:1;F:4;F:4;F:4;F:4;F:4;F:4;F:2;F:2;F:1;F:1",
765 "|t[s]:FSC uptime"
766 "|FAD_Ud[V]:FAD digital (crate 0-3)"
767 "|FAD_Up[V]:FAD positive (crate 0-3)"
768 "|FAD_Un[V]:FAD negative (crate 0-3)"
769 "|FPA_Ud[V]:FPA digital (crate 0-3)"
770 "|FPA_Up[V]:FPA positive (crate 0-3)"
771 "|FPA_Un[V]:FPA negative (crate 0-3)"
772 "|ETH_U[V]:Ethernet switch (pos/neg)"
773 "|FTM_U[V]:FTM - trigger master (pos/neg)"
774 "|FFC_U[V]:FFC"
775 "|FLP_U[V]:FLP - light pulser"),
776 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",
777 "|t[s]:FSC uptime"
778 "|FAD_Id[A]:FAD digital (crate 0-3)"
779 "|FAD_Ip[A]:FAD positive (crate 0-3)"
780 "|FAD_In[A]:FAD negative (crate 0-3)"
781 "|FPA_Id[A]:FPA digital (crate 0-3)"
782 "|FPA_Ip[A]:FPA positive (crate 0-3)"
783 "|FPA_In[A]:FPA negative (crate 0-3)"
784 "|ETH_I[A]:Ethernet switch (pos/neg)"
785 "|FTM_I[A]:FTM - trigger master (pos/neg)"
786 "|FFC_I[A]:FFC"
787 "|FLP_I[A]:FLP - light pulser")
788 {
789 fLastRms[0] = 1.5;
790 }
791
792 // 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
793};
794
795// ------------------------------------------------------------------------
796
797template <class T, class S>
798class StateMachineFSC : public StateMachineAsio<T>
799{
800private:
801 S fFSC;
802
803 int Disconnect()
804 {
805 // Close all connections
806 fFSC.PostClose(false);
807
808 return T::GetCurrentState();
809 }
810
811 int Reconnect(const EventImp &evt)
812 {
813 // Close all connections to supress the warning in SetEndpoint
814 fFSC.PostClose(false);
815
816 // Now wait until all connection have been closed and
817 // all pending handlers have been processed
818 ba::io_service::poll();
819
820 if (evt.GetBool())
821 fFSC.SetEndpoint(evt.GetString());
822
823 // Now we can reopen the connection
824 fFSC.PostClose(true);
825
826 return T::GetCurrentState();
827 }
828
829 int Execute()
830 {
831 return fFSC.IsConnected() ? State::kConnected : State::kDisconnected;
832 }
833
834 bool CheckEventSize(size_t has, const char *name, size_t size)
835 {
836 if (has==size)
837 return true;
838
839 ostringstream msg;
840 msg << name << " - Received event has " << has << " bytes, but expected " << size << ".";
841 T::Fatal(msg);
842 return false;
843 }
844
845 int SetVerbosity(const EventImp &evt)
846 {
847 if (!CheckEventSize(evt.GetSize(), "SetVerbosity", 1))
848 return T::kSM_FatalError;
849
850 fFSC.SetVerbose(evt.GetBool());
851
852 return T::GetCurrentState();
853 }
854
855 int SetDumpStream(const EventImp &evt)
856 {
857 if (!CheckEventSize(evt.GetSize(), "SetDumpStream", 1))
858 return T::kSM_FatalError;
859
860 fFSC.SetDumpStream(evt.GetBool());
861
862 return T::GetCurrentState();
863 }
864
865public:
866 StateMachineFSC(ostream &out=cout) :
867 StateMachineAsio<T>(out, "FSC_CONTROL"), fFSC(*this, *this)
868 {
869 // State names
870 T::AddStateName(State::kDisconnected, "Disconnected",
871 "FSC board not connected via ethernet.");
872
873 T::AddStateName(State::kConnected, "Connected",
874 "Ethernet connection to FSC established.");
875
876 // Verbosity commands
877 T::AddEvent("SET_VERBOSE", "B:1")
878 (bind(&StateMachineFSC::SetVerbosity, this, placeholders::_1))
879 ("set verbosity state"
880 "|verbosity[bool]:disable or enable verbosity for received data (yes/no), except dynamic data");
881
882 T::AddEvent("DUMP_STREAM", "B:1")
883 (bind(&StateMachineFSC::SetDumpStream, this, placeholders::_1))
884 (""
885 "");
886
887 // Conenction commands
888 T::AddEvent("DISCONNECT", State::kConnected)
889 (bind(&StateMachineFSC::Disconnect, this))
890 ("disconnect from ethernet");
891
892 T::AddEvent("RECONNECT", "O", State::kDisconnected, State::kConnected)
893 (bind(&StateMachineFSC::Reconnect, this, placeholders::_1))
894 ("(Re)connect ethernet connection to FTM, a new address can be given"
895 "|[host][string]:new ethernet address in the form <host:port>");
896
897 fFSC.StartConnect();
898 }
899
900 void SetEndpoint(const string &url)
901 {
902 fFSC.SetEndpoint(url);
903 }
904
905 vector<pair<double,double>> ReadVector(const string &filename) const
906 {
907 vector<pair<double,double>> vec;
908
909 ifstream fin(filename);
910 while (1)
911 {
912 double x, y;
913 fin >> x;
914 fin >> y;
915 if (!fin)
916 break;
917
918 vec.emplace_back(x, y);
919 }
920
921 return vec;
922 }
923
924 int EvalOptions(Configuration &conf)
925 {
926 fFSC.SetVerbose(!conf.Get<bool>("quiet"));
927
928 const string fname1 = conf.Get<string>("sesnor-pos-file");
929 const auto v1 = ReadVector(fname1);
930 if (v1.size() != 31)
931 {
932 Error("Reading sensor positions from "+fname1+"failed ("+to_string(v1.size())+")");
933 return 1;
934 }
935
936 const string fname2 = conf.Get<string>("patch-pos-file");
937 const auto v2 = ReadVector(fname2);
938 if (v2.size() != 320)
939 {
940 Error("Reading bias patch positions from "+fname2+"failed ("+to_string(v2.size())+")");
941 return 1;
942 }
943
944 fFSC.SetPositionsSensors(v1);
945 fFSC.SetPositionsBias(v2);
946
947 SetEndpoint(conf.Get<string>("addr"));
948
949 return -1;
950 }
951};
952
953// ------------------------------------------------------------------------
954
955#include "Main.h"
956
957template<class T, class S, class R>
958int RunShell(Configuration &conf)
959{
960 return Main::execute<T, StateMachineFSC<S, R>>(conf);
961}
962
963void SetupConfiguration(Configuration &conf)
964{
965 po::options_description control("FTM control options");
966 control.add_options()
967 ("no-dim", po_bool(), "Disable dim services")
968 ("addr,a", var<string>("localhost:5000"), "Network address of FSC")
969 ("sensor-pos-file", var<string>()->required(), "File with the positions of the 31 temperature sensors")
970 ("patch-pos-file", var<string>()->required(), "File with the positions of the 320 bias patches")
971 ("quiet,q", po_bool(true), "Disable printing contents of all received messages (except dynamic data) in clear text.")
972 ;
973
974 conf.AddOptions(control);
975}
976
977/*
978 Extract usage clause(s) [if any] for SYNOPSIS.
979 Translators: "Usage" and "or" here are patterns (regular expressions) which
980 are used to match the usage synopsis in program output. An example from cp
981 (GNU coreutils) which contains both strings:
982 Usage: cp [OPTION]... [-T] SOURCE DEST
983 or: cp [OPTION]... SOURCE... DIRECTORY
984 or: cp [OPTION]... -t DIRECTORY SOURCE...
985 */
986void PrintUsage()
987{
988 cout <<
989 "The fscctrl controls the FSC (FACT Slow Control) board.\n"
990 "\n"
991 "The default is that the program is started without user intercation. "
992 "All actions are supposed to arrive as DimCommands. Using the -c "
993 "option, a local shell can be initialized. With h or help a short "
994 "help message about the usuage can be brought to the screen.\n"
995 "\n"
996 "Usage: fscctrl [-c type] [OPTIONS]\n"
997 " or: fscctrl [OPTIONS]\n";
998 cout << endl;
999}
1000
1001void PrintHelp()
1002{
1003 Main::PrintHelp<StateMachineFSC<StateMachine, ConnectionFSC>>();
1004
1005 /* Additional help text which is printed after the configuration
1006 options goes here */
1007
1008 /*
1009 cout << "bla bla bla" << endl << endl;
1010 cout << endl;
1011 cout << "Environment:" << endl;
1012 cout << "environment" << endl;
1013 cout << endl;
1014 cout << "Examples:" << endl;
1015 cout << "test exam" << endl;
1016 cout << endl;
1017 cout << "Files:" << endl;
1018 cout << "files" << endl;
1019 cout << endl;
1020 */
1021}
1022
1023int main(int argc, const char* argv[])
1024{
1025 Configuration conf(argv[0]);
1026 conf.SetPrintUsage(PrintUsage);
1027 Main::SetupConfiguration(conf);
1028 SetupConfiguration(conf);
1029
1030 if (!conf.DoParse(argc, argv, PrintHelp))
1031 return 127;
1032
1033 //try
1034 {
1035 // No console access at all
1036 if (!conf.Has("console"))
1037 {
1038 if (conf.Get<bool>("no-dim"))
1039 return RunShell<LocalStream, StateMachine, ConnectionFSC>(conf);
1040 else
1041 return RunShell<LocalStream, StateMachineDim, ConnectionDimFSC>(conf);
1042 }
1043 // Cosole access w/ and w/o Dim
1044 if (conf.Get<bool>("no-dim"))
1045 {
1046 if (conf.Get<int>("console")==0)
1047 return RunShell<LocalShell, StateMachine, ConnectionFSC>(conf);
1048 else
1049 return RunShell<LocalConsole, StateMachine, ConnectionFSC>(conf);
1050 }
1051 else
1052 {
1053 if (conf.Get<int>("console")==0)
1054 return RunShell<LocalShell, StateMachineDim, ConnectionDimFSC>(conf);
1055 else
1056 return RunShell<LocalConsole, StateMachineDim, ConnectionDimFSC>(conf);
1057 }
1058 }
1059 /*catch (std::exception& e)
1060 {
1061 cerr << "Exception: " << e.what() << endl;
1062 return -1;
1063 }*/
1064
1065 return 0;
1066}
Note: See TracBrowser for help on using the repository browser.