Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  1. support already present in <ibek-support>
  2. support present as git project
  3. support not present at all → put in the condition 2

Use an existing ibek support
Anchor
existing ibek support
existing ibek support

If a support is present in <ibek-support>, it's very simple to use it just create a yaml that instantiates  your device(s).

...

Code Block
languagebash
titleDocker image creation and run as ioc
docker run -p 5064:5064/udp -p 5064:5064/tcp -p 5065:5065/udp -p 5065:5065/tcp -it -v .:/epics/ioc/config baltig.infn.it:4567/epics-containers/infn-epics-ioc:localdevel 


A generic asyn motor OPI interface  can be used to drive the motor. Motor OPIs Remember to add localhost to your phoebus 

...

Once the IOC runs correctly as docker can be inserted in the EPIK8S configuration


Build a support from existing git support

This is path is more complex, but gives much more satisfaction, in fact each time you add a new support as much generic possible you greatly simplify the life of your self and in principle many other people will use the your support.

Step 1 create a directory inside ibek-support


Create by copy and renaming one of the existing support. Suppose you want to add the support for <mydevmodule>, you should have:

...

So in general just two file must be added: install.sh and mydevmodule.ibek.support.yaml.

install.sh

This file  contains instructions on howto retrieve, compile and link  dependencies of your module mydevmodule. In general if the mydevmodule  is well structured from a build epics point of view needs only to be patched like that:

Code Block
languagebash
titleinstall.sh
#!/bin/bash

# ARGUMENTS:
#  $1 VERSION to install (must match repo tag)
VERSION=${1}
NAME=<mydevmodule>  ## as compare in the git repository
FOLDER=$(dirname $(readlink -f $0))

# log output and abort on failure
set -xe

# get the source and fix up the configure/RELEASE files
ibek support git-clone ${NAME} ${VERSION} --org http://gitrepo ## repository git root
ibek support register ${NAME}

# declare the libs and DBDs that are required in ioc/iocApp/src/Makefile
ibek support add-libs <mydevmodulelib> <support1lib> <support2lib> asyn ## optional libraries that must be linked
ibek support add-dbds <mydevmodule>.dbd <optsupport1.dbd> <optsupport2>.dbd ### optional dbd supports
# global config settings
${FOLDER}/../_global/install.sh ${NAME}

# compile the support module
ibek support compile ${NAME}
# prepare *.bob, *.pvi, *.ibek.support.yaml for access outside the container.
ibek support generate-links ${FOLDER}




mydevmodule.ibek.support.yaml

This also has a very simple syntax and gives instructions on how to expand a future yaml configuration.

...

Code Block
languageyml
titleExample
# yaml-language-server: $schema=https://github.com/epics-containers/ibek/releases/download/1.5.0/ibek.support.schema.json

# #errlogInit(5000)
# < envPaths
# # Tell EPICS all about the record types, device-support modules, drivers,
# # etc.
# dbLoadDatabase("../../dbd/newport.dbd")
# newport_registerRecordDeviceDriver(pdbbase)

# ### Motors
# dbLoadTemplate "motor.substitutions.SMC100"

# ### Serial port setup
# drvAsynSerialPortConfigure("serial1", "/dev/ttyS0", 0, 0, 0)
# asynSetOption(serial1,0,baud,57600)
# asynOctetSetInputEos("serial1",0,"\r\n")
# asynOctetSetOutputEos("serial1",0,"\r\n")

# ### Newport SMC100 support
# # (driver port, serial port, axis num, ms mov poll, ms idle poll, egu per step)
# SMC100CreateController("SMC100_1", "serial1",1, 100, 0, "0.00005")

# file "$(TOP)/db/basic_asyn_motor.db"
# {
# pattern
# {P,      N,     M,         DTYP,      PORT,  ADDR,    DESC,        EGU,     DIR,  VELO,  VBAS,  ACCL,  BDST,  BVEL,  BACC,  MRES,  PREC,  DHLM,  DLLM,  INIT, RTRY}
# {IOC:,  1,  "m$(N)",  "asynMotor",  "SMC100_1",  0,  "GTS30V",      mm,     Pos,  1,     0,    .2,    0,     .5,     .2,    0.00001,  6,     25,   -5,  ""}
# }
# iocInit

module: motorNewport

