SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
cavget.cc File Reference

Detailed Description

Read Channel Access (CA) and pvAccess (PVA) Process Variable (PV) values from the command line.

This program allows the user to retrieve values from specified Process Variables (PVs) from the command line, supporting various formats and filtering options. It processes the inputs, establishes connections to the EPICS database, retrieves values, and optionally applies statistical analysis or despiking.

Usage

cavget [-list=<string>[=<value>][,<string>[=<value>]...]]
[-range=begin=<integer>,end=<integer>[,format=<string>][,interval=<integer>]]
[-floatformat=<printfString>]
[-charArray]
{
[-delimiter=<string>]
[-labeled]
[-noQuotes]
[-embrace=start=<string>,end=<string>]
| [-cavputForm]
}
[-statistics=number=<value>,pause=<value>[,format=[tagvalue][pretty][SDDS,file=<filename]]]
[-pendIoTime=<seconds>]
[-repeat=number=<integer>,pause=<seconds>[,average[,sigma]]]
[-numerical]
[-errorValue=<string>]
[-excludeErrors]
[-despike[[neighbors=<integer>][,passes=<integer>][,averageOf=<integer>][,threshold=<value>]]]
[-provider={ca|pva}]
[-info]
[-printErrors]

Options

Option Description
-list Specifies PV name components.
-range Defines a range of integers for PV name construction.
-pendiotime Maximum wait time for connections/returns. Default is 1.0 seconds.
-statistics Enables statistical analysis with various formats: tagvalue, pretty, or SDDS.
-despike Removes spikes based on specified neighbors, passes, and thresholds.
-repeat Repeatedly reads PV values at intervals.
-provider Specifies the provider for the PVs (default is ca).
-dryrun Displays PV names/values without sending to IOCs.
-floatformat Custom printf-style format for floating-point values.
-info Prints metadata for the specified PVs.
-delimiter Sets the delimiter for output values. Default is a newline.
-noquotes Suppresses quotes around string values.
-embrace Adds custom braces around values.
-errorvalue Output for timeouts/errors. Default is ?.
-excludeerrors Suppresses output for errors.
-numerical Forces numerical values for enumerated types.
-chararray Prints character arrays as strings.

Incompatibilities

  • -statistics is incompatible with:
    • -repeat
    • -cavputform
  • For -despike:
    • Requires either -repeat or -statistics to be specified.
License
This file is distributed under the terms of the Software License Agreement found in the file LICENSE included with this distribution.
Authors
  • M. Borland
  • R. Soliday

Definition in file cavget.cc.

#include <complex>
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <unistd.h>
#include <cadef.h>
#include <epicsVersion.h>
#include "mdb.h"
#include "scan.h"
#include "match_string.h"
#include "SDDS.h"
#include "pvMultList.h"

Go to the source code of this file.

Functions

void sleep_us (unsigned int nusecs)
 
long printResult (FILE *fp, char *startBrace, long labeled, long connectedInTime, long channelType, PV_VALUE PVvalue, char *endBrace, char *floatFormat, short charArray, char *errorValue, long quotes, long cavputForm, long excludeErrors, long delimNeeded, char *delimiter, long secondValue, long doRepeats, long doStats, long repeats, double *value, long average, short printErrors)
 
void printResultPretty (FILE *fp, long *channelType, PV_VALUE *PVvalue, long PVs, long quotes, short *connectedInTime, char *errorValue, short printErrors)
 
long writeStatisticsToSDDSFile (char *outputFile, long *channelType, PV_VALUE *PVvalue, long PVs, short *connectedInTime, char *errorValue, short printErrors)
 
void oag_ca_exception_handler (struct exception_handler_args args)
 
int main (int argc, char **argv)
 

Function Documentation

◆ main()

int main ( int argc,
char ** argv )

Definition at line 234 of file cavget.cc.

