#ifndef epicsPV_h #define epicsPV_h #include #include #include /* How epicsPVs work: * A PV is a container for a remote named value provided via a so * called EPICS "channel". It is "linked" to the channel in PVcreate() * or later with PVlink(). * Because the original value is remote, the PV can only contain * a copy of the value. * With the caget() call, one or more PVs are updated from the remote value. * After that, the updated value can be read as long, double or string. * With the caput() call, the remote value is updated from the PV. */ #ifndef PV_DEFAULT_GET_TIMEOUT_SEC #define PV_DEFAULT_GET_TIMEOUT_SEC 2.0 #endif #ifndef PV_DEFAULT_PUT_TIMEOUT_SEC #define PV_DEFAULT_PUT_TIMEOUT_SEC 10.0 #endif typedef struct epicsPV_s* epicsPV; typedef void (*PVconnectionCallback) (epicsPV pv, int connectionUp, void* userarg); /* Channel Access datatypes (plus caTypeNative as default value) * depending on the datatype of a PV, exporting the value * to double, long or const char* may give different results */ typedef enum { caTypeString, caTypeShort, caTypeFloat, caTypeEnum, caTypeChar, caTypeLong, caTypeDouble, caTypeNoAccess, caTypeNative } caDatatype; /* You don't need to access anything in epicsPV_priv.h directly */ #include "epicsPV_priv.h" /* create PV and optionally link it to an EPICS channel * normally, you call createPV with channelName but without * preferredDatatype to use the native datatype of the channel * you may read back datatype after connection * if channelName is NULL you must call PVlink later * a callback can be installed to track connection state changes * connectionUp is 1 when the PV connected, 0 when it disconnected * userarg is an arbitrary pointer that will be provided with the callback */ #define PVcreate(channelName) PVcreateWithTypeAndCallback(channelName, caTypeNative, NULL, NULL) #define PVcreateWithType(channelName, type) PVcreateWithTypeAndCallback(channelName, type, NULL, NULL) #define PVcreateWithCallback(channelName, cb, userarg) PVcreateWithTypeAndCallback(name, caTypeNative, cb, userarg) epicsPV PVcreateWithTypeAndCallback(const char* channelName, caDatatype preferredDatatype, PVconnectionCallback cb, void* userarg); /* destroy PV and free all resources */ void PVdestroy(epicsPV pv); /* explititely (re-)link PV to a (different) EPICS channel * an unlink PV from a channel * it is normally done implicitely by PVcreate and PVdestroy * note: linking does not yet send a search request to the * network until PVwaitForConnect is called (probably implicitely by caget, caput, camonitor) */ #define linkPV(pv, channelName)linkPVwithType(pv, channelName, caTypeNative) int PVlinkWithType(epicsPV pv, const char* channelName, caDatatype preferredDatatype); void PVunlink(epicsPV pv); /* wait until one or all PVs are connected * timeoutSec = 0.0 just sends connect requests but does not wait * timeoutSec < 0.0 means wait forever * returns remaining seconds * calling this function is optional because it will be called * implicitely before the first get or put on an unconnected PV * using the get or put timeout */ double PVwaitForConnect(epicsPV pv, double timeoutSec); #define PVwaitForConnectAll(timeoutSec) PVwaitForConnect(NULL, timeoutSec) /* return channel name (what you provided to PVlink or PVcreate) */ #define PVname(pv) ((pv)->channel?ca_name((pv)->channel):"") /* return error status of PV * see $(EPICS_BASE)/include/caerr.h for error codes */ #define PVerrorStatus(pv) ((pv)->status) #define PVerrorStatusString(pv) (ca_message((pv)->status)) /* return connection state * see $(EPICS_BASE)/include/cadef.h for valid values */ #define PVconnectionState(pv) ((pv)->channel?ca_state((pv)->channel):cs_never_conn) #define PVconnectionStateString(pv) PVconnectionStateStrings[PVconnectionState(pv)] /* The following functions return information which is available * as soon as the PV is connected. */ /* return currently used data type */ #define PVdatatype(pv) ((pv)->usedDatatype) #define PVdatatypeString(pv) PVdataTypeStrings[PVdatatype(pv)] /* return number of elements for array data */ #define PVnumberOfElements(pv) ((pv)->channel?ca_element_count((pv)->channel):0) /* return units and precision (.EGU and .PREC fields) * if PV does not have units or precision it returns "" and/or 0 */ #define PVunits(pv) ((pv)->units) #define PVprecision(pv) ((pv)->precision) /* return access rights (might change at run-time) */ #define PVhasReadAccess(pv) ((pv)->channel?ca_read_access((pv)->channel):0) #define PVhasWriteAccess(pv) ((pv)->channel?ca_write_access((pv)->channel):0) /* get value from remote server * do caget with as many PVs as possible in parallel to increase performance */ #define caget(pvs...) cagetList(PV_DEFAULT_GET_TIMEOUT_SEC, pvs, NULL) #define cagetWithTimeout(timeoutSec, pvs...) cagetList(timeoutSec, pvs, NULL) /* The following functions return information which is available * after a successful get() or a monitor. */ /* return alarm severity and status (.SEVR and .STAT fields) * see $(EPICS_BASE)/include/alarm.h for valid values * not conencted PV returns epicsSevInvalid/epicsAlarmNone */ #define PValarmSeverity(pv) ((pv)->STRING?(pv)->STRING->severity:epicsSevInvalid) #define PValarmSeverityString(pv) epicsAlarmSeverityStrings[PValarmSeverity(pv)] #define PValarmStatus(pv) ((pv)->STRING?(pv)->STRING->status:epicsAlarmUDF) #define PValarmStatusString(pv) epicsAlarmConditionStrings[PValarmStatus(pv)] /* return time of record processing (.TIME field) as (epicsTimeStamp*) * see $(EPICS_BASE)/include/epicsTime.h for epicsTimeStamp */ extern epicsTimeStamp PVinvalidTimestamp; #define PVtimestamp(pv) &((pv)->STRING?(pv)->STRING->stamp:PVinvalidTimestamp) /* return value of pv as long double or string * for arrays use PVto*Element to access each element */ long PVtoLongElement(epicsPV pv, unsigned long index); #define PVtoLong(pv) PVtoLongElement(pv,0) double PVtoDoubleElement(epicsPV pv, unsigned long index); #define PVtoDouble(pv) PVtoDoubleElement(pv,0) /* flags for toString() */ const char* PVtoStringElement(epicsPV pv, int flags, unsigned long index); #define PVtoStringWithUnits(pv) PVtoStringElement(pv,PV_WITHUNITS,0) #define PVtoString(pv) PVtoStringElement(pv,0,0) #define caputDouble(pv1, value1...) caputDoubleList(0.0, pv1, value1) #define caputWaitDouble(timeoutSec, pv1, val1, ...) caputDoubleList(timeoutSec, pv1, value1) int caputDoubleList(double timeoutSec, int flags, epicsPV pv1, double val1, ...); #define caputLong(pv1, val1, ...) #define caputString(pv1, val1, ...) #endif