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

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