234 {
235 int32_t beginRange, endRange, rangeInterval;
236 long dryRun;
237 long PVs, j, i_arg, labeled, quotes, numerical;
238 PV_VALUE *PVvalue;
239 TERM_LIST *List;
240 unsigned long flags;
241 SCANNED_ARG *s_arg;
242 char *rangeFormat, *floatFormat, *delimiter;
243 short charArray=0;
244 double pendIOTime, repeatPause, despikeThreshold;
245 chid *channelID;
246 short *connectedInTime = NULL;
247 char *startBrace, *endBrace;
248 long average, sigma, repeats0, cavputForm, excludeErrors, doStats, doRepeat, doDespike;
249 int32_t repeats, despikeNeighbors, despikePasses, despikeAverageOf;
250 char *errorValue = (char *)"?";
251 char *statsFormat, *statsOutput;
252 double **value = NULL;
253 long *channelType = NULL;
254 short printErrors = 0;
255 long providerMode = 0;
256 long infoMode = 0;
257#if (EPICS_VERSION > 3)
258 PVA_OVERALL pva;
259#else
260 long delimNeeded;
261#endif
262
263 argc = scanargs(&s_arg, argc, argv);
264 if (argc < 2) {
265 fprintf(stderr, "%s\n", USAGE);
266 exit(EXIT_FAILURE);
267 }
268 statsFormat = statsOutput = NULL;
269 PVvalue = NULL;
270 List = NULL;
271 PVs = dryRun = labeled = numerical = 0;
272 floatFormat = (char *)"%g";
273 delimiter = (char *)"\n";
274 quotes = 1;
275 pendIOTime = 1.0;
276 startBrace = endBrace = NULL;
277 repeats = average = sigma = 0;
278 doStats = doRepeat = doDespike = 0;
279 repeatPause = 1;
280 cavputForm = excludeErrors = 0;
281 channelID = NULL;
282 despikeNeighbors = 10;
283 despikePasses = 2;
284 despikeAverageOf = 4;
285 despikeThreshold = 0;
286
287 for (i_arg = 1; i_arg < argc; i_arg++) {
288 if (s_arg[i_arg].arg_type == OPTION) {
289 delete_chars(s_arg[i_arg].list[0], (char *)"_");
290 switch (match_string(s_arg[i_arg].list[0], commandline_option, COMMANDLINE_OPTIONS, 0)) {
291 case CLO_LIST:
292 if (s_arg[i_arg].n_items < 2)
293 SDDS_Bomb((char *)"invalid -list syntax (cavget)");
294 List = (TERM_LIST *)trealloc(List, sizeof(*List) * (s_arg[i_arg].n_items - 1));
295 for (j = 1; j < s_arg[i_arg].n_items; j++) {
296 List[j - 1].flags = 0;
297 List[j - 1].string = s_arg[i_arg].list[j];
298 List[j - 1].value = NULL;
299 }
300 multiplyWithList(&PVvalue, &PVs, List, s_arg[i_arg].n_items - 1);
301 break;
302 case CLO_RANGE:
303 s_arg[i_arg].n_items--;
304 rangeFormat = NULL;
305 rangeInterval = 1;
306 if (!scanItemList(&flags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
307 "begin", SDDS_LONG, &beginRange, 1, BEGIN_GIVEN,
308 "end", SDDS_LONG, &endRange, 1, END_GIVEN,
309 "interval", SDDS_LONG, &rangeInterval, 1, INTERVAL_GIVEN,
310 "format", SDDS_STRING, &rangeFormat, 1, FORMAT_GIVEN,
311 NULL) ||
312 !(flags & BEGIN_GIVEN) || !(flags & END_GIVEN) || beginRange > endRange ||
313 (flags & FORMAT_GIVEN && SDDS_StringIsBlank(rangeFormat)))
314 SDDS_Bomb((char *)"invalid -range syntax/values");
315 if (!rangeFormat)
316 rangeFormat = (char *)"%ld";
317 multiplyWithRange(&PVvalue, &PVs, beginRange, endRange, rangeInterval, rangeFormat);
318 s_arg[i_arg].n_items++;
319 break;
320 case CLO_PENDIOTIME:
321 if (s_arg[i_arg].n_items != 2)
322 SDDS_Bomb((char *)"wrong number of items for -pendIoTime");
323 if (sscanf(s_arg[i_arg].list[1], "%lf", &pendIOTime) != 1 ||
324 pendIOTime <= 0)
325 SDDS_Bomb((char *)"invalid -pendIoTime value (cavget)");
326 break;
327 case CLO_DRYRUN:
328 dryRun = 1;
329 break;
330 case CLO_LABELED:
331 labeled = 1;
332 break;
333 case CLO_PRINTERRORS:
334 printErrors = 1;
335 break;
336 case CLO_INFO:
337 infoMode = 1;
338 break;
339 case CLO_CHARARRAY:
340 charArray = 1;
341 break;
342 case CLO_FLOATFORMAT:
343 if (s_arg[i_arg].n_items != 2)
344 SDDS_Bomb((char *)"wrong number of items for -floatFormat");
345 floatFormat = s_arg[i_arg].list[1];
346 break;
347 case CLO_DELIMITER:
348 if (s_arg[i_arg].n_items != 2)
349 SDDS_Bomb((char *)"wrong number of items for -delimiter");
350 delimiter = s_arg[i_arg].list[1];
351 break;
352 case CLO_NOQUOTES:
353 quotes = 0;
354 break;
355 case CLO_EMBRACE:
356 s_arg[i_arg].n_items--;
357 startBrace = (char *)"{";
358 endBrace = (char *)"}";
359 if (!scanItemList(&flags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
360 "start", SDDS_STRING, &startBrace, 1, 0,
361 "end", SDDS_STRING, &endBrace, 1, 0,
362 NULL))
363 SDDS_Bomb((char *)"invalid -embrace syntax");
364 s_arg[i_arg].n_items++;
365 break;
366 case CLO_DESPIKE:
367 s_arg[i_arg].n_items--;
368 doDespike = 1;
369 if (!scanItemList(&flags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
370 "neighbors", SDDS_LONG, &despikeNeighbors, 1, 0,
371 "passes", SDDS_LONG, &despikePasses, 1, 0,
372 "averageOf", SDDS_LONG, &despikeAverageOf, 1, 0,
373 "threshold", SDDS_DOUBLE, &despikeThreshold, 1, 0,
374 NULL) ||
375 despikeNeighbors < 0 ||
376 despikePasses < 0 || despikeAverageOf < 0 || despikeThreshold < 0)
377 SDDS_Bomb((char *)"invalid -despike syntax");
378 s_arg[i_arg].n_items++;
379 break;
380 case CLO_REPEAT:
381 s_arg[i_arg].n_items--;
382 doRepeat = 1;
383 repeats = average = 0;
384 if (!scanItemList(&flags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
385 "number", SDDS_LONG, &repeats, 1, 0,
386 "pause", SDDS_DOUBLE, &repeatPause, 1, 0,
387 "average", -1, NULL, 0, REPEAT_AVERAGE,
388 "sigma", -1, NULL, 0, REPEAT_SIGMA,
389 NULL) ||
390 repeats < 1)
391 SDDS_Bomb((char *)"invalid -repeat syntax");
392 if (flags & REPEAT_AVERAGE)
393 average = 1;
394 if (flags & REPEAT_SIGMA)
395 sigma = 1;
396 s_arg[i_arg].n_items++;
397 break;
398 case CLO_STATISTICS:
399 s_arg[i_arg].n_items--;
400 doStats = 1;
401 repeats = 0;
402 if (!scanItemList(&flags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
403 "number", SDDS_LONG, &repeats, 1, 0,
404 "pause", SDDS_DOUBLE, &repeatPause, 1, 0,
405 "format", SDDS_STRING, &statsFormat, 1, 0,
406 "file", SDDS_STRING, &statsOutput, 1, 0,
407 NULL) ||
408 repeats < 1)
409 SDDS_Bomb((char *)"invalid -statistics syntax");
410 if (!statsFormat)
411 SDDS_Bomb((char *)"invalid -statistics syntax, the format is not given.");
412 switch (match_string(statsFormat, statisticsFormat, STATISTICS_FORMATS, 0)) {
413 case CLO_STATS_TAGVALUE:
414 case CLO_STATS_PRETTY:
415 if (statsOutput)
416 SDDS_Bomb((char *)"invalid -statics format syntax");
417 break;
418 case CLO_STATS_SDDS:
419 if (!statsOutput)
420 SDDS_Bomb((char *)"invalid -statics format=SDDS syntax, output filename is not given");
421 break;
422 default:
423 SDDS_Bomb((char *)"unknown format given to -statistics option");
424 break;
425 }
426 s_arg[i_arg].n_items++;
427 break;
428 case CLO_ERRORVALUE:
429 if (s_arg[i_arg].n_items != 2)
430 SDDS_Bomb((char *)"invalid -errorValue syntax");
431 errorValue = s_arg[i_arg].list[1];
432 break;
433 case CLO_NUMERICAL:
434 numerical = 1;
435 break;
436 case CLO_CAVPUTFORM:
437 cavputForm = 1;
438 break;
439 case CLO_EXCLUDEERRORS:
440 excludeErrors = 1;
441 break;
442 case CLO_PROVIDER:
443 if (s_arg[i_arg].n_items != 2)
444 SDDS_Bomb((char *)"no value given for option -provider");
445 if ((providerMode = match_string(s_arg[i_arg].list[1], providerOption,
446 PROVIDER_COUNT, 0)) < 0)
447 SDDS_Bomb((char *)"invalid -provider");
448 break;
449 default:
450 SDDS_Bomb((char *)"unknown option (cavget)");
451 break;
452 }
453 } else
454 SDDS_Bomb((char *)"unknown option");
455 }
456
457 if (doRepeat && doStats)
458 SDDS_Bomb((char *)"-repeat and -statistics are imcompatible.");
459
460 /*if (cavputForm && doStats)
461 SDDS_Bomb((char*)"-cavputForm and -statistics are imcompatible."); */
462 if (doDespike) {
463 if (!doRepeat && !doStats)
464 SDDS_Bomb((char *)"neither repeat or statistics is given, can not do despiking!");
465 if (doRepeat) {
466 sigma = 0;
467 average = 1;
468 }
469 if (despikeNeighbors > repeats)
470 despikeNeighbors = repeats;
471 if (despikeAverageOf > repeats)
472 despikeAverageOf = repeats;
473 }
474 if (cavputForm)
475 delimiter = (char *)",";
476 if (dryRun) {
477 for (j = 0; j < PVs; j++) {
478 if (strncmp(PVvalue[j].name, "pva://", 6) == 0) {
479 PVvalue[j].name += 6;
480 printf("%32s\n", PVvalue[j].name);
481 PVvalue[j].name -= 6;
482 } else if (strncmp(PVvalue[j].name, "ca://", 5) == 0) {
483 PVvalue[j].name += 5;
484 printf("%32s\n", PVvalue[j].name);
485 PVvalue[j].name -= 5;
486 } else {
487 printf("%32s\n", PVvalue[j].name);
488 }
489 }
490 } else {
491#if (EPICS_VERSION > 3)
492 //Allocate memory for pva structure
493 allocPVA(&pva, PVs, repeats);
494 //List PV names
495 epics::pvData::shared_vector<std::string> names(pva.numPVs);
496 epics::pvData::shared_vector<std::string> provider(pva.numPVs);
497 for (j = 0; j < pva.numPVs; j++) {
498 if (strncmp(PVvalue[j].name, "pva://", 6) == 0) {
499 PVvalue[j].name += 6;
500 names[j] = PVvalue[j].name;
501 PVvalue[j].name -= 6;
502 provider[j] = "pva";
503 } else if (strncmp(PVvalue[j].name, "ca://", 5) == 0) {
504 PVvalue[j].name += 5;
505 names[j] = PVvalue[j].name;
506 PVvalue[j].name -= 5;
507 provider[j] = "ca";
508 } else {
509 names[j] = PVvalue[j].name;
510 if (providerMode == PROVIDER_PVA)
511 provider[j] = "pva";
512 else
513 provider[j] = "ca";
514 }
515 }
516 pva.pvaChannelNames = freeze(names);
517 pva.pvaProvider = freeze(provider);
518 //Connect to PVs
519 ConnectPVA(&pva, pendIOTime);
520
521
522
523 repeats0 = 0;
524
525 do {
526 //Get data from PVs and return a PVStructure
527 if (infoMode) {
528 pva.includeAlarmSeverity = true;
529 }
530 if (GetPVAValues(&pva) == 1) {
531 return (EXIT_FAILURE);
532 }
533 if (infoMode) {
534 GetInfoData(&pva, PVvalue);
535 exit(EXIT_SUCCESS);
536 }
537 //Change enumerated PV values to int from string if the numerical option is given
538 if ((repeats0 == 0) && (numerical)) {
539 for (j = 0; j < PVs; j++) {
540 if (pva.isConnected[j] && pva.pvaData[j].pvEnumeratedStructure) {
541 pva.pvaData[j].scalarType = epics::pvData::pvInt;
542 }
543 }
544 }
545
546 if (!repeats) {
547 for (j = 0; j < PVs; j++) {
548 if ((pva.pvaData[j].numGetElements == 1) && (pva.pvaData[j].numeric)) {
549 pva.pvaData[j].mean = pva.pvaData[j].getData[0].values[0];
550 }
551 }
552 }
553 repeats0++;
554 if ((repeats0 < repeats) && (repeatPause > 0)) {
555 usleepSystemIndependent(repeatPause * 1000000);
556 }
557 } while (repeats0 < repeats);
558
559 if (repeats) {
560 for (j = 0; j < PVs; j++) {
561 if ((pva.pvaData[j].numGetElements == 1) && (pva.pvaData[j].numeric)) {
562 double *v;
563 long i;
564 v = (double *)malloc(sizeof(double) * repeats);
565 for (i = 0; i < repeats; i++) {
566 v[i] = pva.pvaData[j].getData[i].values[0];
567 }
568 if (doDespike) {
569 despikeData(v, repeats, despikeNeighbors, despikePasses, despikeAverageOf, despikeThreshold, 0);
570 }
571 find_min_max(&pva.pvaData[j].min, &pva.pvaData[j].max, v, repeats);
572 computeMoments(&pva.pvaData[j].mean, &pva.pvaData[j].rms, &pva.pvaData[j].stDev, &pva.pvaData[j].MAD, v, repeats);
573 pva.pvaData[j].spread = pva.pvaData[j].max - pva.pvaData[j].min;
574 pva.pvaData[j].sigma = pva.pvaData[j].stDev / sqrt(repeats);
575 find_median(&pva.pvaData[j].median, v, repeats);
576 free(v);
577 }
578 }
579 }
580
581 if (!statsFormat ||
582 match_string(statsFormat, statisticsFormat, STATISTICS_FORMATS, 0) == CLO_STATS_TAGVALUE) {
583 printResultPVA(startBrace, labeled, &pva, PVvalue, endBrace,
584 floatFormat, charArray, errorValue, quotes, cavputForm,
585 excludeErrors, delimiter, sigma,
586 doRepeat, doStats, repeats, average, printErrors);
587 }
588 if (statsFormat) {
589 switch (match_string(statsFormat, statisticsFormat, STATISTICS_FORMATS, 0)) {
590 case CLO_STATS_PRETTY:
591 printResultPrettyPVA(&pva, quotes, errorValue, printErrors);
592 break;
593 case CLO_STATS_SDDS:
594 writeStatisticsToSDDSFilePVA(statsOutput, &pva, quotes, errorValue, printErrors);
595 break;
596 default:
597 break;
598 }
599 }
600 if (PVvalue) {
601 for (j = 0; j < PVs; j++) {
602 if (PVvalue[j].name)
603 free(PVvalue[j].name);
604 }
605 free(PVvalue);
606 }
607 freePVA(&pva);
608 if (statsFormat)
609 free(statsFormat);
610 if (statsOutput)
611 free(statsOutput);
612 if (List)
613 free(List);
614 free_scanargs(&s_arg, argc);
615 return (EXIT_SUCCESS);
616#else
617 if (!(value = (double **)malloc(sizeof(double *) * PVs)))
618 SDDS_Bomb((char *)"memory allocation failure (cavget)");
619 for (j = 0; j < PVs; j++) {
620 if (repeats) {
621 if (!(value[j] = (double *)calloc((repeats), sizeof(double))))
622 SDDS_Bomb((char *)"memory allocation failure (cavget)");
623 } else {
624 if (!(value[j] = (double *)calloc(1, sizeof(double))))
625 SDDS_Bomb((char *)"memory allocation failure (cavget)");
626 }
627 }
628 repeats0 = 0;
629
630 ca_task_initialize();
631 ca_add_exception_event(oag_ca_exception_handler, NULL);
632 if (!(channelID = (chid *)malloc(sizeof(*channelID) * PVs)) ||
633 !(channelType = (long *)malloc(sizeof(*channelType) * PVs)) ||
634 !(connectedInTime = (short *)malloc(sizeof(*connectedInTime) * PVs)))
635 SDDS_Bomb((char *)"memory allocation failure (cavget)");
636 for (j = 0; j < PVs; j++)
637 if (ca_search(PVvalue[j].name, channelID + j) != ECA_NORMAL) {
638 fprintf(stderr, "error (cavget): problem doing search for %s\n",
639 PVvalue[j].name);
640 ca_task_exit();
641 exit(EXIT_FAILURE);
642 }
643 ca_pend_io(pendIOTime);
644 if (numerical)
645 for (j = 0; j < PVs; j++) {
646 channelType[j] = ca_field_type(channelID[j]);
647 if ((channelType[j] = ca_field_type(channelID[j])) == DBF_ENUM)
648 channelType[j] = DBF_DOUBLE;
649 }
650 else
651 for (j = 0; j < PVs; j++)
652 channelType[j] = ca_field_type(channelID[j]);
653 do {
654 for (j = 0; j < PVs; j++) {
655 if (!(connectedInTime[j] = ca_state(channelID[j]) == cs_conn))
656 continue;
657 switch (channelType[j]) {
658 case DBF_STRING:
659 case DBF_ENUM:
660 PVvalue[j].value = (char *)malloc(sizeof(char) * 256);
661 if (ca_get(DBR_STRING, channelID[j], PVvalue[j].value) != ECA_NORMAL) {
662 fprintf(stderr, "problem doing get for %s\n",
663 PVvalue[j].name);
664 ca_task_exit();
665 exit(EXIT_FAILURE);
666 }
667 break;
668 case DBF_NO_ACCESS:
669 fprintf(stderr, "Error: No access to PV %s\n", PVvalue[j].name);
670 ca_task_exit();
671 exit(EXIT_FAILURE);
672 break;
673 default:
674 if (ca_get(DBR_DOUBLE, channelID[j],
675 &value[j][repeats0]) != ECA_NORMAL) {
676 fprintf(stderr, "problem doing get for %s\n",
677 PVvalue[j].name);
678 ca_task_exit();
679 exit(EXIT_FAILURE);
680 }
681 break;
682 }
683 }
684 ca_pend_io(pendIOTime);
685 repeats0++;
686 if (!repeats) {
687 for (j = 0; j < PVs; j++)
688 PVvalue[j].mean = value[j][0];
689 }
690 if ((repeats0 < repeats) && (repeatPause > 0)) {
691 ca_pend_event(repeatPause);
692 }
693 } while (repeats0 < repeats);
694
695 if (repeats) {
696 for (j = 0; j < PVs; j++) {
697 if (doDespike) {
698 despikeData(value[j], repeats, despikeNeighbors, despikePasses, despikeAverageOf,
699 despikeThreshold, 0);
700 }
701 find_min_max(&PVvalue[j].min, &PVvalue[j].max, value[j], repeats);
702 computeMoments(&PVvalue[j].mean, &PVvalue[j].rms, &PVvalue[j].stDev, &PVvalue[j].MAD,
703 value[j], repeats);
704 PVvalue[j].spread = PVvalue[j].max - PVvalue[j].min;
705 PVvalue[j].sigma = PVvalue[j].stDev / sqrt(repeats);
706 find_median(&PVvalue[j].median, value[j], repeats);
707 }
708 }
709
710 delimNeeded = 0;
711 if (!statsFormat ||
712 match_string(statsFormat, statisticsFormat, STATISTICS_FORMATS, 0) == CLO_STATS_TAGVALUE) {
713 for (j = 0; j < PVs; j++) {
714 if (printResult(stdout, startBrace, labeled, connectedInTime[j],
715 channelType[j], PVvalue[j], endBrace,
716 floatFormat, charArray, errorValue, quotes, cavputForm,
717 excludeErrors, delimNeeded, delimiter, sigma, doRepeat, doStats, repeats, value[j], average,
718 printErrors))
719 delimNeeded = 1;
720 }
721 if (delimNeeded)
722 fputc('\n', stdout);
723 }
724 if (statsFormat) {
725 switch (match_string(statsFormat, statisticsFormat, STATISTICS_FORMATS, 0)) {
726 case CLO_STATS_PRETTY:
727 printResultPretty(stdout, channelType, PVvalue, PVs, quotes, connectedInTime, errorValue, printErrors);
728 break;
729 case CLO_STATS_SDDS:
730 writeStatisticsToSDDSFile(statsOutput, channelType, PVvalue, PVs, connectedInTime, errorValue, printErrors);
731 break;
732 default:
733 break;
734 }
735 }
736 ca_task_exit();
737#endif
738 }
739 for (j = 0; j < PVs; j++) {
740 if (PVvalue[j].name)
741 free(PVvalue[j].name);
742 if (PVvalue[j].value)
743 free(PVvalue[j].value);
744 PVvalue[j].name = PVvalue[j].value = NULL;
745 }
746 if (value) {
747 for (j = 0; j < PVs; j++)
748 free(value[j]);
749 free(value);
750 }
751 if (PVvalue)
752 free(PVvalue);
753 if (channelID)
754 free(channelID);
755 if (channelType)
756 free(channelType);
757 if (connectedInTime)
758 free(connectedInTime);
759 free_scanargs(&s_arg, argc);
760 if (List)
761 free(List);
762
763 return EXIT_SUCCESS;
764}
int32_t SDDS_StringIsBlank(char *s)
Checks if a string is blank (contains only whitespace characters).
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:342
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
Definition SDDStypes.h:61
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
void * trealloc(void *old_ptr, uint64_t size_of_block)
Reallocates a memory block to a new size.
Definition array.c:181
char * delete_chars(char *s, char *t)
Removes all occurrences of characters found in string t from string s.
int find_min_max(double *min, double *max, double *list, int64_t n)
Finds the minimum and maximum values in a list of doubles.
Definition findMinMax.c:33
void usleepSystemIndependent(long usec)
Sleep for a given number of microseconds, system-independently.
long match_string(char *string, char **option, long n_options, long mode)
Matches a given string against an array of option strings based on specified modes.
long computeMoments(double *mean, double *rms, double *standDev, double *meanAbsoluteDev, double *x, long n)
Computes the mean, RMS, standard deviation, and mean absolute deviation of an array.
Definition moments.c:108
long find_median(double *value, double *x, long n)
Finds the median value of an array of doubles and returns the index of the median.
Definition rowmedian.c:32
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
Definition scanargs.c:36
void free_scanargs(SCANNED_ARG **scanned, int argc)
Definition scanargs.c:584
long scanItemList(unsigned long *flags, char **item, long *items, unsigned long mode,...)
Scans a list of items and assigns values based on provided keywords and types.
long despikeData(double *data, long rows, long neighbors, long passes, long averageOf, double threshold, long countLimit)
Remove spikes from a data array by comparing each point to its neighbors.
Definition smooth.c:86

