wir schaffen wissen – heute für morgen psi,30. oktober 2015 paul scherrer institut python channel...
TRANSCRIPT
Wir schaffen Wissen – heute für morgen
PSI, 20. April 2023
Paul Scherrer Institut
Python Channel Access Client/Server Extension
Xiaoqiang Wang
EPICS Spring Collaboration Meeting, ITER
Motivation
• Geoff Savage created caPython/CaChannel interface in 1999.– SWIG 1.1 based– EPICS 3.13 – Stable sine 2000, problematic to build on new system (SWIG 1.3)– Many scripts are using the CaChannel interface
• Noboru Yamamoto has PythonCA – Python/C API– EPICS 3.14– Actively maintained
• “New” CaChannel interface based on PythonCA– Full docstring test– 99% compatible– Preemptive callback enabled– Transparent thread safety
CaChannel Interface
Connection• search• search_and_connect• clear_channel• searchw
Synchronization• pend_io• pend_event• poll• flush_io
Write• array_put• array_put_callback• putw
Read• array_get• array_get_callback• getw
Monitors• add_masked_array_event• clear_event
Group operation• sg_create• sg_delete• sg_get• sg_put• sg_reset• sg_block• sg_test
Higher Level Interfaces• ca_util• epicsPV, epicsMotor, epicsScan
Portable Channel Access Server
• SWIG wrapper of channel access server library– No significant C++ code written– 4 classes wrapped: caServe, casPV, casChannel, gdd– Main problem is dealing with gdd object
– 1 new class PV to dispatch read request using gddAppFuncTable– 8 typemap definition to convert data in/out– pythonic get/put methods
20. April 2023PSI,
A minimal example - source
20. April 2023PSI, Seite 8
1 import cas 2 3 class myPV(cas.casPV): 4 def __init__(self, name): 5 cas.casPV.__init__(self) 6 self.name = name 7 self.value = 3 8 9 def write(self, context, value): 10 self.value= value.get() 11 return cas.S_casApp_success 12 13 def getValue(self, value): 14 value.put(self.value) 15 value.setTimeStamp() 16 return cas.S_casApp_success 17 18 def getPrecision(self, value): 19 value.put(3) 20 return cas.S_casApp_success 2122 def bestExternalType(self): 23 return cas.aitEnumFloat64 24 25 def getName(self): 26 return self.name 27
28 class myServer(cas.caServer): 29 def __init__(self): 30 cas.caServer.__init__(self) 31 self.pv = myPV(‘jimi’)3233 def
pvExistTest(self,context,addr,name): 34 if name == ‘jimi’: 35 return cas.pverExistsHere36 else: 37 return
cas.pverDoesNotExistHere3839 def pvAttach(self, context, name): 40 if name == ‘jimi’: 41 return self.pv42 else: 43 return cas.S_casApp_pvNotFound444546 if __name__ == ‘__main__’: 47 s = myServer() 48 s.setDebugLevel(3) 49 while True: 50 cas.process(0.01)
A minimal example - output
[bash SLSBASE=/work]$ caput jimi 1.6Old : jimi 0New : jimi 1.6[bash SLSBASE=/work]$ cainfo jimijimi:NAME jimiVAL 1.6EGU {}SIZE 1SEVR NO_ALARMSTAT NO_ALARMTIME {05/26/10 13:00:43.351047609}TYPE DBF_DOUBLEHOPR 0LOPR 0DRVH 0DRVL 0HIHI 0HIGH 0LOLO 0LOW 0PREC 3ACCESS RWIOC gfalc05.psi.ch
References
PythonCA: http://controls.web.psi.ch/cgi-bin/twiki/view/Main/NewPythonEpicsInterfacePyCAS: http://controls.web.psi.ch/cgi-bin/twiki/view/Main/PythonChannelAccessServerCAS: http://www.aps.anl.gov/epics/extensions/cas/index.php