The VisAO Camera
ShutterRemoteControl.cpp
Go to the documentation of this file.
1 /************************************************************
2 * ShutterRemoteControl.cpp
3 *
4 * Author: Jared R. Males (jrmales@email.arizona.edu)
5 *
6 * Shutter control from the AO Supervisor.
7 *
8 * Developed as part of the Magellan Adaptive Optics system.
9 ************************************************************/
10 
11 /** \file ShutterRemoteControl.cpp
12  * \author Jared R. Males
13  * \brief Definitions for shutter control from the AO Supervisor.
14  *
15 */
16 
17 #include "ShutterRemoteControl.h"
18 
19 
20 using namespace Arcetri;
21 
22 // Mutex to lock out other threads during complex operations
23 pthread_mutex_t threadMutex;
24 
25 namespace VisAO
26 {
27 
28 ShutterRemoteControl::ShutterRemoteControl( std::string name, const std::string &conffile) throw (AOException) : AOApp(name, conffile)
29 {
30  Create();
31 }
32 
33 ShutterRemoteControl::ShutterRemoteControl( int argc, char **argv) throw (AOException) : AOApp( argc, argv)
34 {
35  Create();
36 }
37 
38 void ShutterRemoteControl::Create() throw (AOException)
39 {
40 
41  //int stat;
42 
43  Logger::get()->log( Logger::LOG_LEV_TRACE, "ShutterRemoteControl Create");
44 
45  LoadConfig();
46 
47  errmsg = "";
48 
49  ERRMSG_LEN = 20;
50 
51  pthread_mutex_init(&threadMutex, NULL);
52 
53 }
54 
55 int ShutterRemoteControl::LoadConfig()
56 {
57  //Set up the fifo_path
58  std::string pathtmp;
59  std::string visao_root = getenv("VISAO_ROOT");
60  try
61  {
62  pathtmp = (std::string)(ConfigDictionary())["fifo_path"];
63  }
64  catch(Config_File_Exception)
65  {
66  pathtmp = "fifos";
67  }
68  fifo_path = visao_root + "/" + pathtmp + "/shuttercontrol_com_remote_";
69  _logger->log(Logger::LOG_LEV_INFO, "Set fifo_path: %s", fifo_path.c_str());
70 
71 
72  setup_fifo_list(1);
73  set_fifo_list_channel(&fl, 0, 100,(char *)std::string(fifo_path + "out").c_str(), (char *) std::string(fifo_path + "in").c_str(), &read_fifo_channel, 0);
74 
75  try
76  {
77  wait_to = (float32)(ConfigDictionary())["wait_to"];
78  _logger->log(Logger::LOG_LEV_INFO, "shutter timeout (wait_to) set to %f sec.", (float) wait_to);
79  }
80  catch(Config_File_Exception)
81  {
82  wait_to = DEFAULT_WAIT_TO;
83  _logger->log(Logger::LOG_LEV_INFO, "shutter timeout (wait_to) set to default: %f sec.", (float) wait_to);
84  }
85 
86  try
87  {
88  wait_sleep = (float32)(ConfigDictionary())["wait_sleep"];
89  _logger->log(Logger::LOG_LEV_INFO, "shutter comm. sleep (wait_sleep) set to %f sec.", (float) wait_sleep);
90  }
91  catch(Config_File_Exception)
92  {
93  wait_sleep = DEFAULT_WAIT_SLEEP;
94  _logger->log(Logger::LOG_LEV_INFO, "shutter comm. sleep (wait_sleep) set to default: %f sec.", (float) wait_sleep);
95  }
96 
97  return NO_ERROR;
98 }
99 
100 void ShutterRemoteControl::SetupVars()
101 {
102  try
103  {
104  var_state_cur = RTDBvar( MyFullName(), "STATE", CUR_VAR, INT_VARIABLE, 1,1);
105  var_state_req = RTDBvar( MyFullName(), "STATE", REQ_VAR, INT_VARIABLE, 1,1);
106 
107  var_sw_state = RTDBvar( MyFullName(), "SW_STATE", CUR_VAR, INT_VARIABLE, 1,1);
108  var_hw_state = RTDBvar( MyFullName(), "HW_STATE", CUR_VAR, INT_VARIABLE, 1,1);
109 
110  var_cmode_cur = RTDBvar( MyFullName(), "ConMode", CUR_VAR, INT_VARIABLE, 1,1);
111  var_cmode_req = RTDBvar( MyFullName(), "ConMode", REQ_VAR, INT_VARIABLE, 1,1);
112  }
113  catch (AOVarException &e)
114  {
115  Logger::get()->log(Logger::LOG_LEV_FATAL, "%s:%s: %s", __FILE__, __LINE__, e.what().c_str());
116  throw AOException("Error creating RTDB variables");
117  }
118 
119  this->Notify( var_state_req, ((ShutterRemoteControl *)this)->StateReqChanged);
120  this->Notify( var_cmode_req, ((ShutterRemoteControl *)this)->CModeReqChanged);
121 
122 }
123 
124 int ShutterRemoteControl::parse_state_string(std::string ansstr)
125 {
126  //std::cout << ansstr << "\n";
127  std::string tmp;
128  int cmode;
129  int st, swst, hwst, pwrst;
130  int sp = ansstr.find_first_of(" \r\n", 0);
131  tmp.assign(ansstr, 0, sp);
132  switch(tmp[0])
133  {
134  case 'N':
135  cmode = 0;
136  break;
137  case 'R':
138  cmode = 1;
139  break;
140  case 'L':
141  cmode = 2;
142  break;
143  case 'S':
144  cmode = 3;
145  break;
146  case 'A':
147  cmode = 4;
148  var_state_cur.Set(0, 0, FORCE_SEND);
149  var_sw_state.Set(0, 0, FORCE_SEND);
150  var_hw_state.Set(0, 0, FORCE_SEND);
151  var_cmode_cur.Set(cmode, 0, FORCE_SEND);
152  setCurState(STATE_OPERATING);
153  return 0;
154  default:
155  cmode = -1;
156  break;
157  }
158 
159  int sp2 = ansstr.find_first_of(" \r\n", sp+1);
160  tmp.assign(ansstr, sp+1, sp2-sp-1);
161  st = atoi(tmp.c_str());
162  sp = sp2;
163  sp2 = ansstr.find_first_of(" \r\n", sp+1);
164  tmp.assign(ansstr, sp+1, sp2-sp-1);
165  swst = atoi(tmp.c_str());
166  sp = sp2;
167  sp2 = ansstr.find_first_of(" \r\n", sp+1);
168  tmp.assign(ansstr, sp+1, sp2-sp-1);
169  hwst = atoi(tmp.c_str());
170 
171  sp = sp2;
172  sp2 = ansstr.find_first_of(" \r\n", sp+1);
173  tmp.assign(ansstr, sp+1, sp2-sp-1);
174  pwrst = atoi(tmp.c_str());
175 
176  if(pwrst) setCurState(STATE_READY);
177  else setCurState(STATE_OFF);
178 
179  var_state_cur.Set(st, 0, FORCE_SEND);
180  var_sw_state.Set(swst, 0, FORCE_SEND);
181  var_hw_state.Set(hwst, 0, FORCE_SEND);
182  var_cmode_cur.Set(cmode, 0, FORCE_SEND);
183 
184  return 0;
185 }
186 
187 double get_curr_t()
188 {
189  timeval tp;
190  gettimeofday(&tp, 0);
191  return (double) tp.tv_sec + ((double) tp.tv_usec)/1e6;
192 
193 }
194 
195 int ShutterRemoteControl::TestNetwork(void)
196 {
197  int stat;
198 
199  pthread_mutex_lock(&mutex);
200 
201 
202  // SendCommand() will lock the mutex by itself
203  stat = send_shutter_command("state?");
204  if (stat<0)
205  {
206  Logger::get()->log( Logger::LOG_LEV_TRACE, "Shutter: Error sending test command");
207  pthread_mutex_unlock(&mutex);
208  return stat;
209  }
210 
211 
212 
213  double startT;
214 
215  startT = get_curr_t();
216  read_fifo_channel(&fl.fifo_ch[0]);
217  while((fl.fifo_ch[0].server_response[0] == '\0') && (get_curr_t() - startT < wait_to))
218  {
219  nusleep((int) (wait_sleep * 1e6)); //Sleep for a bit, give shutter time to respond
220 
221  //SIGIO is blocked if we are here, so start reading
222  read_fifo_channel(&fl.fifo_ch[0]); //try again
223  }
224  if(fl.fifo_ch[0].server_response[0] == '\0')
225  {
226  _logger->log(Logger::LOG_LEV_ERROR, "ShutterControl response timeout in TestNetwork. wait_to=%f.", wait_to);
227  stat = -1;
228  }
229  else stat = NO_ERROR;
230 
231  pthread_mutex_unlock(&mutex);
232 
233  // Check if there actually was an answer
234  if (stat != 0)
235  {
236  Logger::get()->log( Logger::LOG_LEV_TRACE, "Shutter: No answer to test command");
237  return COMMUNICATION_ERROR;
238  }
239 
240  std::string ansstr = fl.fifo_ch[0].server_response;
241 
242  parse_state_string(ansstr);
243 
244  Logger::get()->log( Logger::LOG_LEV_TRACE, "Network test OK - answer %s", fl.fifo_ch[0].server_response);
245  return NO_ERROR;
246 }
247 
248 void ShutterRemoteControl::Run()
249 {
250  signal(SIGIO, SIG_IGN);
252 
253  global_fifo_list = &fl;
254 
255 
256  _logger->log( Logger::LOG_LEV_INFO, "Running...");
257 
258  while(!TimeToDie())
259  {
260  try
261  {
262  DoFSM();
263  }
264  catch (AOException &e)
265  {
266  _logger->log( Logger::LOG_LEV_ERROR, "Caught exception (at %s:%d): %s", __FILE__, __LINE__, e.what().c_str());
267 
268  // When the exception is thrown, the mutex was held!
269  pthread_mutex_unlock(&threadMutex);
270  }
271  }
272 }
273 
274 
275 int ShutterRemoteControl::DoFSM()
276 {
277 
278  int status;//, stat;
279  static float delay=1.0;
280 
281  // Lock out everyone else!!
282  pthread_mutex_lock(&threadMutex);
283 
284  if(TestNetwork() != NO_ERROR) setCurState(STATE_NOCONNECTION);
285  //else setCurState(STATE_OPERATING);
286 /* }
287 
288  switch(status)
289  {
290  case STATE_NOCONNECTION:*/
291  /*if (SetupNetwork() == NO_ERROR)
292  {*/
293  // if (TestNetwork() == NO_ERROR) setCurState(STATE_CONNECTED);
294  /*else ShutdownNetwork();
295  }*/
296  //setCurState(STATE_CONNECTED);
297  // break;
298 /* case STATE_CONNECTED:
299  //Add a ping here.
300  //std::cout << "connected.\n";
301  //setCurState(STATE_OPERATING);*/
302  /*** STATE_OPERATING and STATE_OFF are set by parse_state_string ***/
303 // break;
304  //}
305  // Always set current status (for external watchdog)
306  setCurState( getCurState());
307  pthread_mutex_unlock(&threadMutex);
308  nusleep( (unsigned int)(delay * 1e6));
309 
310  return NO_ERROR;
311 }
312 
313 int ShutterRemoteControl::StateReqChanged(void *pt, Variable *msgb)
314 {
315  int stat, newstate;
316 
317  pthread_mutex_lock(&threadMutex);
318 
319  newstate = msgb->Value.Lv[0];
320 
321  if(newstate == 1) stat = ((ShutterRemoteControl *)pt)->send_shutter_command("open");
322  if(newstate == -1) stat = ((ShutterRemoteControl *)pt)->send_shutter_command("close");
323 
324  pthread_mutex_unlock(&threadMutex);
325 
326  return stat;
327 }
328 
329 int ShutterRemoteControl::CModeReqChanged(void *pt, Variable *msgb)
330 {
331  int stat, newstate;
332  pthread_mutex_lock(&threadMutex);
333 
334  newstate = msgb->Value.Lv[0];
335 
336  if(newstate == 1) stat = ((ShutterRemoteControl *)pt)->send_shutter_command("REMOTE");
337  if(newstate == 10) stat = ((ShutterRemoteControl *)pt)->send_shutter_command("XREMOTE");
338  if(newstate == 0) stat = ((ShutterRemoteControl *)pt)->send_shutter_command("~REMOTE");
339 
340  pthread_mutex_unlock(&threadMutex);
341  return stat;
342 }
343 
344 int ShutterRemoteControl::send_shutter_command(const char * com)
345 {
346  //std::cout << "Sending " << com << "\n";
347  //return SerialOut(com, strlen(com));
348  return write_fifo_channel(0, com, strlen(com)+1, 0);
349 }
350 
351 } //namespace VisAO
352 
int write_fifo_channel(fifo_channel *fc, const char *com, int comlen)
Write data to the output channel.
Definition: fifoutils.c:194
int setup_fifo_list(fifo_list *fl, int nch)
Setup a fifo_list.
Definition: fifoutils.c:354
fifo_list * global_fifo_list
The global fifo_list, for signal handling.
Definition: dioserver.cpp:19
int read_fifo_channel(fifo_channel *fc)
Read data from the input fifo channel.
Definition: fifoutils.c:246
pthread_mutex_t threadMutex
Mutex to lock out other threads during complex operations.
int TimeToDie
Global set by SIGTERM.
int connect_fifo_list(fifo_list *fl)
Open each fifo in the list, with exclusive lock on the input fifo.
Definition: fifoutils.c:379
Declarations for shutter control from the AO Supervisor.
The namespace of VisAO software.
int set_fifo_list_channel(fifo_list *fl, int nch, int buffsz, const char *fin, const char *fout, int(*inp_hand)(fifo_channel *), void *adata)
Set the details of one channel in the list.
Definition: fifoutils.c:373