◆ oag_ca_exception_handler()

void oag_ca_exception_handler ( struct exception_handler_args args)

Definition at line 1004 of file cavget.cc.

1004 {
1005 char *pName;
1006 int severityInt;
1007 static const char *severity[] =
1008 {
1009 "Warning",
1010 "Success",
1011 "Error",
1012 "Info",
1013 "Fatal",
1014 "Fatal",
1015 "Fatal",
1016 "Fatal"};
1017
1018 severityInt = CA_EXTRACT_SEVERITY(args.stat);
1019
1020 fprintf(stderr, "CA.Client.Exception................\n");
1021 fprintf(stderr, " %s: \"%s\"\n",
1022 severity[severityInt],
1023 ca_message(args.stat));
1024
1025 if (args.ctx) {
1026 fprintf(stderr, " Context: \"%s\"\n", args.ctx);
1027 }
1028 if (args.chid) {
1029 pName = (char *)ca_name(args.chid);
1030 fprintf(stderr, " Channel: \"%s\"\n", pName);
1031 fprintf(stderr, " Type: \"%s\"\n", dbr_type_to_text(args.type));
1032 }
1033 fprintf(stderr, "This sometimes indicates an IOC that is hung up.\n");
1034 _exit(EXIT_FAILURE);
1035}

