Accelerator Independent Data Access / PVAccess 2.0
AIDA-PVA is the latest version of the AIDA framework. Built on top of EPICS 7 it enables client applications to programmatically access and manage any device or database on the SLAC Network using simple channel names.
Loading...
Searching...
No Matches
AIDASLCUTIL_SERVER.c
Go to the documentation of this file.
1/** @file
2 * @brief Utility Native Provider implementation.
3 * **MEMBER**=SLCLIBS:AIDA_PVALIB
4 * **ATTRIBUTES**=JNI,LIBR_NOGLOBAL
5 */
6#include <descrip.h> /* for definition of $DESCRIPTOR */
7#include <float.h>
8#include "aida_pva.h"
9#include "descr.h" /* DESCR* macros */
10#include "ref.h" /* passing by reference macros */
11#include "crrcntl_parms.h"
12#include "bpmutil_proto.h"
13#include "AIDASLCUTIL_SERVER.h"
14
15static Table setTriggerValue(JNIEnv* env, const char* uri, Arguments arguments, Value value);
16static Table setMkbValue(JNIEnv* env, const char* uri, Arguments arguments, Value value);
17static short getTrigStatus(JNIEnv* env, const char* uri, Arguments arguments);
18static void setBGrp(JNIEnv* env, Arguments arguments, Value value);
19static void setFeedback(JNIEnv* env, const char* uri, Arguments arguments, Value value);
20static int4u faStatus(JNIEnv* env, const char* uri, int newHSTA, BOOLEAN retrieveOnly);
21static short getShortFaStatus(JNIEnv* env, const char* uri);
22static char* GetStringFaStatus(JNIEnv* env, const char* uri);
23static Table phaseScan(JNIEnv* env, const char* uri, Arguments arguments);
24static bool getAcqParameters(JNIEnv* env, Arguments arguments, char** buttonFileName,
25 char** primaryStepVariable, float* primaryLow, float* primaryHigh, int* primarySteps, float* primarySettleTime,
26 float* primaryExtraSettleTime,
27 char** secondaryStepVariable, float* secondaryLow, float* secondaryHigh, int* secondarySteps,
28 float* secondarySettleTime, float* secondaryExtraSettleTime, short* bpmd, long* nrpos, long* dtizavg,
29 char** magnetFunction);
30static void
31createCorrelationPlotTable(JNIEnv* env, Table* table, int totalSampleVariables, int nSteps, char* primaryStepVariable,
32 bool secondaryStepVariableProvided,
33 char* secondaryStepVariable, float* samples, long* samplesOk);
34static int countSampleVariables(JNIEnv* env, long* nSampleVariables);
35
36// API Stubs
37VERSION("1.0.0")
49
50/**
51 * Initialise the service
52 * @param env to be used to throw exceptions using aidaThrow() and aidaThrowNonOsException()
53 * @throws ServerInitialisationException if the service fails to initialise
54 */
55void aidaServiceInit(JNIEnv* env) {
56 vmsstat_t status;
57 if (!$VMS_STATUS_SUCCESS(status = init("AIDA_SLCUTIL", false))) {
58 aidaThrow(env, status, SERVER_INITIALISATION_EXCEPTION, "initialising Utility Service");
59 } else {
60 printf("AIDA-PVA Utility Provider\n");
61 }
62}
63
64/**
65 * Get a short
66 *
67 * @param uri the uri
68 * @param env to be used to throw exceptions using aidaThrow() and aidaThrowNonOsException()
69 * @param arguments the arguments
70 * @return the short
71 */
72short aidaRequestShort(JNIEnv* env, const char* uri, Arguments arguments) {
73 if (startsWith(uri, "FBCK")) {
74 return getShortFaStatus(env, uri);
75 } else {
76 return getTrigStatus(env, uri, arguments);
77 }
78}
79
80/**
81 * Get an integer
82 *
83 * @param uri the uri
84 * @param env to be used to throw exceptions using aidaThrow() and aidaThrowNonOsException()
85 * @param arguments the arguments
86 * @return the integer
87 */
88int aidaRequestInteger(JNIEnv* env, const char* uri, Arguments arguments) {
89 return getShortFaStatus(env, uri);
90}
91
92/**
93 * Get a Boolean
94 *
95 * @param uri the uri
96 * @param env to be used to throw exceptions using aidaThrow() and aidaThrowNonOsException()
97 * @param arguments the arguments
98 * @return the boolean
99 */
100int aidaRequestBoolean(JNIEnv* env, const char* uri, Arguments arguments) {
101 return getShortFaStatus(env, uri) == 0 ? false : true;
102}
103
104/**
105 * Get a integer
106 *
107 * @param env to be used to throw exceptions using aidaThrow() and aidaThrowNonOsException()
108 * @param uri the uri
109 * @param arguments the arguments
110 * @return the integer
111 */
112long aidaRequestLong(JNIEnv* env, const char* uri, Arguments arguments) {
113 if (startsWith(uri, "FBCK")) {
114 return (long)faStatus(env, uri, 0, TRUE_B);
115 } else {
116 return (long)getTrigStatus(env, uri, arguments);
117 }
118}
119
120/**
121 * Get a string. Allocate memory for string and it will be freed for you by framework
122 *
123 * @param env to be used to throw exceptions using aidaThrow() and aidaThrowNonOsException()
124 * @param uri the uri
125 * @param arguments the arguments
126 * @return the string
127 */
128char* aidaRequestString(JNIEnv* env, const char* uri, Arguments arguments) {
129 if (startsWith(uri, "FBCK")) {
130 return GetStringFaStatus(env, uri);
131 } else {
132 // Read the status
133 short trig_status = getTrigStatus(env, uri, arguments);
135
136 if (trig_status) {
137 return ALLOCATE_STRING(env, "activated", "string");
138 } else {
139 return ALLOCATE_STRING(env, "deactivated", "string");
140 }
141 }
142}
143
144/**
145 * Implement Correlated Plots
146 *
147 * @param env to be used to throw exceptions using aidaThrow() and aidaThrowNonOsException()
148 * @param uri the uri
149 * @param arguments the arguments
150 * @return the table
151 *
152 * The `FILE` contains the name of the button file and is used
153 * The `PRIMSTV` contains a structure with configuration for the primary step variable
154 * The `SECNSTV` optionally contains a structure with configuration for the secondary step variable
155 *
156 * First the button file is loaded and then it is executed.
157 * A table with the following fields is returned:
158 * `primary` FLOAT_ARRAY value of primary step variable for this data set
159 * `secondary` FLOAT_ARRAY value of secondary step variable for this data set. Omitted if no secondary step variable specified
160 * `samp{n}` FLOAT_ARRAY For each sample variable found in the given FILE a column is returned. {n} is the sample var number
161 *
162 * The labels for each column are set to the device name
163 */
164Table aidaRequestTable(JNIEnv* env, const char* uri, Arguments arguments) {
165 REF_DECLARE;
166 DESCR_DECLARE;
167
169
170 // Blank table
171 Table table;
172 table.columnCount = 0;
173
174 // Get button file name
175 char* buttonFileName;
176 char* primaryStepVariable, * secondaryStepVariable, * magnetFunction;
177 float primaryLow, primaryHigh, primarySettleTime, primaryExtraSettleTime, secondaryLow, secondaryHigh, secondarySettleTime, secondaryExtraSettleTime, settle;
178 int primarySteps, secondarySteps;
179 long nrpos = NRPOS_DEFAULT, dtizavg;
180 short bpmd = BPMD_ROGUE;
181
182 bool secondaryStepVariableProvided = getAcqParameters(env, arguments, &buttonFileName, &primaryStepVariable,
183 &primaryLow, &primaryHigh, &primarySteps,
184 &primaryExtraSettleTime, &primarySettleTime, &secondaryStepVariable, &secondaryLow, &secondaryHigh,
185 &secondarySteps,
186 &secondarySettleTime, &secondaryExtraSettleTime, &bpmd, &nrpos, &dtizavg, &magnetFunction);
188 TRACK_MEMORY(buttonFileName)
189 TRACK_MEMORY(primaryStepVariable)
190 TRACK_MEMORY(secondaryStepVariable)
191
192 vmsstat_t status;
193
194 // Initialize correlation plot context
195 status = CRR_RESET_ALL();
196 if (!SUCCESS(status)) {
198 "error resetting correlation plots: %s", buttonFileName, table)
199 }
200
201 // Local constant for fortran parameter
202 float wire_size = 0.0f;
203 float inc = (primaryHigh - primaryLow) / (float)(primarySteps - 1);
204
205 // Set up primary step variable
206 status = CRR_SET_VAR_NAME_FREEFORM(REFINT4_1(DEFINE_STEP), REFINT4_2(1), DESCRN1(primaryStepVariable),
207 REFINT4_3(0));
208 if (!SUCCESS(status)) {
210 "error setting primary step variable name: %s", primaryStepVariable, table)
211 }
212 status = CRR_SET_STEP(REFINT4_1(1), &primaryLow, &inc, &primarySteps, &primarySettleTime);
213 if (!SUCCESS(status)) {
215 "error setting primary step variable: %s", primaryStepVariable, table)
216 }
217
218 // Set secondary step variable
219 if (secondaryStepVariableProvided) {
220 status = CRR_SET_VAR_NAME_FREEFORM(REFINT4_1(DEFINE_STEP), REFINT4_2(-1), DESCRN1(secondaryStepVariable),
221 REFINT4_3(0));
222 if (!SUCCESS(status)) {
224 "error setting secondary step variable name: %s", secondaryStepVariable, table)
225 }
226
227 inc = (secondaryHigh - secondaryLow) / (float)(secondarySteps - 1);
228 status = CRR_SET_STEP(REFINT4_1(-1), &secondaryLow, &inc, &secondarySteps, &secondarySettleTime);
229 if (!SUCCESS(status)) {
231 "error setting secondary step variable: %s", secondaryStepVariable, table)
232 }
233 }
234
235 // Make absolute file name
236 char fullyQualifiedButtonFileName[strlen(buttonFileName) + strlen(SLC_BUTTON_DIR) + 1];
237 sprintf(fullyQualifiedButtonFileName, "%s%s", SLC_BUTTON_DIR, buttonFileName);
238
239 // Load button file
240 status = CRR_RESTORE_BUTTON_FILE(DESCRN1(fullyQualifiedButtonFileName));
241 if (!SUCCESS(status)) {
243 "error loading scan parameters from button file: %s", fullyQualifiedButtonFileName, table)
244 }
245
246 // Set BPM Measurement Definition if it has been specified
247 if (bpmd != BPMD_ROGUE) {
248 status = BPMD_SELECT_UTIL(&bpmd, NULL, NULL, NULL, NULL, NULL);
249 if (!SUCCESS(status)) {
250 fprintf(stderr, "Failed to set Measurement Definition: %hd", bpmd);
252 "error initializing correlation plot acquisition: %s", buttonFileName, table)
253 }
254 }
255
256 long magfunc;
257 memcpy(&magfunc, magnetFunction, 4);
258 float settleExtra[2];
259 settleExtra[0] = primaryExtraSettleTime;
260 settleExtra[1] = secondaryExtraSettleTime;
261
262 status = CRR_SET_SAMP_PARMS(&nrpos, &dtizavg, NULL, &magfunc, NULL, NULL, NULL, &settleExtra[0]);
263 if (!SUCCESS(status)) {
264 fprintf(stderr,
265 "Failed to set sample params. nrpos: %ld, dtizavg: %ld, magfunc: %ld, primSettleExtra: %f, secnSettleExtra: %f",
266 nrpos, dtizavg, magfunc, settleExtra[0], settleExtra[1]);
268 "error initializing correlation plot acquisition: %s", buttonFileName, table)
269 }
270
271 status = CRR_DATA_ACQ_INIT();
272 if (!SUCCESS(status)) {
274 "error initializing correlation plot acquisition: %s", buttonFileName, table)
275 }
276
277 // Run Correlation plot
278 status = CRR_DATA_ACQ(DESCRN1("*"));
279 if (!SUCCESS(status)) {
280 CRR_DATA_ACQ_DONE();
282 "executing correlation plot: %s", buttonFileName, table)
283 }
284 printf("Scan Complete");
285
286 // Number of Samples
287 long nSampleVariables;
288 if (countSampleVariables(env, &nSampleVariables)) {
289 CRR_DATA_ACQ_DONE();
290 return table;
291 }
292
293 // Get step count.
294 int nSteps = CRR_SAMPLES();
295 if (!SUCCESS(status)) {
296 CRR_DATA_ACQ_DONE();
298 "error getting number of steps: %s", buttonFileName, table)
299 }
300
301 // Get total number of samples
302 long totalSampleVariables = nSampleVariables + ((secondaryStepVariableProvided) ? 2 : 1);
303 if (!totalSampleVariables || !nSampleVariables) {
304 CRR_DATA_ACQ_DONE();
305 fprintf(stderr, "Invalid number of sample variables. totalSampleVariables: %ld, nSampleVariables: %ld",
306 totalSampleVariables, nSampleVariables);
308 "No sample variables have been specified in the given file: %s", buttonFileName, table)
309 }
310
311 // Query results variables
312 if (!nSteps) {
313 CRR_DATA_ACQ_DONE();
315 "Total number of steps derived from specified step variables is: %s", "0", table)
316 }
317
318 // Space for samples. Organised as sets of values for all sample variables
319 float* samples;
320 long* samplesOk;
321
322 printf("Tabulating Scan Results: %d x %ld\n", nSteps, totalSampleVariables);
323 ALLOCATE_AND_TRACK_MEMORY_AND_ON_ERROR_RETURN_(env, samples, nSteps * totalSampleVariables * sizeof(float) * 2,
324 "store acquired data", table)
325 ALLOCATE_AND_TRACK_MEMORY_AND_ON_ERROR_RETURN_(env, samplesOk, nSteps * totalSampleVariables * sizeof(long),
326 "store acquired data ok", table)
327
328 // Clean up correlation plot context
329 status = CRR_DATA_ACQ_DONE();
330 if (!SUCCESS(status)) {
332 "cleaning up after correlation plot: %s", buttonFileName, table)
333 }
334
335 // Allocate a dynamic table of with as many columns as samples and step variables
336 table = tableCreateDynamic(env, nSteps, (int)totalSampleVariables * 3);
338
339 // Create the correlation plot table
340 createCorrelationPlotTable(env, &table, ((int)totalSampleVariables), nSteps,
341 primaryStepVariable,
342 secondaryStepVariableProvided, secondaryStepVariable,
343 samples, samplesOk);
344
345 // Free all allocated memory
347
348 return table;
349}
350
351/**
352 * Count the number of sampled variables by excluding all those that are ZERO or SAMP
353 * @param env
354 * @param nSampleVariables
355 */
356static int countSampleVariables(JNIEnv* env, long* nSampleVariables) {
357 REF_DECLARE;
358 long allVars;
359 *nSampleVariables = 0;
360 vmsstat_t status = CRR_GET_NVAR(&allVars);
361 if (!SUCCESS(status)) {
362 aidaThrow(env, status, UNABLE_TO_GET_DATA_EXCEPTION, "unable to get number of vars");
363 return EXIT_FAILURE;
364 }
365
366 // Loop over all variables discarding all that are ZERO
367 for (long varNum = 1; varNum < allVars; varNum++) {
368 long prim, micr, unit, secn, secn2, elem2;
369 status = CRR_GET_VAR_NAME(REFINT4_1(DEFINE_SAMPLE), &varNum, &prim, &micr, &unit, &secn, &secn2, &elem2);
370 if (!SUCCESS(status)) {
371 aidaThrow(env, status, UNABLE_TO_GET_DATA_EXCEPTION, "unable to get var name");
372 return EXIT_FAILURE;
373 }
374
375 if (prim != ZERO_SV) {
376 (*nSampleVariables)++;
377 }
378 }
379
380 return EXIT_SUCCESS;
381}
382
383/**
384 * Add the provided samples to the given table and create the fields, and labels as well
385 *
386 * @param env to be used to throw exceptions using aidaThrow() and aidaThrowNonOsException()
387 * @param table given table
388 * @param totalSampleVariables the total number of samples for which the scan was done
389 * @param nSteps the number of steps over which the plot was executed
390 * @param primaryStepVariable the name of the primary step variable
391 * @param secondaryStepVariableProvided true if a secondary step variable was provided
392 * @param secondaryStepVariable the secondary step variable
393 * @param sampleDescriptors the sample descriptors in for of longs representing PRIM, MICRO, UNIT, SECN
394 * @param samples array of sample values organised as vectors
395 */
396static void createCorrelationPlotTable(JNIEnv* env, Table* table, int totalSampleVariables, int nSteps,
397 char* primaryStepVariable, bool secondaryStepVariableProvided, char* secondaryStepVariable,
398 float* samples, long* samplesOk) {
399 REF_DECLARE;
400 char name[MAX_URI_LEN];
401 char sampleFieldName[MAX_URI_LEN + 1], sampleLabelName[MAX_URI_LEN + 1];
402
403 char* tableFieldName, * tableLabelName;
404 int secondaryAdjust = (secondaryStepVariableProvided ? 1 : 0);
405 vmsstat_t status;
406 int samplesAdded = 0;
407 for (long varNum = -secondaryAdjust; samplesAdded < totalSampleVariables; varNum++) {
408 bool isTime = false, isATime = false, isSamp = false;
409 long prim, micr, unit, secn, secn2, elem2;
410 status = CRR_GET_VAR_NAME(REFINT4_1(DEFINE_SAMPLE), &varNum, &prim, &micr, &unit, &secn, &secn2, &elem2);
411 isTime = prim == TIME_SV;
412 isATime = prim == ATIME_SV;
413 isSamp = prim == SAMP_SV;
414
415 if (varNum == 0) { // Primary step variable
416 tableFieldName = "primary";
417 tableLabelName = primaryStepVariable;
418 } else if (varNum == -1) {
419 tableFieldName = "secondary";
420 tableLabelName = secondaryStepVariable;
421 } else {
422 if (!SUCCESS(status)) {
423 aidaThrow(env, status, UNABLE_TO_GET_DATA_EXCEPTION, "unable to get var name");
424 return;
425 }
426
427 if (prim == ZERO_SV) {
428 continue;
429 }
430
431 sprintf(sampleFieldName, "sample%ld", varNum);
432 tableFieldName = sampleFieldName;
433
434 unsigned long rawName[AP_DESCSIZE];
435 CRR_GET_VAR_DEF(REFINT4_1(DEFINE_SAMPLE), &varNum, (long*)&rawName[0]);
436 char part[10];
437// struct dsc$descriptor desc = AP_DEV_TO_STR(&rawName[0]);
438// tableLabelName = desc.dsc$a_pointer;
439// sprintf(sampleLabelName, "sample%ld", varNum);
440 sprintf(sampleLabelName, "%.4s", (char*)&rawName[0]);
441 sprintf(part, "%.4s", (char*)&rawName[1]);
442 if (part[0] != '-') {
443 sprintf(sampleLabelName + strlen(sampleLabelName), ":%.4s", part);
444 sprintf(part, "%.4s", (char*)&rawName[2]);
445 if (part[0] != '-') {
446 sprintf(sampleLabelName + strlen(sampleLabelName), ":%.4s", part);
447 sprintf(part, "%.4s", (char*)&rawName[3]);
448 if (part[0] != '-') {
449 sprintf(sampleLabelName + strlen(sampleLabelName), ":%.4s", part);
450 sprintf(part, "%.4s", (char*)&rawName[4]);
451 if (part[0] != '-') {
452 sprintf(sampleLabelName + strlen(sampleLabelName), " %.4s", part);
453 }
454 }
455 }
456 }
457 tableLabelName = sampleLabelName;
458 }
459
460 // Get sample var data
461 long dataOffset = table->_currentColumn * nSteps;
462 long errorOffset = dataOffset + nSteps;
463 if (isTime || isATime || isSamp) {
464 status = CRR_GET_VAR(&varNum, &samples[dataOffset], NULL, NULL, NULL);
465 } else {
466 status = CRR_GET_VAR(&varNum, &samples[dataOffset], &samples[errorOffset], &samplesOk[dataOffset], NULL);
467 }
468 if (!SUCCESS(status)) {
469 aidaThrow(env, status, UNABLE_TO_GET_DATA_EXCEPTION, "unable to get sample data");
470 return;
471 }
472
473 // Data column
474 if (isTime || isATime) {
475 tableAddColumn(env, table, AIDA_LONG_TYPE, &samples[dataOffset], false);
476 } else if (isSamp) {
477 tableAddColumn(env, table, AIDA_LONG_TYPE, &samples[dataOffset], false);
478 } else {
479 tableAddColumn(env, table, AIDA_FLOAT_TYPE, &samples[dataOffset], true);
480 }
482 tableAddField(env, table, tableFieldName);
484 tableAddLabel(env, table, tableLabelName);
486
487 if (isTime || isATime || isSamp) {
488 table->columnCount -= 2;
489 } else {
490 // Error column
491 tableAddColumn(env, table, AIDA_FLOAT_TYPE, &samples[errorOffset], true);
493 sprintf(name, "%sError", tableFieldName);
494 tableAddField(env, table, name);
496 sprintf(name, "%s Error", tableLabelName);
497 tableAddLabel(env, table, name);
499
500 // Data OK column
501 tableAddColumn(env, table, AIDA_LONG_TYPE, &samplesOk[dataOffset], false);
503 sprintf(name, "%sOk", tableFieldName);
504 tableAddField(env, table, name);
506 sprintf(name, "%s Ok?", tableLabelName);
507 tableAddLabel(env, table, name);
509 }
510
511 samplesAdded++;
512 }
513}
514
515/**
516 * Get the user parameters required for the correlation plot functionality
517 *
518 * @param env to be used to throw exceptions using aidaThrow() and aidaThrowNonOsException()
519 * @param arguments the provided user arguments
520 * @param buttonFileName pointer to store pointer to allocated button file name
521 * @param primaryStepVariable pointer to store the allocated step variable name
522 * @param primaryLow pointer to store primary step variable starting point
523 * @param primaryHigh pointer to store primary step variable end point
524 * @param primarySteps pointer to store primary number of steps
525 * @param primarySettleTime pointer to store optional primary settle time
526 * @param secondaryStepVariable pointer to store optional secondary step variable name
527 * @param secondaryLow pointer to store optional secondary step variable starting point
528 * @param secondaryHigh pointer to store optional secondary step variable end point
529 * @param secondarySteps pointer to store optional secondary number of steps
530 * @param secondarySettleTime pointer to store optional secondary step variable settle time
531 * @return true if secondary step variable has been set
532 */
533static bool getAcqParameters(JNIEnv* env, Arguments arguments, char** buttonFileName,
534 char** primaryStepVariable, float* primaryLow, float* primaryHigh, int* primarySteps, float* primarySettleTime,
535 float* primaryExtraSettleTime,
536 char** secondaryStepVariable, float* secondaryLow, float* secondaryHigh, int* secondarySteps,
537 float* secondarySettleTime, float* secondaryExtraSettleTime, short* bpmd, long* nrpos, long* dtizavg,
538 char** magnetFunction) {
539 *primarySettleTime = 0.0f;
540
541 *secondaryStepVariable = NULL;
542 *secondaryLow = FLT_MAX;
543 *secondaryHigh = FLT_MAX;
544 *primaryExtraSettleTime = 0.0f;
545 *secondaryExtraSettleTime = 0.0f;
546 *secondarySteps = -1;
547 *secondarySettleTime = 0.0f;
548
549 if (ascanf(env, &arguments, "%s %s %f %f %d %of %of %os %of %of %od %of %of %ohd %old %old %os",
550 "file", buttonFileName,
551
552 "primstv.name", primaryStepVariable,
553 "primstv.low", primaryLow,
554 "primstv.high", primaryHigh,
555 "primstv.steps", primarySteps,
556 "primstv.settle", primarySettleTime,
557 "primstv.extrasettle", primaryExtraSettleTime,
558
559 "secnstv.name", secondaryStepVariable,
560 "secnstv.low", secondaryLow,
561 "secnstv.high", secondaryHigh,
562 "secnstv.steps", secondarySteps,
563 "secnstv.settle", secondarySettleTime,
564 "secnstv.extrasettle", secondaryExtraSettleTime,
565
566 "bpmd", bpmd,
567 "nrpos", nrpos,
568 "dtizavg", dtizavg,
569 "magfunc", magnetFunction
570
571 )) {
572 return false;
573 }
574 bool allSecSet =
575 *secondaryStepVariable && *secondaryLow != FLT_MAX && *secondaryHigh != FLT_MAX && *secondarySteps != -1;
576 bool noSecSet =
577 !*secondaryStepVariable && *secondaryLow == FLT_MAX && *secondaryHigh == FLT_MAX && *secondarySteps == -1;
578
579 // All fields must be specified for the secondary or none of them
580 if (!allSecSet && !noSecSet) {
582 "You have to specify name, low, high and step for the secondary step variable. You missed at least one");
583 return false;
584 }
585
586 if (*primarySteps < 2 || (allSecSet && *secondarySteps < 2)) {
587 aidaThrowNonOsException(env, UNABLE_TO_GET_DATA_EXCEPTION, "Steps must be at least 2");
588 }
589 return allSecSet;
590}
591
592/**
593 * Set a value: BGRP Set Variable or SCP transverse feedback
594 *
595 * @param env to be used to throw exceptions using aidaThrow() and aidaThrowNonOsException()
596 * @param uri the uri
597 * @param arguments the arguments
598 * @param value to set
599 */
600void aidaSetValue(JNIEnv* env, const char* uri, Arguments arguments, Value value) {
601 if (startsWith(uri, "FBCK")) {
602 setFeedback(env, uri, arguments, value);
603 } else {
604 setBGrp(env, arguments, value);
605 }
606}
607
608/**
609 * Set a value and return a table as a response
610 *
611 * @param env to be used to throw exceptions using aidaThrow() and aidaThrowNonOsException()
612 * @param uri the uri
613 * @param arguments the arguments
614 * @param value to set
615 * @return a table
616 */
617Table aidaSetValueWithResponse(JNIEnv* env, const char* uri, Arguments arguments, Value value) {
618 if (strcasecmp(uri, "MKB:VAL") == 0) {
619 // set Multi Knob value
620 return setMkbValue(env, uri, arguments, value);
621 } else {
622 // set TRIGGER value
623 return setTriggerValue(env, uri, arguments, value);
624 }
625}
626
627/**
628 * Set a value: BGRP Set Variable
629 * Parameters:
630 * BGRP : The BGRP name
631 * VARNAME : BGRP variable name for the specified BGRP
632 *
633 * @param env to be used to throw exceptions using aidaThrow() and aidaThrowNonOsException()
634 * @param uri the uri
635 * @param arguments the arguments
636 * @param value to set
637 */
638static void setBGrp(JNIEnv* env, Arguments arguments, Value value) {
640
641 vmsstat_t status;
642 char* bgrp, * varname, * valueString;
643
644 // Check if operations are enabled?
645 if (!DPSLCUTIL_BGRP_ACCESSENABLED()) {
647 "Aida access to BGRP set variable operations is not currently enabled");
648 return;
649 }
650
651 if (avscanf(env, &arguments, &value, "%s %s %s",
652 "value", &valueString,
653 "bgrp", &bgrp,
654 "varname", &varname
655 )) {
656 return;
657 }
658
659 TRACK_MEMORY(bgrp)
660 TRACK_MEMORY(varname)
661 TRACK_MEMORY(valueString)
662
663 if (strcasecmp(valueString, "Y") != 0 && strcasecmp(valueString, "N") != 0) {
666 "'BGRP Set Variable requires Value argument to be 'Y' or 'N'");
667 return;
668 }
669
670 // Set the value
671 status = DPSLCUTIL_BGRP_SETVAR(bgrp, varname, valueString);
673 if (!SUCCESS(status)) {
674 aidaThrow(env, status, UNABLE_TO_SET_DATA_EXCEPTION, "Failed to set data");
675 }
676}
677
678/**
679 * Set Multi-knob value
680 *
681 * @param env
682 * @param uri
683 * @param arguments
684 * @param value
685 * @return
686 */
687static Table setMkbValue(JNIEnv* env, const char* uri, Arguments arguments, Value value) {
689
690 // Check if operations are enabled?
691 if (!DPSLCUTIL_MKB_ACCESSENABLED()) {
693 "Aida multiknob operations are not currently enabled");
695 }
696
697 // Get arguments
698 char* mkb;
699 float floatValue;
700 if (avscanf(env, &arguments, &value, "%f %s",
701 "value", &floatValue,
702 "mkb", &mkb
703 )) {
705 }
706 TRACK_MEMORY(mkb)
707 CONVERT_TO_VMS_FLOAT(&floatValue, 1)
708
709 // Set the value
710 int num_devices;
711 vmsstat_t status;
712 status = DPSLCUTIL_DO_MKB(mkb, &floatValue, &num_devices);
714 if (!SUCCESS(status)) {
715 aidaThrow(env, status, UNABLE_TO_SET_DATA_EXCEPTION, "unable to set value");
716 DPSLCUTIL_MKB_GETCLEANUP();
718 }
719
720 if (DPSLCUTIL_MKB_GETABSFLAG()) {
722 "Specified multiknob file is absolute, which is not permitted");
723 DPSLCUTIL_MKB_GETCLEANUP();
725 }
726
727 // Now get the new values to return
728
729 // To hold the data
730 char namesData[(num_devices * MAX_DEVICE_STRING_LEN)];
731 float secondaryValuesData[num_devices];
732
733 // Names
734 DPSLCUTIL_MKB_GETNAMES(namesData);
735
736 // Secondary values
737 DPSLCUTIL_MKB_GETSECNVALUES(secondaryValuesData);
738
739 // cleanup
740 DPSLCUTIL_MKB_GETCLEANUP();
741
742 // Now create table to return
743 Table table = tableCreate(env, num_devices, 2);
745 tableAddFixedWidthStringColumn(env, &table, namesData, MAX_DEVICE_STRING_LEN);
747 tableAddColumn(env, &table, AIDA_FLOAT_TYPE, secondaryValuesData, false);
748
749 return table;
750}
751
752/**
753 * Set Trigger value
754 *
755 * @param env
756 * @param uri
757 * @param arguments
758 * @param value
759 * @return
760 */
761static Table setTriggerValue(JNIEnv* env, const char* uri, Arguments arguments, Value value) {
762 // Check if operations are enabled?
763 if (!DPSLCUTIL_TRIG_ACCESSENABLED()) {
765 "Aida access to trigger operations is not currently enabled");
767 }
768
769 // Get arguments
770 int beam;
771 short flag;
772 if (avscanf(env, &arguments, &value, "%hd %d",
773 "value", &flag,
774 "beam", &beam
775 )) {
777 }
778
779 // Set the trigger value
780 vmsstat_t status;
781 TO_DGROUP(dGroupName, uri)
782 status = DPSLCUTIL_TRIG_SETDEACTORREACT(dGroupName, flag, beam);
783 if (!SUCCESS(status)) {
784 aidaThrow(env, status, UNABLE_TO_SET_DATA_EXCEPTION, "unable to set value");
786 }
787
788 // Read back status
789 status = DPSLCUTIL_TRIG_GETSTATUS(dGroupName, beam, &flag);
790 if (!SUCCESS(status)) {
791 aidaThrow(env, status, UNABLE_TO_SET_DATA_EXCEPTION, "unable to read-back value");
793 }
794
795 // Now create table to return the flag
796 Table table = tableCreate(env, 1, 1);
798 tableAddSingleRowShortColumn(env, &table, flag);
799
800 return table;
801}
802
803/**
804 * Read the trig status and return the value
805 *
806 * @param env to report errors
807 * @param uri the uri
808 * @param arguments the arguments
809 * @return the beam status
810 */
811static short getTrigStatus(JNIEnv* env, const char* uri, Arguments arguments) {
812 // Get the arguments
813 int beam;
814
815 if (ascanf(env, &arguments, "%d", "beam", &beam)) {
816 return -1;
817 }
818
819 // Read the status
820 vmsstat_t status;
821 short trig_status;
822 TO_DGROUP(dGroupName, uri)
823 status = DPSLCUTIL_TRIG_GETSTATUS((char*)dGroupName, beam, &trig_status);
824 if (!SUCCESS(status)) {
825 aidaThrow(env, status, UNABLE_TO_GET_DATA_EXCEPTION, "Unable to get beam status");
826 }
827 return trig_status;
828}
829
830/**
831 * Get feedback status as an integer
832 * @param env to report errors
833 * @param uri the uri
834 * @return 0 = off, 1 = compute, 2 = feedback
835 */
836static short getShortFaStatus(JNIEnv* env, const char* uri) {
837 int4u haStatus = faStatus(env, uri, 0, TRUE_B);
839 switch (haStatus) {
840 case FBCK_FEEDBACK_STATE:
841 return 2;
842 case FBCK_COMPUTE_STATE:
843 return 1;
844 case FBCK_OFF_STATE:
845 case FBCK_SAMPLE_STATE:
846 case FBCK_ACTUATE_STATE:
847 case FBCK_DITHER_STATE:
848 default:
849 return 0;
850 }
851}
852
853/**
854 * Get the feedback status as a string
855 *
856 * @param env to report errors
857 * @param uri the uri
858 * @return sample, compute, actuate, dither, feedback or off (default)
859 */
860static char* GetStringFaStatus(JNIEnv* env, const char* uri) {
861 int4u haStatus = faStatus(env, uri, 0, TRUE_B);
863 switch (haStatus) {
864 case FBCK_SAMPLE_STATE:
865 return ALLOCATE_STRING(env, "sample", "string");
866 case FBCK_COMPUTE_STATE:
867 return ALLOCATE_STRING(env, "compute", "string");
868 case FBCK_ACTUATE_STATE:
869 return ALLOCATE_STRING(env, "actuate", "string");
870 case FBCK_DITHER_STATE:
871 return ALLOCATE_STRING(env, "dither", "string");
872 case FBCK_FEEDBACK_STATE:
873 return ALLOCATE_STRING(env, "feedback", "string");
874 case FBCK_OFF_STATE:
875 default:
876 return ALLOCATE_STRING(env, "off", "string");
877 }
878}
879
880/**
881 * Set SCP transverse feedback and return the prior setting
882 *
883 * @param env to report errors
884 * @param uri the uri
885 * @param newHSTA new value
886 * @param retrieveOnly don't set only retrieve prior setting if true
887 */
888static int4u faStatus(JNIEnv* env, const char* uri, int newHSTA, BOOLEAN retrieveOnly) {
889 // Get SCP transverse feedback name from uri
890 DESCR_DECLARE;
891 PMU_STRING_FROM_URI(pmu_str, uri)
892 vmsstat_t status;
893 fbckhsta_tu lastHsta;
894
895 // Change secondary to HSTA
896 printf("SLC NAME: %s", pmu_str);
897
898 // Change the Feedback state or throw an exception on failure
899 status = FA_CHANGE_HSTA(DESCRA1(pmu_str), newHSTA, retrieveOnly, &lastHsta.bit_s);
900 if (!SUCCESS(status)) {
901 if (retrieveOnly) {
902 aidaThrow(env, status, UNABLE_TO_GET_DATA_EXCEPTION, "unable to get feedback state");
903 } else {
904 aidaThrow(env, status, UNABLE_TO_SET_DATA_EXCEPTION, "unable to set feedback state");
905 }
906 return 0;
907 }
908 return lastHsta.lword;
909}
910
911/**
912 * Sets the specified SCP transverse feedback to off, sample, compute, on, actuate, dither, or feedback
913 *
914 * @param env to be used to throw exceptions using aidaThrow() and aidaThrowNonOsException()
915 * @param uri the uri containing the specified SCP transverse feedback to set
916 * @param arguments the arguments containing the value parameter
917 * @param value to set: `off`, `sample`, `compute`, `on`, `actuate`, `dither`, `feedback`, `true`, `false`, `0`, `1`, or `2`
918 */
919static void setFeedback(JNIEnv* env, const char* uri, Arguments arguments, Value value) {
920 char* valueString;
921 int newHSTA;
922
923 // Get value string
924 if (avscanf(env, &arguments, &value, "%s", "value", &valueString)) {
925 return;
926 }
927
928 // Convert value string to new state
929 if (strcasecmp(valueString, "OFF") == 0 || strcasecmp(valueString, "0") == 0
930 || strcasecmp(valueString, "false") == 0) {
931 newHSTA = FBCK_OFF_STATE;
932 } else if (strcasecmp(valueString, "SAMPLE") == 0) {
933 newHSTA = FBCK_SAMPLE_STATE;
934 } else if (strcasecmp(valueString, "ON") == 0 || strcasecmp(valueString, "1") == 0
935 || strcasecmp(valueString, "COMPUTE") == 0) {
936 newHSTA = FBCK_COMPUTE_STATE;
937 } else if (strcasecmp(valueString, "ACTUATE") == 0) {
938 newHSTA = FBCK_ACTUATE_STATE;
939 } else if (strcasecmp(valueString, "DITHER") == 0) {
940 newHSTA = FBCK_DITHER_STATE;
941 } else if (strcasecmp(valueString, "FEEDBACK") == 0 || strcasecmp(valueString, "2") == 0
942 || strcasecmp(valueString, "true") == 0) {
943 newHSTA = FBCK_FEEDBACK_STATE;
944 } else {
946 "Unsupported value for feedback control: Must be OFF, SAMPLE, COMPUTE, ON, ACTUATE, DITHER, or FEEDBACK");
947 return;
948 }
949 faStatus(env, uri, newHSTA, FALSE_B);
950}
951
Table aidaSetValueWithResponse(JNIEnv *env, const char *uri, Arguments arguments, Value value)
Set a value and return a table as a response.
void aidaSetValue(JNIEnv *env, const char *uri, Arguments arguments, Value value)
Set a value: BGRP Set Variable or SCP transverse feedback.
char * aidaRequestString(JNIEnv *env, const char *uri, Arguments arguments)
Get a string.
Table aidaRequestTable(JNIEnv *env, const char *uri, Arguments arguments)
Implement Correlated Plots.
int aidaRequestInteger(JNIEnv *env, const char *uri, Arguments arguments)
Get an integer.
REQUEST_STUB_BYTE REQUEST_STUB_FLOAT REQUEST_STUB_DOUBLE REQUEST_STUB_BOOLEAN_ARRAY REQUEST_STUB_BYTE_ARRAY REQUEST_STUB_SHORT_ARRAY REQUEST_STUB_INTEGER_ARRAY REQUEST_STUB_LONG_ARRAY REQUEST_STUB_FLOAT_ARRAY REQUEST_STUB_DOUBLE_ARRAY REQUEST_STUB_STRING_ARRAY void aidaServiceInit(JNIEnv *env)
Initialise the service.
short aidaRequestShort(JNIEnv *env, const char *uri, Arguments arguments)
Get a short.
int aidaRequestBoolean(JNIEnv *env, const char *uri, Arguments arguments)
Get a Boolean.
long aidaRequestLong(JNIEnv *env, const char *uri, Arguments arguments)
Get a integer.
The Header File for the AIDA-PVA Module functions.
#define REQUEST_STUB_BYTE
aidaRequestByte API Stub
Definition: aida_pva_api.h:259
#define VERSION(_version)
Use this macro to define the version of the provider.
Definition: aida_pva_api.h:40
#define REQUEST_STUB_LONG_ARRAY
aidaRequestLongArray API Stub
Definition: aida_pva_api.h:326
#define REQUEST_STUB_INTEGER_ARRAY
aidaRequestIntegerArray API Stub
Definition: aida_pva_api.h:321
#define REQUEST_STUB_DOUBLE
aidaRequestDouble API Stub
Definition: aida_pva_api.h:284
#define REQUEST_STUB_SHORT_ARRAY
aidaRequestShortArray API Stub
Definition: aida_pva_api.h:316
#define REQUEST_STUB_BYTE_ARRAY
aidaRequestByteArray API Stub
Definition: aida_pva_api.h:311
#define RETURN_NULL_TABLE
Return an empty table response.
Definition: aida_pva_api.h:380
#define REQUEST_STUB_FLOAT_ARRAY
aidaRequestFloatArray API Stub
Definition: aida_pva_api.h:331
#define REQUEST_STUB_DOUBLE_ARRAY
aidaRequestDoubleArray API Stub
Definition: aida_pva_api.h:336
#define REQUEST_STUB_BOOLEAN_ARRAY
aidaRequestBooleanArray API Stub
Definition: aida_pva_api.h:306
#define REQUEST_STUB_FLOAT
aidaRequestFloat API Stub
Definition: aida_pva_api.h:279
#define REQUEST_STUB_STRING_ARRAY
aidaRequestStringArray API stub
Definition: aida_pva_api.h:342
#define CONVERT_TO_VMS_FLOAT(_float, _count)
Convert in-place, floating point numbers from ieee to VMS format.
#define ON_EXCEPTION_RETURN_VOID
Check to see if an exception has been raised, and return void,.
#define SERVER_INITIALISATION_EXCEPTION
Use this string to signal Server Initialisation Exceptions in aidaThrow()
#define SPRINTF_ERROR_STATUS_FREE_MEMORY_AND_RETURN_(_status, _exception, _errorText, _ref, _r)
Format an error message, throw it in an exception, free any allocated memory and return the error cod...
#define UNABLE_TO_SET_DATA_EXCEPTION
Use this string to signal Exceptions when trying to Set Data in aidaThrow()
#define MISSING_REQUIRED_ARGUMENT_EXCEPTION
Use this string to signal Missing Required Argument Exceptions in aidaThrow()
#define ON_EXCEPTION_RETURN_(_r)
Check to see if an exception has been raised, and return the given return value.
#define SPRINTF_ERROR_FREE_MEMORY_AND_RETURN_(_exception, _errorText, _ref, _r)
Format an error message, throw it in an exception, free any allocated memory and return the error cod...
#define ON_EXCEPTION_FREE_MEMORY_AND_RETURN_(_r)
Check to see if an exception has been raised, then free tracked memory, and return the given return v...
#define UNABLE_TO_GET_DATA_EXCEPTION
Use this string to signal Exceptions when trying to Get Data in aidaThrow()
#define TRACK_ALLOCATED_MEMORY
Create tracking variables so that memory can be freed with FREE_MEMORY macro.
#define ALLOCATE_STRING(_env, _string, _purpose)
Allocate memory for a string and copy the given string into this allocated space.
#define FREE_MEMORY
Free any allocated memory.
#define ALLOCATE_AND_TRACK_MEMORY_AND_ON_ERROR_RETURN_(_env, _var, _size, _purpose, _r)
Allocate memory and add it to the tracked memory list so that it can be freed automatically later.
#define TRACK_MEMORY(_ptr)
Register this newly allocated memory so that it will be freed by FREE_MEMORY.
int startsWith(const char *str, char *prefix)
Check if a string starts with another string.
void aidaThrow(JNIEnv *env, vmsstat_t status, char *exception, const char *message)
To log any exceptions and throw back to java.
vmsstat_t init(const char *processName, bool initMessageServices)
Call standalone_init()
void aidaThrowNonOsException(JNIEnv *env, char *exception, const char *message)
To log any non-OS exceptions and throw back to java.
@ AIDA_FLOAT_TYPE
Represents a float.
@ AIDA_LONG_TYPE
Represents a long.
void tableAddField(JNIEnv *env, Table *table, char *fieldName)
Add a dynamic field to a table.
void tableAddFixedWidthStringColumn(JNIEnv *env, Table *table, char *data, int width)
This reads data from an allocated space that is rows * width with each string occupying width charact...
int ascanf(JNIEnv *env, Arguments *arguments, const char *formatString,...)
ascanf(), avscanf()
Table tableCreate(JNIEnv *env, int rows, int columns)
Make a Table for return to client.
void tableAddLabel(JNIEnv *env, Table *table, char *labelName)
Add a dynamic column to a table.
void tableAddSingleRowShortColumn(JNIEnv *env, Table *table, short data)
Add a short column to a Table with only one row.
void tableAddColumn(JNIEnv *env, Table *table, Type type, void *data, bool ieeeFormat)
Add a column of arbitrary type to a Table.
int avscanf(JNIEnv *env, Arguments *arguments, Value *value, const char *formatString,...)
ascanf(), avscanf()
Table tableCreateDynamic(JNIEnv *env, int rows, int columns)
Make a Dynamic Table for return to client.
#define MAX_URI_LEN
The maximum length of a URI.
Definition: aida_pva_uri.h:20
#define PMU_STRING_FROM_URI(_var, _uri)
Get a PMU (Primary-Micro-Unit) string from the supplied URI.
Definition: aida_pva_uri.h:36
#define TO_DGROUP(_var, _uri)
Get a display group name from the provided uri and store it in the given variable name.
Definition: aida_pva_uri.h:69
An Arguments structure stores all of the arguments passed from the request to the Native Channel Prov...
Table structure.
int columnCount
number of columns in table
int _currentColumn
For internal use by addColumn() etc.
This special type represents a Value.