Epics PV Server Protocol
EpicsPvServer is the EPICS V4 server-side bridge for exposing PyRogue tree
variables as PVs.
What It Does
EpicsPvServer publishes and serves EPICS-facing process variables using
the PyRogue integration layer.
Server Behavior
EpicsPvServer:
Requires a running
Rootbefore startup.Builds PV mappings either automatically (
base:path) or frompvMap.Supports include and exclude group filtering (default excludes
NoServe).Creates one
EpicsPvHolderper served variable and exposeslist()anddump()helpers for mapping inspection.
Constructor and Mapping Overview
EpicsPvServer(base=..., root=..., incGroups=..., excGroups=..., pvMap=...)
uses two mapping modes:
Automatic mode (
pvMap=None): serves variables that pass group filters using<base>:<path.with.colons>naming.Explicit mode (
pvMapdict): serves only mapped variable paths with user-defined PV names.
Default exclusion is ['NoServe'] when excGroups is not provided.
Setup Example
import pyrogue as pr
import pyrogue.protocols.epicsV4 as pep
class MyRoot(pr.Root):
def __init__(self):
super().__init__(name='MyRoot')
# Add variables/devices here as usual.
# Build EPICS server with automatic path-based naming.
self.epics = pep.EpicsPvServer(
base='MyIoc',
root=self,
incGroups=None,
excGroups=['NoServe'],
pvMap=None,
)
# Register as protocol so Root lifecycle starts/stops it.
self.addProtocol(self.epics)
with MyRoot() as root:
# Inspect active mapping.
root.epics.dump()
# Optionally write mapping to file for IOC/client integration.
root.epics.dump('epics_map.txt')
Typical Usage Pattern
The common setup follows this pattern:
Create and start a
Rootwith Local and Remote variables.Construct
EpicsPvServer(base=..., root=..., pvMap=...).Register it with
root.addProtocol(...).Use a P4P client to put and get values and confirm round-trip behavior.
Use
ctxt.rpc()to invoke PyRogue Commands through EPICS.
RPC for Commands
PyRogue Commands (LocalCommand and RemoteCommand) are automatically
exposed through EPICS RPC when served by EpicsPvServer. The server-side
EpicsPvHandler.rpc() method dispatches incoming RPC requests to the bound
PyRogue Command.
Commands appear in the PV namespace alongside variables and can be invoked from
any P4P client using ctxt.rpc().
Invoking a Command Without Arguments
Use an NTURI with an empty query to call a no-argument command:
from p4p.client.thread import Context
from p4p.nt import NTURI
ctxt = Context('pva')
pv_name = 'MyIoc:MyRoot:MyDevice:ResetCounter'
uri = NTURI([])
ctxt.rpc(pv_name, uri.wrap(pv_name))
On the server side, the handler sees no arg field in the query and calls
the command with no argument.
Invoking a Command With an Argument
To pass a value into a command, declare a query field named arg in the
NTURI. The handler extracts val.arg from the query and forwards it
to the PyRogue command:
from p4p.client.thread import Context
from p4p.nt import NTURI
ctxt = Context('pva')
pv_name = 'MyIoc:MyRoot:MyDevice:SetThreshold'
uri = NTURI([('arg', 'i')]) # 'i' = int32; use 'd' for float64, 's' for string
ctxt.rpc(pv_name, uri.wrap(pv_name, kws={'arg': 42}))
The NTURI type code for the arg field should match the expected value type.
Common type codes are 'i' (int32), 'l' (int64), 'd' (float64), and
's' (string).
P4P Context Behavior After RPC
Note
Calling ctxt.rpc() on a P4P Context may cause subsequent
ctxt.get() calls to return raw p4p.wrapper.Value structs instead of
auto-unwrapped scalars. If you need to continue using ctxt.get() after
an RPC call, use a separate Context for the RPC operation:
rpc_ctxt = Context('pva')
rpc_ctxt.rpc(pv_name, uri.wrap(pv_name))
rpc_ctxt.close()
# The original context continues to return unwrapped scalars.
value = ctxt.get(other_pv)
When To Use It
You need external EPICS clients to consume or control values exposed by Rogue.
Your deployment requires EPICS compatibility alongside existing PyRogue tooling.
You want an explicit server boundary for EPICS protocol behavior.
Integration Guidance
Keep naming and unit conventions aligned between tree variables and EPICS PVs.
Document which PVs are authoritative control points versus status mirrors.
Pair this page with tree-side validation and polling strategy docs when the deployment depends on them.
Logging
EpicsPvServer uses Python logging.
Logger name:
pyrogue.EpicsPvServerLogging API:
pyrogue.setLogLevel('pyrogue.EpicsPvServer', 'DEBUG')
This logger is used for PV mapping errors and other server-side operational messages emitted by the Python implementation.
What To Explore Next
Per-variable EPICS publication behavior: Epics PV Holder Protocol
API Reference
See EpicsPvServer for generated API details.