EPICS PV Access

EPICS PVA transport requires fastcs[epicspva] to be installed.

Supported SECoP data types

EPICS PVA transport supports the following SECoP data types (using the corresponding PVA normative types):

  • double (NTScalar[double])

  • scaled (NTScalar[double])

  • int (NTScalar[int])

  • bool (NTScalar[boolean])

  • enum (NTEnum)

  • string (NTScalar[string])

  • blob (NTNDArray[ubyte])

  • array of double/int/bool/enum* (NTNDArray)

  • tuple of double/int/bool/enum*/string elements (NTTable with one row)

  • struct of double/int/bool/enum*/string elements (NTTable with one row)

  • matrix (NTNDArray)

  • command (if arguments and return values are empty or one of the above types)

Other data types can only be read or written in ‘raw’ mode.

PVI

fastcs exports PVI PVs with the PVA transport.

SECoP modules can be found under the top-level PVI structure, while SECoP accessibles can be found under module_name:PVI. This means that the IOC is self-describing to downstream clients.

Example PVA IOC

"""Example PVA IOC using :py:obj:`fastcs_secop`."""

import argparse
import asyncio
import logging
import socket

from fastcs.connections import IPConnectionSettings
from fastcs.launch import FastCS
from fastcs.logging import LogLevel, configure_logging

from fastcs_secop import SecopController, SecopQuirks

if __name__ == "__main__":
    from fastcs.transports import EpicsIOCOptions
    from fastcs.transports.epics.pva import EpicsPVATransport

    parser = argparse.ArgumentParser(description="Demo PVA ioc")
    parser.add_argument("-i", "--ip", type=str, default="127.0.0.1", help="IP to connect to")
    parser.add_argument("-p", "--port", type=int, help="Port to connect to")
    args = parser.parse_args()

    configure_logging(level=LogLevel.DEBUG)
    logging.basicConfig(level=LogLevel.DEBUG)

    asyncio.get_event_loop().slow_callback_duration = 1000

    epics_options = EpicsIOCOptions(pv_prefix=f"TE:{socket.gethostname().upper()}:SECOP")
    epics_pva = EpicsPVATransport(epicspva=epics_options)

    quirks = SecopQuirks(
        raw_accessibles=[
            ("valve_controller", "_domains_to_extract"),
            ("valve_controller", "_terminal_values"),
        ],
    )

    controller = SecopController(
        settings=IPConnectionSettings(ip=args.ip, port=args.port),
        quirks=quirks,
    )

    fastcs = FastCS(
        controller,
        [epics_pva],
    )
    fastcs.run(interactive=True)