/* Simple CA Client with Callbacks */ #define TIMEOUT 1.0 #define SCA_OK 1 #define SCA_ERR 0 #define MAX_STRING 40 #include #include #include #include #include /* Function prototypes */ int main(int argc, char **argv); static void connectionChangedCB(struct connection_handler_args args); static void valueChangedCB(struct event_handler_args args); static char *timeStamp(void); static int parseCommand(int argc, char **argv); static void usage(void); /* Global variables */ int pvSpecified=0; char name[MAX_STRING]; time_t curTime, startTime; double timeout=TIMEOUT; /***************************** main ***********************************/ int main(int argc, char **argv) { int stat; chid pCh; /* Parse the command line */ if(parseCommand(argc,argv) != SCA_OK) exit(1); if(!pvSpecified) { printf("No PV specified\n"); exit(1); } /* Initialize */ stat=ca_context_create(ca_disable_preemptive_callback); if(stat != ECA_NORMAL) { printf("ca_context_create failed:\n%s\n",ca_message(stat)); exit(1); } /* Search */ stat=ca_create_channel(name,connectionChangedCB,NULL,CA_PRIORITY_DEFAULT,&pCh); if(stat != ECA_NORMAL) { printf("ca_create_channel failed:\n%s\n",ca_message(stat)); exit(1); } printf("%s Search started for %s\n",timeStamp(),name); /* Wait */ startTime=curTime; ca_pend_event(timeout); printf("%s ca_pend_event timed out after %g sec\n",timeStamp(),timeout); /* Clear the channel */ stat=ca_clear_channel(pCh); if(stat != ECA_NORMAL) { printf("ca_clear_channel failed:\n%s\n",ca_message(stat)); } /* Exit */ ca_context_destroy(); return(0); } /***************************** connectionChangedCB ********************/ static void connectionChangedCB(struct connection_handler_args args) { chid pCh=args.chid; int stat; /* Branch depending on the state */ switch (ca_state(pCh)) { case cs_conn: printf("%s Connection successful\n",timeStamp()); stat=ca_array_get_callback(DBR_STRING,1,pCh, valueChangedCB,NULL); if(stat != ECA_NORMAL) { printf("ca_array_get_callback:\n%s\n",ca_message(stat)); exit(1); } break; case cs_never_conn: printf("%s Cannot connect\n",timeStamp()); break; case cs_prev_conn: printf("%s Lost connection\n",timeStamp()); break; case cs_closed: printf("%s Connection closed\n",timeStamp()); break; } } /***************************** valueChangedCB *************************/ static void valueChangedCB(struct event_handler_args args) { /* Print the value */ if(args.status == ECA_NORMAL && args.dbr) { printf("%s Value is: %s\n",timeStamp(),(char *)args.dbr); printf("Elapsed time: %ld sec\n",curTime-startTime); } else { printf("%s Bad value\n",timeStamp()); } } /***************************** timeStamp ******************************/ static char *timeStamp(void) /* Gets current time and puts it in a static array * The calling program should copy it to a safe place * e.g. strcpy(savetime,timestamp()); */ { static char timeStampStr[16]; time_t now; struct tm *tblock; time(&now); curTime=now; tblock=localtime(&now); strftime(timeStampStr,20,"%b %d %H:%M:%S",tblock); return timeStampStr; } /**************************** parseCommand ********************************/ static int parseCommand(int argc, char **argv) { int i; for(i=1; i < argc; i++) { if (argv[i][0] == '-') { switch(argv[i][1]) { case 'h': usage(); exit(0); case 't': timeout=atof(argv[++i]); break; default: fprintf(stderr,"\n\nInvalid option: %s\n",argv[i]); usage(); return SCA_ERR; } } else { if(!pvSpecified) { strncpy(name,argv[i],MAX_STRING); name[MAX_STRING-1]='\0'; pvSpecified=1; } else { printf("\n\nInvalid option: %s\n",argv[i]); usage(); return SCA_ERR; } } } return SCA_OK; } /**************************** usage ***************************************/ static void usage(void) { printf( "\nUsage: simpleca [Options] pvname\n" " Connects to pvname and gets the value\n" "\n" " Options:\n" " -h help This message\n" " -t float Timeout in seconds (Default: %g)\n",TIMEOUT); }