/* chk_modtr_time.c * program to read the shared memory location where modtronix data should * be and write a message into modx_status.txt that can be used by other * applications. currently outputs 2 lines: * * emontgomery@usgs.gov 8/23/11 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define DO_PSHM # include "pshm.h" #define MAX_BUF_SIZE 255 int get_modx(void); static void my_exit(int sig); char buf[MAX_BUF_SIZE]; int display_data=1; FILE *ofile; #if defined DO_PSHM int pshm_fd; char *addr; struct stat sb; sem_t *sem; #endif struct modx_data modx_data; int main( int argc, char* argv[] ) { int ik, tdif=0, ier=0, tstat; float ang_ori, ang_dif; struct timeval tv; struct tm gm, *gmp; char buf[MAX_BUF_SIZE]; char *statfile="/var/sda/logs/modx_status.txt"; signal(SIGINT,my_exit); /* terminal interuppt (e.g., ctrl-C) */ signal(SIGTERM,my_exit); /* terminate process */ ofile=fopen(statfile,"wt"); if(ofile == NULL) { fprintf(stderr,"Problem opening log file %s\n",statfile); my_exit(SIGUSR1); } /* Open existing share memory object and semaphore */ pshm_fd = shm_open(SHMEM_NAME, O_RDONLY, 0); /* Open existing object */ if (pshm_fd == -1){ snprintf(buf,MAX_BUF_SIZE,"shm_open error"); printf("%s\n",buf); exit(-1); } if (fstat(pshm_fd, &sb) == -1){ snprintf(buf,MAX_BUF_SIZE,"fstat error"); printf("%s\n",buf); exit(-1); } addr = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, pshm_fd, 0); if (addr == MAP_FAILED){ snprintf(buf,MAX_BUF_SIZE,"mmap error"); printf("%s\n",buf); exit(-1); } if (close(pshm_fd) == -1){ /* fd is no longer needed */ snprintf(buf,MAX_BUF_SIZE,"sem close error"); printf("%s\n",buf); exit(-1); } sem = sem_open(SEM_NAME,O_RDWR,(S_IRUSR | S_IWUSR),1); /* open semaphore */ if(sem==SEM_FAILED){ snprintf(buf,MAX_BUF_SIZE,"sem_open error"); printf("%s\n",buf); exit(-1); } // get the current Moxa system time tstat=gettimeofday(&tv,NULL); gmp = gmtime(&tv.tv_sec); gm=*gmp; // Check for Modtronix data ik=0; ier=0; while (++ik<5 && ier == 0){ ier=get_modx(); } ang_ori=modx_data.angle[1]; if(ier==0){ snprintf(buf,MAX_BUF_SIZE,"No Modtronix data."); printf("%s\n",buf); my_exit( SIGUSR1 ); } else { // check the data is current before doing anything with it //printf("seconds from modtr IG20 time is %d\n",(int)modx_data.tv.tv_sec); //printf("seconds from moxa time now is %ld\n",tv.tv_sec); tdif = (int)(tv.tv_sec-modx_data.tv.tv_sec); //printf("difference between now and modtronix is %ld\n",tdif); } if ( abs(tdif) < 60 ){ //fprintf(ofile,"At %4d %02d %02d %02d:%02d, the data in shared memory is too old- restart gmsm-mx!\n", fprintf(ofile,"At %4d %02d %02d %02d:%02d, the data in shared memory is up-to-date.\n", 1900+gm.tm_year,gm.tm_mon+1,gm.tm_mday,gm.tm_hour,gm.tm_min); } else if ( abs(tdif) > 59 && abs(tdif) < 7200 ) { fprintf(ofile,"At %4d %02d %02d %02d:%02d, the data in shared memory is old- may be OK.\n", 1900+gm.tm_year,gm.tm_mon+1,gm.tm_mday,gm.tm_hour,gm.tm_min); //send email to operators? } else { fprintf(ofile,"At %4d %02d %02d %02d:%02d, the data in shared memory is is old- restart gmsm-mx.\n", 1900+gm.tm_year,gm.tm_mon+1,gm.tm_mday,gm.tm_hour,gm.tm_min); //send email to operators? } //then output the most recent data fprintf(ofile," angle: %f, status: %d, amps: %d, tach: %d, cvolts: %d, tripped: %d.\n", modx_data.angle[1],modx_data.istatus,modx_data.ad_current, modx_data.ad_tach, modx_data.cvolts,modx_data.ibreaker); // now get it again and see which way it's going sleep (5); ier=get_modx(); ang_dif=modx_data.angle[1]-ang_ori; printf("difference in angles is %f\n", ang_dif); if ((abs(ang_dif) < .2) && (modx_data.ad_tach < 50)) fprintf(ofile,"not moving\n"); else if (ang_dif > 0) fprintf(ofile,"moving down\n"); else fprintf(ofile,"moving up\n"); fclose(ofile); close(pshm_fd); return(1); } int get_modx( void ) { // Get Modtronix data from shared memory int ier = -1; char buf[MAX_BUF_SIZE]; struct timespec abs_timeout; // check system clock and calculate timeout clock_gettime( CLOCK_REALTIME, &abs_timeout ); abs_timeout.tv_sec+=0; // seconds abs_timeout.tv_nsec+=100000; // about 1/10 sec ier=sem_timedwait( sem, &abs_timeout ); // blocks until sem>0, then decrements to zero if(ier==-1){ //TODO - Do something sensible if no modtronix data is forthcoming snprintf(buf,MAX_BUF_SIZE,"sem_timedwait > 1.1 sec"); printf("%s\n",buf); //ier = my_output( fdp_log, buf, display_data ); } else { // update shared memory here memcpy(&modx_data, addr, sb.st_size); sem_post( sem ); // unblocks ier = 1; } return ier; } static void my_exit(int sig) { // sig is assigned by signal or passed by user // UNSAFE use of printf() flush(), close(), and exit() // TODO - Do this with async-safe calls? // (1) identify cause of exit and close log file switch (sig) { case SIGINT : { printf("Caught SIGINT, exiting\n"); fclose(ofile); break; } case SIGTERM : { printf("Caught SIGTERM, exiting\n"); fclose(ofile); break; } case SIGUSR1 : { printf("Caught SIGUSR1, exiting\n"); break; } default : { printf("Unknown signal\n"); } } exit(0); }