9. 將EPICS集成到GDA中?

../_images/epics_logo.png

EPICS

在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_dispatchergov.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>