Line data Source code
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 :
13 : namespace MagAOX
14 : {
15 : namespace app
16 : {
17 : namespace 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 : */
35 : template<class derivedT>
36 : class dssShutter
37 : {
38 : protected:
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 :
62 : public:
63 :
64 : /// Default c'tor
65 : /**
66 : * Sets derived().m_hasShutter to true.
67 : */
68 : dssShutter();
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 : */
101 : int appStartup();
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 : */
125 : int appShutdown();
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 : */
137 : int onPowerOff();
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 : */
149 : int whilePowerOff();
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 :
174 : protected:
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 : */
202 : void openThreadExec();
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 : */
220 : void shutThreadExec();
221 :
222 : ///@}
223 : protected:
224 : /** \name INDI
225 : *
226 : *@{
227 : */
228 : protected:
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 :
235 : public:
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 :
289 : private:
290 :
291 : /// Access the derived class.
292 51 : derivedT & derived()
293 : {
294 51 : return *static_cast<derivedT *>(this);
295 : }
296 : };
297 :
298 : template<class derivedT>
299 111 : dssShutter<derivedT>::dssShutter()
300 : {
301 111 : }
302 :
303 : template<class derivedT>
304 4 : void dssShutter<derivedT>::setupConfig(mx::app::appConfigurator & config)
305 : {
306 56 : config.add("shutter.powerDevice", "", "shutter.powerDevice", argType::Required, "shutter", "powerDevice", false, "string", "The device controlling this shutter's power");
307 56 : config.add("shutter.powerChannel", "", "shutter.powerChannel", argType::Required, "shutter", "powerChannel", false, "string", "The channel controlling this shutter's power");
308 :
309 56 : config.add("shutter.dioDevice", "", "shutter.dioDevice", argType::Required, "shutter", "dioDevice", false, "string", "The device controlling this shutter's digital I/O.");
310 :
311 56 : config.add("shutter.sensorChannel", "", "shutter.sensorChannel", argType::Required, "shutter", "sensorChannel", false, "string", "The channel reading this shutter's sensor.");
312 :
313 56 : config.add("shutter.triggerChannel", "", "shutter.triggerChannel", argType::Required, "shutter", "triggerChannel", false, "string", "The channel sending this shutter's trigger.");
314 :
315 56 : 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 52 : 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 4 : }
320 :
321 : template<class derivedT>
322 4 : void dssShutter<derivedT>::loadConfig(mx::app::appConfigurator & config)
323 : {
324 8 : config(m_powerDevice, "shutter.powerDevice");
325 8 : config(m_powerChannel, "shutter.powerChannel");
326 8 : config(m_dioDevice, "shutter.dioDevice");
327 8 : config(m_sensorChannel, "shutter.sensorChannel");
328 8 : config(m_triggerChannel, "shutter.triggerChannel");
329 8 : config(m_shutterWait, "shutter.wait");
330 4 : config(m_shutterTimeout, "shutter.timeout");
331 4 : }
332 :
333 :
334 : template<class derivedT>
335 1 : int dssShutter<derivedT>::appStartup()
336 : {
337 : //Register the powerChannel property for updates
338 1 : if( derived().registerIndiPropertySet( m_indiP_powerChannel, m_powerDevice, m_powerChannel, st_setCallBack_powerChannel) < 0)
339 : {
340 : #ifndef DSSSHUTTER_TEST_NOLOG
341 0 : derivedT::template log<software_error>({__FILE__,__LINE__});
342 : #endif
343 0 : return -1;
344 : }
345 :
346 : //Register the sensorChannel property for updates
347 1 : if( derived().registerIndiPropertySet( m_indiP_sensorChannel, m_dioDevice, m_sensorChannel, st_setCallBack_sensorChannel) < 0)
348 : {
349 : #ifndef DSSSHUTTER_TEST_NOLOG
350 0 : derivedT::template log<software_error>({__FILE__,__LINE__});
351 : #endif
352 0 : return -1;
353 : }
354 :
355 : //Register the triggerChannel property for updates
356 1 : if( derived().registerIndiPropertySet( m_indiP_triggerChannel, m_dioDevice, m_triggerChannel, st_setCallBack_triggerChannel) < 0)
357 : {
358 : #ifndef DSSSHUTTER_TEST_NOLOG
359 0 : derivedT::template log<software_error>({__FILE__,__LINE__});
360 : #endif
361 0 : return -1;
362 : }
363 :
364 :
365 :
366 5 : if(derived().threadStart( m_openThread, m_openThreadInit, m_openThreadID, m_openThreadProp, 0, "", "open", this, openThreadStart) < 0)
367 : {
368 0 : derivedT::template log<software_error>({__FILE__, __LINE__});
369 0 : return -1;
370 : }
371 :
372 5 : if(derived().threadStart( m_shutThread, m_shutThreadInit, m_shutThreadID, m_shutThreadProp, 0, "", "shut", this, shutThreadStart) < 0)
373 : {
374 0 : derivedT::template log<software_error>({__FILE__, __LINE__});
375 0 : 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 1 : act.sa_sigaction = &sigUsr1Handler;
383 1 : act.sa_flags = SA_SIGINFO;
384 1 : sigemptyset(&set);
385 1 : act.sa_mask = set;
386 :
387 1 : errno = 0;
388 1 : if( sigaction(SIGUSR1, &act, 0) < 0 )
389 : {
390 0 : std::string logss = "Setting handler for SIGUSR1 failed. Errno says: ";
391 0 : logss += strerror(errno);
392 :
393 0 : derivedT::template log<software_error>({__FILE__, __LINE__, errno, 0, logss});
394 :
395 0 : return -1;
396 0 : }
397 :
398 1 : return 0;
399 :
400 : }
401 :
402 : template<class derivedT>
403 21 : int dssShutter<derivedT>::appLogic()
404 : {
405 21 : if(m_powerState !=0 && m_powerState != 1)
406 : {
407 21 : derived().m_shutterStatus = "UNKNOWN";
408 21 : derived().m_shutterState = -1;
409 21 : return 0;
410 : }
411 :
412 0 : if(m_powerState == 0)
413 : {
414 0 : derived().m_shutterStatus = "POWEROFF";
415 0 : derived().m_shutterState = -1;
416 0 : return 0;
417 : }
418 :
419 0 : derived().m_shutterStatus = "READY";
420 :
421 0 : if(m_sensorState == 0)
422 : {
423 0 : derived().m_shutterState = 0;
424 0 : return 0;
425 : }
426 :
427 0 : if(m_sensorState == 1)
428 : {
429 0 : derived().m_shutterState = 1;
430 0 : return 0;
431 : }
432 :
433 0 : return 0;
434 : }
435 :
436 : template<class derivedT>
437 2 : int dssShutter<derivedT>::appShutdown()
438 : {
439 2 : if(m_openThread.joinable())
440 : {
441 1 : pthread_kill(m_openThread.native_handle(), SIGUSR1);
442 : }
443 :
444 2 : if(m_shutThread.joinable())
445 : {
446 1 : pthread_kill(m_shutThread.native_handle(), SIGUSR1);
447 : }
448 :
449 2 : if(m_openThread.joinable())
450 : {
451 : try
452 : {
453 1 : m_openThread.join(); //this will throw if it was already joined
454 : }
455 0 : catch(...)
456 : {
457 : }
458 : }
459 :
460 2 : if(m_shutThread.joinable())
461 : {
462 : try
463 : {
464 1 : m_shutThread.join(); //this will throw if it was already joined
465 : }
466 0 : catch(...)
467 : {
468 : }
469 : }
470 2 : return 0;
471 : }
472 :
473 : template<class derivedT>
474 1 : int dssShutter<derivedT>::onPowerOff()
475 : {
476 1 : return appLogic(); //Power state of derived() does not say anything about power state of the shutter
477 : }
478 :
479 : template<class derivedT>
480 1 : int dssShutter<derivedT>::whilePowerOff()
481 : {
482 1 : return appLogic(); //Power state of derived() does not say anything about power state of the shutter
483 : }
484 :
485 : template<class derivedT>
486 1 : int dssShutter<derivedT>::setShutterState( int sh )
487 : {
488 1 : if( sh == 1 )
489 : {
490 0 : m_doOpen = true;
491 :
492 0 : pthread_kill(m_openThread.native_handle(), SIGUSR1);
493 :
494 0 : return 0;
495 : }
496 1 : else if( sh == 0)
497 : {
498 0 : m_doShut = true;
499 :
500 0 : pthread_kill(m_shutThread.native_handle(), SIGUSR1);
501 :
502 0 : return 0;
503 : }
504 : else
505 : {
506 1 : derivedT::template log<software_error>({ __FILE__, __LINE__,"invalid shutter request"});
507 :
508 1 : return -1;
509 : }
510 : }
511 :
512 : template<class derivedT>
513 0 : int dssShutter<derivedT>::open()
514 : {
515 0 : if(m_powerState != 1) return 0;
516 :
517 0 : int startss = m_sensorState;
518 :
519 0 : derived().recordCamera(true);
520 0 : if(startss) return 0; //already open
521 :
522 : //First try:
523 0 : int startts = m_triggerState;
524 :
525 0 : derived().sendNewProperty (m_indiP_triggerChannel, "target", (int) !m_triggerState);
526 :
527 0 : double t0 = mx::sys::get_curr_time();
528 0 : while( m_sensorState != 1 )
529 : {
530 0 : mx::sys::milliSleep( m_shutterWait );
531 0 : if( (mx::sys::get_curr_time() - t0)*1000 > m_shutterTimeout) break;
532 : }
533 :
534 0 : if(m_sensorState == 1)
535 : {
536 0 : derived().recordCamera(true);
537 0 : derivedT::template log<text_log>("shutter open");
538 0 : return 0;
539 : }
540 :
541 0 : if( m_triggerState == startts )
542 : {
543 0 : 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 0 : derived().sendNewProperty (m_indiP_triggerChannel, "target", (int) !m_triggerState);
550 :
551 0 : t0 = mx::sys::get_curr_time();
552 0 : while( m_sensorState != 1 )
553 : {
554 0 : mx::sys::milliSleep( m_shutterWait );
555 0 : if( (mx::sys::get_curr_time() - t0)*1000 > m_shutterTimeout) break;
556 : }
557 :
558 : ///\todo need shutter log types
559 0 : if(m_sensorState == 1)
560 : {
561 0 : derived().recordCamera(true);
562 0 : derivedT::template log<text_log>("shutter open");
563 0 : return 0;
564 : }
565 :
566 0 : if( m_triggerState == !startts )
567 : {
568 0 : return derivedT::template log<software_error,-1>({__FILE__, __LINE__, "shutter trigger did not change state"});
569 : }
570 :
571 0 : return derivedT::template log<software_error,-1>({__FILE__, __LINE__, "shutter failed to open"});
572 : }
573 :
574 : template<class derivedT>
575 0 : int dssShutter<derivedT>::shut()
576 : {
577 0 : if(m_powerState != 1) return 0;
578 :
579 0 : int startss = m_sensorState;
580 :
581 0 : if(!startss) return 0; //already shut
582 :
583 : //First try:
584 0 : int startts = m_triggerState;
585 :
586 0 : derived().sendNewProperty (m_indiP_triggerChannel, "target", (int) !m_triggerState);
587 :
588 0 : double t0 = mx::sys::get_curr_time();
589 0 : while( m_sensorState != 0 )
590 : {
591 0 : mx::sys::milliSleep( m_shutterWait );
592 0 : if( (mx::sys::get_curr_time() - t0)*1000 > m_shutterTimeout) break;
593 : }
594 :
595 : ///\todo need shutter log types
596 0 : if(m_sensorState == 0)
597 : {
598 0 : derived().recordCamera(true);
599 0 : derivedT::template log<text_log>("shutter shut");
600 0 : return 0;
601 : }
602 :
603 0 : if( m_triggerState == startts )
604 : {
605 0 : 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 0 : derived().sendNewProperty (m_indiP_triggerChannel, "target", (int) !m_triggerState);
613 :
614 0 : t0 = mx::sys::get_curr_time();
615 0 : while( m_sensorState != 0 )
616 : {
617 0 : mx::sys::milliSleep( m_shutterWait );
618 0 : if( (mx::sys::get_curr_time() - t0)*1000 > m_shutterTimeout) break;
619 : }
620 :
621 : ///\todo need shutter log types
622 0 : if(m_sensorState == 0)
623 : {
624 0 : derived().recordCamera(true);
625 0 : derivedT::template log<text_log>("shutter shut");
626 0 : return 0;
627 : }
628 :
629 0 : if( m_triggerState == !startts )
630 : {
631 0 : return derivedT::template log<software_error,-1>({__FILE__, __LINE__, "shutter trigger did not change state"});
632 : }
633 :
634 0 : return derivedT::template log<software_error,-1>({__FILE__, __LINE__, "shutter failed to shut"});
635 :
636 :
637 : }
638 :
639 : template<class derivedT>
640 1 : void dssShutter<derivedT>::openThreadStart( dssShutter * d )
641 : {
642 1 : d->openThreadExec();
643 1 : }
644 :
645 : template<class derivedT>
646 1 : void dssShutter<derivedT>::openThreadExec( )
647 : {
648 1 : m_openThreadID = syscall(SYS_gettid);
649 :
650 2 : while( m_openThreadInit == true && derived().shutdown() == 0)
651 : {
652 1 : sleep(1);
653 : }
654 :
655 1 : while(derived().shutdown() == 0)
656 : {
657 0 : if( m_doOpen )
658 : {
659 0 : if(open() < 0)
660 : {
661 0 : derivedT::template log<software_error>({__FILE__,__LINE__});
662 : }
663 0 : m_doOpen = false;
664 : }
665 :
666 0 : sleep(1);
667 :
668 : }
669 :
670 1 : return;
671 : }
672 :
673 : template<class derivedT>
674 1 : void dssShutter<derivedT>::shutThreadStart( dssShutter * d )
675 : {
676 1 : d->shutThreadExec();
677 1 : }
678 :
679 : template<class derivedT>
680 1 : void dssShutter<derivedT>::shutThreadExec( )
681 : {
682 1 : m_shutThreadID = syscall(SYS_gettid);
683 :
684 2 : while( m_shutThreadInit == true && derived().shutdown() == 0)
685 : {
686 1 : sleep(1);
687 : }
688 :
689 1 : while(derived().shutdown() == 0)
690 : {
691 0 : if( m_doShut )
692 : {
693 0 : if(shut() < 0)
694 : {
695 0 : derivedT::template log<software_error>({__FILE__,__LINE__});
696 : }
697 0 : m_doShut = false;
698 : }
699 :
700 0 : sleep(1);
701 : }
702 :
703 1 : return;
704 : }
705 :
706 : template<class derivedT>
707 0 : int dssShutter<derivedT>::st_setCallBack_powerChannel( void * app,
708 : const pcf::IndiProperty &ipRecv
709 : )
710 : {
711 0 : return static_cast<derivedT *>(app)->setCallBack_powerChannel(ipRecv);
712 : }
713 :
714 : template<class derivedT>
715 0 : int dssShutter<derivedT>::setCallBack_powerChannel( const pcf::IndiProperty &ipRecv )
716 : {
717 0 : std::string ps;
718 :
719 0 : if(ipRecv.getName() != m_indiP_powerChannel.getName()) return 0;
720 :
721 0 : m_indiP_powerChannel = ipRecv;
722 :
723 0 : if(!ipRecv.find("state")) return 0;
724 :
725 0 : ps = ipRecv["state"].get<std::string>();
726 :
727 0 : if(ps == "On")
728 : {
729 0 : m_powerState = 1;
730 : }
731 0 : else if (ps == "Off")
732 : {
733 0 : m_powerState = 0;
734 : }
735 : else
736 : {
737 0 : m_powerState = -1;
738 : }
739 :
740 0 : return 0;
741 0 : }
742 :
743 : template<class derivedT>
744 0 : int dssShutter<derivedT>::st_setCallBack_sensorChannel( void * app,
745 : const pcf::IndiProperty &ipRecv
746 : )
747 : {
748 0 : return static_cast<derivedT *>(app)->setCallBack_sensorChannel(ipRecv);
749 : }
750 :
751 : template<class derivedT>
752 0 : int dssShutter<derivedT>::setCallBack_sensorChannel( const pcf::IndiProperty &ipRecv )
753 : {
754 :
755 0 : if(ipRecv.getName() != m_indiP_sensorChannel.getName()) return 0;
756 :
757 0 : m_indiP_sensorChannel = ipRecv;
758 :
759 0 : if(!ipRecv.find("current")) return 0;
760 :
761 0 : int ss = ipRecv["current"].get<int>();
762 :
763 0 : if(ss == 1)
764 : {
765 0 : m_sensorState = 1;
766 : }
767 0 : else if (ss == 0)
768 : {
769 0 : m_sensorState = 0;
770 : }
771 : else
772 : {
773 0 : m_sensorState = -1;
774 : }
775 :
776 0 : return 0;
777 : }
778 :
779 :
780 : template<class derivedT>
781 0 : int dssShutter<derivedT>::st_setCallBack_triggerChannel( void * app,
782 : const pcf::IndiProperty &ipRecv
783 : )
784 : {
785 0 : return static_cast<derivedT *>(app)->setCallBack_triggerChannel(ipRecv);
786 : }
787 :
788 : template<class derivedT>
789 0 : int dssShutter<derivedT>::setCallBack_triggerChannel( const pcf::IndiProperty &ipRecv )
790 : {
791 0 : if(ipRecv.getName() != m_indiP_triggerChannel.getName()) return 0;
792 :
793 0 : m_indiP_triggerChannel = ipRecv;
794 :
795 0 : if(!ipRecv.find("current")) return 0;
796 :
797 0 : int ts = ipRecv["current"].get<int>();
798 :
799 0 : if(ts == 1)
800 : {
801 0 : m_triggerState = 1;
802 : }
803 0 : else if (ts == 0)
804 : {
805 0 : m_triggerState = 0;
806 : }
807 : else
808 : {
809 0 : m_triggerState = -1;
810 : }
811 :
812 0 : return 0;
813 : }
814 :
815 :
816 :
817 :
818 :
819 : } //namespace dev
820 : } //namespace app
821 : } //namespace MagAOX
822 :
823 : #endif //dssShutter_hpp
|