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

Last change on this file since 12450 was 12309, checked in by tbretz, 13 years ago
First woring and tested version.
File size: 29.3 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 fRa;
58 double fDec;
59
60 double fNominalZd;
61 double fNominalAz;
62
63 double fPointingZd;
64 double fPointingAz;
65
66 double fFeedbackZd;
67 double fFeedbackAz;
68
69 uint16_t fNumLeds;
70 uint16_t fNumRings;
71
72 double fCenterX;
73 double fCenterY;
74 double fCenterMag;
75
76 double fStarX;
77 double fStarY;
78 double fStarMag;
79
80 double fRealMag;
81
82 } __attribute__((__packed__));
83};
84
85
86
87// ------------------------------------------------------------------------
88
89class ConnectionDrive : public Connection
90{
91 int fState;
92
93 bool fIsVerbose;
94
95 // --verbose
96 // --hex-out
97 // --dynamic-out
98 // --load-file
99 // --leds
100 // --trigger-interval
101 // --physcis-coincidence
102 // --calib-coincidence
103 // --physcis-window
104 // --physcis-window
105 // --trigger-delay
106 // --time-marker-delay
107 // --dead-time
108 // --clock-conditioner-r0
109 // --clock-conditioner-r1
110 // --clock-conditioner-r8
111 // --clock-conditioner-r9
112 // --clock-conditioner-r11
113 // --clock-conditioner-r13
114 // --clock-conditioner-r14
115 // --clock-conditioner-r15
116 // ...
117
118 virtual void UpdatePointing(const Time &, const array<double, 2> &)
119 {
120 }
121
122 virtual void UpdateTracking(const Time &, const array<double, 7> &)
123 {
124 }
125
126 virtual void UpdateStarguider(const Time &, const Drive::DimStarguider &)
127 {
128 }
129
130 virtual void UpdateTPoint(const Time &, const Drive::DimTPoint &, const string &)
131 {
132 }
133
134protected:
135 map<uint16_t, int> fCounter;
136
137 ba::streambuf fBuffer;
138
139 Time ReadTime(istream &in)
140 {
141 uint16_t y, m, d, hh, mm, ss, ms;
142 in >> y >> m >> d >> hh >> mm >> ss >> ms;
143
144 return Time(y, m, d, hh, mm, ss, ms*1000);
145 }
146
147 double ReadAngle(istream &in)
148 {
149 char sgn;
150 uint16_t d, m;
151 float s;
152
153 in >> sgn >> d >> m >> s;
154
155 const double ret = ((60.0 * (60.0 * (double)d + (double)m) + s))/3600.;
156 return sgn=='-' ? -ret : ret;
157 }
158
159 void HandleReceivedReport(const boost::system::error_code& err, size_t bytes_received)
160 {
161 // Do not schedule a new read if the connection failed.
162 if (bytes_received==0 || err)
163 {
164 if (err==ba::error::eof)
165 Warn("Connection closed by remote host (FTM).");
166
167 // 107: Transport endpoint is not connected (bs::error_code(107, bs::system_category))
168 // 125: Operation canceled
169 if (err && err!=ba::error::eof && // Connection closed by remote host
170 err!=ba::error::basic_errors::not_connected && // Connection closed by remote host
171 err!=ba::error::basic_errors::operation_aborted) // Connection closed by us
172 {
173 ostringstream str;
174 str << "Reading from " << URL() << ": " << err.message() << " (" << err << ")";// << endl;
175 Error(str);
176 }
177 PostClose(err!=ba::error::basic_errors::operation_aborted);
178 return;
179 }
180
181 istream is(&fBuffer);
182
183 string line;
184 getline(is, line);
185
186 if (fIsVerbose)
187 Out() << line << endl;
188
189 StartReadReport();
190
191 if (line.substr(0, 13)=="STARG-REPORT ")
192 {
193 istringstream stream(line.substr(16));
194
195 // 0: Error
196 // 1: Standby
197 // 2: Monitoring
198 uint16_t status1;
199 stream >> status1;
200 const Time t1 = ReadTime(stream);
201
202 uint16_t status2;
203 stream >> status2;
204 const Time t2 = ReadTime(stream);
205
206 double misszd, missaz;
207 stream >> misszd >> missaz;
208
209 const double zd = ReadAngle(stream);
210 const double az = ReadAngle(stream);
211
212 double cx, cy;
213 stream >> cx >> cy;
214
215 int ncor;
216 stream >> ncor;
217
218 double bright, mjd;
219 stream >> bright >> mjd;
220
221 int nled, nring, nstars;
222 stream >> nled >> nring >> nstars;
223
224 if (stream.fail())
225 return;
226
227 Drive::DimStarguider data;
228
229 data.fMissZd = misszd;
230 data.fMissAz = missaz;
231 data.fNominalZd = zd;
232 data.fNominalAz = az;
233 data.fCenterX = cx;
234 data.fCenterY = cy;
235 data.fNumCorrelated = ncor;
236 data.fBrightness = bright;
237 data.fNumLeds = nled;
238 data.fNumRings = nring;
239 data.fNumStars = nstars;
240
241 UpdateStarguider(Time(mjd), data);
242
243 return;
244
245 }
246
247 if (line.substr(0, 14)=="TPOINT-REPORT ")
248 {
249 istringstream stream(line.substr(17));
250
251 uint16_t status1;
252 stream >> status1;
253 const Time t1 = ReadTime(stream);
254
255 uint16_t status2;
256 stream >> status2;
257 const Time t2 = ReadTime(stream);
258
259 char type;
260 stream >> type;
261 if (type != 'T')
262 return;
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.fRa = ra;
286 tpoint.fDec = dec;
287
288 tpoint.fNominalZd = 90-alt1-dzd;
289 tpoint.fNominalAz = 90-az1 +daz;
290
291 tpoint.fPointingZd = 90-alt1;
292 tpoint.fPointingAz = az1;
293
294 tpoint.fFeedbackZd = 90-alt2;
295 tpoint.fFeedbackAz = az2;
296
297 tpoint.fNumLeds = nled;
298 tpoint.fNumRings = nring;
299
300 tpoint.fCenterX = cx;
301 tpoint.fCenterY = cy;
302 tpoint.fCenterMag = cmag;
303
304 tpoint.fStarX = sx;
305 tpoint.fStarY = sy;
306 tpoint.fStarMag = smag;
307
308 tpoint.fRealMag = mag;
309
310 UpdateTPoint(t1, tpoint, name);
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 array<double, 2> point = {{ zd2, az2 }};
380 UpdatePointing(t1, point);
381
382 const array<double, 7> track =
383 {{
384 ra, dec, ha,
385 zd1, az1,
386 zd_err/3600, az_err/3600
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 ostringstream 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 DimDescribedService fDimTPoint;
537
538 virtual void UpdatePointing(const Time &t,
539 const array<double, 2> &arr)
540 {
541 fDimPointing.setData(arr);
542 fDimPointing.Update(t);
543 }
544
545 virtual void UpdateTracking(const Time &t,
546 const array<double, 7> &arr)
547 {
548 fDimTracking.setData(arr);
549 fDimTracking.Update(t);
550 }
551 virtual void UpdateTPoint(const Time &t,
552 const Drive::DimTPoint &data,
553 const string &name)
554 {
555 vector<char> dim(sizeof(data)+name.length()+1);
556 memcpy(dim.data(), &data, sizeof(data));
557 memcpy(dim.data()+sizeof(data), name.c_str(), name.length()+1);
558
559 fDimTPoint.setData(dim);
560 fDimTPoint.Update(t);
561 }
562
563public:
564 ConnectionDimDrive(ba::io_service& ioservice, MessageImp &imp) :
565 ConnectionDrive(ioservice, imp),
566 fDimPointing("DRIVE_CONTROL/POINTING_POSITION", "D:1;D:1",
567 "|Zd[deg]:Zenith distance (encoder readout)"
568 "|Az[deg]:Azimuth angle (encoder readout)"),
569 fDimTracking("DRIVE_CONTROL/TRACKING_POSITION", "D:1;D:1;D:1;D:1;D:1;D:1;D:1",
570 "|Ra[h]:Command right ascension"
571 "|Dec[deg]:Command declination"
572 "|Ha[h]:Corresponding hour angle"
573 "|Zd[deg]:Nominal zenith distance"
574 "|Az[deg]:Nominal azimuth angle"
575 "|dZd[deg]:Control deviation Zd"
576 "|dAz[deg]:Control deviation Az"),
577 fDimTPoint("DRIVE_CONTROL/TPOINT", "D:1;D:1;D:1;D:1;D:1;D:1;D:1;D:1;S:1;D:1;D:1;D:1;D:1;D:1;D:1;D:1;C",
578 "|Ra[h]:Command right ascension"
579 "|Dec[deg]:Command declination"
580 "|Zd_nom[deg]:Nominal zenith distance"
581 "|Az_nom[deg]:Nominal azimuth angle"
582 "|Zd_cur[deg]:Current zenith distance (calculated from image)"
583 "|Az_cur[deg]:Current azimuth angle (calculated from image)"
584 "|Zd_enc[deg]:Feedback zenith axis (from encoder)"
585 "|Az_enc[deg]:Feedback azimuth angle (from encoder)"
586 "|N_leds[cnt]:Number of detected LEDs"
587 "|N_rings[cnt]:Number of rings used to calculate the camera center"
588 "|Xc[pix]:X position of center in CCD camera frame"
589 "|Yc[pix]:Y position of center in CCD camera frame"
590 "|Ic[au]:Average intensity (LED intensity weighted with their frequency of occurance in the calculation)"
591 "|Xs[pix]:X position of start in CCD camera frame"
592 "|Ys[pix]:Y position of star in CCD camera frame"
593 "|Ms[mag]:Artifical magnitude of star (calculated form image))"
594 "|Mc[mag]:Catalog magnitude of star")
595
596 {
597 }
598
599 // 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
600};
601
602// ------------------------------------------------------------------------
603
604template <class T, class S>
605class StateMachineDrive : public T, public ba::io_service, public ba::io_service::work
606{
607 int Wrap(boost::function<void()> f)
608 {
609 f();
610 return T::GetCurrentState();
611 }
612
613 boost::function<int(const EventImp &)> Wrapper(boost::function<void()> func)
614 {
615 return bind(&StateMachineDrive::Wrap, this, func);
616 }
617
618private:
619 S fDrive;
620
621 enum states_t
622 {
623 kStateDisconnected = 1,
624 kStateConnected,
625 kStateArmed,
626 kStateMoving,
627 kStateTracking,
628 };
629
630 // Status 0: Error
631 // Status 1: Unlocked
632 // Status 2: Locked
633 // Status 3: Stopping || Moving
634 // Status 4: Tracking
635
636 bool CheckEventSize(size_t has, const char *name, size_t size)
637 {
638 if (has==size)
639 return true;
640
641 ostringstream msg;
642 msg << name << " - Received event has " << has << " bytes, but expected " << size << ".";
643 T::Fatal(msg);
644 return false;
645 }
646
647 enum Coordinates
648 {
649 kPoint,
650 kTrackSlow,
651 kTrackFast
652 };
653
654 string AngleToStr(double angle)
655 {
656 /* Handle sign */
657 const char sgn = angle<0?'-':'+';
658
659 /* Round interval and express in smallest units required */
660 double a = round(3600. * fabs(angle)); // deg to seconds
661
662 /* Separate into fields */
663 const double ad = trunc(a/3600.);
664 a -= ad * 3600.;
665 const double am = trunc(a/60.);
666 a -= am * 60.;
667 const double as = trunc(a);
668
669 /* Return results */
670 ostringstream str;
671 str << sgn << " " << uint16_t(ad) << " " << uint16_t(am) << " " << as;
672 return str.str();
673 }
674
675 int SendCommand(const string &str)
676 {
677 fDrive.PostMessage(str);
678 return T::GetCurrentState();
679 }
680
681 int SendCoordinates(const EventImp &evt, const Coordinates type)
682 {
683 if (!CheckEventSize(evt.GetSize(), "SendCoordinates", 16))
684 return T::kSM_FatalError;
685
686 const double *dat = evt.Ptr<double>();
687
688 string command;
689
690 switch (type)
691 {
692 case kPoint: command += "ZDAZ "; break;
693 case kTrackSlow: command += "RADEC "; break;
694 case kTrackFast: command += "GRB "; break;
695 }
696
697 command += AngleToStr(dat[0]) + ' ' + AngleToStr(dat[1]);
698
699 return SendCommand(command);
700 }
701
702 int SetLedBrightness(const EventImp &evt)
703 {
704 if (!CheckEventSize(evt.GetSize(), "SetLedBrightness", 8))
705 return T::kSM_FatalError;
706
707 const uint32_t *led = evt.Ptr<uint32_t>();
708
709 ostringstream cmd;
710 cmd << "LEDS " << led[0] << " " << led[1];
711 return SendCommand(cmd.str());
712 }
713
714
715 int SetVerbosity(const EventImp &evt)
716 {
717 if (!CheckEventSize(evt.GetSize(), "SetVerbosity", 1))
718 return T::kSM_FatalError;
719
720 fDrive.SetVerbose(evt.GetBool());
721
722 return T::GetCurrentState();
723 }
724
725 int Disconnect()
726 {
727 // Close all connections
728 fDrive.PostClose(false);
729
730 /*
731 // Now wait until all connection have been closed and
732 // all pending handlers have been processed
733 poll();
734 */
735
736 return T::GetCurrentState();
737 }
738
739 int Reconnect(const EventImp &evt)
740 {
741 // Close all connections to supress the warning in SetEndpoint
742 fDrive.PostClose(false);
743
744 // Now wait until all connection have been closed and
745 // all pending handlers have been processed
746 poll();
747
748 if (evt.GetBool())
749 fDrive.SetEndpoint(evt.GetString());
750
751 // Now we can reopen the connection
752 fDrive.PostClose(true);
753
754 return T::GetCurrentState();
755 }
756
757 int Execute()
758 {
759 // Dispatch (execute) at most one handler from the queue. In contrary
760 // to run_one(), it doesn't wait until a handler is available
761 // which can be dispatched, so poll_one() might return with 0
762 // handlers dispatched. The handlers are always dispatched/executed
763 // synchronously, i.e. within the call to poll_one()
764 poll_one();
765
766 return fDrive.GetState();
767 }
768
769
770public:
771 StateMachineDrive(ostream &out=cout) :
772 T(out, "DRIVE_CONTROL"), ba::io_service::work(static_cast<ba::io_service&>(*this)),
773 fDrive(*this, *this)
774 {
775 // ba::io_service::work is a kind of keep_alive for the loop.
776 // It prevents the io_service to go to stopped state, which
777 // would prevent any consecutive calls to run()
778 // or poll() to do nothing. reset() could also revoke to the
779 // previous state but this might introduce some overhead of
780 // deletion and creation of threads and more.
781
782 // State names
783 AddStateName(kStateDisconnected, "Disconnected",
784 "No connection to cosy");
785
786 AddStateName(kStateConnected, "Connected",
787 "Cosy connected, drive stopped");
788
789 AddStateName(kStateArmed, "Armed",
790 "Cosy armed, drive stopped");
791
792 AddStateName(kStateMoving, "Moving",
793 "Telescope moving");
794
795 AddStateName(kStateTracking, "Tracking",
796 "Telescope tracking");
797
798 // kStateIdle
799 // kStateArmed
800 // kStateMoving
801 // kStateTracking
802
803 // Init
804 // -----------
805 // "ARM lock"
806 // "STGMD off"
807
808 /*
809 [ ] WAIT -> WM_WAIT
810 [x] STOP! -> WM_STOP
811 [x] RADEC ra(+ d m s.f) dec(+ d m s.f)
812 [x] GRB ra(+ d m s.f) dec(+ d m s.f)
813 [x] ZDAZ zd(+ d m s.f) az (+ d m s.f)
814 [ ] CELEST id offset angle
815 [ ] MOON wobble offset
816 [ ] PREPS string
817 [ ] TPOIN star mag
818 [ ] ARM lock/unlock
819 [ ] STGMD on/off
820 */
821
822 // Drive Commands
823 T::AddEvent("MOVE_TO", "D:2", kStateArmed) // ->ZDAZ
824 (bind(&StateMachineDrive::SendCoordinates, this, placeholders::_1, kPoint))
825 ("Move the telescope to the given local coordinates"
826 "|Zd[deg]:Zenith distance"
827 "|Az[deg]:Azimuth");
828
829 T::AddEvent("TRACK", "D:2", kStateArmed) // ->RADEC/GRB
830 (bind(&StateMachineDrive::SendCoordinates, this, placeholders::_1, kTrackSlow))
831 ("Move the telescope to the given sky coordinates and start tracking them"
832 "|Ra[h]:Right ascension"
833 "|Dec[deg]:Declination");
834
835 T::AddEvent("MOON", kStateArmed)
836 (bind(&StateMachineDrive::SendCommand, this, "MOON 0 0"))
837 ("Start tracking the moon");
838 T::AddEvent("VENUS", kStateArmed)
839 (bind(&StateMachineDrive::SendCommand, this, "CELEST 2 0 0"))
840 ("Start tracking Venus");
841 T::AddEvent("MARS", kStateArmed)
842 (bind(&StateMachineDrive::SendCommand, this, "CELEST 4 0 0"))
843 ("Start tracking Mars");
844 T::AddEvent("JUPITER", kStateArmed)
845 (bind(&StateMachineDrive::SendCommand, this, "CELEST 5 0 0"))
846 ("Start tracking Jupiter");
847 T::AddEvent("SATURN", kStateArmed)
848 (bind(&StateMachineDrive::SendCommand, this, "CELEST 6 0 0"))
849 ("Start tracking Saturn");
850
851 T::AddEvent("TAKE_TPOINT")
852 (bind(&StateMachineDrive::SendCommand, this, "TPOIN FACT 0"))
853 ("Take a TPoint");
854
855 T::AddEvent("SET_LED_BRIGHTNESS", "I:2")
856 (bind(&StateMachineDrive::SetLedBrightness, this, placeholders::_1))
857 ("Set the LED brightness of the top and bottom leds"
858 "|top[au]:Allowed range 0-32767 for top LEDs"
859 "|bot[au]:Allowed range 0-32767 for bottom LEDs");
860
861 T::AddEvent("LEDS_OFF")
862 (bind(&StateMachineDrive::SendCommand, this, "LEDS 0 0"))
863 ("Switch off TPoint LEDs");
864
865 T::AddEvent("STOP")
866 (bind(&StateMachineDrive::SendCommand, this, "STOP!"))
867 ("Stop any kind of movement.");
868
869// T::AddEvent("ARM", kStateConnected)
870// (bind(&StateMachineDrive::SendCommand, this, "ARM lock"))
871// ("");
872
873
874 // Verbosity commands
875 T::AddEvent("SET_VERBOSE", "B")
876 (bind(&StateMachineDrive::SetVerbosity, this, placeholders::_1))
877 ("set verbosity state"
878 "|verbosity[bool]:disable or enable verbosity for received data (yes/no), except dynamic data");
879
880 // Conenction commands
881 AddEvent("DISCONNECT", kStateConnected, kStateArmed)
882 (bind(&StateMachineDrive::Disconnect, this))
883 ("disconnect from ethernet");
884
885 AddEvent("RECONNECT", "O", kStateDisconnected, kStateConnected, kStateArmed)
886 (bind(&StateMachineDrive::Reconnect, this, placeholders::_1))
887 ("(Re)connect ethernet connection to FTM, a new address can be given"
888 "|[host][string]:new ethernet address in the form <host:port>");
889
890 fDrive.StartConnect();
891 }
892
893 void SetEndpoint(const string &url)
894 {
895 fDrive.SetEndpoint(url);
896 }
897
898 int EvalOptions(Configuration &conf)
899 {
900 SetEndpoint(conf.Get<string>("addr"));
901
902 fDrive.SetVerbose(!conf.Get<bool>("quiet"));
903
904 return -1;
905 }
906};
907
908// ------------------------------------------------------------------------
909
910#include "Main.h"
911
912
913template<class T, class S, class R>
914int RunShell(Configuration &conf)
915{
916 return Main::execute<T, StateMachineDrive<S, R>>(conf);
917}
918
919void SetupConfiguration(Configuration &conf)
920{
921 po::options_description control("FTM control options");
922 control.add_options()
923 ("no-dim,d", po_switch(), "Disable dim services")
924 ("addr,a", var<string>("localhost:7404"), "Network address of FTM")
925 ("quiet,q", po_bool(true), "Disable printing contents of all received messages (except dynamic data) in clear text.")
926 ;
927
928 conf.AddOptions(control);
929}
930
931/*
932 Extract usage clause(s) [if any] for SYNOPSIS.
933 Translators: "Usage" and "or" here are patterns (regular expressions) which
934 are used to match the usage synopsis in program output. An example from cp
935 (GNU coreutils) which contains both strings:
936 Usage: cp [OPTION]... [-T] SOURCE DEST
937 or: cp [OPTION]... SOURCE... DIRECTORY
938 or: cp [OPTION]... -t DIRECTORY SOURCE...
939 */
940void PrintUsage()
941{
942 cout <<
943 "The drivectrl is an interface to cosy.\n"
944 "\n"
945 "The default is that the program is started without user intercation. "
946 "All actions are supposed to arrive as DimCommands. Using the -c "
947 "option, a local shell can be initialized. With h or help a short "
948 "help message about the usuage can be brought to the screen.\n"
949 "\n"
950 "Usage: drivectrl [-c type] [OPTIONS]\n"
951 " or: drivectrl [OPTIONS]\n";
952 cout << endl;
953}
954
955void PrintHelp()
956{
957// Main::PrintHelp<StateMachineFTM<StateMachine, ConnectionFTM>>();
958
959 /* Additional help text which is printed after the configuration
960 options goes here */
961
962 /*
963 cout << "bla bla bla" << endl << endl;
964 cout << endl;
965 cout << "Environment:" << endl;
966 cout << "environment" << endl;
967 cout << endl;
968 cout << "Examples:" << endl;
969 cout << "test exam" << endl;
970 cout << endl;
971 cout << "Files:" << endl;
972 cout << "files" << endl;
973 cout << endl;
974 */
975}
976
977int main(int argc, const char* argv[])
978{
979 Configuration conf(argv[0]);
980 conf.SetPrintUsage(PrintUsage);
981 Main::SetupConfiguration(conf);
982 SetupConfiguration(conf);
983
984 if (!conf.DoParse(argc, argv, PrintHelp))
985 return -1;
986
987 //try
988 {
989 // No console access at all
990 if (!conf.Has("console"))
991 {
992 if (conf.Get<bool>("no-dim"))
993 return RunShell<LocalStream, StateMachine, ConnectionDrive>(conf);
994 else
995 return RunShell<LocalStream, StateMachineDim, ConnectionDimDrive>(conf);
996 }
997 // Cosole access w/ and w/o Dim
998 if (conf.Get<bool>("no-dim"))
999 {
1000 if (conf.Get<int>("console")==0)
1001 return RunShell<LocalShell, StateMachine, ConnectionDrive>(conf);
1002 else
1003 return RunShell<LocalConsole, StateMachine, ConnectionDrive>(conf);
1004 }
1005 else
1006 {
1007 if (conf.Get<int>("console")==0)
1008 return RunShell<LocalShell, StateMachineDim, ConnectionDimDrive>(conf);
1009 else
1010 return RunShell<LocalConsole, StateMachineDim, ConnectionDimDrive>(conf);
1011 }
1012 }
1013 /*catch (std::exception& e)
1014 {
1015 cerr << "Exception: " << e.what() << endl;
1016 return -1;
1017 }*/
1018
1019 return 0;
1020}
Note: See TracBrowser for help on using the repository browser.