epics access from python geoff savage dØ workshop thursday june 22, 2000

50
D D EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

Upload: jocelyn-berry

Post on 04-Jan-2016

218 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

EPICS Access from Python

Geoff SavageDØ Workshop

Thursday June 22, 2000

Page 2: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 2

Game Plan

Discuss EPICS channel access (CA) C library High level discussion

Provide examples from CaChannel Python class that wraps CA library Wrap = provide python interface Delve further into CA functionality

Page 3: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 3

EPICS Channel Access

Role in EPICS architecture Architecture Services Library functionality

Page 4: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 4

Role in EPICS Architecture

IOC

Host

IOC

Network

Transfer information

between host and IOC

Page 5: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 5

CA Architecture

Client-server architecture IOC = server Host application = client

Client makes requests to server Channel = client-server

connection Connection between client and PV All channel creation requests made

by name Host and IOC must be on network

Page 6: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 6

CA Services

Dynamic channel creation Automatic reconnect Read/Write Monitoring

Events Access control Connection

Data type conversions Composite data structures

Page 7: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 7

Channel Creation

IOCIOCIOCHostWho has channel ‘XXXX’?

(broadcast)

IOCIOCIOCHost

I have channel ‘XXXX’.

IOCIOCIOCHostNegotiate connection.

(point-to-point)

Page 8: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 8

CA Library

Messages Connection Synchronous Asynchronous Group

Page 9: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 9

CA Messages

All CA requests are buffered in host Connect, get, put, … Increased efficiency

Buffer is sent when full or upon user request

PV get/put requests can’t be in same message as connection request

Page 10: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 10

Connection (CA Lib)

“Establish and maintain a virtual circuit between application and PV in a CA server”

Connection must be made before accessing PV

Network transparency (by name) Callback on connection status

change

Page 11: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 11

Synchronous (CA Lib)

Make requests Flush request buffer into

message Wait until all requests in

message have been completed or timeout occurs

Return control to application

Page 12: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 12

Asynchronous (CA Lib)

Make requests and specify callback

Flush request buffer into message

Return control to application You are notified of completion

through execution of callback at a later timeSynchronous and Asynchronousrequests can be in the same message

Page 13: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 13

Group (CA Lib)

“Guarantee that a set of CA requests have completed”

Synchronous (no callback) Create Get/put Block waiting for completion

(timeout) Test for completion Remove uncompleted requests

Page 14: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 14

EPICS CA Summary

High level discussion Role = transfer information Architecture = client-server Services - Covered in more detail

during CaChannel discussion Library functionality

Buffering for efficiency, Connections, Synchronous, Asynchronous, Group

Page 15: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 15

CaChannel

Architecture Simple examples Data types Synchronous I/O Asynchronous I/O Monitoring Use with Tkinter

Page 16: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 16

CaChannel Architecture

EPICS channel access C library

Collection of C functions

Distributed with EPICS

caPython

Python wrapper around the C library

Collection of python functions

CaChannel

Python class

Calls caPython functions

Move from C function to Python class interface.

Page 17: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 17

<d0olb> setup d0python

<d0olb> python

