10 #define dssShutter_hpp
35 template<
class derivedT>
243 const pcf::IndiProperty &
ipRecv
260 const pcf::IndiProperty &
ipRecv
276 const pcf::IndiProperty &
ipRecv
294 return *
static_cast<derivedT *
>(
this);
298 template<
class derivedT>
303 template<
class derivedT>
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");
309 config.add(
"shutter.dioDevice",
"",
"shutter.dioDevice", argType::Required,
"shutter",
"dioDevice",
false,
"string",
"The device controlling this shutter's digital I/O.");
311 config.add(
"shutter.sensorChannel",
"",
"shutter.sensorChannel", argType::Required,
"shutter",
"sensorChannel",
false,
"string",
"The channel reading this shutter's sensor.");
313 config.add(
"shutter.triggerChannel",
"",
"shutter.triggerChannel", argType::Required,
"shutter",
"triggerChannel",
false,
"string",
"The channel sending this shutter's trigger.");
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.");
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.");
321 template<
class derivedT>
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");
334 template<
class derivedT>
338 if( derived().registerIndiPropertySet( m_indiP_powerChannel, m_powerDevice, m_powerChannel, st_setCallBack_powerChannel) < 0)
340 #ifndef DSSSHUTTER_TEST_NOLOG
341 derivedT::template log<software_error>({__FILE__,__LINE__});
347 if( derived().registerIndiPropertySet( m_indiP_sensorChannel, m_dioDevice, m_sensorChannel, st_setCallBack_sensorChannel) < 0)
349 #ifndef DSSSHUTTER_TEST_NOLOG
350 derivedT::template log<software_error>({__FILE__,__LINE__});
356 if( derived().registerIndiPropertySet( m_indiP_triggerChannel, m_dioDevice, m_triggerChannel, st_setCallBack_triggerChannel) < 0)
358 #ifndef DSSSHUTTER_TEST_NOLOG
359 derivedT::template log<software_error>({__FILE__,__LINE__});
366 if(derived().threadStart( m_openThread, m_openThreadInit, m_openThreadID, m_openThreadProp, 0,
"",
"open",
this, openThreadStart) < 0)
368 derivedT::template log<software_error>({__FILE__, __LINE__});
372 if(derived().threadStart( m_shutThread, m_shutThreadInit, m_shutThreadID, m_shutThreadProp, 0,
"",
"shut",
this, shutThreadStart) < 0)
374 derivedT::template log<software_error>({__FILE__, __LINE__});
379 struct sigaction act;
383 act.sa_flags = SA_SIGINFO;
388 if( sigaction(SIGUSR1, &act, 0) < 0 )
390 std::string logss =
"Setting handler for SIGUSR1 failed. Errno says: ";
391 logss += strerror(errno);
393 derivedT::template log<software_error>({__FILE__, __LINE__, errno, 0, logss});
402 template<
class derivedT>
405 if(m_powerState !=0 && m_powerState != 1)
407 derived().m_shutterStatus =
"UNKNOWN";
408 derived().m_shutterState = -1;
412 if(m_powerState == 0)
414 derived().m_shutterStatus =
"POWEROFF";
415 derived().m_shutterState = -1;
419 derived().m_shutterStatus =
"READY";
421 if(m_sensorState == 0)
423 derived().m_shutterState = 0;
427 if(m_sensorState == 1)
429 derived().m_shutterState = 1;
436 template<
class derivedT>
439 if(m_openThread.joinable())
441 pthread_kill(m_openThread.native_handle(), SIGUSR1);
444 if(m_shutThread.joinable())
446 pthread_kill(m_shutThread.native_handle(), SIGUSR1);
449 if(m_openThread.joinable())
460 if(m_shutThread.joinable())
473 template<
class derivedT>
479 template<
class derivedT>
485 template<
class derivedT>
492 pthread_kill(m_openThread.native_handle(), SIGUSR1);
500 pthread_kill(m_shutThread.native_handle(), SIGUSR1);
506 derivedT::template log<software_error>({ __FILE__, __LINE__,
"invalid shutter request"});
512 template<
class derivedT>
515 if(m_powerState != 1)
return 0;
517 int startss = m_sensorState;
519 derived().recordCamera(
true);
520 if(startss)
return 0;
523 int startts = m_triggerState;
525 derived().sendNewProperty (m_indiP_triggerChannel,
"target", (
int) !m_triggerState);
527 double t0 = mx::sys::get_curr_time();
528 while( m_sensorState != 1 )
530 mx::sys::milliSleep( m_shutterWait );
531 if( (mx::sys::get_curr_time() - t0)*1000 > m_shutterTimeout)
break;
534 if(m_sensorState == 1)
536 derived().recordCamera(
true);
537 derivedT::template log<text_log>(
"shutter open");
541 if( m_triggerState == startts )
543 return derivedT::template
log<software_error,-1>({__FILE__, __LINE__,
"shutter trigger did not change state"});
549 derived().sendNewProperty (m_indiP_triggerChannel,
"target", (
int) !m_triggerState);
551 t0 = mx::sys::get_curr_time();
552 while( m_sensorState != 1 )
554 mx::sys::milliSleep( m_shutterWait );
555 if( (mx::sys::get_curr_time() - t0)*1000 > m_shutterTimeout)
break;
559 if(m_sensorState == 1)
561 derived().recordCamera(
true);
562 derivedT::template log<text_log>(
"shutter open");
566 if( m_triggerState == !startts )
568 return derivedT::template
log<software_error,-1>({__FILE__, __LINE__,
"shutter trigger did not change state"});
571 return derivedT::template
log<software_error,-1>({__FILE__, __LINE__,
"shutter failed to open"});
574 template<
class derivedT>
577 if(m_powerState != 1)
return 0;
579 int startss = m_sensorState;
581 if(!startss)
return 0;
584 int startts = m_triggerState;
586 derived().sendNewProperty (m_indiP_triggerChannel,
"target", (
int) !m_triggerState);
588 double t0 = mx::sys::get_curr_time();
589 while( m_sensorState != 0 )
591 mx::sys::milliSleep( m_shutterWait );
592 if( (mx::sys::get_curr_time() - t0)*1000 > m_shutterTimeout)
break;
596 if(m_sensorState == 0)
598 derived().recordCamera(
true);
599 derivedT::template log<text_log>(
"shutter shut");
603 if( m_triggerState == startts )
605 return derivedT::template
log<software_error,-1>({__FILE__, __LINE__,
"shutter trigger did not change state"});
612 derived().sendNewProperty (m_indiP_triggerChannel,
"target", (
int) !m_triggerState);
614 t0 = mx::sys::get_curr_time();
615 while( m_sensorState != 0 )
617 mx::sys::milliSleep( m_shutterWait );
618 if( (mx::sys::get_curr_time() - t0)*1000 > m_shutterTimeout)
break;
622 if(m_sensorState == 0)
624 derived().recordCamera(
true);
625 derivedT::template log<text_log>(
"shutter shut");
629 if( m_triggerState == !startts )
631 return derivedT::template
log<software_error,-1>({__FILE__, __LINE__,
"shutter trigger did not change state"});
634 return derivedT::template
log<software_error,-1>({__FILE__, __LINE__,
"shutter failed to shut"});
639 template<
class derivedT>
645 template<
class derivedT>
648 m_openThreadID = syscall(SYS_gettid);
650 while( m_openThreadInit ==
true && derived().shutdown() == 0)
655 while(derived().shutdown() == 0)
661 derivedT::template log<software_error>({__FILE__,__LINE__});
673 template<
class derivedT>
679 template<
class derivedT>
682 m_shutThreadID = syscall(SYS_gettid);
684 while( m_shutThreadInit ==
true && derived().shutdown() == 0)
689 while(derived().shutdown() == 0)
695 derivedT::template log<software_error>({__FILE__,__LINE__});
706 template<
class derivedT>
708 const pcf::IndiProperty &
ipRecv
711 return static_cast<derivedT *
>(app)->setCallBack_powerChannel(
ipRecv);
714 template<
class derivedT>
719 if(
ipRecv.getName() != m_indiP_powerChannel.getName())
return 0;
721 m_indiP_powerChannel =
ipRecv;
723 if(!
ipRecv.find(
"state"))
return 0;
725 ps =
ipRecv[
"state"].get<std::string>();
731 else if (ps ==
"Off")
743 template<
class derivedT>
745 const pcf::IndiProperty &
ipRecv
748 return static_cast<derivedT *
>(app)->setCallBack_sensorChannel(
ipRecv);
751 template<
class derivedT>
755 if(
ipRecv.getName() != m_indiP_sensorChannel.getName())
return 0;
757 m_indiP_sensorChannel =
ipRecv;
759 if(!
ipRecv.find(
"current"))
return 0;
761 int ss =
ipRecv[
"current"].get<
int>();
780 template<
class derivedT>
782 const pcf::IndiProperty &
ipRecv
785 return static_cast<derivedT *
>(app)->setCallBack_triggerChannel(
ipRecv);
788 template<
class derivedT>
791 if(
ipRecv.getName() != m_indiP_triggerChannel.getName())
return 0;
793 m_indiP_triggerChannel =
ipRecv;
795 if(!
ipRecv.find(
"current"))
return 0;
797 int ts =
ipRecv[
"current"].get<
int>();
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.
dssShutter()
Default c'tor.
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.
derivedT & derived()
Access the derived class.
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.
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.
const pcf::IndiProperty & ipRecv