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

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