defs:
  - name: SMC100CreateController
    description: |-
      Creates a SMC100 motion controller connected to an ethernetToSerialServer

    args:
      - type: id
        name: controllerName
        description: |-
          The name of the controller and its Asyn Port Name
      
      - type: str
        name: P
        description: |-
          Device PV Prefix

      - type: str
        name: IP
        description: |-
          IP address of the ethernet2serial
        default: 127.0.0.1 ## localhost

      - type: int
        name: TCPPORT
        description: |-
          Port of the ethernet2serial
        default: 4001
      
      - type: int
        name: POLL
        description: |-
          Movement poll ms
        default: 100
      
      - type: float
        name: EGUXSTEP
        description: |-
          EGU PER STEP
        default: 0.00005

      - type: int
        name: ASYNPRIO
        description: |-
          ASYN   PRIORITY, Default : 0
        default: 0

      - type: int
        name: AUTOCONNECT
        description: |-
          Asyn auto connect
          0: Auto connection
          1: no Auto connection
        default: 0

      - type: int
        name: NOPRECESSESOS
        description: |-
          ASYN   noProcessEos, Default : 0
          https://epics.anl.gov/tech-talk/2020/msg01705.php
        default: 0

      

      - type: int
        name: numAxes
        description: |-
          The number of axes to create

    pre_init:

      - value: |
          # epicsEnvSet "STREAM_PROTOCOL_PATH", "$(MOTORNEWPORT)/protocol/"
          # Create Asyn Port
          drvAsynIPPortConfigure("{{controllerName}}_ASYN", "{{IP}}:{{TCPPORT}}", {{ASYNPRIO}}, {{AUTOCONNECT}}, {{NOPRECESSESOS}})
          # asynInterposeEosConfig("{{controllerName}}_ASYN",0,2000,0)
          SMC100CreateController("SMC100_{{controllerName}}", "{{controllerName}}_ASYN","{{numAxes}}", "{{POLL}}", 0, "{{EGUXSTEP}}")
          asynOctetSetInputEos({{controllerName}}_ASYN,0,"\r\n")
          asynOctetSetOutputEos({{controllerName}}_ASYN,0,"\r\n")
          asynReport 10
          

  - name: motorAxis
    description: |-
      Creates a motor axis

    args:
      - type: object
        name: controller
        description: |-
          a reference to the motion controller

      - type: str
        name: M
        description: |-
          PV suffix for the motor record

      - type: int
        name: ADDR
        description: |-
          The axis number (allowed to be from 0 to controller.numAxes-1)

      - type: str
        name: DESC
        description: |-
          The description of the axis

      - type: int
        name: DLLM
        description: |-
          The low limit of the axis
        default: -5

      - type: int
        name: DHLM
        description: |-
          The high limit of the axis
        default: 25

      - type: int
        name: VELO
        description: |-
          Velocity
        default: 1

      - type: int
        name: home
        description: |-
          The home position of the axis (in counts)

      - type: int
        name: start
        description: |-
          The starting position of the axis (in counts)
        default: 0

      - type: enum
        name: DIR
        description: |-
          The direction of the axis
        default: 0
        values:
          Pos: 0
          Neg: 1

      - type: str
        name: EGU
        description: |-
          Engineering Units
        default: "mm"
      
      - type: float
        name: VBAS
        description: |-
          Base Velocity (EGU/s)
        default: 0.2

      - type: float
        name: ACCL
        description: |-
          Seconds to Velocity
        default: 0.2

      - type: int
        name: BDST
        description: |-
          BL Distance (EGU)
        default: 0

      - type: float
        name: BVEL
        description: |-
          BL Velocity (EGU/s)
        default: 0.5

      - type: float
        name: BACC
        description: |-
          BL Seconds to Veloc.
        default: 0.2

      - type: float
        name: MRES
        description: |-
          Motor Step Size (EGU)
        default: 0.00001

      - type: int
        name: PREC
        description: |-
          Display precision (EGU)
        default: 6
      
    databases:
      # TODO as this is a simulation I have hard coded some of the DB fields,
      # but these could easily be made into arguments above
      #
      # Note: supplying no value means that the argument of the same name is used
      # (the most common case - if you contrive to make args and db fields the same.
      # Which is  good idea for ease of transition from traditional IOCs)
      - file: basic_asyn_motor.db
        args:
          P: "{{controller.P}}"
          N: "{{ADDR +1 }}"
          M:
          DTYP: "asynMotor"
          PORT: "SMC100_{{controller}}"
          ADDR:
          DESC:
          EGU: 
          DIR:
          VELO:
          VBAS:
          ACCL:
          BDST:
          BVEL:
          BACC:
          MRES: 
          PREC:
          DHLM: 
          DLLM: 
          INIT: ""
    post_init:
      - value: |
          dbl


Step 2 add an entry into Dockerfile

Modify the Dockerfile in the project:

Code Block
titleDockerfile
##### build stage ##############################################################

ARG TARGET_ARCHITECTURE
ARG BASE=7.0.8ec1b3
ARG REGISTRY=ghcr.io/epics-containers

FROM  ${REGISTRY}/epics-base-${TARGET_ARCHITECTURE}-developer:${BASE} AS developer


# The devcontainer mounts the project root to /epics/generic-source
# Using the same location here makes devcontainer/runtime differences transparent.
ENV SOURCE_FOLDER=/epics/generic-source
# connect ioc source folder to its know location
RUN ln -s ${SOURCE_FOLDER}/ioc ${IOC}

# Get latest ibek while in development. Will come from epics-base when stable
COPY requirements.txt requirements.txt
RUN pip install --upgrade -r requirements.txt

WORKDIR ${SOURCE_FOLDER}/ibek-support

# copy the global ibek files
COPY ibek-support/_global/ _global

COPY ibek-support/iocStats/ iocStats
RUN iocStats/install.sh 3.2.0

################################################################################
#  TODO - Add further support module installations here
################################################################################

COPY ibek-support/asyn/ asyn/
RUN asyn/install.sh R4-44

