aioca API#
Common Notes#
All four functions take an argument pv which can specify the name of a
single PV or can be a list of PVs. In all cases the returned result has the
same “shape” as the pv argument, in other words, if pv is a single
string then a single value (error code, value, or subscription) is returned, and
if pv is a list then a list of exactly the same length is returned.
In general there are advantages to calling caput, caget or connect on a
list of PVs, as in this case the channel connection and access delays will occur
in parallel.
Several arguments are common through this API: throw determines how errors are
handled, timeout determines timeouts, and finally datatype, format and
count determine data formats and are documented in Augmented Values.
timeoutThe
timeoutargument specified how longcaputorcagetwill wait for the entire operation to complete. This timeout is in seconds, and can be one of several formats: a timeout interval in seconds, an absolute deadline (intime.timeformat) as a single element tuple, or None to specify that no timeout will occur. Note that a timeout of 0 will timeout immediately if any waiting is required.If a timeout occurs then a
CANothingwill be raised unlessthrow=Falsehas been set.throwThis parameter determines the behaviour of
caget,caput, andconnectwhen an error occurs. Ifthrow=True(the default) is set then an exception is raised, otherwise ifFalseis specified an error code value is returned for each failing PV.
Functions#
- async aioca.caput(pv: str, value, datatype: Datatype = None, wait: bool = False, timeout: Timeout = 5.0, throw: bool = True) CANothing[source]#
- async aioca.caput(pvs: List[str] | Tuple[str, ...], values, repeat_value: bool = ..., datatype: Datatype = None, wait: bool = False, timeout: Timeout = 5.0, throw: bool = True) List[CANothing]
Writes values to one or more PVs
If a list of PVs is given, then normally value will have the same length and value[i] is written to pv[i]. If value is a scalar or repeat_value=True then the same value is written to all PVs.
- Parameters:
repeat_value – If True and a list of PVs is given, write the same value to every PV.
datatype – Override
Datatypeto a non-native typewait – Do a caput with callback, waiting for completion
timeout – After how long should a caput with wait=True
Timeoutthrow – If False then return
CANothinginstead of raising an exception
- Returns:
The return value from caput is either a list or a single value,
depending on the shape of pv. For each PV a CANothing success
code is returned on success, otherwise either an exception is raised or an
appropriate error code is returned for each failing PV if throw=True is
set. The return code can be tested for boolean success, so for example it
is possible to write:
if not caput(pv, value, throw=False):
# process caput error
If all the PVs listed in pv have already been connected, through a
successful call to any aioca method, then the library guarantees
that the puts for each PV will occur strictly in sequence. For any PVs
which need a connection to be established the order of execution of puts
is completely undefined.
- async aioca.caget(pv: str, datatype: Datatype = None, format: Format = 0, count: Count = 0, timeout: Timeout = 5.0, throw: bool = True) AugmentedValue[source]#
- async aioca.caget(pvs: List[str] | Tuple[str, ...], datatype: Datatype = None, format: Format = 0, count: Count = 0, timeout: Timeout = 5.0, throw: bool = True) List[AugmentedValue]
Retrieves an
AugmentedValuefrom one or more PVs.- Parameters:
- Returns:
AugmentedValuefor single PV or [AugmentedValue] for a list of PVs
The various arguments control the behaviour of caget as follows:
datatype,format,countSee documentation for Augmented Values below.
timeout,throwDocumented in Common Notes above. If a value cannot be retrieved and
throw=Falseis set then for each failing PV an empty value with.ok==Falseis returned.
The format of values returned depends on the number of values requested for each PV. If only one value is requested then the value is returned as a scalar, otherwise as a numpy array.
- aioca.camonitor(pv: str, callback: Callable[[Any], None | Awaitable], events: Dbe = None, datatype: Datatype = None, format: Format = 0, count: Count = 0, all_updates: bool = False, notify_disconnect: bool = False, connect_timeout: Timeout = None) Subscription[source]#
- aioca.camonitor(pv: List[str] | Tuple[str, ...], callback: Callable[[Any, int], None | Awaitable], events: Dbe = None, datatype: Datatype = None, format: Format = 0, count: Count = 0, all_updates: bool = False, notify_disconnect: bool = False, connect_timeout: Timeout = None) List[Subscription]
Create a subscription to one or more PVs
- Parameters:
callback – Regular function or async function
events – Bit-wise or of
Dbetypes to notify about. If not given the default mask depends on the requested formatdatatype – Override
Datatypeto a non-native typeformat – Request extra
Formatfieldscount – Request a specific element
Countin an arrayall_updates – If True then every update received from channel access will trigger a callback, otherwise any updates received during the previous callback will be merged into the most recent value, incrementing
Subscription.dropped_callbacksnotify_disconnect – If True then IOC disconnect events will be reported by calling the callback with a
CANothingerror with .ok False, otherwise only valid values will be passed to the callback routineconnect_timeout – If specified then the camonitor will report a disconnection event after the specified interval if connection has not completed by this time. Note that this notification will be made even if notify_disconnect is False, and that if the PV subsequently connects it will update as normal.
- Returns:
Subscriptionfor single PV or [Subscription] for a list of PVs
For a single pv callbacks will be called as:
callback(value)
for each update where value is an AugmentedValue. For a list of pvs then
each update is called as:
callback(value, index)
where index is the position in the original array of pvs of the name generating this update.
If an async function as passed as a callback, then it will be awaited and no
further callbacks will be run for this particular Subscription until this
completes. This can be useful in conjunction with the default
all_updates=False for running periodic updating code like:
async def about_once_a_second(value):
do_something_with(value)
await asyncio.sleep(1)
camonitor(pv, callback=about_once_a_second)
Note
If you have the choice between sync and async functions (like
asyncio.Queue.put_nowait vs asyncio.Queue.put on an unbounded Queue)
then choose the sync option for better performance
Subscriptions will remain active until the close() method
is called on the returned subscription object:
- class aioca.Subscription[source]#
A Subscription object wraps a single channel access subscription, and notifies all updates through an event queue.
- async aioca.connect(pv: str, wait: bool = True, timeout: Timeout = 5.0, throw: bool = True) CANothing[source]#
- async aioca.connect(pv: List[str] | Tuple[str, ...], wait: bool = True, timeout: Timeout = 5.0, throw: bool = True) List[CANothing]
Establishes a connection to one or more PVs
A single PV or a list of PVs can be given. This does not normally need to be called, as the ca…() routines will establish their own connections as required, but after a successful connection we can guarantee that caput(…, wait=False) will complete immediately without suspension.
This routine can safely be called repeatedly without any extra side effects.
- async aioca.cainfo(pv: str, wait: bool = True, timeout: Timeout = 5.0, throw: bool = True) CAInfo[source]#
- async aioca.cainfo(pv: List[str] | Tuple[str, ...], wait: bool = True, timeout: Timeout = 5.0, throw: bool = True) List[CAInfo]
Returns a
CAInfostructure for the given PVs.See the documentation for
connect()for details of arguments.
- class aioca.CAInfo[source]#
Object representing the information returned from
cainfo- state_strings = ['never connected', 'previously connected', 'connected', 'closed']#
Converts
stateinto a printable description of the connection state.
The str representation of this structure can be printed to
produce output similar to that produced by the cainfo command line
tool.
It is possible to test whether a channel has successfully connected without
provoking suspension by calling cainfo(pv, wait=False) and testing the
.state attribute of the result.
All of the above functions will make a connection to a channel which is cached for future calls. If you need to clear this cache (e.g. in tests) you can call:
- aioca.purge_channel_caches()#
Remove cached channel connections. This will close all subscriptions
All the async functions in the aioca interface can be run under the asyncio
event loop. A convenience function is provided to do this:
- aioca.run(coro, forever=False)[source]#
Convenience function that makes an event loop and runs the async function within it.
- Parameters:
forever – If True then run the event loop forever, otherwise return on completion of the coro
- aioca.get_channel_infos() List[ChannelInfo][source]#
Return information about all Channels
Working with Values#
There are two types of values returned by aioca functions:
Augmented Values and Error Code Values. The caput function only returns
an error code value (which may indicate success), while caget and
camonitor will normally return (or deliver) augmented values, but will
return (or deliver) an error code on failure.
The following fields are common to both types of value. This means that is is
always safe to test value.ok for a value returned by caget or
caput or delivered by camonitor.
okSet to
Trueif the data is good,Falseif there was an error. For augmented valuesokis always set toTrue.nameName of the pv.
Values and their Types#
The type of values returned by caget or delivered by camonitor
callbacks is determined by the requested datatype in the original caget
or camonitor call together with the underlying length of the requested
EPICS field.
If the underlying length (element_count) of the EPICS value is 1 then
the value will be returned as a Python scalar, and will be one of the three
basic scalar types (string, integer or floating point number), but wrapped as an
augmented type.
If on the other hand element_count is not 1 then the value is treated
as an array and is always returned as a numpy array, again wrapped as an
augmented type. Note that this means that even if caget(pv, count=1) is
used to fetch a value with one element, if the underlying PV is an array then
the result returned will be an array.
The table below enumerates the possibilities:
- class aioca.ca_str#
- class aioca.ca_int#
- class aioca.ca_float#
Scalar types derived from basic Python types.
- class aioca.ca_array#
Array type derived from
numpy.ndarray. The associateddtypewill be as close a fit to the underlying data as possible.
Error Code Values#
- class aioca.CANothing(name: str, errorcode=1)[source]#
This value is returned as a success or failure indicator from
caput, as a failure indicator fromcaget, and may be raised as an exception to report a data error on caget or caput with wait.
The following ECA error codes from epicscorelibs.ca.cadef are worth noting:
ECA_SUCCESSSuccess error code. In this case
.okisTrue. Returned by successfulcaputandconnectcalls.ECA_DISCONNChannel disconnected. This is used by
camonitorto report channel disconnect events.ECA_TIMEOUTChannel timed out. Reported if user specified timeout ocurred before completion and if
throw=Falsespecified.
Augmented Values#
Augmented values are normally Python or numpy values with extra fields:
the .ok and .name fields are already mentioned above, and
further extra fields will be present depending on format requested for the data.
As pointed out above, .ok is always True for valid data.
Four different types of augmented value are returned: strings, integers, floating point numbers or arrays, depending on the length of the data requested – an array is only used when the data length is >1.
In almost all circumstances an augmented value will behave exactly like a
normal value, but there are a few rare cases where differences in behaviour are
observed (these are mostly bugs). If this occurs the augumentation can be
stripped from an augmented value value by writing +value – this returns
the underlying value.
The type of augmented values is determined both by parameters passed to caget
and camonitor and by the underlying datatype. Both of these functions share
parameters datatype, format and count which can be used to control
the type of the data returned:
datatypeFor
cagetandcamonitorthis controls the format of the data that will be requested, while forcaputthe data will be coerced into the requested format.datatypecan be any of the following:None(the default). In this case the “native” datatype provided by the channel will be returned.A
Dbrvalue. See items 5 onwards for details of the special values.A python type compatible with any of the above values, such as
int,floatorstr. These correspond toDBR_LONG,DBR_DOUBLEandDBR_STRINGrespectively.Any
numpy.dtypecompatible with any of the above values.One of the special values
DBR_CHAR_STR,DBR_CHAR_UNICODE, orDBR_CHAR_BYTES. This is used to request a char array which is then converted to a Pythonstrorbytesstring on receipt. It is not sensible to specifycountwith this option. The optionsDBR_CHAR_BYTESandDBR_CHAR_UNICODEare meaningless and not supported forcaput.Note that if the PV name ends in
$anddatatypeis not specified thenDBR_CHAR_STRwill be used.The special value
DBR_ENUM_STR, only forcagetandcamonitor. In this case the “native” channel datatype is used unless the channel is an enumeration, in which case the corresponding string is returned.For
cagetandcamonitortwo further special values are supported. In both of these casesformatis ignored:- aioca.DBR_STSACK_STRING#
Returns the current value as a string together with extra fields
status,severity,ackt,acks.
- aioca.DBR_CLASS_NAME#
Returns the name of the “enclosing interface”, typically the record type, and typically the same as the EPICS
.RTYPfield.
For
caputalso two further values are supported:- aioca.DBR_PUT_ACKT#
- aioca.DBR_PUT_ACKS#
These are used for global alarm acknowledgement, where
DBR_PUT_ACKTconfigures whether alarms need to be acknowleged andDBR_PUT_ACKSacknowledges alarms of a particular severity.
formatThe
Formatcontrols how much auxilliary information will be returned with the retrieved data.countThe
Countdetermines how many elements to fetch for arrays
- class aioca.types.AugmentedValue(*args, **kwargs)[source]#
Protocol representing a value returned from
cagetorcamonitorThe value itself depends on the number of values requested for the PV. If only one value is requested then the value is returned as a scalar, otherwise as a numpy array.
The value will also be “augmented” with extra fields depending on the
FormatandDatatypeof the pv, and if the operation was successful.Every value has the
okandnamefields.If
okis False thenerrorcodeis set to the appropriate ECA error code and str(value) will return an appropriate error message.If
okis True thendatatypeandelement_countwill be present.If FORMAT_TIME is requested then
status,severity,timestampandraw_stampwill be presentIf FORMAT_CTRL is requested then
statusandseveritywill be present, along with otherDbrspecific fields:DBR_SHORT, DBR_CHAR, DBR_LONG will also have
units,upper_disp_limit,lower_disp_limit,upper_alarm_limit,lower_alarm_limit,upper_warning_limit,lower_warning_limit,upper_ctrl_limit,lower_ctrl_limitDBR_FLOAT, DBR_DOUBLE will have the DBR_LONG fiels together with a
precisionfieldDBR_ENUM will have
enumsDBR_STRING does not support FORMAT_CTRL, so FORMAT_TIME data is returned instead
- acks: int#
Used for global alarm acknowledgement. The highest alarm severity to acknowledge. If the current alarm severity is less then or equal to this value the alarm is acknowledged.
- ackt: int#
Used for global alarm acknowledgement. Do transient alarms have to be acknowledged? (0,1) means (no, yes).
- datetime: datetime#
This is a dynamic property which returns
timestampas adatetimevalue, taking local time into account
- element_count: int#
Number of elements in the underlying EPICS value. If this is not 1 then the value is treated as an array, otherwise up to this many elements may be present in the value.
- raw_stamp: Tuple[int, int]#
Record timestamp in raw format as provided by EPICS (but in the local Unix epoch, not the EPICS epoch). Is a tuple of the form
(secs, nsec)with integer seconds and nanosecond values, provided in case full ns timestamp precision is required.
- severity: int#
EPICS alarm severity, normally one of the values listed below.
0
No alarm
1
Alarm condition, minor severity
2
Alarm condition, major severity.
3
Invalid value.
- aioca.types.Count#
How many array elements to retrieve from the server. One of the following
0
Server and data dependent waveform length
-1
The full data length
+ve int
A maximum of this number of elements
- aioca.types.Datatype#
The format of the requested data can be one of the following
None (the default)
In this case the “native” datatype provided by the channel will be returned
A
DbrvalueTo request this type from the IOC
A python type
Compatible with any of the above values, such as int, float or str
A numpy dtype
Compatible with any of the above values
alias of
None|Literal[0, 1, 2, 3, 4, 5, 6, 35, 36, 37, 38, 996, 997, 998, 999] |Type
- aioca.types.Dbe#
A bitwise or of DBE event codes from epicscorelibs.ca.dbr
DBE_VALUE
Trigger an event when a significant change in the channel’s value occurs. Relies on the monitor deadband field on the server
DBE_LOG
Trigger an event when an archive significant change in the channel’s value occurs. Relies on the archiver monitor deadband field on the server
DBE_ALARM
Trigger an event when the alarm state changes
DBE_PROPERTY
Trigger an event when a property change (control limit, graphical limit, status string, enum string …) occurs.
If not specified then the default value depends on the requested
FormatFormat
Default value for events
FORMAT_RAW
DBE_VALUE
FORMAT_TIME
DBE_VALUE | DBE_ALARM
FORMAT_CTRL
DBE_VALUE | DBE_ALARM | DBE_PROPERTY
- aioca.types.Dbr#
A DBR request code from epicscorelibs.ca.dbr. One of
DBR_STRING
40 character strings
DBR_SHORT
16 bit signed
DBR_FLOAT
32 bit float
DBR_ENUM
16 bit unsigned
DBR_CHAR
8 bit unsigned
DBR_LONG
32 bit signed
DBR_DOUBLE
64 bit float
DBR_PUT_ACKT
Configure global alarm acknowledgement
DBR_PUT_ACKS
Acknowledge global alarm
DBR_STSACK_STRING
Returns status ack structure
DBR_CLASS_NAME
Returns record type (same as .RTYP)
DBR_ENUM_STR
Enums as strings, default otherwise
DBR_CHAR_BYTES
Long byte strings as char arrays
DBR_CHAR_UNICODE
Long unicode strings as char arrays
DBR_CHAR_STR
Long strings as char arrays
alias of
Literal[0, 1, 2, 3, 4, 5, 6, 35, 36, 37, 38, 996, 997, 998, 999]
- aioca.types.Format#
How much auxilliary information will be returned with the retrieved data. From epicscorelibs.ca.dbr, one of the following
FORMAT_RAW
The data is returned unaugmented except for the .name field
FORMAT_TIME
The data is augmented by the data timestamp together with .alarm .status and .severity fields.
FORMAT_CTRL
The data is augmented by channel access “control” fields. This set of fields depends on the underlying datatype
alias of
Literal[0, 1, 2]