◆ printResult()

long printResult ( FILE * fp,
char * startBrace,
long labeled,
long connectedInTime,
long channelType,
PV_VALUE PVvalue,
char * endBrace,
char * floatFormat,
short charArray,
char * errorValue,
long quotes,
long cavputForm,
long excludeErrors,
long delimNeeded,
char * delimiter,
long secondValue,
long doRepeats,
long doStats,
long repeats,
double * value,
long average,
short printErrors )

Definition at line 766 of file cavget.cc.

771 {
772 long i;
773
774 if (excludeErrors && !connectedInTime)
775 return 0;
776 if (delimNeeded && delimiter)
777 fputs(delimiter, fp);
778 if (cavputForm) {
779 fprintf(fp, "%s=", PVvalue.name);
780 quotes = 0;
781 } else {
782 if (startBrace)
783 fputs(startBrace, fp);
784 if (labeled)
785 fprintf(fp, "%s ", PVvalue.name);
786 }
787 if (!connectedInTime) {
788 if (printErrors)
789 fprintf(stderr, "%s is not connected or invalid PV name.\n", PVvalue.name);
790 else
791 fputs(errorValue, fp);
792 } else {
793 switch (channelType) {
794 case DBF_SHORT:
795 case DBF_LONG:
796 case DBF_CHAR:
797 if (cavputForm || (!doRepeat && !doStats)) {
798 fprintf(fp, "%.0f", PVvalue.mean);
799 } else {
800 if (doRepeat) {
801 if (!average) {
802 for (i = 0; i < repeats; i++) {
803 fprintf(fp, "%.0f ", value[i]);
804 }
805 } else {
806 fprintf(fp, "%.0f", PVvalue.mean);
807 if (secondValue) {
808 fprintf(fp, " ");
809 fprintf(fp, "%.0f", PVvalue.sigma);
810 }
811 }
812 }
813 if (doStats) {
814 fprintf(fp, "mean ");
815 fprintf(fp, "%.0f", PVvalue.mean);
816 fprintf(fp, " median ");
817 fprintf(fp, "%.0f", PVvalue.median);
818 fprintf(fp, " sigma ");
819 fprintf(fp, "%.0f", PVvalue.sigma);
820 fprintf(fp, " stDev ");
821 fprintf(fp, "%.0f", PVvalue.stDev);
822 fprintf(fp, " MAD ");
823 fprintf(fp, "%.0f", PVvalue.MAD);
824 fprintf(fp, " min ");
825 fprintf(fp, "%.0f", PVvalue.min);
826 fprintf(fp, " max ");
827 fprintf(fp, "%.0f", PVvalue.max);
828 fprintf(fp, " spread ");
829 fprintf(fp, "%.0f", PVvalue.spread);
830 }
831 }
832 break;
833 case DBF_STRING:
834 case DBF_ENUM:
835 if (!quotes)
836 fputs(PVvalue.value, fp);
837 else {
838 if (SDDS_StringIsBlank(PVvalue.value) ||
839 SDDS_HasWhitespace(PVvalue.value))
840 fprintf(fp, "\"%s\"", PVvalue.value);
841 else
842 fputs(PVvalue.value, fp);
843 }
844 break;
845 case DBF_DOUBLE:
846 case DBF_FLOAT:
847 default:
848 if (cavputForm || (!doRepeat && !doStats)) {
849 fprintf(fp, floatFormat, PVvalue.mean);
850 } else {
851 if (doRepeat) {
852 if (!average) {
853 for (i = 0; i < repeats; i++) {
854 fprintf(fp, floatFormat, value[i]);
855 fprintf(fp, " ");
856 }
857 } else {
858 fprintf(fp, floatFormat, PVvalue.mean);
859 if (secondValue) {
860 fprintf(fp, " ");
861 fprintf(fp, floatFormat, PVvalue.sigma);
862 }
863 }
864 }
865 if (doStats) {
866 fprintf(fp, " mean ");
867 fprintf(fp, floatFormat, PVvalue.mean);
868 fprintf(fp, " median ");
869 fprintf(fp, floatFormat, PVvalue.median);
870 fprintf(fp, " sigma ");
871 fprintf(fp, floatFormat, PVvalue.sigma);
872 fprintf(fp, " stDev ");
873 fprintf(fp, floatFormat, PVvalue.stDev);
874 fprintf(fp, " MAD ");
875 fprintf(fp, floatFormat, PVvalue.MAD);
876 fprintf(fp, " min ");
877 fprintf(fp, floatFormat, PVvalue.min);
878 fprintf(fp, " max ");
879 fprintf(fp, floatFormat, PVvalue.max);
880 fprintf(fp, " spread ");
881 fprintf(fp, floatFormat, PVvalue.spread);
882 }
883 }
884 break;
885 }
886 }
887 if (endBrace && !cavputForm)
888 fputs(endBrace, fp);
889 return 1;
890}
int32_t SDDS_HasWhitespace(char *string)
Checks if a string contains any whitespace characters.

