9. 將EPICS集成到GDA中?

在GDA中整合EPICS的內容包括:
Java Channel Access(JCA)的配置;
鉆石GDA.EPICS接口規范.模式和XML文件
創建可與EPICS對話的掃描儀和探測器,作為通道接入客戶端,允許將設備合并到完整的數據采集系統中;
9.1. 配置JCA?
GDA使用Java的通道訪問 (CAJ )-EPICS Channel Access JCA庫的100%純Java實現-與EPICS IOC通信。
要啟用對EPICS處理變量(PV)的GDA訪問,必須使用屬性啟動GDA服務器(如果客戶端需要直接與PV對話,則為客戶端 gov.aps.jca.JCALibrary.properties 設置,例如:
-Dgov.aps.jca.JCALibrary.properties=${gda.config}/jca/live/JCALibrary.properties
屬性文件 JCALibrary.properties
應包含以下屬性(對應于 EPICS Channel Access enviroment variables ):
com.cosylab.epics.caj.CAJContext.addr_list = 172.23.111.255
com.cosylab.epics.caj.CAJContext.auto_addr_list = true
com.cosylab.epics.caj.CAJContext.connection_timeout = 30.0
com.cosylab.epics.caj.CAJContext.beacon_period = 15.0
com.cosylab.epics.caj.CAJContext.repeater_port = 5065
com.cosylab.epics.caj.CAJContext.server_port = 5064
com.cosylab.epics.caj.CAJContext.max_array_bytes = 4000000
#com.cosylab.epics.caj.CAJContext.event_dispatcher= gov.aps.jca.event.QueuedEventDispatcher
#com.cosylab.epics.caj.CAJContext.event_dispatcher= gov.aps.jca.event.LatestMonitorOnlyQueuedEventDispatcher
com.cosylab.epics.caj.CAJContext.event_dispatcher= gov.aps.jca.event.SplitQueuedEventDispatcher
com.cosylab.epics.caj.CAJContext.logger = com.cosylab.epics.caj.CAJContext
com.cosylab.epics.caj.impl.CachedByteBufferAllocator.buffer_size=32000
com.cosylab.epics.caj.impl.reactor.lf.LeaderFollowersThreadPool.thread_pool_size = 5
其中,最常更改的屬性包括:
com.cosylab.epics.caj.CAJContext.addr_list = 172.0.0.1
com.cosylab.epics.caj.CAJContext.auto_addr_list = false
com.cosylab.epics.caj.CAJContext.repeater_port = 6065
com.cosylab.epics.caj.CAJContext.server_port = 6064
用于與本地主機上運行的EPICS IOC通信,并使用CA服務器端口6064。
GDA還將設置 com.cosylab.epics.caj.CAJContext.event_dispatcher 到 gov.aps.jca.event.SplitQueuedEventDispatcher
后兩個屬性是特定于CAJ的。在大多數情況下,您不需要設置它們,因為默認值就足夠了。但是,如果需要,您可以使用這些屬性來自定義CAJ的內部字節緩沖區大小和線程池大小。
在戴蒙德,我們在一臺EPICS模擬服務器上運行 dasc-epics.diamond.ac.uk
用于GDA軟件的離線開發。其IP地址為172.23.7.113,服務器端口為6064,中繼端口為6065。
9.2. GDA-EPICS接口?
雖然有可能 caget
發件人和 caput
對于GDA內的PV,就像在鉆石控制臺上一樣,為EPICS控制系統與鉆石數據采集系統的集成開發了GDA-EPICS接口規范。此規范在XML中描述 Schema
,它目前定義了此接口中可用的60多種類型的設備。對此接口使用架構定義的好處是:
它確保了GDA和EPICS之間接口的穩定性和兼容性,因為EPICS構建系統為接口生成的XML文件對于此模式始終有效,從而確保EPICS IOC服務的PV始終符合GDA的期望;
它提供了簡單性和設備安全性,使我們能夠僅暴露實驗控制和數據采集過程所需的每個設備的PV子集;
它是直觀和透明的,通過將PV集分組為邏輯單元作為設備,可以使用Java-XML數據綁定提供的特定于域的語言(例如MotorType)輕松訪問這些設備;
允許以后根據開發需要添加新設備類型是可擴展的。
Java-XML數據綁定是使用 CASTOR source code generator 。目前,這是一個手動過程,只有在更新架構時才需要。要建立一個新的 epics-xxx.jar
,您需要在上面運行Ant Build build.xml 在里面 uk.ac.gda.epics/epics.jar.generator/Epics_Interface (Phase II)/
。請記住在中更改版本號 build.xml 根據頂部的說明,所以不要覆蓋現有的EPICS JAR文件,以允許回滾的可能性。在新的 epics-xxx.jar
生成后,必須將其添加到EPICS插件的類路徑中才能生效。
您可以查看支持的設備類型列表 here
9.3. 訪問中的PV字符串 BLxxI-gda-interface.xml
文件?
接口XML文件中定義的設備的PV名稱可以通過上面生成的epics-xxx.jar中的接口類型類進行訪問。例如,在EPICS訪問類中 ADBaseImpl.java
,您可以通過先檢索接口類型配置,然后檢索 Temperature
元素為::
ADBaseType config = Configurator.getConfiguration(getDeviceName(), ADBaseType.class);
String pvString = config.getTemperature().getPv()
您可能已經注意到,我們在這里遵循了命名模式: <ADBase>
中的元素 BLxxI-gda-interface.xml
可以使用 ADBaseType
在epics-xxx.jar中,它用于 ADBaseImpl
班級。它們都共享相同的基本名稱 ADBase
。這樣,我們就可以很容易地從XML接口文件中找到要在Java類中使用的接口類型。
9.4. 獲取/放入腳本的最快方法?
要獲取PV測試值:Sensor1::
from gda.epics import CAClient ca = CAClient() val = ca.caget("test:sensor1")
返回字符串值,
要進行PV測試:Sensor1的值為1::
from gda.epics import CAClient ca = CAClient() ca.caput("test:sensor", 1.0) ca.caput("test:sensor", "1.0")
接受本機類型和字符串
9.5. 獲取/放入腳本的更具表現力的方法?
只需創建一次對象即可重復使用:
from gda.epics import CAClient ca = CAClient("test:sensor1") val = ca.caget() ... some time later ca.caput(1.0) ... when done close the channel ca.clearup()
Caget/Caput因類型不同而不同
Caput可以接受監聽程序或超時
9.6. 使用CAClient使可掃描?
epics_scannables.py::中定義的類
from gda.device.scannable import ScannableMotionBase from gda.epics import CAClient class SimpleEPICSMonitor(ScannableMotionBase): def __init__(self, name, pvstring, unitstring, formatstring): self.setName(name); self.setInputNames([]) self.setExtraNames([name]) self.Units=[unitstring] self.setOutputFormat([formatstring]) self.ca=CAClient(pvstring) self.ca.configure() def rawGetPosition(self): return self.ca.caget() def rawAsynchronousMoveTo(self,position): pass def rawIsBusy(self): return False
導入類定義并創建可掃描的::
import epics_scannables sensor1 = epics_scannables.SimpleEPICSMonitor('sensor1', 'test:sensor1', 'mm', '%.4f') .... pos sensor1 scan motor1 1. 10. 1. sensor1
9.7. 用Java訪問EPICS?
用于獲取/放置雙精度字段的精簡Java Scanable類::
public class SimpleDoubleScannable extends ScannableBase{ ... configure(){ controller = EpicsController.getInstance(); channel = controller.createChannel(pvName); ... asynchronousMoveTo(Object value){ busy = true; controller.caput(getChannel(), (Double) value, putListener); ... (In putListener putCompleted method set busy to false) ... boolean isBusy(){ return busy ... Object rawGetPosition(){ return controller.cagetDouble(channel); ... }
9.8. 一個可掃描的通用類EpicsScan?
在腳本中使用以獲取/設置測試:Sensor2::
from gda.device.scannable import EpicsScannable sensor2=EpicsScannable() sensor2.setName("sensor2") sensor2.setPvName("test:sensor2") sensor2.setUseNameAsInputName(True) sensor2.setUserUnits("mm") sensor2.configure() ... pos sensor2 pos sensor2 "1.2 mm" pos sensor2 "1.2 m"
使用Spring添加到系統::
<bean id="sensor3" class="gda.device.scannable.EpicsScannable"> <property name="PvName" value="test:sensor3"/> <property name="useNameAsInputName" value="true"/> <property name="userUnits" value="mm"/> </bean>
9.9. GDA中的特定設備類?
使用Spring添加到系統::
<bean id="m1_motor" class="gda.device.motor.EpicsMotor"> <property name="pvName" value="test:m1"/> <property name="local" value="true"/> </bean> ... <bean id="m1" class="gda.device.scannable.ScannableMotor"> <property name="motor" ref="m1_motor" /> </bean>