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

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