source: trunk/FACT++/src/drivectrl.cc@ 11570

Last change on this file since 11570 was 11483, checked in by tbretz, 13 years ago
Added a registry for wildcarded options to detect unaccessed options; for this EvalConfiguration(const Configuration&) has been changed to EvalOptions(Configuration&)
File size: 29.4 KB
Line 
1#include <boost/bind.hpp>
2
3#include "FACT.h"
4#include "Dim.h"
5#include "Event.h"
6#include "Shell.h"
7#include "StateMachineDim.h"
8#include "Connection.h"
9#include "Configuration.h"
10#include "Timers.h"
11#include "Console.h"
12#include "Converter.h"
13
14#include "tools.h"
15
16
17namespace ba = boost::asio;
18namespace bs = boost::system;
19namespace dummy = ba::placeholders;
20
21using namespace std;
22
23// ------------------------------------------------------------------------
24
25namespace Drive
26{
27 struct DimPointing
28 {
29 } __attribute__((__packed__));
30
31 struct DimTracking
32 {
33 } __attribute__((__packed__));
34
35 struct DimStarguider
36 {
37 double fMissZd;
38 double fMissAz;
39
40 double fNominalZd;
41 double fNominalAz;
42
43 double fCenterX;
44 double fCenterY;
45
46 double fBrightness;
47
48 uint16_t fNumCorrelated;
49 uint16_t fNumLeds;
50 uint16_t fNumRings;
51 uint16_t fNumStars;
52
53 } __attribute__((__packed__));
54
55 struct DimTPoint
56 {
57 double fNominalAlt;
58 double fNominalAz;
59
60 double fCurrentAlt;
61 double fCurrentAz;
62
63 double fDevZd;
64 double fDevAz;
65
66 double fRa;
67 double fDec;
68
69 double fCenterX;
70 double fCenterY;
71 double fCenterMag;
72
73 double fStarX;
74 double fStarY;
75 double fStarMag;
76
77 double fBrightness;
78 double fRealMag;
79
80 uint16_t fNumLeds;
81 uint16_t fNumRings;
82 uint16_t fNumStars;
83 uint16_t fNumCorrelated;
84
85 } __attribute__((__packed__));
86};
87
88
89
90// ------------------------------------------------------------------------
91
92class ConnectionDrive : public Connection
93{
94 int fState;
95
96 bool fIsVerbose;
97
98 // --verbose
99 // --hex-out
100 // --dynamic-out
101 // --load-file
102 // --leds
103 // --trigger-interval
104 // --physcis-coincidence
105 // --calib-coincidence
106 // --physcis-window
107 // --physcis-window
108 // --trigger-delay
109 // --time-marker-delay
110 // --dead-time
111 // --clock-conditioner-r0
112 // --clock-conditioner-r1
113 // --clock-conditioner-r8
114 // --clock-conditioner-r9
115 // --clock-conditioner-r11
116 // --clock-conditioner-r13
117 // --clock-conditioner-r14
118 // --clock-conditioner-r15
119 // ...
120
121 virtual void UpdatePointing(const Time &, const array<double, 2> &)
122 {
123 }
124
125 virtual void UpdateTracking(const Time &, const array<double, 7> &)
126 {
127 }
128
129 virtual void UpdateStarguider(const Time &, const Drive::DimStarguider &)
130 {
131 }
132
133 virtual void UpdateTPoint(const Time &, const Drive::DimTPoint &)
134 {
135 }
136
137protected:
138 map<uint16_t, int> fCounter;
139
140 ba::streambuf fBuffer;
141
142 Time ReadTime(istream &in)
143 {
144 uint16_t y, m, d, hh, mm, ss, ms;
145 in >> y >> m >> d >> hh >> mm >> ss >> ms;
146
147 return Time(y, m, d, hh, mm, ss, ms*1000);
148 }
149
150 double ReadAngle(istream &in)
151 {
152 char sgn;
153 uint16_t d, m;
154 float s;
155
156 in >> sgn >> d >> m >> s;
157
158 const double ret = ((60.0 * (60.0 * (double)d + (double)m) + s))/3600.;
159 return sgn=='-' ? -ret : ret;
160 }
161
162 void HandleReceivedReport(const boost::system::error_code& err, size_t bytes_received)
163 {
164 // Do not schedule a new read if the connection failed.
165 if (bytes_received==0 || err)
166 {
167 if (err==ba::error::eof)
168 Warn("Connection closed by remote host (FTM).");
169
170 // 107: Transport endpoint is not connected (bs::error_code(107, bs::system_category))
171 // 125: Operation canceled
172 if (err && err!=ba::error::eof && // Connection closed by remote host
173 err!=ba::error::basic_errors::not_connected && // Connection closed by remote host
174 err!=ba::error::basic_errors::operation_aborted) // Connection closed by us
175 {
176 ostringstream str;
177 str << "Reading from " << URL() << ": " << err.message() << " (" << err << ")";// << endl;
178 Error(str);
179 }
180 PostClose(err!=ba::error::basic_errors::operation_aborted);
181 return;
182 }
183
184 istream is(&fBuffer);
185
186 string line;
187 getline(is, line);
188
189 if (fIsVerbose)
190 Out() << line << endl;
191
192 StartReadReport();
193
194 if (line.substr(0, 13)=="STARG-REPORT ")
195 {
196 istringstream stream(line.substr(16));
197
198 // 0: Error
199 // 1: Standby
200 // 2: Monitoring
201 uint16_t status1;
202 stream >> status1;
203 const Time t1 = ReadTime(stream);
204
205 uint16_t status2;
206 stream >> status2;
207 const Time t2 = ReadTime(stream);
208
209 double misszd, missaz;
210 stream >> misszd >> missaz;
211
212 const double zd = ReadAngle(stream);
213 const double az = ReadAngle(stream);
214
215 double cx, cy;
216 stream >> cx >> cy;
217
218 int ncor;
219 stream >> ncor;
220
221 double bright, mjd;
222 stream >> bright >> mjd;
223
224 int nled, nring, nstars;
225 stream >> nled >> nring >> nstars;
226
227 if (stream.fail())
228 return;
229
230 Drive::DimStarguider data;
231
232 data.fMissZd = misszd;
233 data.fMissAz = missaz;
234 data.fNominalZd = zd;
235 data.fNominalAz = az;
236 data.fCenterX = cx;
237 data.fCenterY = cy;
238 data.fNumCorrelated = ncor;
239 data.fBrightness = bright;
240 data.fNumLeds = nled;
241 data.fNumRings = nring;
242 data.fNumStars = nstars;
243
244 UpdateStarguider(Time(mjd), data);
245
246 return;
247
248 }
249
250 if (line.substr(0, 14)=="TPOINT-REPORT ")
251 {
252 istringstream stream(line.substr(17));
253
254 uint16_t status1;
255 stream >> status1;
256 const Time t1 = ReadTime(stream);
257
258 uint16_t status2;
259 stream >> status2;
260 const Time t2 = ReadTime(stream);
261
262 double az1, alt1, az2, alt2, ra, dec, dzd, daz;
263 stream >> az1 >> alt1 >> az2 >> alt2 >> ra >> dec >> dzd >> daz;
264
265 // c: center, s:start
266 double mjd, cmag, smag, cx, cy, sx, sy;
267 stream >> mjd >> cmag >> smag >> cx >> cy >> sx >> sy;
268
269 int nled, nring, nstar, ncor;
270 stream >> nled >> nring >> nstar >> ncor;
271
272 double bright, mag;
273 stream >> bright >> mag;
274
275 string name;
276 stream >> name;
277
278 if (stream.fail())
279 return;
280
281 Drive::DimTPoint tpoint;
282
283 tpoint.fNominalAz = az1;
284 tpoint.fNominalAlt = alt1;
285 tpoint.fCurrentAz = az2;
286 tpoint.fCurrentAlt = alt2;
287 tpoint.fDevAz = daz;
288 tpoint.fDevZd = dzd;
289 tpoint.fRa = ra;
290 tpoint.fDec = dec;
291
292 tpoint.fCenterX = cx;
293 tpoint.fCenterY = cy;
294 tpoint.fCenterMag = cmag;
295
296 tpoint.fStarX = sx;
297 tpoint.fStarY = sy;
298 tpoint.fStarMag = smag;
299
300 tpoint.fBrightness = bright;
301
302 tpoint.fNumCorrelated = ncor;
303 tpoint.fNumLeds = nled;
304 tpoint.fNumRings = nring;
305 tpoint.fNumStars = nstar;
306
307 tpoint.fRealMag = mag;
308
309 return;
310 }
311
312 if (line.substr(0, 13)=="DRIVE-REPORT ")
313 {
314 // DRIVE-REPORT M1
315 // 01 2011 05 14 11 31 19 038
316 // 02 1858 11 17 00 00 00 000
317 // + 000 00 000 + 000 00 000
318 // + 000 00 000
319 // 55695.480081
320 // + 000 00 000 + 000 00 000
321 // + 000 00 000 + 000 00 000
322 // 0000.000 0000.000
323 // 0 2
324
325 // status
326 // year month day hour minute seconds millisec
327 // year month day hour minute seconds millisec
328 // ra(+ h m s) dec(+ d m s) ha(+ h m s)
329 // mjd
330 // zd(+ d m s) az(+ d m s)
331 // zd(+ d m s) az(+ d m s)
332 // zd_err az_err
333 // armed(0=unlocked, 1=locked)
334 // stgmd(0=none, 1=starguider, 2=starguider off)
335 istringstream stream(line.substr(16));
336
337 uint16_t status1;
338 stream >> status1;
339 const Time t1 = ReadTime(stream);
340
341 uint16_t status2;
342 stream >> status2;
343 const Time t2 = ReadTime(stream);
344
345 const double ra = ReadAngle(stream);
346 const double dec = ReadAngle(stream);
347 const double ha = ReadAngle(stream);
348
349 double mjd;
350 stream >> mjd;
351
352 const double zd1 = ReadAngle(stream);
353 const double az1 = ReadAngle(stream);
354 const double zd2 = ReadAngle(stream);
355 const double az2 = ReadAngle(stream);
356
357 double zd_err, az_err;
358 stream >> zd_err;
359 stream >> az_err;
360
361 uint16_t armed, stgmd;
362 stream >> armed;
363 stream >> stgmd;
364
365 if (stream.fail())
366 return;
367
368 // Status 0: Error
369 // Status 1: Stopped
370 // Status 3: Stopping || Moving
371 // Status 4: Tracking
372 if (status1==0)
373 status1 = 99;
374 fState = status1==1 ? armed+1 : status1;
375
376 const array<double, 2> point = {{ zd2, az2 }};
377 UpdatePointing(t1, point);
378
379 const array<double, 7> track =
380 {{
381 ra, dec, ha,
382 zd1, az1,
383 zd_err, az_err
384 }};
385 UpdateTracking(Time(mjd), track);
386
387 // ---- DIM ----> t1 as event time
388 // status1
389 // mjd
390 // ra/dec/ha
391 // zd/az (nominal)
392 // zd/az (current)
393 // err(zd/az)
394 // [armed] [stgmd]
395
396 // Maybe:
397 // POINTING_POSITION --> t1, zd/az (current), [armed, stgmd, status1]
398 //
399 // if (mjd>0)
400 // TRACKING_POSITION --> mjd, zd/az (nominal), err(zd/az)
401 // ra/dec, ha(not well defined),
402 // [Nominal + Error == Current]
403
404 // MJD is the time which corresponds to the nominal position
405 // t1 is the time which corresponds to the current position/HA
406
407 return;
408 }
409 }
410
411 void StartReadReport()
412 {
413 boost::asio::async_read_until(*this, fBuffer, '\n',
414 boost::bind(&ConnectionDrive::HandleReceivedReport, this,
415 dummy::error, dummy::bytes_transferred));
416 }
417
418 boost::asio::deadline_timer fKeepAlive;
419
420 void KeepAlive()
421 {
422 PostMessage(string("KEEP_ALIVE"));
423
424 fKeepAlive.expires_from_now(boost::posix_time::seconds(10));
425 fKeepAlive.async_wait(boost::bind(&ConnectionDrive::HandleKeepAlive,
426 this, dummy::error));
427 }
428
429 void HandleKeepAlive(const bs::error_code &error)
430 {
431 // 125: Operation canceled (bs::error_code(125, bs::system_category))
432 if (error && error!=ba::error::basic_errors::operation_aborted)
433 {
434 ostringstream str;
435 str << "Write timeout of " << URL() << ": " << error.message() << " (" << error << ")";// << endl;
436 Error(str);
437
438 PostClose(false);
439 return;
440 }
441
442 if (!is_open())
443 {
444 // For example: Here we could schedule a new accept if we
445 // would not want to allow two connections at the same time.
446 return;
447 }
448
449 // Check whether the deadline has passed. We compare the deadline
450 // against the current time since a new asynchronous operation
451 // may have moved the deadline before this actor had a chance
452 // to run.
453 if (fKeepAlive.expires_at() > ba::deadline_timer::traits_type::now())
454 return;
455
456 KeepAlive();
457 }
458
459
460private:
461 // This is called when a connection was established
462 void ConnectionEstablished()
463 {
464 StartReadReport();
465 KeepAlive();
466 }
467
468 /*
469 void HandleReadTimeout(const bs::error_code &error)
470 {
471 if (error && error!=ba::error::basic_errors::operation_aborted)
472 {
473 stringstream str;
474 str << "Read timeout of " << URL() << ": " << error.message() << " (" << error << ")";// << endl;
475 Error(str);
476
477 PostClose();
478 return;
479
480 }
481
482 if (!is_open())
483 {
484 // For example: Here we could schedule a new accept if we
485 // would not want to allow two connections at the same time.
486 return;
487 }
488
489 // Check whether the deadline has passed. We compare the deadline
490 // against the current time since a new asynchronous operation
491 // may have moved the deadline before this actor had a chance
492 // to run.
493 if (fInTimeout.expires_at() > ba::deadline_timer::traits_type::now())
494 return;
495
496 Error("Timeout reading data from "+URL());
497
498 PostClose();
499 }*/
500
501
502public:
503
504 static const uint16_t kMaxAddr;
505
506public:
507 ConnectionDrive(ba::io_service& ioservice, MessageImp &imp) : Connection(ioservice, imp()),
508 fState(0), fIsVerbose(true), fKeepAlive(ioservice)
509 {
510 SetLogStream(&imp);
511 }
512
513 void SetVerbose(bool b)
514 {
515 fIsVerbose = b;
516 }
517
518 int GetState() const { return IsConnected() ? fState+1 : 1; }
519};
520
521const uint16_t ConnectionDrive::kMaxAddr = 0xfff;
522
523// ------------------------------------------------------------------------
524
525#include "DimDescriptionService.h"
526
527class ConnectionDimDrive : public ConnectionDrive
528{
529private:
530
531 DimDescribedService fDimPointing;
532 DimDescribedService fDimTracking;
533
534 template<size_t N>
535 void Update(DimDescribedService &svc, const Time &t, const array<double, N> &arr) const
536 {
537 svc.setTimestamp(int(t.UnixTime()), t.ms());
538 svc.setData(const_cast<double*>(arr.data()), arr.size()*sizeof(double));
539 svc.updateService();
540 }
541
542 virtual void UpdatePointing(const Time &t,
543 const array<double, 2> &arr)
544 {
545 Update(fDimPointing, t, arr);
546 }
547
548 virtual void UpdateTracking(const Time &t,
549 const array<double, 7> &arr)
550 {
551 Update(fDimTracking, t, arr);
552 }
553
554public:
555 ConnectionDimDrive(ba::io_service& ioservice, MessageImp &imp) :
556 ConnectionDrive(ioservice, imp),
557 fDimPointing("FTM_CONTROL/POINTING_POSITION", "D:2", ""),
558 fDimTracking("FTM_CONTROL/TRACKING_POSITION", "D:7", "")
559 {
560 }
561
562 // 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
563};
564
565// ------------------------------------------------------------------------
566
567template <class T, class S>
568class StateMachineDrive : public T, public ba::io_service, public ba::io_service::work
569{
570 int Wrap(boost::function<void()> f)
571 {
572 f();
573 return T::GetCurrentState();
574 }
575
576 boost::function<int(const EventImp &)> Wrapper(boost::function<void()> func)
577 {
578 return bind(&StateMachineDrive::Wrap, this, func);
579 }
580
581private:
582 S fDrive;
583
584 enum states_t
585 {
586 kStateDisconnected = 1,
587 kStateConnected,
588 kStateArmed,
589 kStateMoving,
590 kStateTracking,
591 };
592
593 // Status 0: Error
594 // Status 1: Unlocked
595 // Status 2: Locked
596 // Status 3: Stopping || Moving
597 // Status 4: Tracking
598
599 bool CheckEventSize(size_t has, const char *name, size_t size)
600 {
601 if (has==size)
602 return true;
603
604 ostringstream msg;
605 msg << name << " - Received event has " << has << " bytes, but expected " << size << ".";
606 T::Fatal(msg);
607 return false;
608 }
609
610 enum Coordinates
611 {
612 kPoint,
613 kTrackSlow,
614 kTrackFast
615 };
616
617 string AngleToStr(double angle)
618 {
619 /* Handle sign */
620 const char sgn = angle<0?'-':'+';
621
622 /* Round interval and express in smallest units required */
623 double a = round(3600. * fabs(angle)); // deg to seconds
624
625 /* Separate into fields */
626 const double ad = trunc(a/3600.);
627 a -= ad * 3600.;
628 const double am = trunc(a/60.);
629 a -= am * 60.;
630 const double as = trunc(a);
631
632 /* Return results */
633 ostringstream str;
634 str << sgn << " " << uint16_t(ad) << " " << uint16_t(am) << " " << as;
635 return str.str();
636 }
637
638 int SendCommand(const string &str)
639 {
640 fDrive.PostMessage(str);
641 return T::GetCurrentState();
642 }
643
644 int SendCoordinates(const EventImp &evt, const Coordinates type)
645 {
646 if (!CheckEventSize(evt.GetSize(), "SendCoordinates", 16))
647 return T::kSM_FatalError;
648
649 const double *dat = evt.Ptr<double>();
650
651 string command;
652
653 switch (type)
654 {
655 case kPoint: command += "ZDAZ "; break;
656 case kTrackSlow: command += "RADEC "; break;
657 case kTrackFast: command += "GRB "; break;
658 }
659
660 command += AngleToStr(dat[0]) + ' ' + AngleToStr(dat[1]);
661
662 return SendCommand(command);
663 }
664
665 int SetVerbosity(const EventImp &evt)
666 {
667 if (!CheckEventSize(evt.GetSize(), "SetVerbosity", 1))
668 return T::kSM_FatalError;
669
670 fDrive.SetVerbose(evt.GetBool());
671
672 return T::GetCurrentState();
673 }
674
675 int Disconnect()
676 {
677 // Close all connections
678 fDrive.PostClose(false);
679
680 /*
681 // Now wait until all connection have been closed and
682 // all pending handlers have been processed
683 poll();
684 */
685
686 return T::GetCurrentState();
687 }
688
689 int Reconnect(const EventImp &evt)
690 {
691 // Close all connections to supress the warning in SetEndpoint
692 fDrive.PostClose(false);
693
694 // Now wait until all connection have been closed and
695 // all pending handlers have been processed
696 poll();
697
698 if (evt.GetBool())
699 fDrive.SetEndpoint(evt.GetString());
700
701 // Now we can reopen the connection
702 fDrive.PostClose(true);
703
704 return T::GetCurrentState();
705 }
706
707 int Execute()
708 {
709 // Dispatch (execute) at most one handler from the queue. In contrary
710 // to run_one(), it doesn't wait until a handler is available
711 // which can be dispatched, so poll_one() might return with 0
712 // handlers dispatched. The handlers are always dispatched/executed
713 // synchronously, i.e. within the call to poll_one()
714 poll_one();
715
716 return fDrive.GetState();
717 }
718
719
720public:
721 StateMachineDrive(ostream &out=cout) :
722 T(out, "DRIVE_CONTROL"), ba::io_service::work(static_cast<ba::io_service&>(*this)),
723 fDrive(*this, *this)
724 {
725 // ba::io_service::work is a kind of keep_alive for the loop.
726 // It prevents the io_service to go to stopped state, which
727 // would prevent any consecutive calls to run()
728 // or poll() to do nothing. reset() could also revoke to the
729 // previous state but this might introduce some overhead of
730 // deletion and creation of threads and more.
731
732 // State names
733 AddStateName(kStateDisconnected, "Disconnected",
734 "");
735
736 AddStateName(kStateConnected, "Connected",
737 "");
738
739 AddStateName(kStateArmed, "Armed",
740 "");
741
742 AddStateName(kStateMoving, "Moving",
743 "");
744
745 AddStateName(kStateTracking, "Tracking",
746 "");
747
748 // kStateIdle
749 // kStateArmed
750 // kStateMoving
751 // kStateTracking
752
753 // Init
754 // -----------
755 // "ARM lock"
756 // "STGMD off"
757
758 /*
759 [ ] WAIT -> WM_WAIT
760 [x] STOP! -> WM_STOP
761 [x] RADEC ra(+ d m s.f) dec(+ d m s.f)
762 [x] GRB ra(+ d m s.f) dec(+ d m s.f)
763 [x] ZDAZ zd(+ d m s.f) az (+ d m s.f)
764 [ ] CELEST id offset angle
765 [ ] MOON wobble offset
766 [ ] PREPS string
767 [ ] TPOIN star mag
768 [ ] ARM lock/unlock
769 [ ] STGMD on/off
770 */
771
772 // Drive Commands
773 T::AddEvent("MOVE_TO", "D:2", kStateArmed) // ->ZDAZ
774 (bind(&StateMachineDrive::SendCoordinates, this, placeholders::_1, kPoint))
775 (""
776 "|zd[deg]:"
777 "|az[deg]:");
778
779 T::AddEvent("TRACK", "D:2", kStateArmed) // ->RADEC/GRB
780 (bind(&StateMachineDrive::SendCoordinates, this, placeholders::_1, kTrackSlow))
781 (""
782 "|ra[h]:"
783 "|dec[deg]:");
784
785 T::AddEvent("MOON", kStateArmed)
786 (bind(&StateMachineDrive::SendCommand, this, "MOON 0 0"))
787 ("");
788 T::AddEvent("VENUS", kStateArmed)
789 (bind(&StateMachineDrive::SendCommand, this, "CELEST 2 0 0"))
790 ("");
791 T::AddEvent("MARS", kStateArmed)
792 (bind(&StateMachineDrive::SendCommand, this, "CELEST 4 0 0"))
793 ("");
794 T::AddEvent("JUPITER", kStateArmed)
795 (bind(&StateMachineDrive::SendCommand, this, "CELEST 5 0 0"))
796 ("");
797 T::AddEvent("SATURN", kStateArmed)
798 (bind(&StateMachineDrive::SendCommand, this, "CELEST 6 0 0"))
799 ("");
800
801 T::AddEvent("TPOINT")
802 (bind(&StateMachineDrive::SendCommand, this, "TPOIN FACT 0"))
803 ("");
804
805 T::AddEvent("STOP")
806 (bind(&StateMachineDrive::SendCommand, this, "STOP!"))
807 ("");
808
809 T::AddEvent("ARM", kStateConnected)
810 (bind(&StateMachineDrive::SendCommand, this, "ARM lock"))
811 ("");
812
813
814 // Verbosity commands
815 T::AddEvent("SET_VERBOSE", "B")
816 (bind(&StateMachineDrive::SetVerbosity, this, placeholders::_1))
817 ("set verbosity state"
818 "|verbosity[bool]:disable or enable verbosity for received data (yes/no), except dynamic data");
819
820 // Conenction commands
821 AddEvent("DISCONNECT", kStateConnected, kStateArmed)
822 (bind(&StateMachineDrive::Disconnect, this))
823 ("disconnect from ethernet");
824
825 AddEvent("RECONNECT", "O", kStateDisconnected, kStateConnected, kStateArmed)
826 (bind(&StateMachineDrive::Reconnect, this, placeholders::_1))
827 ("(Re)connect ethernet connection to FTM, a new address can be given"
828 "|[host][string]:new ethernet address in the form <host:port>");
829
830 fDrive.StartConnect();
831 }
832
833 void SetEndpoint(const string &url)
834 {
835 fDrive.SetEndpoint(url);
836 }
837
838 int EvalOptions(Configuration &conf)
839 {
840 SetEndpoint(conf.Get<string>("addr"));
841
842 fDrive.SetVerbose(!conf.Get<bool>("quiet"));
843
844 return -1;
845 }
846};
847
848// ------------------------------------------------------------------------
849
850#include "Main.h"
851
852/*
853void RunThread(StateMachineImp *io_service)
854{
855 // This is necessary so that the StateMachien Thread can signal the
856 // Readline to exit
857 io_service->Run();
858 Readline::Stop();
859}
860*/
861/*
862template<class S, class T>
863int RunDim(Configuration &conf)
864{
865 WindowLog wout;
866
867 ReadlineColor::PrintBootMsg(wout, conf.GetName(), false);
868
869 if (conf.Has("log"))
870 if (!wout.OpenLogFile(conf.Get<string>("log")))
871 wout << kRed << "ERROR - Couldn't open log-file " << conf.Get<string>("log") << ": " << strerror(errno) << endl;
872
873 // Start io_service.Run to use the StateMachineImp::Run() loop
874 // Start io_service.run to only use the commandHandler command detaching
875 StateMachineDrive<S, T> io_service(wout);
876 if (!io_service.EvalConfiguration(conf))
877 return -1;
878
879 io_service.Run();
880
881 return 0;
882}
883*/
884
885template<class T, class S, class R>
886int RunShell(Configuration &conf)
887{
888 return Main<T, StateMachineDrive<S, R>>(conf);
889/*
890 static T shell(conf.GetName().c_str(), conf.Get<int>("console")!=1);
891
892 WindowLog &win = shell.GetStreamIn();
893 WindowLog &wout = shell.GetStreamOut();
894
895 if (conf.Has("log"))
896 if (!wout.OpenLogFile(conf.Get<string>("log")))
897 win << kRed << "ERROR - Couldn't open log-file " << conf.Get<string>("log") << ": " << strerror(errno) << endl;
898
899 StateMachineDrive<S, R> io_service(wout);
900 if (!io_service.EvalConfiguration(conf))
901 return -1;
902
903 shell.SetReceiver(io_service);
904
905 boost::thread t(bind(RunThread, &io_service));
906 // boost::thread t(bind(&StateMachineDrive<S>::Run, &io_service));
907
908 if (conf.Has("cmd"))
909 {
910 const vector<string> v = conf.Get<vector<string>>("cmd");
911 for (vector<string>::const_iterator it=v.begin(); it!=v.end(); it++)
912 shell.ProcessLine(*it);
913 }
914
915 if (conf.Has("exec"))
916 {
917 const vector<string> v = conf.Get<vector<string>>("exec");
918 for (vector<string>::const_iterator it=v.begin(); it!=v.end(); it++)
919 shell.Execute(*it);
920 }
921
922 if (conf.Get<bool>("quit"))
923 shell.Stop();
924
925 shell.Run(); // Run the shell
926 io_service.Stop(); // Signal Loop-thread to stop
927 // io_service.Close(); // Obsolete, done by the destructor
928
929 // Wait until the StateMachine has finished its thread
930 // before returning and destroying the dim objects which might
931 // still be in use.
932 t.join();
933
934 return 0;
935 */
936}
937
938void SetupConfiguration(Configuration &conf)
939{
940 const string n = conf.GetName()+".log";
941
942 po::options_description config("Program options");
943 config.add_options()
944 ("dns", var<string>("localhost"), "Dim nameserver host name (Overwites DIM_DNS_NODE environment variable)")
945 ("log,l", var<string>(n), "Write log-file")
946 ("no-dim,d", po_switch(), "Disable dim services")
947 ("console,c", var<int>(), "Use console (0=shell, 1=simple buffered, X=simple unbuffered)")
948 ("cmd", vars<string>(), "Execute one or more commands at startup")
949 ("exec,e", vars<string>(), "Execute one or more scrips at startup")
950 ("quit", po_switch(), "Quit after startup");
951 ;
952
953 po::options_description control("FTM control options");
954 control.add_options()
955 ("addr,a", var<string>("localhost:7404"), "Network address of FTM")
956 ("quiet,q", po_bool(), "Disable printing contents of all received messages (except dynamic data) in clear text.")
957 ;
958
959 conf.AddEnv("dns", "DIM_DNS_NODE");
960
961 conf.AddOptions(config);
962 conf.AddOptions(control);
963}
964
965/*
966 Extract usage clause(s) [if any] for SYNOPSIS.
967 Translators: "Usage" and "or" here are patterns (regular expressions) which
968 are used to match the usage synopsis in program output. An example from cp
969 (GNU coreutils) which contains both strings:
970 Usage: cp [OPTION]... [-T] SOURCE DEST
971 or: cp [OPTION]... SOURCE... DIRECTORY
972 or: cp [OPTION]... -t DIRECTORY SOURCE...
973 */
974void PrintUsage()
975{
976 cout <<
977 "The drivectrl is an interface to cosy.\n"
978 "\n"
979 "The default is that the program is started without user intercation. "
980 "All actions are supposed to arrive as DimCommands. Using the -c "
981 "option, a local shell can be initialized. With h or help a short "
982 "help message about the usuage can be brought to the screen.\n"
983 "\n"
984 "Usage: drivectrl [-c type] [OPTIONS]\n"
985 " or: drivectrl [OPTIONS]\n";
986 cout << endl;
987}
988
989void PrintHelp()
990{
991 /* Additional help text which is printed after the configuration
992 options goes here */
993
994 /*
995 cout << "bla bla bla" << endl << endl;
996 cout << endl;
997 cout << "Environment:" << endl;
998 cout << "environment" << endl;
999 cout << endl;
1000 cout << "Examples:" << endl;
1001 cout << "test exam" << endl;
1002 cout << endl;
1003 cout << "Files:" << endl;
1004 cout << "files" << endl;
1005 cout << endl;
1006 */
1007}
1008
1009int main(int argc, const char* argv[])
1010{
1011 Configuration conf(argv[0]);
1012 conf.SetPrintUsage(PrintUsage);
1013 SetupConfiguration(conf);
1014
1015 po::variables_map vm;
1016 try
1017 {
1018 vm = conf.Parse(argc, argv);
1019 }
1020#if BOOST_VERSION > 104000
1021 catch (po::multiple_occurrences &e)
1022 {
1023 cerr << "Program options invalid due to: " << e.what() << " of '" << e.get_option_name() << "'." << endl;
1024 return -1;
1025 }
1026#endif
1027 catch (exception& e)
1028 {
1029 cerr << "Program options invalid due to: " << e.what() << endl;
1030 return -1;
1031 }
1032
1033 if (conf.HasVersion() || conf.HasPrint())
1034 return -1;
1035
1036 if (conf.HasHelp())
1037 {
1038 PrintHelp();
1039 return -1;
1040 }
1041
1042 Dim::Setup(conf.Get<string>("dns"));
1043
1044 //try
1045 {
1046 // No console access at all
1047 if (!conf.Has("console"))
1048 {
1049 if (conf.Get<bool>("no-dim"))
1050 return RunShell<LocalStream, StateMachine, ConnectionDrive>(conf);
1051 else
1052 return RunShell<LocalStream, StateMachineDim, ConnectionDimDrive>(conf);
1053 }
1054 // Cosole access w/ and w/o Dim
1055 if (conf.Get<bool>("no-dim"))
1056 {
1057 if (conf.Get<int>("console")==0)
1058 return RunShell<LocalShell, StateMachine, ConnectionDrive>(conf);
1059 else
1060 return RunShell<LocalConsole, StateMachine, ConnectionDrive>(conf);
1061 }
1062 else
1063 {
1064 if (conf.Get<int>("console")==0)
1065 return RunShell<LocalShell, StateMachineDim, ConnectionDimDrive>(conf);
1066 else
1067 return RunShell<LocalConsole, StateMachineDim, ConnectionDimDrive>(conf);
1068 }
1069 }
1070 /*catch (std::exception& e)
1071 {
1072 cerr << "Exception: " << e.what() << endl;
1073 return -1;
1074 }*/
1075
1076 return 0;
1077}
Note: See TracBrowser for help on using the repository browser.