Python 1.5.2 (#6, May 10 1999, 21:44:32) [C] on osf1V4

Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam

>>> from CaChannel import *

>>> ch = CaChannel()

>>> ch.searchw('catest')

>>> ch.putw(123.456)

>>> ch.getw()

123.456

Simple Interpreter Example

Each method performsone synchronous request.

connect

write

read

Page 18: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 18

Simple Script Example

#! /bin/env python

#

from CaChannel import *

def main():

try:

catest = CaChannel()

catest.searchw('catest')

catest.putw(123.456)

print catest.getw()

except CaChannelException, status:

print ca.message(status)

main()

Page 19: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 19

Data Types … Each PV has a

native type Different data

types can be requested

Requests using native type most efficient

>>> ch.getw()

123.456

>>> ch.getw(ca.DBR_INT)

123

>>> ch.getw(ca.DBR_STRING)

'123'

>>> ch.field_type()

6

>>> ca.dbr_text(ch.field_type())

'DBR_DOUBLE‘

>>>

Not all caPython functions

implemented as methods.

Page 20: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 20

… Data Types …>>> scan = CaChannel()

>>> scan.searchw('catest.SCAN')

>>> scan.getw()

6

>>> scan.getw(ca.DBR_STRING)

'1 second'

>>> scan.putw(5)

>>> scan.getw(ca.DBR_STRING)

'2 second‘

>>> ca.dbr_text(scan.field_type())

'DBR_ENUM'

>>>

Page 21: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 21

… Data Types>>> scan.putw('1 second')

Traceback (innermost last):

File "<stdin>", line 1, in ?

File "/d0usr/products/d0python/OSF1/v02_03/lib/CaChannel.py", line 383, in putw

count, pval = self.__setup_put(value, req_type)

File "/d0usr/products/d0python/OSF1/v02_03/lib/CaChannel.py", line 131, in __setup_put

CaChannel.dbr_d[req_type]['convert'](value),

ValueError: invalid literal for int(): 1 second

>>> scan.putw('1 second', ca.DBR_STRING)

>>> scan.getw(ca.DBR_STRING)

'1 second'

Page 22: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 22

Request Data Types

Request type

Python type Comments

DBR_STRING String

DBR_ENUM Integer Enumerated

DBR_CHAR Integer 8 bits

DBR_INT Integer 16 bits

DBR_LONG Integer 32 bits

DBR_FLOAT Float

DBR_DOUBLE

Float

Array of DBR List of type

Page 23: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 23

Synchronous I/O …

pend_io = flush request buffer and wait for CA requests to complete

pend_io affects requests from all CaChannel instances

Only one request buffer for all CaChannel instances

Page 24: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 24

… Synchronous I/O … Multiple requests

can be issued before each pend_io

All connections must be made before get or put

On a get a value is not valid until pend_io has returned with no errors

>>>

>>> ch.search('catest')

>>> ch.pend_io()

>>>

>>> ch.array_put(123.456)

>>> ch.pend_io()

>>>

>>> ch.array_get()

>>> ch.pend_io()

>>> ch.getValue()

123.456

Page 25: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 25

… Synchronous I/O catest.array_get()

cawave.array_get()

scan.array_get()

ca.pend_io(1.0)

print catest.getValue()

print cawave.getValue()

print scan.getValue()

except CaChannelException,status:

print ca.message(status)

try: catest = CaChannel() cawave = CaChannel() scan = CaChannel()

catest.search('catest') cawave.search('cawave') scan.search('catest.SCAN') catest.pend_io()

t=(0,1,2,3,4,5,6,7,8,9,10, 11,12,13,14,15,16,17,18,19) catest.array_put(123.456) cawave.array_put(t) scan.array_put("1 second“, ca.DBR_STRING) cawave.pend_io()

Page 26: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 26

Asynchronous I/O … No waiting for CA requests to

complete A user specified callback function

is executed when the request has completed

ca_pend_event = flush the request buffer and wait for timeout seconds or until all CA background activity is processed

ca_flush_io = flush the request buffer

Page 27: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 27

… Asynchronous I/O …

Asynchronous callbacks do not preempt the main thread

Instead ca_pend_io, ca_pend_event, or ca_poll must be called at least every 15 seconds to allow background activity to process

ca_poll = ca_pend_event with short (0.001 second) timeout

Page 28: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 28

… Asynchronous I/O …try: chan = CaChannel() chan.search_and_connect('catest', connectCb) chan.flush_io() for i in range(20): chan.pend_event() chan.array_put_callback(3.3, None, None, putCb) chan.flush_io() for i in range(20): chan.pend_event() chan.array_get_callback(None, None, getCb1) chan.flush_io() for i in range(20): chan.pend_event() chan.array_get_callback(ca.dbf_type_to_DBR_STS( chan.field_type()), None,getCb2) chan.flush_io() for i in range(20): chan.pend_event()except CaChannelException, status: print ca.message(status)

Page 29: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 29

Compound Data Types

Only supported in asynchronous mode

Extra information with the value Status – alarm values Time – status + timestamp Graphics – status + alarm limits +

display limits Control – graphics + control limits

Routines are provided to convert DBR type to compound type

Page 30: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 30

Connection Callback

epics_args = 2 element tuple t[1] = channel identifier, used to get

the channels name t[2] = connection state

CA_OP_CONN_UP CA_OP_CONN_DOWN

user_args = tuple containing all python objects specified after the callback in the method

def connectCb(epics_args, user_args):

print epics_args

print user_args

Page 31: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 31

Put Callback

chid = channel identifier type = request type (DBR_XXXX) count = element count status = CA status code from server

def putCb(epics_args, user_args):

print ca.name(epics_args['chid'])

print ca.dbr_text(epics_args['type'])

print epics_args['count']

print ca.message(epics_args['status'])

print user_args

Page 32: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 32

Get Callback

value(s) = data returned by the server. Multiple data elements are returned in a tuple.

def getCb1(epics_args, user_args):

print "pvName = ", ca.name(epics_args['chid'])

print "type = ", ca.dbr_text(epics_args['type'])

print "count = ", epics_args['count']

print "status = ", ca.message(epics_args['status'])

print "user args = ", user_args

print "value(s) = ", epics_args['pv_value']

Page 33: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 33

Get Callback with Status

pv_severity = alarm severity pv_status = alarm status

def getCb2(epics_args, user_args):

print "pvName = ", ca.name(epics_args['chid'])

print "type = ", ca.dbr_text(epics_args['type'])

print "count = ", epics_args['count']

print "status = ", ca.message(epics_args['status'])

print "user args = ", user_args

print "value(s) = ", epics_args['pv_value']

print ca.alarmSeverityString(epics_args['pv_severity'])

print ca.alarmStatusString(epics_args['pv_status'])

Page 34: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 34

Asynchronous I/O Usage Tip

To obtain the CaChannel instance to which the callback corresponds use the name

Create a dictionary whose keys are names and contents are the CaChannel instances

Page 35: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 35

… Asynchronous I/O

Callbacks implemented for Time Graphics Control

Page 36: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 36

Monitoring …

Access rights Connection For technical reasons neither of

these are in the CaChannel interface

They can be implemented as a C function

Page 37: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 37

… Monitoring …

Asynchronous I/O originated at the server

Client requests notification from the server when the channel’s value changes by

more than the value dead band or alarm dead band

the channel’s alarm state changes Callbacks match those described

under asynchronous I/O

Page 38: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 38

… Monitoring …def eventCb(epics_args, user_args): print ca.message(epics_args['status']) print "new value = ", epics_args['pv_value'] print ca.alarmSeverityString(epics_args['pv_severity']) print ca.alarmStatusString(epics_args['pv_status'])

try: chan = CaChannel() chan.searchw('catest') chan.add_masked_array_event( ca.dbf_type_to_DBR_STS(chan.field_type()), None, ca.DBE_VALUE | ca.DBE_ALARM, eventCb)except CaChannelException, status: print ca.message(status)

Page 39: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 39

… Monitoring

Monitor mask Notification condition

ca.DBE_VALUEwhen the channel’s value changes by more than MDEL

ca.DBE_LOGwhen the channel’s value changes by more than MDEL

ca.DBE_ALARMwhen the channel’s alarm state changes

Page 40: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 40

Tkinter and CaChannel

EPICS CA is not thread safe All CaChannel activity must be

performed in the main thread Use the Tkinter after method to

interrupt the mainloop at regular intervals to allow CA backgroud activity to execute

Execute CaChannel calls from the update function called by after

Page 41: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 41

CaChannel Summary

Architecture = Python wrapper around C library

Data types = native types most efficient, extended types

Synchronous I/O = interpreter or scripts, easy to use

Asynchronous I/O and monitoring Callbacks Background activity

Page 42: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 42

Documentation

In the doc directory of the d0python package

CaChannel Guide caPython Guide Working on getting up to date

Time, graphic, and control return types

Timeouts (pend_io, pend_event)

Page 43: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 43

CaChannel Internals

Constructor searchw() – connect putw() - write getw() - read

Page 44: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 44

CaChannel Constructor def __init__(self):

# Un-initialized channel id structure

self.__chid = ca.new_chid()

# Monitor event id

self.__evid = None

self.__timeout = None # override class timeout

Page 45: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 45

searchw() def searchw(self, pvName):

status = ca.search(pvName, self.__chid)

if (ca.ECA_NORMAL != status):

raise CaChannelException, status

if self.__timeout is None:

timeout = CaChannel.ca_timeout

else:

timeout = self.__timeout

status = ca.pend_io(timeout)

if (ca.ECA_NORMAL != status):

raise CaChannelException, status

Page 46: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 46

putw() def putw(self, value, req_type=None): if(None == req_type): req_type = self.field_type() count, pval = self.__setup_put(value, req_type) status = ca.array_put(req_type, count, self.__chid, pval) if (ca.ECA_NORMAL != status): ca.ptrfree(pval) raise CaChannelException, status if self.__timeout is None: timeout = CaChannel.ca_timeout else: timeout = self.__timeout status = ca.pend_io(timeout) if (ca.ECA_NORMAL != status): ca.ptrfree(pval) raise CaChannelException, status ca.ptrfree(pval)

Page 47: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 47

getw() …def getw(self, req_type=None): if(None == req_type): req_type = ca.field_type(self.__chid) count, pval = self.__setup_get(req_type) status = ca.array_get(req_type, count, self.__chid, pval) if (ca.ECA_NORMAL != status): ca.ptrfree(pval) raise CaChannelException, status if self.__timeout is None: timeout = CaChannel.ca_timeout else: timeout = self.__timeout status = ca.pend_io(timeout)

Page 48: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 48

… getw() if (ca.ECA_NORMAL != status):

ca.ptrfree(pval)

raise CaChannelException, status

if(1 == count):

value = ca.ptrvalue(pval)

else:

value = self.__build_list(pval, count)

ca.ptrfree(pval)

return value

Page 49: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 49

Simple C Example …/*caExample.c*/#include <stddef.h>#include <stdlib.h>#include <stdio.h>#include <string.h>

#include <cadef.h>

main(int argc,char **argv){ struct dbr_ctrl_enum data; int ndx; int status; chid mychid;

Page 50: EPICS Access from Python Geoff Savage DØ Workshop Thursday June 22, 2000

DD

6/22/00 DZero Workshop 50

… Simple C Example SEVCHK(ca_task_initialize(),"ca_task_initialize");

SEVCHK(ca_search(argv[1],&mychid),"ca_search failure");

SEVCHK(ca_pend_io(5.0),"ca_pend_io failure");

SEVCHK(ca_get(DBR_CTRL_ENUM,mychid,(void *)&data),"ca_get failure");

SEVCHK(ca_get(DBR_CTRL_ENUM,mychid,(void *)&data),"ca_get failure");

SEVCHK(ca_pend_io(5.0),"ca_pend_io failure");

printf("status: %d, severity: %d, count: %d\n",

data.status, data.severity, data.no_str);

for (ndx = 0; ndx < data.no_str; ndx += 1)

printf(" %2d %s\n", ndx, data.strs[ndx]);

return(0);

}