35template<
class derivedT>
 
  243                                           const pcf::IndiProperty &
ipRecv  
  260                                           const pcf::IndiProperty &
ipRecv  
  276                                           const pcf::IndiProperty &
ipRecv  
  294      return *
static_cast<derivedT *
>(
this);
 
 
  298template<
class derivedT>
 
  303template<
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.");
 
 
  321template<
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");
 
 
  334template<
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});
 
 
  402template<
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;
 
 
  436template<
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())
 
 
  473template<
class derivedT>
 
  479template<
class derivedT>
 
  485template<
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"});
 
 
  512template<
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"});
 
 
  574template<
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"});
 
 
  639template<
class derivedT>
 
  645template<
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__});
 
 
  673template<
class derivedT>
 
  679template<
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__});
 
 
  706template<
class derivedT>
 
  708                                                       const pcf::IndiProperty &
ipRecv 
  711   return static_cast<derivedT *
>(app)->setCallBack_powerChannel(
ipRecv);
 
 
  714template<
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")
 
 
  743template<
class derivedT>
 
  745                                                        const pcf::IndiProperty &
ipRecv 
  748   return static_cast<derivedT *
>(app)->setCallBack_sensorChannel(
ipRecv);
 
 
  751template<
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>(); 
 
 
  780template<
class derivedT>
 
  782                                                         const pcf::IndiProperty &
ipRecv 
  785   return static_cast<derivedT *
>(app)->setCallBack_triggerChannel(
ipRecv);
 
 
  788template<
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.
 
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.
 
const pcf::IndiProperty & ipRecv