◆ printResultPretty()

void printResultPretty ( FILE * fp,
long * channelType,
PV_VALUE * PVvalue,
long PVs,
long quotes,
short * connectedInTime,
char * errorValue,
short printErrors )

Definition at line 892 of file cavget.cc.

893 {
894 long i;
895
896 fprintf(fp, "%20s", "ControlName");
897 fprintf(fp, "%10s", "mean");
898 fprintf(fp, "%10s", "median");
899 fprintf(fp, "%10s", "sigma");
900 fprintf(fp, "%10s", "stDev");
901 fprintf(fp, "%10s", "MAD");
902 fprintf(fp, "%10s", "min");
903 fprintf(fp, "%10s", "max");
904 fprintf(fp, "%10s", "spread");
905 fputc('\n', fp);
906 for (i = 0; i < 100; i++)
907 fputc('-', fp);
908 fputc('\n', fp);
909
910 for (i = 0; i < PVs; i++) {
911 fprintf(fp, "%20s", PVvalue[i].name);
912 if (!connectedInTime[i]) {
913 if (printErrors)
914 fprintf(stderr, "%s is not connected or invalid PV name.\n", PVvalue[i].name);
915 else {
916 fprintf(fp, " ");
917 fputs(errorValue, fp);
918 }
919 } else {
920 switch (channelType[i]) {
921 case DBF_STRING:
922 case DBF_ENUM:
923 if (!quotes)
924 fputs(PVvalue[i].value, fp);
925 else {
926 if (SDDS_StringIsBlank(PVvalue[i].value) ||
927 SDDS_HasWhitespace(PVvalue[i].value))
928 fprintf(fp, "\"%s\"", PVvalue[i].value);
929 else
930 fputs(PVvalue[i].value, fp);
931 }
932 break;
933 default:
934 fprintf(fp, "%10.4f%10.4f%10.4f%10.4f%10.4f%10.4f%10.4f%10.4f", PVvalue[i].mean,
935 PVvalue[i].median, PVvalue[i].sigma, PVvalue[i].stDev, PVvalue[i].MAD,
936 PVvalue[i].min, PVvalue[i].max, PVvalue[i].spread);
937 break;
938 }
939 }
940 fputc('\n', fp);
941 }
942}

