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

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