COPY ibek-support/autosave/ autosave/
RUN autosave/install.sh R5-11

COPY ibek-support/busy/ busy/
RUN busy/install.sh R1-7-3

COPY ibek-support/StreamDevice/ StreamDevice/
RUN StreamDevice/install.sh 2.8.24

COPY ibek-support/sscan/ sscan/
RUN sscan/install.sh R2-11-6

COPY ibek-support/calc/ calc/
RUN calc/install.sh R3-7-5

COPY ibek-support/motor/ motor/
RUN motor/install.sh R7-3

COPY ibek-support/motorMotorSim/ motorMotorSim/
RUN motorMotorSim/install.sh R1-2

COPY ibek-support/ADCore/ ADCore/
RUN ADCore/install.sh R3-13

COPY ibek-support/ADGenICam ADGenICam/
RUN ADGenICam/install.sh R1-9
COPY ibek-support/ADSimDetector ADSimDetector/
RUN ADSimDetector/install.sh R2-10

COPY ibek-support/modbus/ modbus/
RUN modbus/install.sh R3-3

COPY ibek-support/screen-epics-ioc screen-epics-ioc/
RUN screen-epics-ioc/install.sh v1.3.1

COPY ibek-support/motorNewport motorNewport/
RUN motorNewport/install.sh R1-2-1

# COPY ibek-support/easy-driver-epics/ easy-driver-epics/
# RUN easy-driver-epics/install.sh master

COPY ibek-support/mydevmodule mydevmodule          ### HERE
RUN mydevmodule/install.sh master				   ## HERE


# get the ioc source and build it
COPY ioc/ ${SOURCE_FOLDER}/ioc
RUN cd ${IOC} && ./install.sh && make

##### runtime preparation stage ################################################

FROM developer AS runtime_prep

# get the products from the build stage and reduce to runtime assets only
RUN ibek ioc extract-runtime-assets /assets ${SOURCE_FOLDER}/ibek*

##### runtime stage ############################################################

FROM ${REGISTRY}/epics-base-${TARGET_ARCHITECTURE}-runtime:${BASE} AS runtime

# get runtime assets from the preparation stage
COPY --from=runtime_prep /assets /

# install runtime system dependencies, collected from install.sh scripts
RUN ibek support apt-install-runtime-packages --skip-non-native

ENV TARGET_ARCHITECTURE ${TARGET_ARCHITECTURE}

CMD ["/bin/bash", "-c", "${IOC}/start.sh"]


Step 3 build docker image

...


building:

Code Block
titleBuild Image
git clone https://baltig.infn.it/epics-containers/infn-epics-ioc.git --recurse-submodules
cd infn-epics-ioc
docker build --build-arg TARGET_ARCHITECTURE="linux" --build-arg TARGETARCH="amd64" -t baltig.infn.it:4567/epics-containers/infn-epics-ioc:local ## build

.

building development:

Code Block
titleBuild Image
git clone https://baltig.infn.it/epics-containers/infn-epics-ioc.git --recurse-submodules
cd infn-epics-ioc
docker build -f Dockerfile.devel --build-arg TARGET_ARCHITECTURE="linux" --build-arg TARGETARCH="amd64" -t baltig.infn.it:4567/epics-containers/infn-epics-ioc:devel .

Step 4 motor yaml instance

Write a mymotor.yaml ibek instance of the support just created and built:

Code Block
languageyaml
titleYAML instance
gioc_name: rfmotors
description: RF motors 

entities:

  - type: motorNewport.SMC100CreateController
    controllerName: NEWPORT001
    P: "SPARC:RF:"
    IP: 192.168.190.56
    TCPPORT: 4001
    numAxes: 1

  
  - type: motorNewport.motorAxis
    controller: NEWPORT001
    M: "m0"
    DESC: "Axis"
    ADDR: 0
    DLLM: -25
    DHLM: 25
    home: 1
    start: 10
    VELO: 1
test instance

the following lines will mount the current directory that contains mymotor.yaml in the container /epics/ioc/config and will expose CA ports, then run the support just created:

Code Block
languagebash
titleRun Image and test
docker run -p 5064:5064/udp -p 5064:5064/tcp -p 5065:5065/udp -p 5065:5065/tcp -p 5075:5075/tcp  -p 5076:5076/udp -it -v .:/epics/ioc/config -v .:/epics/ioc/config baltig.infn.it:4567/epics-containers/infn-epics-ioc:local
root@3870c1890419:/epics/generic-source/ioc/config# /epics/ioc/start.sh
... io log
....
....

the following lines use the development image:

Code Block
languagebash
titleRun devel image
cd <myibek yaml instance>
docker run -p 5064:5064/udp -p 5064:5064/tcp -p 5065:5065/udp -p 5065:5065/tcp -p 5075:5075/tcp -p 5076:5076/udp -it -v .:/epics/ioc/config baltig.infn.it:4567/epics-containers/infn-epics-ioc:devel
root@3870c1890419:/epics/generic-source/ioc/config# /epics/ioc/start.sh
...
log
...

For test refer to existing ibek supportFor test refer to Integration and Standardization existing development (IBEK)