The VisAO Camera
ShutterControlDioclient.cpp
Go to the documentation of this file.
1 /************************************************************
2 * ShutterControlDioclient.cpp
3 *
4 * Author: Jared R. Males (jrmales@email.arizona.edu)
5 *
6 * Generic shutter controller as a client of the dioserver
7 *
8 * Developed as part of the Magellan Adaptive Optics system.
9 ************************************************************/
10 
11 /** \file ShutterControlDioclient.cpp
12  * \author Jared R. Males (jrmales@email.arizona.edu)
13  * \brief Definitions for the shutter controller as a client of the dioserver
14  *
15 */
16 
18 
19 #define SHUTTER_AUTO_FIFO_CH 2
20 
21 namespace VisAO
22 {
23 
24 ///For the auto command handler, which live in the main thread.
26 
27 ShutterControlDioclient::ShutterControlDioclient(int argc, char **argv) throw (AOException) : VisAOApp_standalone(argc, argv)
28 {
29  initialize_ShutterControl();
30 }
31 
32 
33 ShutterControlDioclient::ShutterControlDioclient(std::string name, const std::string &conffile) throw (AOException) : VisAOApp_standalone(name, conffile)
34 {
35  initialize_ShutterControl();
36 }
37 
38 
39 ShutterControlDioclient::~ShutterControlDioclient()
40 {
41  saveInit();
42 }
43 
44 
45 int ShutterControlDioclient::initialize_ShutterControl() throw (AOException)
46 {
47  char fin[MAX_FNAME_SZ], fout[MAX_FNAME_SZ];
48 
49  setup_fifo_list(6);
50 
51  std::string pathtmp;
52  std::string visao_root = getenv("VISAO_ROOT");
53 
54  //Set up the dioserver channel numbers
55  try
56  {
57  dio_ch_set = (int)(ConfigDictionary())["dio_ch_set"];
58  _logger->log(Logger::LOG_LEV_INFO, "dioserver channel for setting state (dio_ch_set) set to %i.", dio_ch_set);
59  }
60  catch(Config_File_Exception)
61  {
62  _logger->log(Logger::LOG_LEV_FATAL, "dioserver channel for setting state (dio_ch_set) not set in config file.");
63  throw;
64  }
65  try
66  {
67  dio_ch_get = (int)(ConfigDictionary())["dio_ch_get"];
68  _logger->log(Logger::LOG_LEV_INFO, "dioserver channel for getting state (dio_ch_get) set to %i.", dio_ch_get);
69  }
70  catch(Config_File_Exception)
71  {
72  _logger->log(Logger::LOG_LEV_FATAL, "dioserver channel for getting state (dio_ch_get) not set in config file.");
73  throw;
74  }
75 
76  //Set up the fifo_path
77  try
78  {
79  pathtmp = (std::string)(ConfigDictionary())["diofifo_path"];
80  }
81  catch(Config_File_Exception)
82  {
83  _logger->log(Logger::LOG_LEV_INFO, "Setting diofifo_path to default");
84  pathtmp = "fifos";
85  }
86  diofifo_path = visao_root + "/" + pathtmp + "/diofifo";
87  _logger->log(Logger::LOG_LEV_INFO, "Set diofifo_path: %s", diofifo_path.c_str());
88 
89  get_dio_fnames(fin, fout, (char *)diofifo_path.c_str(), dio_ch_set);
90  set_fifo_list_channel(&fl, 0, 100,fin, fout, 0, 0);
91 
92  get_dio_fnames(fin, fout, (char *)diofifo_path.c_str(), dio_ch_get);
93  set_fifo_list_channel(&fl, 1, 100, fin, fout, 0, 0);
94 
95 
96  setup_baseApp(1, 1, 1, 0, false);
97 
98  com_path_auto = com_path + "_com_auto";
99  set_fifo_list_channel(&fl, SHUTTER_AUTO_FIFO_CH, RWBUFF_SZ, (char *)(com_path_auto + "_in").c_str(), (char *)(com_path_auto + "_out").c_str(), 0, (void *) this);
100  //fl.fifo_ch[SHUTTER_AUTO_FIFO_CH].input_handler = 0;
101 
102 
103  //Read dead_time from config file
104  try
105  {
106  dead_time = (float32)(ConfigDictionary())["dead_time"];
107  _logger->log(Logger::LOG_LEV_INFO, "Shutter dead time (dead_time) set to %f sec.", (float) dead_time);
108  }
109  catch(Config_File_Exception)
110  {
111  _logger->log(Logger::LOG_LEV_FATAL, "Shutter dead time (dead_time) not set in config file.");
112  throw;
113  }
114 
115  //Read ignore_hw_state from config file.
116  try
117  {
118  ignore_hw_state = (int)(ConfigDictionary())["ignore_hw_state"] != 0;
119 
120  if(ignore_hw_state) _logger->log(Logger::LOG_LEV_INFO, "Shutter set to ignore hardware state (ignore_hw_state)");
121  else _logger->log(Logger::LOG_LEV_INFO, "Shutter set to use hardware state (ignore_hw_state)");
122  }
123  catch(Config_File_Exception)
124  {
125  _logger->log(Logger::LOG_LEV_INFO, "Shutter set to use hardware state (ignore_hw_state)");
126  }
127 
128  //Read the power outlet from config file.
129 
130  try
131  {
132  power_outlet = (int)(ConfigDictionary())["powerOutlet"] != 0;
133 
134  _logger->log(Logger::LOG_LEV_INFO, "Shutter powerOutlet set to %i.", power_outlet);
135  }
136  catch(Config_File_Exception)
137  {
138  power_outlet = 4;
139  _logger->log(Logger::LOG_LEV_INFO, "Shutter powerOutlet set to default %i.", power_outlet);
140  }
141 
142  //Set the shared memory key
143  try
144  {
145  shmem_key = (int)(ConfigDictionary())["shmem_key"];
146  }
147  catch(Config_File_Exception)
148  {
149  shmem_key = 8001;
150  }
151  _logger->log(Logger::LOG_LEV_INFO, "Set the shared memory key (shmem_key): %i", shmem_key);
152 
153  //Set the number of timestamps in the shared ring buffer
154  try
155  {
156  num_timestamps = (int)(ConfigDictionary())["num_timestamps"];
157  }
158  catch(Config_File_Exception)
159  {
160  num_timestamps = 72000;
161  }
162  _logger->log(Logger::LOG_LEV_INFO, "Set number of images in the shared image buffer (num_timestamps): %i", num_timestamps);
163 
164 
165  try
166  {
167  initSaveInterval = (int)(ConfigDictionary())["initSaveInterval"];
168  }
169  catch(Config_File_Exception)
170  {
171  initSaveInterval = 200;
172  }
173  _logger->log(Logger::LOG_LEV_INFO, "Set interval to save init info to disk (initSaveInterval): %i", initSaveInterval);
174 
175 
176  if(init_vars)
177  {
178  try
179  {
180  cycleNo = (uint64) (*init_vars)["cycleNo"];
181  }
182  catch(Config_File_Exception)
183  {
184  cycleNo = 0;
185  }
186  }
187 
188 
189  try
190  {
191  logger_pause = (double)(ConfigDictionary())["logger_pause"];
192  }
193  catch(Config_File_Exception)
194  {
195  logger_pause = 5.;
196  }
197  _logger->log(Logger::LOG_LEV_INFO, "Set logger pause time to (logger_pause): %f secs", logger_pause);
198 
199  try
200  {
201  data_log_time_length = (double)(ConfigDictionary())["data_log_time_length"];
202  }
203  catch(Config_File_Exception)
204  {
205  data_log_time_length = 120.;
206  }
207  _logger->log(Logger::LOG_LEV_INFO, "Set logger file length to (data_log_time_length): %f secs", data_log_time_length);
208 
209 
210  try
211  {
212  save_path = (std::string)(ConfigDictionary())["save_path"];
213  }
214  catch(Config_File_Exception)
215  {
216  save_path = "data/syslogs";
217  }
218  _logger->log(Logger::LOG_LEV_INFO, "Set logger save path to (save_path): %s", save_path.c_str());
219 
220  //Now make the directory
221  std::string com = "mkdir -p ";
222  com += getenv("VISAO_ROOT");
223  com += "/";
224  com += save_path;
225  system(com.c_str());
226 
227  size_t sz;
228  psb = (VisAO::power_status_board*) attach_shm(&sz, 13000, 0);
229 
230  if(psb)
231  {
232  switch(power_outlet)
233  {
234  case 1: powerOutlet = &psb->outlet1_state; break;
235  case 2: powerOutlet = &psb->outlet2_state; break;
236  case 3: powerOutlet = &psb->outlet3_state; break;
237  case 4: powerOutlet = &psb->outlet4_state; break;
238  case 5: powerOutlet = &psb->outlet5_state; break;
239  case 6: powerOutlet = &psb->outlet6_state; break;
240  case 7: powerOutlet = &psb->outlet7_state; break;
241  case 8: powerOutlet = &psb->outlet8_state; break;
242  default: powerOutlet = 0;
243  }
244  }
245 
246  //Init the status board
247  statusboard_shmemkey = STATUS_shutterctrl;
248 
249  if(create_statusboard(sizeof(shutter_status_board)) != 0)
250  {
252  _logger->log(Logger::LOG_LEV_ERROR, "Could not create status board.");
253  }
254  else
255  {
257  strncpy(bsb->appname, MyFullName().c_str(), 25);
258  bsb->max_update_interval = pause_time;
259  }
260 
261 
262  //profile->set_base_path("/home/jaredmales/Source/Magellan/visao_base/profile/ShutterControl");
263  return 0;
264 
265 }
266 
267 int ShutterControlDioclient::getPowerStatus()
268 {
269  int powerState;
270  if(!psb)
271  {
272  size_t sz;
273  psb = (VisAO::power_status_board*) attach_shm(&sz, 13000, 0);
274 
275  if(psb)
276  {
277  switch(power_outlet)
278  {
279  case 1: powerOutlet = &psb->outlet1_state; break;
280  case 2: powerOutlet = &psb->outlet2_state; break;
281  case 3: powerOutlet = &psb->outlet3_state; break;
282  case 4: powerOutlet = &psb->outlet4_state; break;
283  case 5: powerOutlet = &psb->outlet5_state; break;
284  case 6: powerOutlet = &psb->outlet6_state; break;
285  case 7: powerOutlet = &psb->outlet7_state; break;
286  case 8: powerOutlet = &psb->outlet8_state; break;
287  default: powerOutlet = 0;
288  }
289  }
290  }
291 
292  if(psb && powerOutlet)
293  {
294  if(get_curr_time() - ts_to_curr_time(&psb->last_update) > 3.*psb->max_update_interval) powerState = -1;
295  else powerState = *powerOutlet;
296  }
297  else powerState = 0;
298 
299  return powerState;
300 }
301 
303 {
304  return start_ShutterControl();
305 }
306 
307 int ShutterControlDioclient::start_ShutterControl()
308 {
309  if(sis.create_shm(shmem_key, num_timestamps, sizeof(sharedim_stack_header) + num_timestamps*sizeof(intptr_t) + (num_timestamps)*(sizeof(sharedim<char>) + 1*sizeof(char))) != 0)
310  {
311  ERROR_REPORT("Error attaching to shared memory for sharedim_stack.");
312  return -1;
313  }
314 
315  sis.header->save_sequence = 0;
316 
317  //Startup the data logging thread
318  if(launchDataLogger() != 0)
319  {
320  ERROR_REPORT("Error starting data logging thread.");
321  return -1;
322  }
323 
324  signal(SIGIO, SIG_IGN);
325  signal(RTSIGIO, SIG_IGN);
326 
327  //Install the main thread handler
329  {
330  ERROR_REPORT("Error installing main thread catcher.");
331  return -1;
332  }
333 
334  //start_profiler();
335 
336  //Startup the I/O signal handling thread, without INHERIT_SCHED
337  if(start_signal_catcher(false) != 0)
338  {
339  ERROR_REPORT("Error starting signal catching thread.");
340  return -1;
341  }
342 
343  sleep(1); //let signal thread get started
344 
345  //Now Block all I/O signals in this thread.
346  if(block_sigio() != 0)
347  {
348  ERROR_REPORT("Error blicking SIGIO.");
349  return -1;
350  }
351 
352  LOG_INFO("starting up . . .");
353 
354  //Setup to catch the ping in this high priority thread
355  //The low priority signal catcher will block it.
356  global_shutter = this;
357 
358  fcntl(fl.fifo_ch[SHUTTER_AUTO_FIFO_CH].fd_in, F_SETOWN, getpid());
359 
360  int rv = fcntl(fl.fifo_ch[SHUTTER_AUTO_FIFO_CH].fd_in, F_SETSIG, RTSIGPING);
361  if(rv < 0)
362  {
363  std::cerr << "Error changing signal.\n";
364  perror("shuttercontrol");
365  }
366 
367  struct sigaction act;
368  sigset_t sset;
369 
370  act.sa_sigaction = &shutter_auto_handler;
371  act.sa_flags = SA_SIGINFO;
372  sigemptyset(&sset);
373  act.sa_mask = sset;
374 
375  errno = 0;
376 
377  if(sigaction(RTSIGPING, &act, 0) < 0)
378  {
379  logss.str("");
380  logss << "Error setting signal handler for RTSIGPING. Errno says: " << strerror(errno) << ".";
381  error_report(Logger::LOG_LEV_ERROR, logss.str());
382  return -1;
383  }
384 
386 
387  sw_state = 1;
388 
389  DO_OPENSHUT = 0;
390 
391  while(!TimeToDie)
392  {
393  pthread_mutex_lock(&signal_mutex);
394  pthread_cond_wait(&signal_cond, &signal_mutex);
395  pthread_mutex_unlock(&signal_mutex);
396 
397  if(DO_OPENSHUT == 1) open_shutter();
398  if(DO_OPENSHUT == -1) close_shutter();
399  DO_OPENSHUT = 0;
400 
401  pthread_cond_broadcast(&profile->thcond);
402  }
403 
404  pthread_join(logger_th, 0);
405  pthread_join(signal_thread, 0);
406 
407  return 0;
408 }//int ShutterControlDioclient::start_ShutterControl()
409 
410 /**/
411 int ShutterControlDioclient::shutdown_ShutterControl()
412 {
413  do_shutter_open(0);
414 
415  return 0;
416 }
417 
419 {
420  std::string resp;
421 
422  if(write_fifo_channel(0, "1", 1, &resp) < 0)
423  {
424  _logger->log(Logger::LOG_LEV_ERROR, "dioserver response error in init_shutter_open");
425  return -2;
426  }
427 
428  if(resp[0] != '1') return -1;
429  return 0;
430 
431 }
432 
433 int ShutterControlDioclient::do_shutter_open(void *adata)
434 {
435  //double startT;
436  //char dso[2] = "0";
437  struct timespec ts, ts1;
438  std::string resp;
439 
440 
441  if(adata)
442  {
443  clock_gettime(CLOCK_REALTIME, &ts);
444  profile->logseqmsg((char *) adata, "dso1", &ts);
445 
446  if(write_fifo_channel(0, "1", 1, &resp, (char *) adata) < 0)
447  {
448  DO_OPENSHUT = 0;
449  return -2;
450  _logger->log(Logger::LOG_LEV_ERROR, "dioserver response error in do_shutter_open");
451  }
452 
453  clock_gettime(CLOCK_REALTIME, &ts1);
454  profile->logseqmsg((char *) adata, "dso2", &ts);
455  }
456  else
457  {
458  clock_gettime(CLOCK_REALTIME, &ts);
459  if(write_fifo_channel(0, "1", 1, &resp) < 0)
460  {
461  DO_OPENSHUT = 0;
462  return -2;
463  _logger->log(Logger::LOG_LEV_ERROR, "dioserver response error in do_shutter_open");
464  }
465  }
466 
467  sim = sis.set_next_image(1, 1);
468  sim->depth = 8;
469  sim->frameNo = ++cycleNo;
470  sim->frame_time.tv_sec = ts.tv_sec;
471  sim->frame_time.tv_usec = ts.tv_nsec/1000;
472  sim->imdata[0] = 1;
474 
475  DO_OPENSHUT = 0;
476 
477  if(resp[0] != '1') return -1;
478  return 0;
479 
480 }
481 
482 int ShutterControlDioclient::do_shutter_close(void *adata)
483 {
484  timespec ts, ts1;
485  std::string resp;
486 
487  if(adata)
488  {
489  clock_gettime(CLOCK_REALTIME, &ts);
490  profile->logseqmsg((char *) adata, "dsc1", &ts);
491 
492  if(write_fifo_channel(0, "0", 1, &resp, (char *) adata) < 0)
493  {
494  DO_OPENSHUT = 0;
495  return -2;
496  _logger->log(Logger::LOG_LEV_ERROR, "dioserver response error in do_shutter_close");
497  }
498 
499  clock_gettime(CLOCK_REALTIME, &ts);
500  profile->logseqmsg((char *) adata, "dsc2", &ts1);
501  }
502  else
503  {
504  clock_gettime(CLOCK_REALTIME, &ts);
505  if(write_fifo_channel(0, "0", 1, &resp) < 0)
506  {
507  DO_OPENSHUT = 0;
508  return -2;
509  _logger->log(Logger::LOG_LEV_ERROR, "dioserver response error in do_shutter_close");
510  }
511  }
512 
513  sim = sis.set_next_image(1, 1);
514  sim->depth = 8;
515  sim->frameNo = ++cycleNo;
516  sim->frame_time.tv_sec = ts.tv_sec;
517  sim->frame_time.tv_usec = ts.tv_nsec/1000;
518  sim->imdata[0] = -1;
520 
521  DO_OPENSHUT = 0;
522 
523  if(resp[0] != '0') return -1;
524  return 0;
525 
526 }
527 
529 {
530  std::ofstream of;
531 
532  of.open((std::string(getenv("VISAO_ROOT")) + "/" + init_file).c_str());
533 
534  of << "cycleNo uint64 " << cycleNo << "\n";
535 
536  of.close();
537 
538  return 0;
539 }
540 
542 {
543  std::string fname;
544  char buffer[21];
545  timeval tv;
546 
547  gettimeofday(&tv, 0);
548  get_visao_filename(buffer, &tv);
549 
550  fname = getenv("VISAO_ROOT");
551  fname += "/";
552  fname += save_path;
553  fname += "/shut_";
554  fname += buffer;
555  fname += ".txt";
556 
557  return fname;
558 }
559 
561 {
562  struct sched_param schedpar;
563  schedpar.sched_priority = 0;
564 
565  pthread_attr_t attr;
566  pthread_attr_init(&attr);
567 
568  pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
569  pthread_attr_setschedpolicy(&attr, SCHED_OTHER);
570  pthread_attr_setschedparam(&attr, &schedpar);
571 
572  return pthread_create(&logger_th, &attr, &__launch_data_logger, (void *) this);
573 }
574 
576 {
577  std::ofstream of;
578  std::string fname;
579  double st;
580  sharedim<char> currData;
581  static int last_image_abs = -1, last_image = 0;
582 
583  bool fileOpen = false;
584  double fileOpenTime = 0;
585 
586  std::string sst;
587  char _sst;
588  try
589  {
590 
591  if(block_sigio() != 0)
592  {
593  ERROR_REPORT("Error blocking SIGIO in data logger thread.");
594  }
595  block_signal(RTSIGPING);
596 
597  std::cout << "Data logger started.\n";
598 
599  //Wait for first loggable event to happen
600  while(!TimeToDie && sis.get_last_image_abs() == -1)
601  {
602  //TimeToDie-proof sleeping - make sure we don't take more than a second to die.
603  st = get_curr_time();
604  while(logger_pause - (get_curr_time() - st) > 1 && !TimeToDie && sis.get_last_image_abs() == -1)
605  {
606  sleep(1);
607  }
608  while(logger_pause - (get_curr_time() - st) > 0 && !TimeToDie&& sis.get_last_image_abs() == -1)
609  {
610  usleep((int)(logger_pause-(get_curr_time()-st))*1000000);
611  }
612  }
613 
614  //last_image_abs = -1; This is true from declaration.
615 
616  while(1)
617  {
618  //Don't check TimeToDie here, always do one last save.
619  while(last_image_abs < sis.get_last_image_abs())
620  {
621  currData = sis.get_image(last_image);
622 
623  if(currData.nx)
624  {
625  if(!fileOpen)
626  {
627  fname = getDataFileName();
628  of.open(fname.c_str());
629  if(!of.good())
630  {
631  ERROR_REPORT("Error opening shutter data file. Shutter data may not be logged correctly");
632  break;
633  }
634  else
635  {
636  fileOpen = true;
637  fileOpenTime = get_curr_time();
638  of << "#Cycle # of first entry: " << currData.frameNo << "\n";
639  }
640  }
641 
642  _sst = currData.imdata[0];
643  if(_sst < 0) sst = "-1";
644  else if(_sst > 0) sst = "1";
645  else sst = "0";
646 
647  of << currData.frame_time.tv_sec << " " << currData.frame_time.tv_usec << " " << sst << "\n";
648 
649  if(!of.good())
650  {
651  ERROR_REPORT("Error in shutter data file. Shutter data may not be logged correctly");
652  }
653 
654  last_image_abs++;
655  last_image++;
656  if(last_image >= sis.get_max_n_images()) last_image = 0;
657  }
658 
659 
660  //Check here, since we will sometimes encounter this while behind
661  if(fileOpen && (get_curr_time()-fileOpenTime > data_log_time_length))
662  {
663  of.close();
664  fileOpen = false;
665  }
666  }
667 
668  if(TimeToDie) break;
669 
670  //TimeToDie-proof sleeping - make sure we don't take more than a second to die.
671  st = get_curr_time();
672  while(logger_pause - (get_curr_time() - st) > 1 && !TimeToDie && last_image_abs >= sis.get_last_image_abs())
673  {
674  sleep(1);
675  }
676  while(logger_pause - (get_curr_time() - st) > 0 && !TimeToDie && last_image_abs >= sis.get_last_image_abs())
677  {
678  usleep((int)(logger_pause-(get_curr_time()-st))*1000000);
679  }
680 
681  //Close the file if it has been opened for long enough
682  if(fileOpen && (get_curr_time()-fileOpenTime > data_log_time_length))
683  {
684  of.close();
685  fileOpen = false;
686  }
687  }
688 
689  if(fileOpen) of.close();
690  std::cout << "Data logging stopped." << std::endl;
691 
692  }
693  catch(...)
694  {
695  ERROR_REPORT("Exception thrown in data logging thread. Shutter data no longer being logged");
696  throw;
697  }
698 }
699 
700 int ShutterControlDioclient::get_hw_state()
701 {
702  int hws;
703  std::string resp;
704 
705  if(!ignore_hw_state)
706  {
707  if(write_fifo_channel(1, "1", 1, &resp) < 0)
708  {
709  _logger->log(Logger::LOG_LEV_ERROR, "dioserver response error in get_hw_state");
710  hw_state = 0;
711  return 0;
712  }
713 
714  hws = (resp[0] == '1');
715  if(hws) hw_state = -1;
716  else hw_state = 1;
717  return hw_state;
718  }
719  else return sw_state;
720 }
721  /*
722  write_fifo_channel(1, gws, 1);
723 
724  startT = get_curr_t();
725  while((fl.fifo_ch[1].server_response[0] == '\0') && (get_curr_t() - startT < wait_to))
726  {
727  //SIGIO is blocked if we are here, so start reading
728  read_fifo_channel(&fl.fifo_ch[1]);
729  }
730  if(fl.fifo_ch[1].server_response[0] == '\0')
731  {
732  _logger->log(Logger::LOG_LEV_ERROR, "dioserver response timeout in get_hw_state. wait_to=%f.", wait_to);
733  hw_state = 0;
734  return 0;
735  }
736  hws = (fl.fifo_ch[1].server_response[0] == '1');
737  if(hws) hw_state = -1;
738  else hw_state = 1;
739 
740  return hw_state;
741  }
742  else return sw_state;*/
743 
744 
745 std::string ShutterControlDioclient::get_state_str()
746 {
747  std::string sstr;
748  char schr[50];
749 
750  //sstr = control_mode_response();
751  //sstr.erase(1,1);
752  switch(control_mode)
753  {
754  case CMODE_NONE:
755  sstr = "N";
756  break;
757  case CMODE_REMOTE:
758  sstr = "R";
759  break;
760  case CMODE_LOCAL:
761  sstr = "L";
762  break;
763  case CMODE_SCRIPT:
764  sstr = "S";
765  break;
766  case CMODE_AUTO:
767  sstr = "A";
768  return sstr;
769  default:
770  sstr = "E";
771  break;
772  }
773 
774  snprintf(schr, 50, "%c %i %i %i %i", sstr[0], get_state(), get_sw_state(), get_hw_state(), getPowerStatus());
775  //sstr = schr;
776 
777  return schr;//sstr;
778 }
779 
780 std::string ShutterControlDioclient::remote_command(std::string com, char *seqmsg __attribute__((unused)))
781 {
782  std::string rstr;
783 
784  rstr = common_command(com, CMODE_REMOTE);
785 
786  if(rstr == "") return "UNKOWN COMMAND: " + com + "\n";
787 
788  seqmsg = 0;//warning suppression
789  return rstr;
790 }
791 
792 std::string ShutterControlDioclient::local_command(std::string com, char *seqmsg __attribute__((unused)))
793 {
794  std::string rstr;
795 
796  //std::cerr << "Shutter Local Command: " << com << std::endl;
797 
798  rstr = common_command(com, CMODE_LOCAL);
799 
800  if(rstr == "") return "UNKOWN COMMAND: " + com + "\n";
801 
802  return rstr;
803 }
804 
805 std::string ShutterControlDioclient::script_command(std::string com, char *seqmsg __attribute__((unused)))
806 {
807  std::string rstr;
808 
809  rstr = common_command(com, CMODE_SCRIPT);
810 
811  if(rstr == "") return "UNKOWN COMMAND: " + com + "\n";
812 
813  return rstr;
814 }
815 
816 
817 std::string ShutterControlDioclient::auto_command(std::string com, char *seqmsg)
818 {
819  //Before we do anything else, check if 0 or 1
820  if(control_mode == CMODE_AUTO && com[0] == '0')
821  {
822  //glob_seqmsg = seqmsg;
823  close_shutter(seqmsg);
824  //if(seqmsg[0]) rv = close_shutter((void *) seqmsg);
825  //else rv = close_shutter(0);
826  //DO_OPENSHUT = -1;
827  //pthread_cond_broadcast(&signal_cond);
828 
829  //Pause to hold seqmsg
830 // if(seqmsg)
831 // {
832 // while(DO_OPENSHUT == -1) usleep(10);
833 // }
834  return "0\n";
835 
836  //if(rv == -1) return "-1\n";
837  //else if (rv == 0) return "0\n";
838  //else return "1\n";
839  }
840 
841  if(control_mode == CMODE_AUTO && com[0] == '1')
842  {
843  //glob_seqmsg = seqmsg;
844  open_shutter(seqmsg);
845  //if(seqmsg[0]) rv = open_shutter((void *) seqmsg);
846  //else rv = open_shutter(0);
847  //DO_OPENSHUT = 1;
848  //pthread_cond_broadcast(&signal_cond);
849 
850  //Pause to hold seqmsg
851 // if(seqmsg)
852 // {
853 // while(DO_OPENSHUT == 1) usleep(10);
854 // }
855  return "0\n";
856 
857  //if(rv == 1) return "1\n";
858  //else if (rv == 0) return "0\n";
859  //else return "-1\n";
860  }
861 
862  std::string rstr;
863 
864  rstr = common_command(com, CMODE_AUTO);
865 
866  if(rstr != "") return rstr;
867 
868  return post_auto_command(com, seqmsg);
869 
870 }
871 
872 std::string ShutterControlDioclient::common_command(std::string com, int calling_cmode)
873 {
874  int rv;
875  char rvstr[50];
876 
877  int pos = com.find_first_of("\n\r", 0);
878  if(pos > -1) com.erase(pos, com.length()-pos);
879 
880  if(com == "open" || com == "1")
881  {
882  if(control_mode == calling_cmode)
883  {
884  if(!getPowerStatus())
885  {
886  return("-1\n");
887  }
888  //rv = open_shutter();
889  glob_seqmsg = 0;
890  DO_OPENSHUT = 1;
891  pthread_cond_broadcast(&signal_cond);
892  rv = 0;
893  snprintf(rvstr, 5, "%i\n", rv);
894  return rvstr;
895  }
896  else
897  {
898  return control_mode_response();
899  }
900  }
901 
902  if(com == "close" || com == "-1")
903  {
904  if(control_mode == calling_cmode)
905  {
906  if(!getPowerStatus())
907  {
908  return("-1\n");
909  }
910  //rv = close_shutter();
911  glob_seqmsg = 0;
912  DO_OPENSHUT = -1;
913  pthread_cond_broadcast(&signal_cond);
914  rv = -1;
915  snprintf(rvstr, 5, "%i\n", rv);
916  return rvstr;
917  }
918  else
919  {
920  return control_mode_response();
921  }
922  }
923 
924  if(com == "state?")
925  {
926  //std::cout << "getting state" << " " << get_state_str().c_str() << std::endl;
927  snprintf(rvstr, 50, "%s\n", get_state_str().c_str());
928  return rvstr;
929  }
930 
931  return "";
932 }
933 
935 {
936  static int lastInitSave = 0;
937 
939  {
941 
943 
944  if(control_mode == CMODE_AUTO)
945  {
946  ssb->in_auto = 1;
947  ssb->sw_state = 0;
948  ssb->hw_state = 0;
949  }
950  else
951  {
952  ssb->in_auto = 0;
953  ssb->sw_state = get_sw_state();
954  ssb->hw_state = get_hw_state();
955  }
956 
957  ssb->sync_enabled = !ignore_hw_state;
958 
959  ssb->power_state = getPowerStatus();
960 
961  }
962 
963  //Regardless, save the init data
964  lastInitSave++;
965  if(lastInitSave > initSaveInterval)
966  {
967 
968  saveInit();
969  lastInitSave = 0;
970  }
971 
972  return 0;
973 }//int ShutterControlDioclient::update_statusboard()
974 
975 
976 void * __launch_data_logger(void * Sctrl)
977 {
978  ((ShutterControlDioclient *) Sctrl)->dataLogger();
979  return 0;
980 }
981 
982 
983 void shutter_auto_handler(int signum, siginfo_t *siginf, void *ucont)
984 {
985  int totbytes;
986  std::string resp;
987  fifo_channel * fc;
988 
989 
990  if(siginf->si_code == POLL_IN)
991  {
992  fc = &global_fifo_list->fifo_ch[SHUTTER_AUTO_FIFO_CH];
993 
994  totbytes = read_fifo_channel(fc);
995 
996  resp = global_shutter->auto_command(fc->server_response, fc->seqmsg);
997 
998  write_fifo_channel(fc, (char *)resp.c_str(), resp.length());
999  }
1000 }
1001 
1002 } //namespace VisAO
1003 
int launchDataLogger()
Launches the data logger thread.
int dio_ch_set
The dioserver channel used for setting shutter state (open or shut)
double data_log_time_length
Time duration of a shutter log file, seconds.
double dead_time
Time to wait between commanded changes in state.
std::string diofifo_path
The base path of the dioserver fifos.
int write_fifo_channel(fifo_channel *fc, const char *com, int comlen)
Write data to the output channel.
Definition: fifoutils.c:194
int enable_next_image()
Increments last_image.
int power_outlet
Configuration variable, setting which power outlet to monitor.
fifo_list * global_fifo_list
The global fifo_list, for signal handling.
Definition: dioserver.cpp:19
double get_curr_time(void)
Gets the current CLOCK_REALTIME time, returns it in seconds to double precision.
Definition: libvisaoc.c:40
virtual int start_signal_catcher(bool inherit_sched=true)
Starts the signal catching loop.
int num_timestamps
The number of shared "images" available in the ring buffer.
pthread_mutex_t signal_mutex
Mutex for the condition signaling.
int read_fifo_channel(fifo_channel *fc)
Read data from the input fifo channel.
Definition: fifoutils.c:246
int shmem_key
The key for the ring buffer shared memory.
The standalone VisAO application, does not interface with the AO Supervisor.
int dio_ch_get
The dioserver channel used for getting shutter state (open or shut)
std::ostringstream logss
Conveninence string stream for building log messages.
void * statusboard_shmemptr
The pointer to the shared memory block for the statusboard.
virtual void error_report(int LogLevel, std::string emsg)
Report an error. Also calls log_msg.
virtual int update_statusboard()
Update the status board.
sharedim_stack_header * header
Convenient pointer to the stack header, has same value as shmemptr.
std::string com_path
The control fifo path base name.
virtual int update_statusboard()
Update the status board.
virtual int setup_baseApp(bool usethreads=false)
Install fifo channels.
int init_shutter_open()
Send shutter open signal for initialization, but do not log or profile this.
fifo_channel * fifo_ch
An array of fifo_channels.
Definition: fifoutils.h:207
int setup_fifo_list(int nfifos)
Allocate the fifo_list.
int * powerOutlet
The power strip outlet controlling shutter power.
pthread_cond_t signal_cond
Condition for telling main thread that something changed.
sharedim< IMDATA_TYPE > * set_next_image(int nx, int ny)
Sets the next image, and returns a pointer to it, but does not increment last_image.
sharedim_stack< char > sis
The shared memory ring buffer for timestamp storage.
int hw_state
1 is open, -1 is shut, 0 is unknown
int sw_state
1 is open, -1 is shut, 0 is unknown
Convenience structure for the stack header.
virtual int block_signal(int signum)
Sets the signal mask to block signal signum.
pthread_t signal_thread
Identifier for the separate signal handling thread.
key_t statusboard_shmemkey
The key used to lookup the shared memory.
virtual int block_sigio()
Sets the signal mask to block SIGIO and RTSIGIO.
int TimeToDie
Global set by SIGTERM.
pthread_t logger_th
Thread which periodically logs data in the sharedim_stack data buffer.
std::string control_mode_response()
Convenience function to return the control type response string, e.g. "A\n".
void * attach_shm(size_t *sz, key_t mkey, int shmemid)
Attach to a shared memory buffer and get its size.
Definition: libvisaoc.c:90
sharedim< char > * sim
Pointer to a shared memory "image".
fifo_list fl
The list of named-pipe fifos used for inter-process comms.
virtual int Run()
The application main loop, to be re-implemented in derived classes.
std::string com_path_auto
The path for the auto control fifos.
double pause_time
Time to pause during application main loop.
Definition: VisAOApp_base.h:84
sharedim< IMDATA_TYPE > get_image(int imno)
Gets an image, as a sharedim structure, with the imdata pointer properly set for the calling process...
std::string auto_command(std::string com, char *seqmsg)
Processing for auto commands - to be overriden.
std::string getDataFileName()
Generate a unique data file name, using the standard VisAO timestamp.
int create_statusboard(size_t sz)
Creates and attaches to the statusboard shared memory.
void * __launch_data_logger(void *Sctrl)
Launches the data logger.
ShutterControlDioclient * global_shutter
For the auto command handler, which live in the main thread.
#define MAX_FNAME_SZ
The maximum allowed filename length.
Definition: fifoutils.h:37
std::string save_path
Path, relative to VISAO_ROOT, where to save data.
double ts_to_curr_time(struct timespec *tsp)
Convert a timespec structure to double seconds.
Definition: libvisaoc.c:30
static int control_mode
The current control mode.
int get_visao_filename(char *buffer, struct timeval *tv)
Writes the standard visao unique filename for a timeval to the buffer.
virtual int install_sig_mainthread_catcher()
Install the SIG_MAINTHREAD signal catcher.
int create_shm(key_t mkey, size_t sz)
For the writer process, creates then attaches the shared memory.
void dataLogger()
Log data at intervals.
The namespace of VisAO software.
Declarations for the shutter controller as a client of the dioserver.
virtual std::string post_auto_command(std::string com, char *seqmsg=0)
Processing for auto commands - not normally overriden.
double logger_pause
Pause time of the logger thread, seconds.
int saveInit()
Save the initialization data to disk.
#define RWBUFF_SZ
The size of the i/o buffer.
Definition: fifoutils.h:43
int get_dio_fnames(char *fout, char *fin, char *fbase, int ch)
Fills in the properly formatted dioserver channel fifo names.
Definition: libvisaoc.c:23
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
bool ignore_hw_state
For when hw_state is unavailable.
int write_fifo_channel(int ch, const char *com, int comlen, std::string *resp)
Write data to a fifo_channel, and get a response if desired.
int get_max_n_images()
Returns the value of max_n_images currently in the header.