API
 
Loading...
Searching...
No Matches
filterWheelCtrl.hpp
Go to the documentation of this file.
1/** \file filterWheelCtrl.hpp
2 * \brief The MagAO-X Filter Wheel Controller
3 *
4 * \ingroup filterWheelCtrl_files
5 */
6
7
8#ifndef filterWheelCtrl_hpp
9#define filterWheelCtrl_hpp
10
11
12#include "../../libMagAOX/libMagAOX.hpp" //Note this is included on command line to trigger pch
13#include "../../magaox_git_version.h"
14
15/** \defgroup filterWheelCtrl Filter Wheel Control
16 * \brief Control of MagAO-X MCBL-based f/w.
17 *
18 * <a href="../handbook/operating/software/apps/filterWheelCtrl.html">Application Documentation</a>
19 *
20 * \ingroup apps
21 *
22 */
23
24/** \defgroup filterWheelCtrl_files Filter Wheel Control Files
25 * \ingroup filterWheelCtrl
26 */
27
28namespace MagAOX
29{
30namespace app
31{
32
33/** MagAO-X application to control a Faulhaber MCBL controlled filter wheel.
34 *
35 * \todo add temperature monitoring
36 * \todo add INDI props to md doc
37 * \todo should move in least time direction, rather than always in the same direction.
38 * \todo add tests
39 * \todo should be an iodevice
40 *
41 * \ingroup filterWheelCtrl
42 */
43class filterWheelCtrl : public MagAOXApp<>, public tty::usbDevice, public dev::stdMotionStage<filterWheelCtrl>, public dev::telemeter<filterWheelCtrl>
44{
45
47
48 friend class dev::telemeter<filterWheelCtrl>;
49
50protected:
51
52 /** \name Non-configurable parameters
53 *@{
54 */
55
56 int m_motorType {2};
57
58 ///@}
59
60 /** \name Configurable Parameters
61 * @{
62 */
63
64 int m_writeTimeOut {1000}; ///< The timeout for writing to the device [msec].
65 int m_readTimeOut {1000}; ///< The timeout for reading from the device [msec].
66
67 double m_acceleration {100};
68 double m_deceleration {50};
69 double m_motorSpeed {3000};
70
71 long m_circleSteps {0}; ///< The number of position counts in 1 360-degree revolution.
72 long m_homeOffset {0}; ///< The number of position counts to offset from the home position
73
74
75
76 ///@}
77
78 /** \name Status
79 * @{
80 */
81
82 bool m_switch{false}; ///< The home switch status
83
84 long m_rawPos {0}; ///< The position of the wheel in motor counts.
85
86 int m_homingState{0}; ///< The homing state, tracks the stages of homing.
87 ///@}
88
89
90public:
91
92 /// Default c'tor.
94
95 /// D'tor, declared and defined for noexcept.
98
99 /// Setup the configuration system (called by MagAOXApp::setup())
100 virtual void setupConfig();
101
102 /// load the configuration system results (called by MagAOXApp::setup())
103 virtual void loadConfig();
104
105 /// Startup functions
106 /** Setsup the INDI vars.
107 *
108 * \returns 0 on success
109 * \returns -1 on error.
110 */
111 virtual int appStartup();
112
113 /// Implementation of the FSM for the TTM Modulator
114 /**
115 * \returns 0 on success
116 * \returns -1 on error.
117 */
118 virtual int appLogic();
119
120 /// Do any needed shutdown tasks. Currently nothing in this app.
121 /**
122 * \returns 0 on success
123 * \returns -1 on error.
124 */
125 virtual int appShutdown();
126
127
128 /// This method is called when the change to poweroff is detected.
129 /**
130 * \returns 0 on success.
131 * \returns -1 on any error which means the app should exit.
132 */
133 virtual int onPowerOff();
134
135 /// This method is called while the power is off, once per FSM loop.
136 /**
137 * \returns 0 on success.
138 * \returns -1 on any error which means the app should exit.
139 */
140 virtual int whilePowerOff();
141
142protected:
143
144 //declare our properties
145
146 ///The position of the wheel in counts
147 pcf::IndiProperty m_indiP_counts;
148
149public:
151
152protected:
153 //Each of these should have m_indiMutex locked before being called.
154
155 /// Set up the MCBL controller, called after each power-on/connection
156 /**
157 * \returns 0 on success.
158 * \returns -1 on error.
159 */
160 int onPowerOnConnect();
161
162 /// Get the home switch status, sets m_switch to true or false.
163 /**
164 * \returns 0 on success.
165 * \returns -1 on error.
166 */
167 int getSwitch();
168
169 /// Get the moving-state of the wheel, sets m_moving to true or false.
170 /**
171 * \returns 0 on success.
172 * \returns -1 on error.
173 */
174 int getMoving();
175
176 /// Get the current position of the wheel, sets m_rawPos to the current motor counts.
177 /**
178 * \returns 0 on success.
179 * \returns -1 on error.
180 */
181 int getPos();
182
183 /// Start a high-level homing sequence.
184 /** For this device this includes the homing dither.
185 *
186 * \returns 0 on success.
187 * \returns -1 on error.
188 */
189 int startHoming();
190
191 int presetNumber();
192
193 /// Start a low-level homing sequence.
194 /** This initiates the device homing sequence.
195 *
196 * \returns 0 on success.
197 * \returns -1 on error.
198 */
199 int home();
200
201 /// Stop the wheel motion immediately.
202 /**
203 * \returns 0 on success.
204 * \returns -1 on error.
205 */
206 int stop();
207
208 /// Move to an absolute position in raw counts.
209 /**
210 * \returns 0 on success.
211 * \returns -1 on error.
212 */
213 int moveToRaw( const long & counts /**< [in] The new position in absolute motor counts*/);
214
215 /// Move to a new position relative to current, in raw counts.
216 /**
217 * \returns 0 on success.
218 * \returns -1 on error.
219 */
220 int moveToRawRelative( const long & counts /**< [in] The new position in relative motor counts*/ );
221
222 /// Move to an absolute position in filter units.
223 /**
224 * \returns 0 on success.
225 * \returns -1 on error.
226 */
227 int moveTo( const double & filters /**< [in] The new position in absolute filter units*/ );
228
229 /** \name Telemeter Interface
230 *
231 * @{
232 */
233 int checkRecordTimes();
234
235 int recordTelem( const telem_stage * );
236
237 int recordTelem( const telem_position * );
238
239 int recordStage( bool force = false );
240
241 int recordPosition( bool force = false );
242
243 ///@}
244};
245
246inline
247filterWheelCtrl::filterWheelCtrl() : MagAOXApp(MAGAOX_CURRENT_SHA1, MAGAOX_REPO_MODIFIED)
248{
249 m_presetNotation = "filter"; //sets the name of the configs, etc.
250
251 m_powerMgtEnabled = true;
252
253 return;
254}
255
256inline
258{
260
261 config.add("timeouts.write", "", "timeouts.write", argType::Required, "timeouts", "write", false, "int", "The timeout for writing to the device [msec]. Default = 1000");
262 config.add("timeouts.read", "", "timeouts.read", argType::Required, "timeouts", "read", false, "int", "The timeout for reading the device [msec]. Default = 1000");
263
264 config.add("motor.acceleration", "", "motor.acceleration", argType::Required, "motor", "acceleration", false, "real", "The motor acceleration parameter. Default=100.");
265 config.add("motor.deceleration", "", "motor.deceleration", argType::Required, "motor", "deceleration", false, "real", "The motor deceleration parameter. Default=50.");
266 config.add("motor.speed", "", "motor.speed", argType::Required, "motor", "speed", false, "real", "The motor speed parameter. Default=3000.");
267 config.add("motor.circleSteps", "", "motor.circleSteps", argType::Required, "motor", "circleSteps", false, "long", "The number of steps in 1 revolution.");
268 config.add("stage.homeOffset", "", "stage.homeOffset", argType::Required, "stage", "homeOffset", false, "long", "The homing offset in motor counts.");
269
271
273}
274
275inline
277{
278 this->m_baudRate = B9600; //default for MCBL controller. Will be overridden by any config setting.
279
280 int rv = tty::usbDevice::loadConfig(config);
281
282 if(rv != 0 && rv != TTY_E_NODEVNAMES && rv != TTY_E_DEVNOTFOUND) //Ignore error if not plugged in
283 {
285 }
286
287 config(m_writeTimeOut, "timeouts.write");
288 config(m_readTimeOut, "timeouts.read");
289
290 config(m_acceleration, "motor.acceleration");
291 config(m_deceleration, "motor.deceleration");
292 config(m_motorSpeed, "motor.speed");
293 config(m_circleSteps, "motor.circleSteps");
294 config(m_homeOffset, "stage.homeOffset");
295
296
298
300}
301
302inline
304{
306 {
307 log<text_log>( "In appStartup but in state UNINITIALIZED.", logPrio::LOG_CRITICAL );
308 return -1;
309 }
310
311 // set up the INDI properties
312 createStandardIndiNumber<long>( m_indiP_counts, "counts", std::numeric_limits<long>::lowest(), std::numeric_limits<long>::max(), 0.0, "%ld");
314
315
317
319 {
320 return log<software_error,-1>({__FILE__,__LINE__});
321 }
322
323 return 0;
324}
325
326inline
328{
330 {
331 log<text_log>( "In appLogic but in state INITIALIZED.", logPrio::LOG_CRITICAL );
332 return -1;
333 }
334
335 if( state() == stateCodes::POWERON )
336 {
338 else
339 {
341 std::stringstream logs;
342 logs << "USB Device " << m_idVendor << ":" << m_idProduct << ":" << m_serial << " found in udev as " << m_deviceName;
343 log<text_log>(logs.str());
344 }
345 }
346
347 if( state() == stateCodes::NODEVICE )
348 {
350 if(rv < 0 && rv != TTY_E_DEVNOTFOUND && rv != TTY_E_NODEVNAMES)
351 {
353 if(!stateLogged())
354 {
356 }
357 return -1;
358 }
359
361 {
363
364 if(!stateLogged())
365 {
366 std::stringstream logs;
367 logs << "USB Device " << m_idVendor << ":" << m_idProduct << ":" << m_serial << " not found in udev";
368 log<text_log>(logs.str());
369 }
370 return 0;
371 }
372 else
373 {
375 if(!stateLogged())
376 {
377 std::stringstream logs;
378 logs << "USB Device " << m_idVendor << ":" << m_idProduct << ":" << m_serial << " found in udev as " << m_deviceName;
379 log<text_log>(logs.str());
380 }
381 }
382 }
383
385 {
386 int rv;
387 {
389 rv = connect();
390 }
391
392 if(rv < 0)
393 {
395 if(nrv < 0 && nrv != TTY_E_DEVNOTFOUND && nrv != TTY_E_NODEVNAMES)
396 {
399 return -1;
400 }
401
403 {
405
406 if(!stateLogged())
407 {
408 std::stringstream logs;
409 logs << "USB Device " << m_idVendor << ":" << m_idProduct << ":" << m_serial << " no longer found in udev";
410 log<text_log>(logs.str());
411 }
412 return 0;
413 }
414
415 //if connect failed, and there is a device, then we have some other problem.
416 sleep(1); //wait to see if power state updates
417 if(m_powerState == 0) return 0;
418
419 //Ok we can't figure this out, die.
422 return -1;
423
424 }
425
426
427
428 if( getPos() == 0 ) state(stateCodes::CONNECTED);
429 else
430 {
431 return 0;
432 }
433
435 {
436 std::stringstream logs;
437 logs << "Connected to filter wheel on " << m_deviceName;
438 log<text_log>(logs.str());
439 }
440
441 }
442
444 {
445 int rv = onPowerOnConnect();
446
447 if(rv < 0)
448 {
451
452 return 0;
453 }
454
455 std::string landfill;
456 tty::ttyRead(landfill, "\r", m_fileDescrip, m_readTimeOut); //read to timeout to kill any missed chars.
457
458 if(m_powerOnHome)
459 {
460 std::lock_guard<std::mutex> guard(m_indiMutex);
461
462 if(startHoming()<0)
463 {
466 return 0;
467 }
468 }
470
471
472 }
473
475 {
476 { //mutex scope
477 //Make sure we have exclusive attention of the device
478 std::lock_guard<std::mutex> guard(m_indiMutex); //Lock the mutex before conducting any communications.
479
480 int rv = getSwitch();
481
482 if(rv != 0 )
483 {
485 return 0;
486 }
487
488 rv = getMoving();
489
490 if(rv != 0 )
491 {
493 return 0;
494 }
495
496 rv = getPos();
497
498 if(rv != 0 )
499 {
501 return 0;
502 }
503
505 }
506
507 if(m_moving)
508 {
509 //Started moving but we don't know yet.
511 }
512 else
513 {
515 {
516 if(m_movingState == 1)
517 {
518 std::lock_guard<std::mutex> guard(m_indiMutex);
519 if(moveToRawRelative(-20000) < 0)
520 {
521 sleep(1);
522 if(m_powerState == 0) return 0;
523
526 }
527
529 }
530 else if(m_movingState == 2)
531 {
532 std::lock_guard<std::mutex> guard(m_indiMutex);
533 if(moveTo(m_preset_target) < 0)
534 {
535 sleep(1);
536 if(m_powerState == 0) return 0;
537
540 }
541
543 }
544 else
545 {
546 m_movingState = 0;
547 state(stateCodes::READY); //stopped moving but was just changing pos
548 }
549
550 }
551 else if (state() == stateCodes::HOMING) //stopped moving but was in the homing sequence
552 {
553 if(m_homingState == 1)
554 {
555 std::lock_guard<std::mutex> guard(m_indiMutex);
556 if(moveToRawRelative(-50000) < 0)
557 {
558 sleep(1);
559 if(m_powerState == 0) return 0;
560
563 }
564
566 }
567 else if (m_homingState == 2)
568 {
569 std::lock_guard<std::mutex> guard(m_indiMutex);
570 if(home()<0)
571 {
572 sleep(1);
573 if(m_powerState == 0) return 0;
574
577 }
578 m_homingState = 3;
579 }
580 else if(m_homingState == 3)
581 {
582 std::lock_guard<std::mutex> guard(m_indiMutex);
584 {
585 sleep(1);
586 if(m_powerState == 0) return 0;
587
590 }
592 }
593 else if(m_homingState == 4)
594 {
595 if(m_homePreset >= 0)
596 {
599
601 }
602 m_homingState = 5;
603 }
604 else
605 {
606 m_homingState = 0;
608
610 }
611 }
612 }
613
614 std::lock_guard<std::mutex> guard(m_indiMutex);
615
616 if(m_moving)
617 {
619 }
620 else
621 {
623 }
624
626
628 recordStage();
629
631 {
633 return 0;
634 }
635
636 return 0;
637 }
638
639 if(state() == stateCodes::ERROR)
640 {
641 sleep(1);
642 if(m_powerState == 0) return 0;
643
644 return log<software_error,-1>({__FILE__,__LINE__, "In state ERROR but no recovery implemented. Terminating."});
645 }
646
647 return log<software_error,-1>({__FILE__,__LINE__, "appLogic fell through. Terminating."});
648
649}
650
651
652
653inline
655{
656 //don't bother
657 return 0;
658}
659
660inline
662{
664 {
666 }
667
668 recordStage(true);
669 recordPosition(true);
670
671 return 0;
672}
673
674inline
676{
678 {
680 }
681
682 //record telem if it's been longer than 10 sec:
684 {
686 }
687
688 return 0;
689}
690
691INDI_NEWCALLBACK_DEFN(filterWheelCtrl, m_indiP_counts)(const pcf::IndiProperty &ipRecv)
692{
693 INDI_VALIDATE_CALLBACK_PROPS(m_indiP_counts, ipRecv);
694
695 double counts = -1;
696 double target_abs = -1;
697 if(ipRecv.find("current"))
698 {
699 counts = ipRecv["current"].get<double>();
700 }
701 if(ipRecv.find("target"))
702 {
703 target_abs = ipRecv["target"].get<double>();
704 }
705 if(target_abs == -1) target_abs = counts;
706
707
708 m_preset_target = ((double) target_abs - m_homeOffset)/m_circleSteps*m_presetNames.size() + 1.0;
709 std::lock_guard<std::mutex> guard(m_indiMutex);
710 return moveToRaw(target_abs);
711
712}
713
714
715
716
718{
719 std::string com;
720
721 int rv;
722
723 std::lock_guard<std::mutex> guard(m_indiMutex);
724
725 rv = tty::ttyWrite( "ANSW0\r", m_fileDescrip, m_writeTimeOut); //turn off replies and asynchronous comms.
727
728 //Send motor type
729 com = "MOTTYP" + std::to_string(m_motorType) + "\r";
732
733 //Set up acceleration and speed.
734 com = "AC" + std::to_string(m_acceleration) + "\r";
737
738 //Set up acceleration and speed.
739 com = "DEC" + std::to_string(m_deceleration) + "\r";
742
743 com = "SP" + std::to_string(m_motorSpeed) + "\r";
746
747 return 0;
748}
749
751{
752 int rv;
753 std::string resp;
754
755 rv = tty::ttyWriteRead( resp, "GAST\r", "\r\n", false, m_fileDescrip, m_writeTimeOut, m_readTimeOut);
756
757 if(rv == 0)
758 {
759
760 if(resp == "1011") m_switch=true;
761 else m_switch=false;
762
763 return 0;
764 }
765
766
767 return rv;
768
769}
770
772{
773 int rv;
774 std::string resp;
775
777
778 if(rv == 0)
779 {
780 int speed;
781 try{ speed = std::stol(resp.c_str());}
782 catch(...){speed=0;}
783
784 if(fabs(speed) > 0.1*m_motorSpeed)
785 {
786 if(m_homingState) m_moving = 2;
787 else m_moving = 1;
788 }
789 else m_moving = 0;
790
791 return 0;
792 }
793
794
795 return rv;
796
797}
798
800{
801 int rv;
802 std::string resp;
803
804 rv = tty::ttyWriteRead( resp, "POS\r", "\r\n", false, m_fileDescrip, m_writeTimeOut, m_readTimeOut);
805
806 if(rv == 0)
807 {
808 try{ m_rawPos = std::stol(resp.c_str());}
809 catch(...){m_rawPos=0;}
810 }
811
812
813 return rv;
814
815}
816
818{
819 m_homingState = 1;
820 m_moving = 2;
821 recordStage(true);
822 recordPosition(true);
823
824 updateSwitchIfChanged(m_indiP_home, "request", pcf::IndiElement::Off, INDI_IDLE);
825 return home();
826}
827
829{
830 //First we calculate current preset name
831 int n = floor(m_preset + 0.5) - 1;
832 if(n < 0)
833 {
834 while(n < 0) n += m_presetNames.size();
835 }
836 if( n > (long) m_presetNames.size()-1 )
837 {
838 while( n > (long) m_presetNames.size()-1 ) n -= m_presetNames.size();
839 }
840
841 if( n < 0)
842 {
843 log<software_error>({__FILE__,__LINE__, "error calculating " + m_presetNotation + " index, n < 0"});
844 return -1;
845 }
846
847 return n;
848}
849
851{
852
854
855 int rv;
856
859
862
865
868
871
872 std::string com = "HOSP" + std::to_string(m_motorSpeed) + "\r";
875
878
879
880
881 return 0;
882}
883
885{
886 m_homingState = 0;
887 //First try without locking
889
890 //Now make sure it goes through
891 std::lock_guard<std::mutex> guard(m_indiMutex);
893
894 updateSwitchIfChanged(m_indiP_stop, "request", pcf::IndiElement::Off, INDI_IDLE);
895
897
898 return 0;
899}
900
901int filterWheelCtrl::moveToRaw( const long & counts )
902{
903
904 std::string com;
905 int rv;
906
907 m_moving = 1;
908 recordStage(true);
909 recordPosition(true);
910
913
914 com = "LA" + std::to_string(counts) + "\r";
917
920
921 updateIfChanged(m_indiP_counts, "target", counts, pcf::IndiProperty::Busy);
922
923 return 0;
924}
925
926int filterWheelCtrl::moveToRawRelative( const long & counts_relative )
927{
928
929 std::string com;
930 int rv;
931
932 m_moving = 1;
933 recordStage(true);
934 recordPosition(true);
935
938
939 com = "LR" + std::to_string(counts_relative) +"\r";
942
945
946
947
948 return 0;
949}
950
951int filterWheelCtrl::moveTo( const double & filters )
952{
953 long counts;
954
955 if(m_circleSteps ==0 || m_presetNames.size() == 0) counts = filters;
957
958 return moveToRaw(counts);
959
960}
961
966
968{
969 return recordStage(true);
970}
971
973{
974 return recordPosition(true);
975}
976
981
983{
984 static long last_pos = 999999999999;
985
986 if( m_rawPos != last_pos || force )
987 {
988 float fpos = m_rawPos;
989
991
993 }
994
995 return 0;
996}
997
998} //namespace app
999} //namespace MagAOX
1000
1001#endif //filterWheelCtrl_hpp
Internal class to manage setuid privilege escalation with RAII.
The base-class for MagAO-X applications.
Definition MagAOXApp.hpp:73
void updateIfChanged(pcf::IndiProperty &p, const std::string &el, const T &newVal, pcf::IndiProperty::PropertyStateType ipState=pcf::IndiProperty::Ok)
Update an INDI property element value if it has changed.
stateCodes::stateCodeT state()
Get the current state code.
int registerIndiPropertyNew(pcf::IndiProperty &prop, int(*)(void *, const pcf::IndiProperty &))
Register an INDI property which is exposed for others to request a New Property for.
int m_powerState
Current power state, 1=On, 0=Off, -1=Unk.
void updateSwitchIfChanged(pcf::IndiProperty &p, const std::string &el, const pcf::IndiElement::SwitchStateType &newVal, pcf::IndiProperty::PropertyStateType ipState=pcf::IndiProperty::Ok)
Update an INDI switch element value if it has changed.
int stateLogged()
Updates and returns the value of m_stateLogged. Will be 0 on first call after a state change,...
static int log(const typename logT::messageT &msg, logPrioT level=logPrio::LOG_DEFAULT)
Make a log entry.
std::mutex m_indiMutex
Mutex for locking INDI communications.
MagAO-X standard motion stage interface.
int loadConfig(mx::app::appConfigurator &config)
load the configuration system results
std::vector< std::string > m_presetNames
The names of each position on the stage.
bool m_powerOnHome
If true, then the motor is homed at startup (by this software or actual power on)
std::string m_presetNotation
Notation used to refer to a preset, should be singular, as in "preset" or "filter".
float m_preset_target
The target numerical preset position [1.0 is index 0 in the preset name vector].
pcf::IndiProperty m_indiP_home
Command the stage to home. .
int setupConfig(mx::app::appConfigurator &config)
Setup the configuration system.
int m_homePreset
If >=0, this preset position is moved to after homing.
int8_t m_moving
Whether or not the stage is moving. -2 means powered off, -1 means not homed, 0 means not moving,...
pcf::IndiProperty m_indiP_stop
Command the stage to halt.
pcf::IndiProperty m_indiP_preset
The position of the stage in presets.
float m_preset
The current numerical preset position [1.0 is index 0 in the preset name vector].
int appStartup()
Startup function.
std::vector< float > m_presetPositions
The positions, in arbitrary units, of each preset. If 0, then the integer position number (starting f...
int8_t m_movingState
Used to track the type of command. If > 1 this is a command to move to a preset. If 0 then it is a mo...
virtual int appLogic()
Implementation of the FSM for the TTM Modulator.
long m_circleSteps
The number of position counts in 1 360-degree revolution.
int home()
Start a low-level homing sequence.
int recordPosition(bool force=false)
virtual void setupConfig()
Setup the configuration system (called by MagAOXApp::setup())
virtual int whilePowerOff()
This method is called while the power is off, once per FSM loop.
virtual int appShutdown()
Do any needed shutdown tasks. Currently nothing in this app.
int getSwitch()
Get the home switch status, sets m_switch to true or false.
pcf::IndiProperty m_indiP_counts
The position of the wheel in counts.
int startHoming()
Start a high-level homing sequence.
int moveToRaw(const long &counts)
Move to an absolute position in raw counts.
long m_homeOffset
The number of position counts to offset from the home position.
INDI_NEWCALLBACK_DECL(filterWheelCtrl, m_indiP_counts)
int onPowerOnConnect()
Set up the MCBL controller, called after each power-on/connection.
int recordStage(bool force=false)
int getPos()
Get the current position of the wheel, sets m_rawPos to the current motor counts.
long m_rawPos
The position of the wheel in motor counts.
int moveTo(const double &filters)
Move to an absolute position in filter units.
virtual void loadConfig()
load the configuration system results (called by MagAOXApp::setup())
virtual int onPowerOff()
This method is called when the change to poweroff is detected.
int m_writeTimeOut
The timeout for writing to the device [msec].
bool m_switch
The home switch status.
int moveToRawRelative(const long &counts)
Move to a new position relative to current, in raw counts.
~filterWheelCtrl() noexcept
D'tor, declared and defined for noexcept.
int m_homingState
The homing state, tracks the stages of homing.
int recordTelem(const telem_stage *)
int getMoving()
Get the moving-state of the wheel, sets m_moving to true or false.
int m_readTimeOut
The timeout for reading from the device [msec].
virtual int appStartup()
Startup functions.
int stop()
Stop the wheel motion immediately.
#define INDI_NEWCALLBACK_DEFN(class, prop)
Define the callback for a new property request.
#define INDI_NEWCALLBACK(prop)
Get the name of the static callback wrapper for a new property.
@ OPERATING
The device is operating, other than homing.
@ NODEVICE
No device exists for the application to control.
@ NOTHOMED
The device has not been homed.
@ HOMING
The device is homing.
@ FAILURE
The application has failed, should be used when m_shutdown is set for an error.
@ ERROR
The application has encountered an error, from which it is recovering (with or without intervention)
@ READY
The device is ready for operation, but is not operating.
@ CONNECTED
The application has connected to the device or service.
@ UNINITIALIZED
The application is unitialized, the default.
@ INITIALIZED
The application has been initialized, set just before calling appStartup().
@ NOTCONNECTED
The application is not connected to the device or service.
@ POWERON
The device power is on.
int ttyWriteRead(std::string &strRead, const std::string &strWrite, const std::string &eot, bool swallowEcho, int fd, int timeoutWrite, int timeoutRead)
Write to a tty on an open file descriptor, then get the result.
std::string ttyErrorString(int ec)
Get a text explanation of a TTY_E_ error code.
Definition ttyErrors.cpp:15
int ttyWrite(const std::string &buffWrite, int fd, int timeoutWrite)
Write to the tty console indicated by a file descriptor.
int ttyRead(std::string &strRead, int bytes, int fd, int timeoutRead)
Read from a tty console indicated by a file-descriptor, until a given number of bytes are read.
#define INDI_VALIDATE_CALLBACK_PROPS(prop1, prop2)
Standard check for matching INDI properties in a callback.
#define INDI_IDLE
Definition indiUtils.hpp:28
#define INDI_BUSY
Definition indiUtils.hpp:30
const pcf::IndiProperty & ipRecv
Definition dm.hpp:24
static constexpr logPrioT LOG_CRITICAL
The process can not continue and will shut down (fatal)
A device base class which saves telemetry.
Definition telemeter.hpp:69
int loadConfig(appConfigurator &config)
Load the device section from an application configurator.
int setupConfig(appConfigurator &config)
Setup an application configurator for the device section.
int checkRecordTimes(const telT &tel, telTs... tels)
Check the time of the last record for each telemetry type and make an entry if needed.
Software ERR log entry.
Log entry recording position stage specific status.
Log entry recording stdMotionStage status.
A USB device as a TTY device.
Definition usbDevice.hpp:33
std::string m_deviceName
The device path name, e.g. /dev/ttyUSB0.
Definition usbDevice.hpp:40
int m_fileDescrip
The file descriptor.
Definition usbDevice.hpp:42
int connect()
Connect to the device.
int getDeviceName()
Get the device name from udev using the vendor, product, and serial number.
std::string m_idProduct
The product id 4-digit code.
Definition usbDevice.hpp:35
int setupConfig(mx::app::appConfigurator &config)
Setup an application configurator for the USB section.
Definition usbDevice.cpp:24
std::string m_serial
The serial number.
Definition usbDevice.hpp:36
int loadConfig(mx::app::appConfigurator &config)
Load the USB section from an application configurator.
Definition usbDevice.cpp:34
speed_t m_baudRate
The baud rate specification.
Definition usbDevice.hpp:38
std::string m_idVendor
The vendor id 4-digit code.
Definition usbDevice.hpp:34
#define TTY_E_NODEVNAMES
Definition ttyErrors.hpp:28
#define TTY_E_DEVNOTFOUND
Definition ttyErrors.hpp:30