Channel Access API¶
EPICS channel access (CA) is the communication protocol used to transfer information between EPICS servers and clients. Process variables (PV) are accessible though channel access. Interactions with EPICS PV include:
- Connect - create a connection between your application and a PV. This must be done before any other communication with the PV.
- Read - read data (and the meta info, limits, units, precision, statestrings) held in the PV.
- Write - write data to the PV.
- Monitor - notification when a PV’s value or alarm state changes.
- Close - close the connection to the PV.
ca
— Low level interface¶
This is a module to present the interface of low level channel access C library.
It has the same API as module caffi.ca
.
Data Types¶
Each PV has a native EPICS type. The native types are then converted to Python types.
This table also lists the EPICS request types. Users can request that the type of the read or write value be changed internally by EPICS. Typically this adds a time penalty and is not recommended.
Native Type | Request Type | C Type | Python Type |
---|---|---|---|
|
|
16bit short | Integer |
|
|
16bit short | Integer |
|
|
32bit int | Integer |
|
|
8bit char | Integer |
|
|
array of chars (max 40) | String |
|
|
16bit short | Integer |
|
|
32bit float | Float |
|
|
64bit double | Float |
The one area where type conversion is extremely useful is dealing with fields of type ca.DBF_ENUM
.
An ENUM value can only be one from a predefined list.
A list consists of a set of string values that correspond to the ENUM values (similar to the C enum type).
It is easier to remember the list in terms of the strings instead of the numbers corresponding to each string.
Error Code¶
Error codes defined in header caerr.h are supported.
Element Count¶
Each data field can contain one or more data elements. The number of data elements is referred to as the native element count for a field. The number of data elements written to or read from a data field with multiple elements is user controllable. All or some data elements can be read. When some data elements are accessed the access is always started at the first element. It is not possible to read part of the data and then read the rest of the data.
CaChannel
¶
CaChannel
module is a (relatively) high level interface to operate on channel access.
It provides almost one to one function map to the channel access C API.
So basic knowledge of channel access is assumed.
But it does make it pythonic in other ways, single CaChannel
object, flexible parameter input
and value return.
-
CaChannel.
USE_NUMPY
¶ If numpy support is enabled at compiling time and numpy package is available at runtime, numeric data types can be returned as numpy arrays when USE_NUMPY=True. This boosts performance on large size arrays (>1M elements).
Exception CaChannelException
¶
Class CaChannel
¶
-
class
CaChannel.
CaChannel
(pvName=None)[source]¶ CaChannel: A Python class with identical API as of caPython/CaChannel.
This class implements the methods to operate on channel access so that you can find their C library counterparts , http://www.aps.anl.gov/epics/base/R3-14/12-docs/CAref.html#Function. Therefore an understanding of C API helps much.
To get started easily, convenient methods are created for often used operations,
Operation Method connect searchw()
read getw()
write putw()
They have shorter names and default arguments. It is recommended to start with these methods. Study the other C alike methods when necessary.
>>> chan = CaChannel('catest') >>> chan.searchw() >>> chan.putw(12.5) >>> chan.getw() 12.5 >>> chan.searchw('cabo') >>> chan.putw('Done') >>> chan.getw(ca.DBR_STRING) 'Done'
Connect¶
CaChannel.
search
(pvName=None)[source]¶Attempt to establish a connection to a process variable.
Parameters: pvName (bytes, str) – process variable name Raises: CaChannelException – if error happens Note
All remote operation requests such as the above are accumulated (buffered) and not forwarded to the IOC until one of execution methods (
pend_io()
,poll()
,pend_event()
,flush_io()
) is called. This allows several requests to be efficiently sent over the network in one message.>>> chan = CaChannel() >>> chan.search('catest') >>> status = chan.pend_io() >>> chan.state() <ChannelState.CONN: 2>
CaChannel.
search_and_connect
(pvName, callback, *user_args)[source]¶Attempt to establish a connection to a process variable.
Parameters:
- pvName (bytes, str) – process variable name
- callback (callable) – function called when connection completes and connection status changes later on.
- user_args – user provided arguments that are passed to callback when it is invoked.
Raises: CaChannelException – if error happens
The user arguments are returned to the user in a tuple in the callback function. The order of the arguments is preserved.
Each Python callback function is required to have two arguments. The first argument is a tuple containing the results of the action. The second argument is a tuple containing any user arguments specified by user_args. If no arguments were specified then the tuple is empty.
Note
All remote operation requests such as the above are accumulated (buffered) and not forwarded to the IOC until one of execution methods (
pend_io()
,poll()
,pend_event()
,flush_io()
) is called. This allows several requests to be efficiently sent over the network in one message.>>> chan = CaChannel('catest') >>> def connCB(epicsArgs, _): ... chid = epicsArgs[0] ... connection_state = epicsArgs[1] ... if connection_state == ca.CA_OP_CONN_UP: ... print(ca.name(chid), "is connected") >>> chan.search_and_connect(None, connCB, chan) >>> status = chan.pend_event(3) # doctest: +SKIP catest is connected >>> chan.search_and_connect('cabo', connCB, chan) >>> status = chan.pend_event(3) # doctest: +SKIP cabo is connected >>> chan.clear_channel()
CaChannel.
searchw
(pvName=None)[source]¶Attempt to establish a connection to a process variable.
Parameters: pvName (str, None) – process variable name Raises: CaChannelException – if timeout or error happens Note
This method waits for connection to be established or fail with exception.
>>> chan = CaChannel('non-exist-channel') >>> chan.searchw() # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ... CaChannelException: User specified timeout on IO operation expired
CaChannel.
clear_channel
()[source]¶Close a channel created by one of the search functions.
Clearing a channel does not cause its connection handler to be called. Clearing a channel does remove any monitors registered for that channel. If the channel is currently connected then resources are freed only some time after this request is flushed out to the server.
Note
All remote operation requests such as the above are accumulated (buffered) and not forwarded to the IOC until one of execution methods (
pend_io()
,poll()
,pend_event()
,flush_io()
) is called. This allows several requests to be efficiently sent over the network in one message.
CaChannel.
change_connection_event
(callback, *user_args)[source]¶Change the connection callback function
Parameters:
- callback (callable) – function called when connection completes and connection status changes later on. The previous connection callback will be replaced. If an invalid callback is given, no connection callback will be used.
- user_args – user provided arguments that are passed to callback when it is invoked.
>>> chan = CaChannel('catest') >>> chan.search() # connect without callback >>> def connCB(epicsArgs, _): ... chid = epicsArgs[0] ... connection_state = epicsArgs[1] ... if connection_state == ca.CA_OP_CONN_UP: ... print(ca.name(chid), "is connected") >>> chan.change_connection_event(connCB) # install connection callback >>> status = chan.pend_event(3) # doctest: +SKIP catest is connected >>> chan.change_connection_event(None) # remove connection callback
Read¶
CaChannel.
array_get
(req_type=None, count=None, **keywords)[source]¶Read a value or array of values from a channel.
The new value is not available until a subsequent
pend_io()
returnsca.ECA_NORMAL
. Then it can be retrieved by a call togetValue()
.
Parameters:
- req_type (int, None) – database request type (
ca.DBR_XXXX
). Defaults to be the native data type.- count (int, None) – number of data values to read, Defaults to be the native count.
- keywords –
optional arguments assigned by keywords
keyword value use_numpy True if waveform should be returned as numpy array. Default CaChannel.USE_NUMPY
.Raises: CaChannelException – if error happens
Note
All remote operation requests such as the above are accumulated (buffered) and not forwarded to the IOC until one of execution methods (
pend_io()
,poll()
,pend_event()
,flush_io()
) is called. This allows several requests to be efficiently sent over the network in one message.See also
>>> chan = CaChannel('catest') >>> chan.searchw() >>> chan.putw(123) >>> chan.array_get() >>> chan.pend_io() >>> chan.getValue() 123.0
CaChannel.
getValue
()[source]¶Return the value(s) after
array_get()
has completed.
Returns: the value returned from the last array_get Return type: int, float, str, list, array, dict If the req_type was not a plain type, the returned value is of dict type. It contains the same keys as in
array_get_callback()
.See also
>>> chan = CaChannel('cabo') >>> chan.searchw() >>> chan.putw(1) >>> chan.array_get(req_type=ca.DBR_CTRL_ENUM) >>> chan.pend_io() >>> for k,v in sorted(chan.getValue().items()): ... if k in ['pv_severity', 'pv_status']: ... print(k, v.name) ... else: ... print(k, v) pv_nostrings 2 pv_severity Minor pv_statestrings ('Done', 'Busy') pv_status State pv_value 1
CaChannel.
array_get_callback
(req_type, count, callback, *user_args, **keywords)[source]¶Read a value or array of values from a channel and execute the user supplied callback after the get has completed.
Parameters:
- req_type (int, None) – database request type (
ca.DBR_XXXX
). Defaults to be the native data type.- count (int, None) – number of data values to read, Defaults to be the native count.
- callback (callable) – function called when the get is completed.
- user_args – user provided arguments that are passed to callback when it is invoked.
- keywords –
optional arguments assigned by keywords
keyword value use_numpy True if waveform should be returned as numpy array. Default CaChannel.USE_NUMPY
.Raises: CaChannelException – if error happens
Each Python callback function is required to have two arguments. The first argument is a dictionary containing the results of the action.
field type comment request type DBR_XXXX DBR_STS_XXXX DBR_TIME_XXXX DBR_GR_XXXX DBR_CTRL_XXXX chid int channels id number X X X X X type int database request type (ca.DBR_XXXX) X X X X X count int number of values to transfered X X X X X status int CA status return code (ca.ECA_XXXX) X X X X X pv_value PV value X X X X X pv_status int PV alarm status X X X X pv_severity int PV alarm severity X X X X pv_seconds int seconds part of timestamp X pv_nseconds int nanoseconds part of timestamp X pv_nostrings int ENUM PV’s number of states X X pv_statestrings string list ENUM PV’s states string X X pv_units string units X X pv_precision int precision X X pv_updislim float upper display limit X X pv_lodislim float lower display limit X X pv_upalarmlim float upper alarm limit X X pv_upwarnlim float upper warning limit X X pv_loalarmlim float lower alarm limit X X pv_lowarnlim float lower warning limit X X pv_upctrllim float upper control limit X pv_loctrllim float lower control limit X The second argument is a tuple containing any user arguments specified by user_args. If no arguments were specified then the tuple is empty.
Note
All remote operation requests such as the above are accumulated (buffered) and not forwarded to the IOC until one of execution methods (
pend_io()
,poll()
,pend_event()
,flush_io()
) is called. This allows several requests to be efficiently sent over the network in one message.>>> def getCB(epicsArgs, _): ... for item in sorted(epicsArgs.keys()): ... if item in ['pv_severity', 'pv_status']: ... print(item,epicsArgs[item].name) ... elif item.startswith('pv_'): ... print(item,epicsArgs[item]) >>> chan = CaChannel('catest') >>> chan.searchw() >>> chan.putw(145) >>> chan.array_get_callback(ca.DBR_CTRL_DOUBLE, 1, getCB) >>> status = chan.pend_event(1) pv_loalarmlim -20.0 pv_loctrllim 0.0 pv_lodislim -20.0 pv_lowarnlim -10.0 pv_precision 4 pv_severity Major pv_status HiHi pv_units mm pv_upalarmlim 20.0 pv_upctrllim 0.0 pv_updislim 20.0 pv_upwarnlim 10.0 pv_value 145.0 >>> chan = CaChannel('cabo') >>> chan.searchw() >>> chan.putw(0) >>> chan.array_get_callback(ca.DBR_CTRL_ENUM, 1, getCB) >>> status = chan.pend_event(1) pv_nostrings 2 pv_severity No pv_statestrings ('Done', 'Busy') pv_status No pv_value 0
CaChannel.
getw
(req_type=None, count=None, **keywords)[source]¶Read the value from a channel.
If the request type is omitted the data is returned to the user as the Python type corresponding to the native format. Multi-element data has all the elements returned as items in a list and must be accessed using a numerical type. Access using non-numerical types is restricted to the first element in the data field.
ca.DBF_ENUM
fields can be read usingca.DBR_ENUM
andca.DBR_STRING
types.ca.DBR_STRING
reads of a field of typeca.DBF_ENUM
returns the string corresponding to the current enumerated value.
ca.DBF_CHAR
fields can be read usingca.DBR_CHAR
andca.DBR_STRING
types.ca.DBR_CHAR
returns a scalar or a sequnece of integers.ca.DBR_STRING
assumes each integer as a character and assemble a string.
Parameters:
- req_type (int, None) – database request type. Defaults to be the native data type.
- count (int, None) – number of data values to read, Defaults to be the native count.
- keywords –
optional arguments assigned by keywords
keyword value use_numpy True if waveform should be returned as numpy array. Default CaChannel.USE_NUMPY
.Returns: If req_type is plain request type, only the value is returned. Otherwise a dict returns with information depending on the request type, same as the first argument passed to user’s callback by
array_get_callback()
.Raises: CaChannelException – if timeout error happens
>>> chan = CaChannel('catest') >>> chan.searchw() >>> chan.putw(0) >>> value = chan.getw(ca.DBR_TIME_DOUBLE) >>> for k,v in sorted(value.items()): # doctest: +ELLIPSIS ... if k in ['pv_severity', 'pv_status']: ... print(k, v.name) ... else: ... print(k, v) pv_nseconds ... pv_seconds ... pv_severity No pv_status No pv_value 0.0Changed in version 3.0: If req_type is DBR_XXX_STRING for a char type PV, a string will be returned from composing each element as a character.
Write¶
CaChannel.
array_put
(value, req_type=None, count=None)[source]¶Write a value or array of values to a channel
Parameters:
- value (int, float, bytes, str, list, tuple, array) – data to be written. For multiple values use a list or tuple
- req_type (int, None) – database request type (
ca.DBR_XXXX
). Defaults to be the native data type.- count (int, None) – number of data values to write. Defaults to be the native count.
Note
All remote operation requests such as the above are accumulated (buffered) and not forwarded to the IOC until one of execution methods (
pend_io()
,poll()
,pend_event()
,flush_io()
) is called. This allows several requests to be efficiently sent over the network in one message.>>> chan = CaChannel('catest') >>> chan.searchw() >>> chan.array_put(123) >>> chan.flush_io() >>> chan.getw() 123.0 >>> chan = CaChannel('cabo') >>> chan.searchw() >>> chan.array_put('Busy', ca.DBR_STRING) >>> chan.flush_io() >>> chan.getw() 1 >>> chan = CaChannel('cawavec') >>> chan.searchw() >>> chan.array_put([1,2,3]) >>> chan.flush_io() >>> chan.getw() [1, 2, 3, 0, 0] >>> chan.getw(count=3, use_numpy=True) array([1, 2, 3], dtype=uint8) >>> chan = CaChannel('cawavec') >>> chan.searchw() >>> chan.array_put('1234',count=3) >>> chan.flush_io() >>> chan.getw(count=4) [49, 50, 51, 0]
CaChannel.
array_put_callback
(value, req_type, count, callback, *user_args)[source]¶Write a value or array of values to a channel and execute the user supplied callback after the put has completed.
Parameters:
- value (int, float, bytes, str, list, tuple, array) – data to be written. For multiple values use a list or tuple.
- req_type (int, None) – database request type (
ca.DBR_XXXX
). Defaults to be the native data type.- count (int, None) – number of data values to write, Defaults to be the native count.
- callback (callable) – function called when the write is completed.
- user_args – user provided arguments that are passed to callback when it is invoked.
Raises: CaChannelException – if error happens
Each Python callback function is required to have two arguments. The first argument is a dictionary containing the results of the action.
field type comment chid capsule channels id structure type int database request type (ca.DBR_XXXX) count int number of values to transfered status int CA status return code (ca.ECA_XXXX) The second argument is a tuple containing any user arguments specified by user_args. If no arguments were specified then the tuple is empty.
Note
All remote operation requests such as the above are accumulated (buffered) and not forwarded to the IOC until one of execution methods (
pend_io()
,poll()
,pend_event()
,flush_io()
) is called. This allows several requests to be efficiently sent over the network in one message.>>> def putCB(epicsArgs, _): ... print(ca.name(epicsArgs['chid']), 'put completed') >>> chan = CaChannel('catest') >>> chan.searchw() >>> chan.array_put_callback(145, None, None, putCB) >>> status = chan.pend_event(1) catest put completed >>> chan = CaChannel('cabo') >>> chan.searchw() >>> chan.array_put_callback('Busy', ca.DBR_STRING, None, putCB) >>> status = chan.pend_event(1) cabo put completed >>> chan = CaChannel('cawave') >>> chan.searchw() >>> chan.array_put_callback([1,2,3], None, None, putCB) >>> status = chan.pend_event(1) cawave put completed >>> chan = CaChannel('cawavec') >>> chan.searchw() >>> chan.array_put_callback('123', None, None, putCB) >>> status = chan.pend_event(1) cawavec put completed
CaChannel.
putw
(value, req_type=None)[source]¶Write a value or array of values to a channel.
If the request type is omitted the data is written as the Python type corresponding to the native format. Multi-element data is specified as a tuple or a list. Internally the sequence is converted to a list before inserting the values into a C array. Access using non-numerical types is restricted to the first element in the data field. Mixing character types with numerical types writes bogus results but is not prohibited at this time.
ca.DBF_ENUM
fields can be written usingca.DBR_ENUM
andca.DBR_STRING
types.ca.DBR_STRING
writes of a field of typeca.DBF_ENUM
must be accompanied by a valid string out of the possible enumerated values.
Parameters:
- value (int, float, bytes, str, tuple, list, array) – data to be written. For multiple values use a list or tuple
- req_type (int, None) – database request type (
ca.DBR_XXXX
). Defaults to be the native data type.Raises: CaChannelException – if timeout or error happens
Note
This method does flush the request to the channel access server.
>>> chan = CaChannel('catest') >>> chan.searchw() >>> chan.putw(145) >>> chan.getw() 145.0 >>> chan = CaChannel('cabo') >>> chan.searchw() >>> chan.putw('Busy', ca.DBR_STRING) >>> chan.getw() 1 >>> chan.getw(ca.DBR_STRING) 'Busy' >>> chan = CaChannel('cawave') >>> chan.searchw() >>> chan.putw([1,2,3]) >>> chan.getw(req_type=ca.DBR_LONG,count=4) [1, 2, 3, 0] >>> chan = CaChannel('cawavec') >>> chan.searchw() >>> chan.putw('123') >>> chan.getw(count=4) [49, 50, 51, 0] >>> chan.getw(req_type=ca.DBR_STRING) '123' >>> chan = CaChannel('cawaves') >>> chan.searchw() >>> chan.putw(['string 1','string 2']) >>> chan.getw() ['string 1', 'string 2', '']
Monitor¶
CaChannel.
add_masked_array_event
(req_type, count, mask, callback, *user_args, **keywords)[source]¶Specify a callback function to be executed whenever changes occur to a PV.
Creates a new event id and stores it on self.__evid. Only one event registered per CaChannel object. If an event is already registered the event is cleared before registering a new event.
Parameters:
- req_type (int, None) – database request type (
ca.DBR_XXXX
). Defaults to be the native data type.- count (int, None) – number of data values to read, Defaults to be the native count.
- mask (int, None) – logical or of
ca.DBE_VALUE
,ca.DBE_LOG
,ca.DBE_ALARM
. Defaults to beca.DBE_VALUE|ca.DBE_ALARM
.- callback (callable) – function called when the get is completed.
- user_args – user provided arguments that are passed to callback when it is invoked.
- keywords –
optional arguments assigned by keywords
keyword value use_numpy True if waveform should be returned as numpy array. Default CaChannel.USE_NUMPY
.Raises: CaChannelException – if error happens
Note
All remote operation requests such as the above are accumulated (buffered) and not forwarded to the IOC until one of execution methods (
pend_io()
,poll()
,pend_event()
,flush_io()
) is called. This allows several requests to be efficiently sent over the network in one message.>>> def eventCB(epicsArgs, _): ... print('pv_value', epicsArgs['pv_value']) ... print('pv_status', epicsArgs['pv_status'].name) ... print('pv_severity', epicsArgs['pv_severity'].name) >>> chan = CaChannel('cabo') >>> chan.searchw() >>> chan.putw(1) >>> chan.add_masked_array_event(ca.DBR_STS_ENUM, None, None, eventCB) >>> status = chan.pend_event(1) pv_value 1 pv_status State pv_severity Minor >>> chan.add_masked_array_event(ca.DBR_STS_STRING, None, None, eventCB) >>> status = chan.pend_event(1) pv_value Busy pv_status State pv_severity Minor >>> chan.clear_event()
CaChannel.
clear_event
()[source]¶Remove previously installed callback function.
Note
All remote operation requests such as the above are accumulated (buffered) and not forwarded to the IOC until one of execution methods (
pend_io()
,poll()
,pend_event()
,flush_io()
) is called. This allows several requests to be efficiently sent over the network in one message.
Execute¶
CaChannel.
pend_io
(timeout=None)[source]¶Flush the send buffer and wait until outstanding queries (
search()
,array_get()
) complete or the specified timeout expires.
Parameters: timeout (float) – seconds to wait Raises: CaChannelException – if timeout or other error happens
CaChannel.
pend_event
(timeout=None)[source]¶Flush the send buffer and process background activity (connect/get/put/monitor callbacks) for
timeout
seconds.It will not return before the specified timeout expires and all unfinished channel access labor has been processed.
Parameters: timeout (float) – seconds to wait Returns: ca.ECA_TIMEOUT
CaChannel.
poll
()[source]¶Flush the send buffer and execute any outstanding background activity.
Returns: ca.ECA_TIMEOUT
Note
It is an alias to
pend_event(1e-12)
.
CaChannel.
flush_io
()[source]¶Flush the send buffer and does not execute outstanding background activity.
Raises: CaChannelException – if error happens
Information¶
CaChannel.
field_type
()[source]¶Native type of the PV in the server,
ca.DBF_XXXX
.>>> chan = CaChannel('catest') >>> chan.searchw() >>> ftype = chan.field_type() >>> ftype <DBF.DOUBLE: 6> >>> ca.dbf_text(ftype) 'DBF_DOUBLE' >>> ca.DBF_DOUBLE == ftype True
CaChannel.
element_count
()[source]¶Maximum array element count of the PV in the server.
>>> chan = CaChannel('catest') >>> chan.searchw() >>> chan.element_count() 1
CaChannel.
name
()[source]¶Channel name specified when the channel was created.
>>> chan = CaChannel('catest') >>> chan.searchw() >>> chan.name() 'catest'
CaChannel.
state
()[source]¶Current state of the CA connection.
States Value Meaning ca.cs_never_conn 0 PV not found ca.cs_prev_conn 1 PV was found but unavailable ca.cs_conn 2 PV was found and available ca.cs_closed 3 PV not closed ca.cs_never_search 4 PV not searched yet >>> chan = CaChannel('catest') >>> chan.state() <ChannelState.NEVER_SEARCH: 4> >>> chan.searchw() >>> chan.state() <ChannelState.CONN: 2>
CaChannel.
host_name
()[source]¶Host name that hosts the process variable.
>>> chan = CaChannel('catest') >>> chan.searchw() >>> host_name = chan.host_name()
Misc¶
CaChannel.
setTimeout
(timeout)[source]¶Set the timeout for this channel object. It overrides the class timeout.
Parameters: timeout (float) – timeout in seconds >>> chan = CaChannel() >>> chan.setTimeout(10.) >>> chan.getTimeout() 10.0
CaChannel.
getTimeout
()[source]¶Retrieve the timeout set for this channel object.
Returns: timeout in seconds for this channel instance Return type: float >>> chan = CaChannel() >>> chan.getTimeout() == CaChannel.ca_timeout True
CaChannel.
replace_access_rights_event
(callback=None, user_args=None)[source]¶Install or replace the access rights state change callback handler for the specified channel.
The callback handler is called in the following situations.
- whenever CA connects the channel immediately before the channel’s connection handler is called
- whenever CA disconnects the channel immediately after the channel’s disconnect callback is called
- once immediately after installation if the channel is connected
- whenever the access rights state of a connected channel changes
When a channel is created no access rights handler is installed.
Parameters:
- callback (callable) – function called when access rights change. If None is given, remove the access rights event callback.
- user_args – user provided arguments that are passed to callback when it is invoked.
>>> chan = CaChannel('catest') >>> chan.searchw() >>> def accessCB(epicsArgs, _): ... print('read:', epicsArgs['read_access'], 'write:', epicsArgs['write_access']) >>> chan.replace_access_rights_event(accessCB) read: True write: True >>> chan.replace_access_rights_event() # clear the callbackNew in version 3.0.
- classmethod
CaChannel.
add_exception_event
(callback=None, user_args=None)[source]¶Install or replace the currently installed CA context global exception handler callback.
When an error occurs in the server asynchronous to the clients thread then information about this type of error is passed from the server to the client in an exception message. When the client receives this exception message an exception handler callback is called. The default exception handler prints a diagnostic message on the client’s standard out and terminates execution if the error condition is severe.
Note that certain fields returned in the callback args are not applicable in the context of some error messages. For instance, a failed get will supply the address in the client task where the returned value was requested to be written. For other failed operations the value of the addr field should not be used.
Parameters:
- callback (callable) – function called.
- user_args – user provided arguments that are passed to callback when it is invoked.
The possible fields available are as defined in the C “struct exception_handler_args” and are: chid, type, count, state, op, ctx, file, lineNo
>>> chan = CaChannel('catest') >>> chan.searchw() >>> def exceptionCB(epicsArgs, _): ... print('op:', epicsArgs['op'], 'file:', epicsArgs['file'], 'line:', epicsArgs['lineNo']) >>> chan.add_exception_event(exceptionCB) # add callback # doctest: +SKIP >>> chan.add_exception_event() # clear the callback # doctest: +SKIPNew in version 3.1.
- classmethod
CaChannel.
replace_printf_handler
(callback=None, user_args=None)[source]¶Install or replace the callback used for formatted CA diagnostic message output. The default is to send to stderr.
Parameters:
- callback (callable) – function called.
- user_args – user provided arguments that are passed to callback when it is invoked.
>>> chan = CaChannel('catest') >>> chan.searchw() >>> def printfCB(message, _): ... print('CA message:', message) >>> chan.replace_printf_handler(printfCB) # add callback # doctest: +SKIP >>> chan.replace_printf_handler() # clear the callback # doctest: +SKIPNew in version 3.1.
epicsPV
¶
This module defines the epicsPV class, which adds additional features to Geoff Savage’s CaChannel class.
Author: Mark Rivers Created: Sept. 16, 2002. Modifications:
- Mar. 25, 2014 Xiaoqiang Wang
- Fix the call sequence inside getCallback
- Mar. 7, 2017 Xiaoqiang Wang
- Reformat the docstring and code indent.
Class epicsPV
¶
-
class
epicsPV.
epicsPV
(pvName=None, wait=True)[source]¶ This class subclasses CaChannel class to add the following features:
- If a PV name is given then the class constructor will
do a
CaChannel.CaChannel.searchw()
by default. setMonitor()
sets a generic callback routine for value change events. Subsequentgetw()
,getValue()
orarray_get()
calls will return the value from the most recent callback, and hence do not result in any network activity or latency. This can greatly improve performance.checkMonitor()
returns a flag to indicate if a callback has occured since the last call tocheckMonitor()
,getw()
,getValue()
orarray_get()
. It can be used to increase efficiency in polling applications.getControl()
reads the “control” and other information from an EPICS PV without having to use callbacks. In addition to the PV value, this will return the graphic, control and alarm limits, etc.putWait()
callsCaChannel.CaChannel.array_put_callback()
and waits for the callback to occur before it returns. This allows programs to wait for record being processed synchronously and without user-written callbacks.
- If a PV name is given then the class constructor will
do a
Constructor¶
epicsPV.
__init__
(pvName=None, wait=True)[source]¶Create an EPICS channel if pvName is specified, and optionally wait for connection.
Parameters:
- pvName (str) – An optional name of an EPICS Process Variable.
- wait (bool) – If wait is True and pvName is not None then this constructor will do a
CaChannel.CaChannel.searchw()
on the PV. If wait is False and pvName ist not None then this constructor will do aCaChannel.CaChannel.search()
on the PV, and the user must subsequently do aCaChannel.CaChannel.pend_io()
on this or anotherepicsPV
orCaChannel
object.
Read¶
epicsPV.
array_get
(req_type=None, count=None, **keywords)[source]¶If
setMonitor()
has not been called then this function simply callsCaChannel.CaChannel.array_get()
. IfsetMonitor()
has been called then it callsCaChannel.CaChannel.pend_event()
with a very short timeout, and then returns the PV value from the last callback.
epicsPV.
getValue
()[source]¶If
setMonitor()
has not been called then this function simply callsCaChannel.CaChannel.getValue()
. If setMonitor has been called then it callsCaChannel.CaChannel.pend_event()
with a very short timeout, and then returns the PV value from the last callback.
epicsPV.
getw
(req_type=None, count=None, **keywords)[source]¶If
setMonitor()
has not been called then this function simply callsCaChannel.CaChannel.getw()
. IfsetMonitor()
has been called then it callsCaChannel.CaChannel.pend_event()
with a very short timeout, and then returns the PV value from the last callback.
epicsPV.
getControl
(req_type=None, count=None, wait=1, poll=0.01)[source]¶Provides a method to read the “control” and other information from an EPICS PV without having to use callbacks.
It calls
CaChannel.CaChannel.CaChannel.array_get_callback()
with a database request type of ca.dbf_type_to_DBR_CTRL(req_type). In addition to the PV value, this will return the graphic, control and alarm limits, etc.
Parameters:
- req_type (int) – request type. Default to field type.
- count (int) – number of elements. Default to native element count.
- wait (bool) – If this keyword is 1 (the default) then this routine waits for the callback before returning. If this keyword is 0 then it is the user’s responsibility to wait or check for the callback by calling
checkMonitor()
.- poll (float) – The timeout for
CaChannel.CaChannel.pend_event()
calls, waiting for the callback to occur. Shorter times reduce the latency at the price of CPU cycles.>>> pv = epicsPV('13IDC:m1') >>> pv.getControl() >>> for field in dir(pv.callBack): ... print field, ':', getattr(pv.callBack, field) chid : _bfffec34_chid_p count : 1 monitorState : 0 newMonitor : 1 putComplete : 0 pv_loalarmlim : 0.0 pv_loctrllim : -22.0 pv_lodislim : -22.0 pv_lowarnlim : 0.0 pv_precision : 4 pv_riscpad0 : 256 pv_severity : 0 pv_status : 0 pv_units : mm pv_upalarmlim : 0.0 pv_upctrllim : 28.0 pv_updislim : 28.0 pv_upwarnlim : 0.0 pv_value : -15.0 status : 1 type : 34
Write¶
epicsPV.
putWait
(value, req_type=None, count=None, poll=0.01)[source]¶Calls
CaChannel.CaChannel.array_put_callback()
and waits for the callback to occur before it returns. This allows programs to wait for record being processed without having to handle asynchronous callbacks.
Parameters:
- value – data to be written. For multiple values use a list or tuple
- req_type – database request type (
ca.DBR_XXXX
). Defaults to be the native data type.- count (int) – number of data values to write. Defaults to be the native count.
- poll (float) – The timeout for
CaChannel.CaChannel.pend_event()
calls, waiting for the callback to occur. Shorter times reduce the latency at the price of CPU cycles.
Monitor¶
epicsPV.
setMonitor
()[source]¶Sets a generic callback routine for value change events.
Subsequent
getw()
,getValue()
orarray_get()
calls will return the value from the most recent callback, do not result in any network latency. This can greatly improve efficiency.
epicsPV.
clearMonitor
()[source]¶Cancels the effect of a previous call to
setMonitor()
.Subsequent
getw()
,getValue()
orarray_get()
calls will no longer return the value from the most recent callback, but will actually result in channel access calls.
epicsPV.
checkMonitor
()[source]¶Returns 1 to indicate if a value callback has occured since the last call to
checkMonitor()
,getw()
,getValue()
orarray_get()
, indicating that a new value is available. Returns 0 if no such callback has occurred. It can be used to increase efficiency in polling applications.
epicsMotor
¶
This module provides support for the EPICS motor record.
Author: Mark Rivers
Created: Sept. 16, 2002
Modifications:
- Mar. 7, 2017 Xiaoqiang Wang
- Reformat the docstring and code indent.
- Use class property to expose certain fields.
Exception epicsMotorException
¶
-
exception
epicsMotor.
epicsMotorException
[source]¶ This exception is raised when
epicsMotor.check_limits()
method detects a soft limit or hard limit violation. TheepicsMotor.move()
andepicsMotor.wait()
methods callepicsMotor.check_limits()
before they return, unless they are called with theignore_limits=True
keyword set.
Class epicsMotor
¶
-
class
epicsMotor.
epicsMotor
(name)[source]¶ This module provides a class library for the EPICS motor record. It uses the
epicsPV.epicsPV
class, which is in turn a subclass ofCaChannel.CaChannel
Certain motor record fields are exposed as class properties. They can be both read and written unless otherwise noted.
Property Description Field slew_speed Slew speed or velocity .VELO base_speed Base or starting speed .VBAS acceleration Acceleration time (sec) .ACCL description Description of motor .DESC resolution Resolution (units/step) .MRES high_limit High soft limit (user) .HLM low_limit Low soft limit (user) .LLM dial_high_limit High soft limit (dial) .DHLM dial_low_limit Low soft limit (dial) .DLLM backlash Backlash distance .BDST offset Offset from dial to user .OFF done_moving 1=Done, 0=Moving, read-only .DMOV >>> m = epicsMotor('13BMD:m38') >>> m.move(10) # Move to position 10 in user coordinates >>> m.wait() # Wait for motor to stop moving >>> m.move(50, dial=True) # Move to position 50 in dial coordinates >>> m.wait() # Wait for motor to stop moving >>> m.move(1, step=True, relative=True) # Move 1 step relative to current position >>> m.wait(start=True, stop=True) # Wait for motor to start, then to stop >>> m.stop() # Stop moving immediately >>> high = m.high_limit # Get the high soft limit in user coordinates >>> m.dial_high_limit = 100 # Set the high limit to 100 in dial coodinates >>> speed = m.slew_speed # Get the slew speed >>> m.acceleration = 0.1 # Set the acceleration to 0.1 seconds >>> val = m.get_position() # Get the desired motor position in user coordinates >>> dval = m.get_position(dial=True)# Get the desired motor position in dial coordinates >>> rbv = m.get_position(readback=True) # Get the actual position in user coordinates >>> rrbv = m.get_position(readback=True, step=True) # Get the actual motor position in steps >>> m.set_position(100) # Set the current position to 100 in user coordinates >>> m.set_position(10000, step=True) # Set the current position to 10000 steps
Constructor¶
Move¶
epicsMotor.
move
(value, relative=False, dial=False, step=False, ignore_limits=False)[source]¶Moves a motor to an absolute position or relative to the current position in user, dial or step coordinates.
Parameters:
- value (float) – The absolute position or relative amount of the move
- relative (bool) – If True, move relative to current position. The default is an absolute move.
- dial (bool) – If True, _value_ is in dial coordinates. The default is user coordinates.
- step (bool) – If True, _value_ is in steps. The default is user coordinates.
- ignore_limits (bool) – If True, suppress raising exceptions if the move results in a soft or hard limit violation.
Raises: epicsMotorException – If software limit or hard limit violation detected, unless ignore_limits=True is set.
Note
The “step” and “dial” keywords are mutually exclusive. The “relative” keyword can be used in user, dial or step coordinates.
>>> m=epicsMotor('13BMD:m38') >>> m.move(10) # Move to position 10 in user coordinates >>> m.move(50, dial=True) # Move to position 50 in dial coordinates >>> m.move(2, step=True, relative=True) # Move 2 steps
epicsMotor.
stop
()[source]¶Immediately stops a motor from moving by writing 1 to the .STOP field.
>>> m=epicsMotor('13BMD:m38') >>> m.move(10) # Move to position 10 in user coordinates >>> m.stop() # Stop motor
epicsMotor.
wait
(start=False, stop=False, poll=0.01, ignore_limits=False)[source]¶Waits for the motor to start moving and/or stop moving.
Parameters:
- start (bool) – If True, wait for the motor to start moving.
- stop (bool) – If True, wait for the motor to stop moving.
- poll (float) – The time to wait between reading the .DMOV field of the record to see if the motor is moving. The default is 0.01 seconds.
- ignore_limits (bool) – If True, suppress raising an exception if a soft or hard limit is detected.
Raises: epicsMotorException – If software limit or hard limit violation detected, unless ignore_limits=True is set.
Note
If neither the “start” nor “stop” keywords are set then “stop” is set to 1, so the routine waits for the motor to stop moving. If only “start” is set to 1 then the routine only waits for the motor to start moving. If both “start” and “stop” are set to 1 then the routine first waits for the motor to start moving, and then to stop moving.
>>> m = epicsMotor('13BMD:m38') >>> m.move(50) # Move to position 50 >>> m.wait(start=True, stop=True) # Wait for the motor to start moving and then to stop moving
Readback¶
epicsMotor.
get_position
(dial=False, readback=False, step=False)[source]¶Returns the target or readback motor position in user, dial or step coordinates.
Parameters:
- readback (bool) – If True, return the readback position in the desired coordinate system. The default is to return the target position of the motor.
- dial (bool) – If True, return the position in dial coordinates. The default is user coordinates.
- step (bool) – If True, return the position in steps. The default is user coordinates.
Note
The “step” and “dial” keywords are mutually exclusive. The “readback” keyword can be used in user, dial or step coordinates.
>>> m = epicsMotor('13BMD:m38') >>> m.move(10) # Move to position 10 in user coordinates >>> pos_dial = m.get_position(dial=True) # Read the target position in dial coordinates >>> pos_step = m.get_position(readback=True, step=True) # Read the actual position in steps
epicsMotor.
check_limits
()[source]¶Check wether there is a soft limit, low hard limit or high hard limit violation.
Raises: epicsMotorException – If software limit or hard limit violation detected.
Config¶
epicsMotor.
set_position
(position, dial=False, step=False)[source]¶Sets the motor position in user, dial or step coordinates.
Parameters:
- position (float) – The new motor position
- dial (bool) – If True, set the position in dial coordinates. The default is user coordinates.
- step (bool) – If True, set the position in steps. The default is user coordinates.
Note
The “step” and “dial” keywords are mutually exclusive.
>>> m = epicsMotor('13BMD:m38') >>> m.set_position(10, dial=True) # Set the motor position to 10 in dial coordinates >>> m.set_position(1000, step=True) # Set the motor position to 1000 steps
CaChannel.util
¶
This module provides functions similiar to those command line tools found in EPICS base,
e.g. caget()
, caput()
, camonitor()
, cainfo()
.
In those functions, CaChannel.CaChannel
objects are created implicitly and cached
in _channel_
dictionary.
>>> import time
>>> caput('catest', 1.23, wait=True)
>>> caget('catest')
1.23
>>> caput('cabo', 'Busy')
>>> caget('cabo')
1
>>> caget('cabo', as_string=True)
'Busy'
>>> caput('cawavec', 'this can be a long string')
>>> caget('cawavec', as_string=True)
'this '
>>> caput('cawave', range(4))
>>> caget('cawave', count=4)
[0.0, 1.0, 2.0, 3.0]
-
CaChannel.util.
caget
(name, as_string=False, count=None)[source]¶ Return PV’s current value.
For enum or char type PV, the string form is returned if as_string is True. If the PV is of multi-element array, count can be used to limit the number of elements.
Parameters: - name (str) – pv name
- as_string (bool) – retrieve enum and char type as string
- count (int) – number of element to request
Returns: pv value
-
CaChannel.util.
caput
(name, value, wait=False, timeout=None)[source]¶ Parameters: - name (str) – pv name
- value – value to write
- wait (bool) – wait for completion
- timeout (float) – seconds to wait
-
CaChannel.util.
camonitor
(name, as_string=False, count=None, callback=None)[source]¶ set a callback to be invoked when pv value or alarm status change.
Parameters: - name (str) – pv name
- as_string (bool) – retrieve enum and char type as string
- count (int) – number of element to request
- callback – callback function. If None is specified, the default callback is to print to the console. If callback is not a valid callable, any previous callback is removed.
>>> camonitor('cacalc') >>> time.sleep(2) # doctest: +ELLIPSIS cacalc ... >>> def monitor_callback(epics_args, _): ... for k in sorted(epics_args): ... print(k, epics_args[k]) >>> camonitor('cacalc', callback=monitor_callback) >>> time.sleep(2) # doctest: +ELLIPSIS chid ... count 1 pv_nseconds ... pv_seconds ... pv_severity AlarmSeverity.No pv_status AlarmCondition.No pv_value ... status ECA.NORMAL type DBR.TIME_DOUBLE chid ... >>> camonitor('cacalc', callback=()) >>> time.sleep(2)