void event_handler (evargs args) { pv* pv = args.usr; pv->status = args.status; if (args.status == ECA_NORMAL) { pv->dbrType = args.type; memcpy(pv->value, args.dbr, dbr_size_n(args.type, args.count)); print_time_val_sts(pv, pv->reqElems); fflush(stdout); } }
static void event_handler (evargs args) { pv* pv = args.usr; pv->status = args.status; if (args.status == ECA_NORMAL) { pv->dbrType = args.type; pv->nElems = args.count; pv->value = (void *) args.dbr; /* casting away const */ print_time_val_sts(pv, reqElems); fflush(stdout); pv->value = NULL; } }
static void connection_handler ( struct connection_handler_args args ) { pv *ppv = ( pv * ) ca_puser ( args.chid ); if ( args.op == CA_OP_CONN_UP ) { nConn++; if (!ppv->onceConnected) { ppv->onceConnected = 1; /* Set up pv structure */ /* ------------------- */ /* Get natural type and array count */ ppv->dbfType = ca_field_type(ppv->chid); ppv->dbrType = dbf_type_to_DBR_TIME(ppv->dbfType); /* Use native type */ if (dbr_type_is_ENUM(ppv->dbrType)) /* Enums honour -n option */ { if (enumAsNr) ppv->dbrType = DBR_TIME_INT; else ppv->dbrType = DBR_TIME_STRING; } else if (floatAsString && (dbr_type_is_FLOAT(ppv->dbrType) || dbr_type_is_DOUBLE(ppv->dbrType))) { ppv->dbrType = DBR_TIME_STRING; } /* Set request count */ ppv->nElems = ca_element_count(ppv->chid); ppv->reqElems = reqElems > ppv->nElems ? ppv->nElems : reqElems; /* Issue CA request */ /* ---------------- */ /* install monitor once with first connect */ ppv->status = ca_create_subscription(ppv->dbrType, ppv->reqElems, ppv->chid, eventMask, event_handler, (void*)ppv, NULL); } } else if ( args.op == CA_OP_CONN_DOWN ) { nConn--; ppv->status = ECA_DISCONN; print_time_val_sts(ppv, reqElems); } }
int main (int argc, char *argv[]) { int returncode = 0; int n = 0; int result; /* CA result */ int opt; /* getopt() current option */ int digits = 0; /* getopt() no. of float digits */ int nPvs; /* Number of PVs */ pv* pvs = 0; /* Array of PV structures */ setvbuf(stdout,NULL,_IOLBF,BUFSIZ); /* Set stdout to line buffering */ while ((opt = getopt(argc, argv, ":nhm:se:f:g:#:d:0:w:t:")) != -1) { switch (opt) { case 'h': /* Print usage */ usage(); return 0; case 'n': /* Print ENUM as index numbers */ enumAsNr=1; break; case 't': /* Select timestamp source(s) and type */ tsSrcServer = 0; tsSrcClient = 0; { int i = 0; char c; while ((c = optarg[i++])) switch (c) { case 's': tsSrcServer = 1; break; case 'c': tsSrcClient = 1; break; case 'n': break; case 'r': tsType = relative; break; case 'i': tsType = incremental; break; case 'I': tsType = incrementalByChan; break; default : fprintf(stderr, "Invalid argument '%c' " "for option '-t' - ignored.\n", c); } } break; case 'w': /* Set CA timeout value */ if(epicsScanDouble(optarg, &caTimeout) != 1) { fprintf(stderr, "'%s' is not a valid timeout value " "- ignored. ('caget -h' for help.)\n", optarg); caTimeout = DEFAULT_TIMEOUT; } break; case '#': /* Array count */ if (sscanf(optarg,"%ld", &reqElems) != 1) { fprintf(stderr, "'%s' is not a valid array element count " "- ignored. ('caget -h' for help.)\n", optarg); reqElems = 0; } break; case 'm': /* Select CA event mask */ eventMask = 0; { int i = 0; char c, err = 0; while ((c = optarg[i++]) && !err) switch (c) { case 'v': eventMask |= DBE_VALUE; break; case 'a': eventMask |= DBE_ALARM; break; case 'l': eventMask |= DBE_LOG; break; default : fprintf(stderr, "Invalid argument '%s' " "for option '-m' - ignored.\n", optarg); eventMask = DBE_VALUE | DBE_ALARM; err = 1; } } break; case 's': /* Select string dbr for floating type data */ floatAsString = 1; break; case 'e': /* Select %e/%f/%g format, using <arg> digits */ case 'f': case 'g': if (sscanf(optarg, "%d", &digits) != 1) fprintf(stderr, "Invalid precision argument '%s' " "for option '-%c' - ignored.\n", optarg, opt); else { if (digits>=0 && digits<=VALID_DOUBLE_DIGITS) sprintf(dblFormatStr, "%%-.%d%c", digits, opt); else fprintf(stderr, "Precision %d for option '-%c' " "out of range - ignored.\n", digits, opt); } break; case '0': /* Select integer format */ switch ((char) *optarg) { case 'x': outType = hex; break; /* 0x print Hex */ case 'b': outType = bin; break; /* 0b print Binary */ case 'o': outType = oct; break; /* 0o print Octal */ default : fprintf(stderr, "Invalid argument '%s' " "for option '-0' - ignored.\n", optarg); } break; case '?': fprintf(stderr, "Unrecognized option: '-%c'. ('caget -h' for help.)\n", optopt); return 1; case ':': fprintf(stderr, "Option '-%c' requires an argument. ('caget -h' for help.)\n", optopt); return 1; default : usage(); return 1; } } nPvs = argc - optind; /* Remaining arg list are PV names */ if (nPvs < 1) { fprintf(stderr, "No pv name specified. ('camonitor -h' for help.)\n"); return 1; } /* Start up Channel Access */ result = ca_context_create(ca_disable_preemptive_callback); if (result != ECA_NORMAL) { fprintf(stderr, "CA error %s occurred while trying " "to start channel access '%s'.\n", ca_message(result), pvs[n].name); return 1; } /* Allocate PV structure array */ pvs = calloc (nPvs, sizeof(pv)); if (!pvs) { fprintf(stderr, "Memory allocation for channel structures failed.\n"); return 1; } /* Connect channels */ /* Copy PV names from command line */ for (n = 0; optind < argc; n++, optind++) { pvs[n].name = argv[optind]; } /* Create CA connections */ returncode = create_pvs(pvs, nPvs, connection_handler); if ( returncode ) { return returncode; } /* Check for channels that didn't connect */ ca_pend_event(caTimeout); for (n = 0; n < nPvs; n++) { if (!pvs[n].onceConnected) print_time_val_sts(&pvs[n], pvs[n].reqElems); } /* Read and print data forever */ ca_pend_event(0); /* Shut down Channel Access */ ca_context_destroy(); return result; }
void connection_handler ( struct connection_handler_args args ) { pv *ppv = ( pv * ) ca_puser ( args.chid ); if ( args.op == CA_OP_CONN_UP ) { int dbrType; /* Set up pv structure */ /* ------------------- */ /* Get natural type and array count */ ppv->nElems = ca_element_count(ppv->chid); ppv->dbfType = ca_field_type(ppv->chid); /* Set up value structures */ dbrType = dbf_type_to_DBR_TIME(ppv->dbfType); /* Use native type */ if (dbr_type_is_ENUM(dbrType)) /* Enums honour -n option */ { if (enumAsNr) dbrType = DBR_TIME_INT; else dbrType = DBR_TIME_STRING; } else if (floatAsString && (dbr_type_is_FLOAT(dbrType) || dbr_type_is_DOUBLE(dbrType))) { dbrType = DBR_TIME_STRING; } /* Adjust array count */ if (reqElems == 0 || ppv->nElems < reqElems){ ppv->reqElems = ppv->nElems; /* Use full number of points */ } else { ppv->reqElems = reqElems; /* Limit to specified number */ } /* Remember dbrType */ ppv->dbrType = dbrType; ppv->onceConnected = 1; nConn++; /* Issue CA request */ /* ---------------- */ /* install monitor once with first connect */ if ( ! ppv->value ) { /* Allocate value structure */ ppv->value = calloc(1, dbr_size_n(dbrType, ppv->reqElems)); if ( ppv->value ) { ppv->status = ca_create_subscription(dbrType, ppv->reqElems, ppv->chid, eventMask, event_handler, (void*)ppv, NULL); if ( ppv->status != ECA_NORMAL ) { free ( ppv->value ); } } } } else if ( args.op == CA_OP_CONN_DOWN ) { nConn--; ppv->status = ECA_DISCONN; print_time_val_sts(ppv, ppv->reqElems); } }
int caget (pv *pvs, int nPvs, OutputT format, chtype dbrType, unsigned long reqElems) { unsigned int i; int n, result; for (n = 0; n < nPvs; n++) { /* Set up pvs structure */ /* -------------------- */ /* Get natural type and array count */ pvs[n].nElems = ca_element_count(pvs[n].chid); pvs[n].dbfType = ca_field_type(pvs[n].chid); pvs[n].dbrType = dbrType; /* Set up value structures */ pvs[n].dbrType = dbf_type_to_DBR_TIME(pvs[n].dbfType); /* Use native type */ if (dbr_type_is_ENUM(pvs[n].dbrType)) /* Enums honour -n option */ { if (enumAsNr) pvs[n].dbrType = DBR_TIME_INT; else pvs[n].dbrType = DBR_TIME_STRING; } if (reqElems == 0 || pvs[n].nElems < reqElems) /* Adjust array count */ pvs[n].reqElems = pvs[n].nElems; else pvs[n].reqElems = reqElems; /* Issue CA request */ /* ---------------- */ if (ca_state(pvs[n].chid) == cs_conn) { nConn++; pvs[n].onceConnected = 1; /* Allocate value structure */ pvs[n].value = calloc(1, dbr_size_n(pvs[n].dbrType, pvs[n].reqElems)); if(!pvs[n].value){ fprintf(stderr,"Allocation failed\n"); exit(1); } result = ca_array_get(pvs[n].dbrType, pvs[n].reqElems, pvs[n].chid, pvs[n].value); pvs[n].status = result; } else { pvs[n].status = ECA_DISCONN; } } if (!nConn) return 1; /* No connection? We're done. */ /* Wait for completion */ /* ------------------- */ result = ca_pend_io(caTimeout); if (result == ECA_TIMEOUT) fprintf(stderr, "Read operation timed out: PV data was not read.\n"); /* Print the data */ /* -------------- */ for (n = 0; n < nPvs; n++) { switch (format) { case plain: /* Emulate old caput behaviour */ if (pvs[n].reqElems <= 1 && fieldSeparator == ' ') printf("%-30s", pvs[n].name); else printf("%s", pvs[n].name); printf("%c", fieldSeparator); case terse: if (pvs[n].status == ECA_DISCONN) printf("*** not connected\n"); else if (pvs[n].status == ECA_NORDACCESS) printf("*** no read access\n"); else if (pvs[n].status != ECA_NORMAL) printf("*** CA error %s\n", ca_message(pvs[n].status)); else if (pvs[n].value == 0) printf("*** no data available (timeout)\n"); else { if (charArrAsStr && dbr_type_is_CHAR(pvs[n].dbrType) && (reqElems || pvs[n].reqElems > 1)) { dbr_char_t *s = (dbr_char_t*) dbr_value_ptr(pvs[n].value, pvs[n].dbrType); int dlen = epicsStrnEscapedFromRawSize((char*)s, strlen((char*)s)); char *d = calloc(dlen+1, sizeof(char)); if(!d){ fprintf(stderr,"Allocation failed\n"); exit(1); } epicsStrnEscapedFromRaw(d, dlen+1, (char*)s, strlen((char*)s)); printf("%s", d); free(d); } else { if (reqElems || pvs[n].nElems > 1) printf("%lu%c", pvs[n].reqElems, fieldSeparator); for (i=0; i<pvs[n].reqElems; ++i) { if (i) printf ("%c", fieldSeparator); printf("%s", val2str(pvs[n].value, pvs[n].dbrType, i)); } } printf("\n"); } break; case all: print_time_val_sts(&pvs[n], reqElems); break; default : break; } } return 0; }