◆ sleep_us()

void sleep_us ( unsigned int nusecs)

Definition at line 200 of file cavget.cc.

200 {
201 struct timeval tval;
202
203 tval.tv_sec = nusecs / 1000000;
204 tval.tv_usec = nusecs % 1000000;
205 select(0, NULL, NULL, NULL, &tval);
206}

◆ writeStatisticsToSDDSFile()

long writeStatisticsToSDDSFile ( char * outputFile,
long * channelType,
PV_VALUE * PVvalue,
long PVs,
short * connectedInTime,
char * errorValue,
short printErrors )

Definition at line 944 of file cavget.cc.

945 {
946 SDDS_DATASET SDDS_out;
947 long i, row;
948
949 for (i = 0; i < PVs; i++) {
950 switch (channelType[i]) {
951 case DBF_STRING:
952 case DBF_ENUM:
953 case DBF_CHAR:
954 fprintf(stderr, "Error, doing statistical analysis for PVs of non-numeric type is meaningless.\n");
955 return 0;
956 default:
957 break;
958 }
959 }
960
961 if (!SDDS_InitializeOutput(&SDDS_out, SDDS_BINARY, 0, NULL, "cavget output", outputFile))
962 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
963 if (SDDS_DefineColumn(&SDDS_out, "ControlName", NULL, NULL, NULL, NULL, SDDS_STRING, 0) < 0 ||
964 SDDS_DefineColumn(&SDDS_out, "Mean", NULL, NULL, NULL, NULL, SDDS_DOUBLE, 0) < 0 ||
965 SDDS_DefineColumn(&SDDS_out, "Median", NULL, NULL, NULL, NULL, SDDS_DOUBLE, 0) < 0 ||
966 SDDS_DefineColumn(&SDDS_out, "Sigma", NULL, NULL, NULL, NULL, SDDS_DOUBLE, 0) < 0 ||
967 SDDS_DefineColumn(&SDDS_out, "StDev", NULL, NULL, NULL, NULL, SDDS_DOUBLE, 0) < 0 ||
968 SDDS_DefineColumn(&SDDS_out, "MAD", NULL, NULL, NULL, NULL, SDDS_DOUBLE, 0) < 0 ||
969 SDDS_DefineColumn(&SDDS_out, "Minimum", NULL, NULL, NULL, NULL, SDDS_DOUBLE, 0) < 0 ||
970 SDDS_DefineColumn(&SDDS_out, "Maximum", NULL, NULL, NULL, NULL, SDDS_DOUBLE, 0) < 0 ||
971 SDDS_DefineColumn(&SDDS_out, "Spread", NULL, NULL, NULL, NULL, SDDS_DOUBLE, 0) < 0)
972 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
973 if (!SDDS_WriteLayout(&SDDS_out))
974 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
975 if (!SDDS_StartTable(&SDDS_out, PVs))
976 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
977 for (i = row = 0; i < PVs; i++, row++) {
978 if (printErrors && !connectedInTime[i])
979 fprintf(stderr, "%s is not connected or invalid PV name.\n", PVvalue[i].name);
980 if (!connectedInTime[i] ||
981 channelType[i] == DBF_STRING || channelType[i] == DBF_ENUM) {
982 row--;
983 continue;
984 } else {
985 if (!SDDS_SetRowValues(&SDDS_out, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, row,
986 "ControlName", PVvalue[i].name,
987 "Mean", PVvalue[i].mean, "Median", PVvalue[i].median,
988 "Sigma", PVvalue[i].sigma, "StDev", PVvalue[i].stDev,
989 "MAD", PVvalue[i].MAD, "Minimum", PVvalue[i].min,
990 "Maximum", PVvalue[i].max, "Spread", PVvalue[i].spread, NULL)) {
991 SDDS_SetError((char *)"Unable to set statistical values in SDDS data set");
992 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
993 return 0;
994 }
995 }
996 }
997 if (!SDDS_WritePage(&SDDS_out))
998 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
999 if (!SDDS_Terminate(&SDDS_out))
1000 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
1001 return 1;
1002}
int32_t SDDS_SetRowValues(SDDS_DATASET *SDDS_dataset, int32_t mode, int64_t row,...)
int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_InitializeOutput(SDDS_DATASET *SDDS_dataset, int32_t data_mode, int32_t lines_per_row, const char *description, const char *contents, const char *filename)
Initializes the SDDS output dataset.
int32_t SDDS_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
int32_t SDDS_DefineColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, int32_t field_length)
Defines a data column within the SDDS dataset.
int32_t SDDS_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the SDDS layout header to the output file.
void SDDS_SetError(char *error_text)
Records an error message in the SDDS error stack.
Definition SDDS_utils.c:379
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:432