API
 
Loading...
Searching...
No Matches
dssShutter.hpp
Go to the documentation of this file.
1/** \file dssShutter.hpp
2 * \brief Uniblitz DSS shutter interface
3 *
4 * \author Jared R. Males (jaredmales@gmail.com)
5 *
6 * \ingroup app_files
7 */
8
9#ifndef dssShutter_hpp
10#define dssShutter_hpp
11
12
13namespace MagAOX
14{
15namespace app
16{
17namespace dev
18{
19
20/// MagAO-X Uniblitz DSS Shutter interface
21/** This is actually an interface to the digital I/O system, which controls the shutter.
22 *
23 * The derived class `derivedT` must be a MagAOXApp<true>, and should declare this class a friend like so:
24 \code
25 friend class dev::dssShutter<derivedT>;
26 \endcode
27 *
28 *
29 * Calls to this class's `setupConfig`, `loadConfig`, `appStartup`, `appLogic`, `appShutdown`
30 * `onPowerOff`, `whilePowerOff`, functions must be placed in the derived class's functions of the same name.
31 *
32 *
33 * \ingroup appdev
34 */
35template<class derivedT>
37{
38protected:
39
40 /** \name Configurable Parameters
41 * @{
42 */
43
44 std::string m_powerDevice; ///< The device controlling this shutter's power
45 std::string m_powerChannel; ///< The channel controlling this shutter's power
46
47 std::string m_dioDevice; ///< The device controlling this shutter's digital I/O.
48 std::string m_sensorChannel; ///< The channel reading this shutter's sensor
49 std::string m_triggerChannel; ///< The channel sending this shutter's trigger
50
51 unsigned m_shutterWait {100}; ///< The time to pause between checks of the sensor state during open/shut [msec]. Default is 100.
52
53 unsigned m_shutterTimeout {2000}; ///< Total time to wait for sensor to change state before timing out [msec]. Default is 2000.
54 ///@}
55
56 int m_powerState {-1}; ///< The current power state, -1 is unknown, 0 is off, 1 is on.
57
58 int m_sensorState {-1}; ///< The current sensor state, -1 is unknown, 0 is shut, 1 is open.
59
60 int m_triggerState {-1}; ///< The current trigger state. -1 is unknown, 0 is low, 1 is high.
61
62public:
63
64 /// Default c'tor
65 /**
66 * Sets derived().m_hasShutter to true.
67 */
69
70 /// Setup the configuration system
71 /**
72 * This should be called in `derivedT::setupConfig` as
73 * \code
74 dssShutter<derivedT>::setupConfig(config);
75 \endcode
76 * with appropriate error checking.
77 */
78 void setupConfig(mx::app::appConfigurator & config /**< [out] the derived classes configurator*/);
79
80 /// load the configuration system results
81 /**
82 * This should be called in `derivedT::loadConfig` as
83 * \code
84 dssShutter<derivedT>::loadConfig(config);
85 \endcode
86 * with appropriate error checking.
87 */
88 void loadConfig(mx::app::appConfigurator & config /**< [in] the derived classes configurator*/);
89
90 /// Startup function
91 /**
92 * This should be called in `derivedT::appStartup` as
93 * \code
94 dssShutter<derivedT>::appStartup();
95 \endcode
96 * with appropriate error checking.
97 *
98 * \returns 0 on success
99 * \returns -1 on error, which is logged.
100 */
102
103 /// application logic
104 /** This should be called in `derivedT::appLogic` as
105 * \code
106 dssShutter<derivedT>::appLogic();
107 \endcode
108 * with appropriate error checking.
109 *
110 * \returns 0 on success
111 * \returns -1 on error, which is logged.
112 */
113 int appLogic();
114
115 /// applogic shutdown
116 /** This should be called in `derivedT::appShutdown` as
117 * \code
118 dssShutter<derivedT>::appShutdown();
119 \endcode
120 * with appropriate error checking.
121 *
122 * \returns 0 on success
123 * \returns -1 on error, which is logged.
124 */
126
127 /// Actions on power off
128 /** This should be called in `derivedT::appPowerOff` as
129 * \code
130 dssShutter<derivedT>::appPowerOff();
131 \endcode
132 * with appropriate error checking.
133 *
134 * \returns 0 on success
135 * \returns -1 on error, which is logged.
136 */
138
139 /// Actions while powered off
140 /** This should be called in `derivedT::whilePowerOff` as
141 * \code
142 dssShutter<derivedT>::whilePowerOff();
143 \endcode
144 * with appropriate error checking.
145 *
146 * \returns 0 on success
147 * \returns -1 on error, which is logged.
148 */
150
151 /// Change shutter state
152 /** Sets m_doOpen or m_doShut and signals the appropriate thread.
153 * \returns 0 on success
154 * \returns -1 on error
155 */
156 int setShutterState( int sh /**< Desired shutter state. 0 for shut,1 for open*/);
157
158 /// Open the shutter
159 /** Do not lock the mutex before calling this.
160 *
161 * \returns 0 on success
162 * \returns -1 on error
163 */
164 int open();
165
166 /// Shut the shutter
167 /** Do not lock the mutex before calling this.
168 *
169 * \returns 0 on success
170 * \returns -1 on error
171 */
172 int shut();
173
174protected:
175
176 /** \name Open/Shut Threads
177 *
178 * Separate threads are used since we need INDI updates while trying to open/shut.
179 * These threads sleep(1), unless interrupted by a signal. When signaled, they check
180 * for the m_doOpen or m_doShut flag, and if true the appropriate open() or shut()
181 * function is called. If not, they go back to sleep unless m_shutdown is true.
182 *
183 * @{
184 */
185
186 bool m_doOpen {false}; ///< Flag telling the open thread that it should actually open the shutter, not just go back to sleep.
187
188 bool m_openThreadInit {true}; ///< Initialization flag for the open thread.
189
190 pid_t m_openThreadID {0}; ///< Open thread PID.
191
192 pcf::IndiProperty m_openThreadProp; ///< The property to hold the open thread details.
193
194 std::thread m_openThread; ///< The opening thread.
195
196 /// Open thread starter function
197 static void openThreadStart( dssShutter * d /**< [in] pointer to this */);
198
199 /// Open thread function
200 /** Runs until m_shutdown is true.
201 */
203
204 bool m_doShut {false}; ///< Flag telling the shut thread that it should actually shut the shutter, not just go back to sleep.
205
206 bool m_shutThreadInit {true}; ///< Initialization flag for the shut thread.
207
208 pid_t m_shutThreadID {0}; ///< Shut thread PID.
209
210 pcf::IndiProperty m_shutThreadProp; ///< The property to hold the shut thread details.
211
212 std::thread m_shutThread; ///< The shutting thread
213
214 /// Shut thread starter function.
215 static void shutThreadStart( dssShutter * d /**< [in] pointer to this */);
216
217 /// Shut thread function
218 /** Runs until m_shutdown is true.
219 */
221
222 ///@}
223protected:
224 /** \name INDI
225 *
226 *@{
227 */
228protected:
229 //declare our properties
230
231 pcf::IndiProperty m_indiP_powerChannel; ///< Property used to monitor the shutter's power state
232 pcf::IndiProperty m_indiP_sensorChannel; ///< Property used to monitor the shutter's hall sensor
233 pcf::IndiProperty m_indiP_triggerChannel; ///< Property used to monitor and set the shutter's trigger
234
235public:
236
237 /// The static callback function to be registered for shutter power channel changes
238 /**
239 * \returns 0 on success.
240 * \returns -1 on error.
241 */
242 static int st_setCallBack_powerChannel( void * app, ///< [in] a pointer to this, will be static_cast-ed to derivedT.
243 const pcf::IndiProperty &ipRecv ///< [in] the INDI property sent with the the new property request.
244 );
245
246 /// The callback called by the static version, to actually process the new request.
247 /**
248 * \returns 0 on success.
249 * \returns -1 on error.
250 */
251 int setCallBack_powerChannel( const pcf::IndiProperty &ipRecv /**< [in] the INDI property sent with the the new property request.*/);
252
253
254 /// The static callback function to be registered for shutter sensor channel changes
255 /**
256 * \returns 0 on success.
257 * \returns -1 on error.
258 */
259 static int st_setCallBack_sensorChannel( void * app, ///< [in] a pointer to this, will be static_cast-ed to derivedT.
260 const pcf::IndiProperty &ipRecv ///< [in] the INDI property sent with the the new property request.
261 );
262
263 /// The callback called by the static version, to actually process the new request.
264 /**
265 * \returns 0 on success.
266 * \returns -1 on error.
267 */
268 int setCallBack_sensorChannel( const pcf::IndiProperty &ipRecv /**< [in] the INDI property sent with the the new property request.*/);
269
270 /// The static callback function to be registered for shutter trigger channel changes
271 /**
272 * \returns 0 on success.
273 * \returns -1 on error.
274 */
275 static int st_setCallBack_triggerChannel( void * app, ///< [in] a pointer to this, will be static_cast-ed to derivedT.
276 const pcf::IndiProperty &ipRecv ///< [in] the INDI property sent with the the new property request.
277 );
278
279 /// The callback called by the static version, to actually process the new request.
280 /**
281 * \returns 0 on success.
282 * \returns -1 on error.
283 */
284 int setCallBack_triggerChannel( const pcf::IndiProperty &ipRecv /**< [in] the INDI property sent with the the new property request.*/);
285
286
287 ///@}
288
289private:
290
291 /// Access the derived class.
292 derivedT & derived()
293 {
294 return *static_cast<derivedT *>(this);
295 }
296};
297
298template<class derivedT>
302
303template<class derivedT>
304void dssShutter<derivedT>::setupConfig(mx::app::appConfigurator & config)
305{
306 config.add("shutter.powerDevice", "", "shutter.powerDevice", argType::Required, "shutter", "powerDevice", false, "string", "The device controlling this shutter's power");
307 config.add("shutter.powerChannel", "", "shutter.powerChannel", argType::Required, "shutter", "powerChannel", false, "string", "The channel controlling this shutter's power");
308
309 config.add("shutter.dioDevice", "", "shutter.dioDevice", argType::Required, "shutter", "dioDevice", false, "string", "The device controlling this shutter's digital I/O.");
310
311 config.add("shutter.sensorChannel", "", "shutter.sensorChannel", argType::Required, "shutter", "sensorChannel", false, "string", "The channel reading this shutter's sensor.");
312
313 config.add("shutter.triggerChannel", "", "shutter.triggerChannel", argType::Required, "shutter", "triggerChannel", false, "string", "The channel sending this shutter's trigger.");
314
315 config.add("shutter.wait", "", "shutter.wait", argType::Required, "shutter", "wait", false, "int", "The time to pause between checks of the sensor state during open/shut [msec]. Default is 100.");
316
317 config.add("shutter.timeout", "", "shutter.timeout", argType::Required, "shutter", "timeout", false, "int", "Total time to wait for sensor to change state before timing out [msec]. Default is 2000.");
318
319}
320
321template<class derivedT>
322void dssShutter<derivedT>::loadConfig(mx::app::appConfigurator & config)
323{
324 config(m_powerDevice, "shutter.powerDevice");
325 config(m_powerChannel, "shutter.powerChannel");
326 config(m_dioDevice, "shutter.dioDevice");
327 config(m_sensorChannel, "shutter.sensorChannel");
328 config(m_triggerChannel, "shutter.triggerChannel");
329 config(m_shutterWait, "shutter.wait");
330 config(m_shutterTimeout, "shutter.timeout");
331}
332
333
334template<class derivedT>
336{
337 //Register the powerChannel property for updates
338 if( derived().registerIndiPropertySet( m_indiP_powerChannel, m_powerDevice, m_powerChannel, st_setCallBack_powerChannel) < 0)
339 {
340 #ifndef DSSSHUTTER_TEST_NOLOG
341 derivedT::template log<software_error>({__FILE__,__LINE__});
342 #endif
343 return -1;
344 }
345
346 //Register the sensorChannel property for updates
347 if( derived().registerIndiPropertySet( m_indiP_sensorChannel, m_dioDevice, m_sensorChannel, st_setCallBack_sensorChannel) < 0)
348 {
349 #ifndef DSSSHUTTER_TEST_NOLOG
350 derivedT::template log<software_error>({__FILE__,__LINE__});
351 #endif
352 return -1;
353 }
354
355 //Register the triggerChannel property for updates
356 if( derived().registerIndiPropertySet( m_indiP_triggerChannel, m_dioDevice, m_triggerChannel, st_setCallBack_triggerChannel) < 0)
357 {
358 #ifndef DSSSHUTTER_TEST_NOLOG
359 derivedT::template log<software_error>({__FILE__,__LINE__});
360 #endif
361 return -1;
362 }
363
364
365
366 if(derived().threadStart( m_openThread, m_openThreadInit, m_openThreadID, m_openThreadProp, 0, "", "open", this, openThreadStart) < 0)
367 {
368 derivedT::template log<software_error>({__FILE__, __LINE__});
369 return -1;
370 }
371
372 if(derived().threadStart( m_shutThread, m_shutThreadInit, m_shutThreadID, m_shutThreadProp, 0, "", "shut", this, shutThreadStart) < 0)
373 {
374 derivedT::template log<software_error>({__FILE__, __LINE__});
375 return -1;
376 }
377
378 //Install empty signal handler for USR1, which is used to interrupt sleeps in the open/shut threads.
379 struct sigaction act;
380 sigset_t set;
381
382 act.sa_sigaction = &sigUsr1Handler;
383 act.sa_flags = SA_SIGINFO;
384 sigemptyset(&set);
385 act.sa_mask = set;
386
387 errno = 0;
388 if( sigaction(SIGUSR1, &act, 0) < 0 )
389 {
390 std::string logss = "Setting handler for SIGUSR1 failed. Errno says: ";
391 logss += strerror(errno);
392
393 derivedT::template log<software_error>({__FILE__, __LINE__, errno, 0, logss});
394
395 return -1;
396 }
397
398 return 0;
399
400}
401
402template<class derivedT>
404{
405 if(m_powerState !=0 && m_powerState != 1)
406 {
407 derived().m_shutterStatus = "UNKNOWN";
408 derived().m_shutterState = -1;
409 return 0;
410 }
411
412 if(m_powerState == 0)
413 {
414 derived().m_shutterStatus = "POWEROFF";
415 derived().m_shutterState = -1;
416 return 0;
417 }
418
419 derived().m_shutterStatus = "READY";
420
421 if(m_sensorState == 0)
422 {
423 derived().m_shutterState = 0;
424 return 0;
425 }
426
427 if(m_sensorState == 1)
428 {
429 derived().m_shutterState = 1;
430 return 0;
431 }
432
433 return 0;
434}
435
436template<class derivedT>
438{
439 if(m_openThread.joinable())
440 {
441 pthread_kill(m_openThread.native_handle(), SIGUSR1);
442 }
443
444 if(m_shutThread.joinable())
445 {
446 pthread_kill(m_shutThread.native_handle(), SIGUSR1);
447 }
448
449 if(m_openThread.joinable())
450 {
451 try
452 {
453 m_openThread.join(); //this will throw if it was already joined
454 }
455 catch(...)
456 {
457 }
458 }
459
460 if(m_shutThread.joinable())
461 {
462 try
463 {
464 m_shutThread.join(); //this will throw if it was already joined
465 }
466 catch(...)
467 {
468 }
469 }
470 return 0;
471}
472
473template<class derivedT>
475{
476 return appLogic(); //Power state of derived() does not say anything about power state of the shutter
477}
478
479template<class derivedT>
481{
482 return appLogic(); //Power state of derived() does not say anything about power state of the shutter
483}
484
485template<class derivedT>
487{
488 if( sh == 1 )
489 {
490 m_doOpen = true;
491
492 pthread_kill(m_openThread.native_handle(), SIGUSR1);
493
494 return 0;
495 }
496 else if( sh == 0)
497 {
498 m_doShut = true;
499
500 pthread_kill(m_shutThread.native_handle(), SIGUSR1);
501
502 return 0;
503 }
504 else
505 {
506 derivedT::template log<software_error>({ __FILE__, __LINE__,"invalid shutter request"});
507
508 return -1;
509 }
510}
511
512template<class derivedT>
514{
515 if(m_powerState != 1) return 0;
516
517 int startss = m_sensorState;
518
519 derived().recordCamera(true);
520 if(startss) return 0; //already open
521
522 //First try:
523 int startts = m_triggerState;
524
525 derived().sendNewProperty (m_indiP_triggerChannel, "target", (int) !m_triggerState);
526
527 double t0 = mx::sys::get_curr_time();
528 while( m_sensorState != 1 )
529 {
530 mx::sys::milliSleep( m_shutterWait );
531 if( (mx::sys::get_curr_time() - t0)*1000 > m_shutterTimeout) break;
532 }
533
534 if(m_sensorState == 1)
535 {
536 derived().recordCamera(true);
537 derivedT::template log<text_log>("shutter open");
538 return 0;
539 }
540
541 if( m_triggerState == startts )
542 {
543 return derivedT::template log<software_error,-1>({__FILE__, __LINE__, "shutter trigger did not change state"});
544 }
545
546 //If here, shutter is not open, and trigger did flip, so it's a starting state issue.
547 //So we try again.
548
549 derived().sendNewProperty (m_indiP_triggerChannel, "target", (int) !m_triggerState);
550
551 t0 = mx::sys::get_curr_time();
552 while( m_sensorState != 1 )
553 {
554 mx::sys::milliSleep( m_shutterWait );
555 if( (mx::sys::get_curr_time() - t0)*1000 > m_shutterTimeout) break;
556 }
557
558 ///\todo need shutter log types
559 if(m_sensorState == 1)
560 {
561 derived().recordCamera(true);
562 derivedT::template log<text_log>("shutter open");
563 return 0;
564 }
565
566 if( m_triggerState == !startts )
567 {
568 return derivedT::template log<software_error,-1>({__FILE__, __LINE__, "shutter trigger did not change state"});
569 }
570
571 return derivedT::template log<software_error,-1>({__FILE__, __LINE__, "shutter failed to open"});
572}
573
574template<class derivedT>
576{
577 if(m_powerState != 1) return 0;
578
579 int startss = m_sensorState;
580
581 if(!startss) return 0; //already shut
582
583 //First try:
584 int startts = m_triggerState;
585
586 derived().sendNewProperty (m_indiP_triggerChannel, "target", (int) !m_triggerState);
587
588 double t0 = mx::sys::get_curr_time();
589 while( m_sensorState != 0 )
590 {
591 mx::sys::milliSleep( m_shutterWait );
592 if( (mx::sys::get_curr_time() - t0)*1000 > m_shutterTimeout) break;
593 }
594
595 ///\todo need shutter log types
596 if(m_sensorState == 0)
597 {
598 derived().recordCamera(true);
599 derivedT::template log<text_log>("shutter shut");
600 return 0;
601 }
602
603 if( m_triggerState == startts )
604 {
605 return derivedT::template log<software_error,-1>({__FILE__, __LINE__, "shutter trigger did not change state"});
606 }
607
608
609 //If here, shutter is not open, and trigger did flip, so it's a starting state issue.
610 //So we try again.
611
612 derived().sendNewProperty (m_indiP_triggerChannel, "target", (int) !m_triggerState);
613
614 t0 = mx::sys::get_curr_time();
615 while( m_sensorState != 0 )
616 {
617 mx::sys::milliSleep( m_shutterWait );
618 if( (mx::sys::get_curr_time() - t0)*1000 > m_shutterTimeout) break;
619 }
620
621 ///\todo need shutter log types
622 if(m_sensorState == 0)
623 {
624 derived().recordCamera(true);
625 derivedT::template log<text_log>("shutter shut");
626 return 0;
627 }
628
629 if( m_triggerState == !startts )
630 {
631 return derivedT::template log<software_error,-1>({__FILE__, __LINE__, "shutter trigger did not change state"});
632 }
633
634 return derivedT::template log<software_error,-1>({__FILE__, __LINE__, "shutter failed to shut"});
635
636
637}
638
639template<class derivedT>
644
645template<class derivedT>
647{
648 m_openThreadID = syscall(SYS_gettid);
649
650 while( m_openThreadInit == true && derived().shutdown() == 0)
651 {
652 sleep(1);
653 }
654
655 while(derived().shutdown() == 0)
656 {
657 if( m_doOpen )
658 {
659 if(open() < 0)
660 {
661 derivedT::template log<software_error>({__FILE__,__LINE__});
662 }
663 m_doOpen = false;
664 }
665
666 sleep(1);
667
668 }
669
670 return;
671}
672
673template<class derivedT>
678
679template<class derivedT>
681{
682 m_shutThreadID = syscall(SYS_gettid);
683
684 while( m_shutThreadInit == true && derived().shutdown() == 0)
685 {
686 sleep(1);
687 }
688
689 while(derived().shutdown() == 0)
690 {
691 if( m_doShut )
692 {
693 if(shut() < 0)
694 {
695 derivedT::template log<software_error>({__FILE__,__LINE__});
696 }
697 m_doShut = false;
698 }
699
700 sleep(1);
701 }
702
703 return;
704}
705
706template<class derivedT>
708 const pcf::IndiProperty &ipRecv
709 )
710{
711 return static_cast<derivedT *>(app)->setCallBack_powerChannel(ipRecv);
712}
713
714template<class derivedT>
716{
717 std::string ps;
718
719 if(ipRecv.getName() != m_indiP_powerChannel.getName()) return 0;
720
721 m_indiP_powerChannel = ipRecv;
722
723 if(!ipRecv.find("state")) return 0;
724
725 ps = ipRecv["state"].get<std::string>();
726
727 if(ps == "On")
728 {
729 m_powerState = 1;
730 }
731 else if (ps == "Off")
732 {
733 m_powerState = 0;
734 }
735 else
736 {
737 m_powerState = -1;
738 }
739
740 return 0;
741}
742
743template<class derivedT>
745 const pcf::IndiProperty &ipRecv
746 )
747{
748 return static_cast<derivedT *>(app)->setCallBack_sensorChannel(ipRecv);
749}
750
751template<class derivedT>
753{
754
755 if(ipRecv.getName() != m_indiP_sensorChannel.getName()) return 0;
756
757 m_indiP_sensorChannel = ipRecv;
758
759 if(!ipRecv.find("current")) return 0;
760
761 int ss = ipRecv["current"].get<int>();
762
763 if(ss == 1)
764 {
765 m_sensorState = 1;
766 }
767 else if (ss == 0)
768 {
769 m_sensorState = 0;
770 }
771 else
772 {
773 m_sensorState = -1;
774 }
775
776 return 0;
777}
778
779
780template<class derivedT>
782 const pcf::IndiProperty &ipRecv
783 )
784{
785 return static_cast<derivedT *>(app)->setCallBack_triggerChannel(ipRecv);
786}
787
788template<class derivedT>
790{
791 if(ipRecv.getName() != m_indiP_triggerChannel.getName()) return 0;
792
793 m_indiP_triggerChannel = ipRecv;
794
795 if(!ipRecv.find("current")) return 0;
796
797 int ts = ipRecv["current"].get<int>();
798
799 if(ts == 1)
800 {
801 m_triggerState = 1;
802 }
803 else if (ts == 0)
804 {
805 m_triggerState = 0;
806 }
807 else
808 {
809 m_triggerState = -1;
810 }
811
812 return 0;
813}
814
815
816
817
818
819} //namespace dev
820} //namespace app
821} //namespace MagAOX
822
823#endif //dssShutter_hpp
MagAO-X Uniblitz DSS Shutter interface.
static int st_setCallBack_triggerChannel(void *app, const pcf::IndiProperty &ipRecv)
The static callback function to be registered for shutter trigger channel changes.
int m_sensorState
The current sensor state, -1 is unknown, 0 is shut, 1 is open.
int appStartup()
Startup function.
std::string m_triggerChannel
The channel sending this shutter's trigger.
bool m_openThreadInit
Initialization flag for the open thread.
pcf::IndiProperty m_indiP_powerChannel
Property used to monitor the shutter's power state.
int whilePowerOff()
Actions while powered off.
pcf::IndiProperty m_indiP_triggerChannel
Property used to monitor and set the shutter's trigger.
void loadConfig(mx::app::appConfigurator &config)
load the configuration system results
std::string m_powerChannel
The channel controlling this shutter's power.
std::thread m_shutThread
The shutting thread.
int setCallBack_sensorChannel(const pcf::IndiProperty &ipRecv)
The callback called by the static version, to actually process the new request.
int shut()
Shut the shutter.
int m_triggerState
The current trigger state. -1 is unknown, 0 is low, 1 is high.
int setCallBack_powerChannel(const pcf::IndiProperty &ipRecv)
The callback called by the static version, to actually process the new request.
std::string m_dioDevice
The device controlling this shutter's digital I/O.
int onPowerOff()
Actions on power off.
pcf::IndiProperty m_indiP_sensorChannel
Property used to monitor the shutter's hall sensor.
pid_t m_openThreadID
Open thread PID.
int appLogic()
application logic
std::string m_sensorChannel
The channel reading this shutter's sensor.
static void shutThreadStart(dssShutter *d)
Shut thread starter function.
void openThreadExec()
Open thread function.
int setCallBack_triggerChannel(const pcf::IndiProperty &ipRecv)
The callback called by the static version, to actually process the new request.
int appShutdown()
applogic shutdown
bool m_doShut
Flag telling the shut thread that it should actually shut the shutter, not just go back to sleep.
static void openThreadStart(dssShutter *d)
Open thread starter function.
pcf::IndiProperty m_openThreadProp
The property to hold the open thread details.
unsigned m_shutterWait
The time to pause between checks of the sensor state during open/shut [msec]. Default is 100.
bool m_shutThreadInit
Initialization flag for the shut thread.
int m_powerState
The current power state, -1 is unknown, 0 is off, 1 is on.
bool m_doOpen
Flag telling the open thread that it should actually open the shutter, not just go back to sleep.
int open()
Open the shutter.
std::string m_powerDevice
The device controlling this shutter's power.
unsigned m_shutterTimeout
Total time to wait for sensor to change state before timing out [msec]. Default is 2000.
pcf::IndiProperty m_shutThreadProp
The property to hold the shut thread details.
void shutThreadExec()
Shut thread function.
static int st_setCallBack_sensorChannel(void *app, const pcf::IndiProperty &ipRecv)
The static callback function to be registered for shutter sensor channel changes.
void setupConfig(mx::app::appConfigurator &config)
Setup the configuration system.
pid_t m_shutThreadID
Shut thread PID.
std::thread m_openThread
The opening thread.
static int st_setCallBack_powerChannel(void *app, const pcf::IndiProperty &ipRecv)
The static callback function to be registered for shutter power channel changes.
derivedT & derived()
Access the derived class.
int setShutterState(int sh)
Change shutter state.
void sigUsr1Handler(int signum, siginfo_t *siginf, void *ucont)
Empty signal handler. SIGUSR1 is used to interrupt sleep in various threads.
Definition MagAOXApp.cpp:42
const pcf::IndiProperty & ipRecv
Definition dm.hpp:24