Helper module for creating EPICS PVAccess servers using p4p
Project description
epicsdev
epicsdev is a small Python toolkit for building EPICS PVAccess servers with
p4p.
It is intended for fast development of simulated devices, instrument front ends, and stress-test servers that publish scalars, waveforms, and images.
Background reading: Why Python-based servers are essential for large EPICS facility like future EIC
What epicsdev provides
- A simple API for defining and hosting PVs
- Built-in IOC-style helper PVs for status and basic statistics
- Autosave/restore of writable PV values
- Optional logging of
putoperations to a separate PV - Example applications for waveforms, images, and text logging
In practice, it combines a Python helper library with a few services commonly expected from EPICS IOCs:
- Autosave: save writable PV values and restore them on restart
- IOC-stats-style PVs: host name, uptime, heartbeat, CPU load, and related PVs
- Put logging: optional forwarding of
putactivity to a logging PV
Package contents
| Module | Purpose |
|---|---|
epicsdev.epicsdev |
Core helper functions for creating PVAccess servers |
epicsdev.imagegen |
Synthetic image generator for high-throughput testing |
epicsdev.putlog |
Text logger driven by a writable PV |
config/ |
Example pypeto pages and a Phoebus display |
Installation
Install the base package:
python -m pip install epicsdev
Optional tools for GUI pages and plotting:
python -m pip install pypeto pvplot
Quick start
Start the built-in demo server:
python -m epicsdev.epicsdev
The demo uses the default PV prefix:
epicsDev0:
Open the example control page
python -m pypeto -c config -f epicsdev
This page gives you:
- basic server control
- live parameter monitoring
- waveform plotting helpers
Screenshots:
Phoebus display
An example Phoebus display file is included at config/epicsdev.bob. Screenshot: Phoebus display
Minimal programming model
The typical workflow is:
- define PVs
- initialize the server with
init_epicsdev() - start a
p4p.server.Server - publish updates from your polling loop
PV definitions are lists with this shape:
[name, description, initial_value, extra]
Where extra is optional and may include keys such as:
features: PV features such as writable or discretetype: explicit EPICS type, for exampleu32orf32units: engineering unitslimitLow,limitHigh: write limitssetter: callback invoked on writesvalueAlarm: value alarm configuration
Normative Type (NT) selection from initial_value
epicsdev selects the underlying PV normative type from initial_value
(unless overridden by extra["type"]).
Current behavior:
initial_value |
features |
Chosen NT | Notes |
|---|---|---|---|
NumPy ndarray |
any | NTNDArray |
Current implementation routes any NumPy array to NTNDArray. |
| list of choices | contains D |
NTEnum |
Value is stored as {choices, index}; initial index is 0. |
scalar (int, float, str) |
no D |
NTScalar |
Default scalar mappings: int -> i32, float -> f32, str -> s. |
| iterable (for example list/tuple) | no D |
NTScalarArray |
Element type is inferred from the first item. |
Type-code mapping follows p4p scalar codes (for example i32, u32, f32,
f64, s8, ...). You can force a specific type using extra["type"].
Examples:
42->NTScalar(i32)3.14->NTScalar(f32)[1, 2, 3]->NTScalarArray(i32)['OFF', 'ON']with{"features": "D"}->NTEnumnp.zeros((120, 120), dtype=np.int16)->NTNDArray
Notes:
- For discrete PVs (
D), autosave stores the enum index rather than the choice text, so updated choice lists can still be restored predictably. - For iterable non-NumPy values, keep the initial sequence non-empty so element type inference is unambiguous.
Minimal example:
from p4p.server import Server
from epicsdev.epicsdev import init_epicsdev, publish, pvv, set_server, sleep
pv_defs = [
["temperature", "Simulated temperature", 25.0, {"features": "W", "units": "C"}],
["waveform", "Example waveform", [0.0], {"units": "V"}],
]
pvs = init_epicsdev("demo0:", pv_defs, verbose=1)
server = Server(providers=[pvs])
set_server("Start")
while True:
publish("temperature", pvv("temperature") + 0.01)
if not sleep():
pass
Example applications
epicsdev.imagegen
imagegen generates synthetic 2D images with a grid of Gaussian blobs and
optional per-row PVs.
It publishes:
- a noisy image
- PVs that control image size, blob count, blob width, and noise level
- 10,000 of dynamicaly-changed waveform int16 PVs, each representing 1000-point row.
- The publishing performance is 55,000 of PVs per second (110 MB/s).
The generated data is intended for high-throughput testing of EPICS clients, transport, and visualization tools.
epicsdev.putlog
putlog hosts a writable PV named dump and appends received text to a file.
Start the logger:
python -m epicsdev.putlog /tmp/putlog.txt
By default, the logger prefix is:
putlog0:
Write text to it with:
pvput putlog0:dump "hello from client"
Notes on autosave and helper PVs
When you initialize a server with init_epicsdev(), epicsdev automatically
adds a standard set of helper PVs before your application-specific PVs. These
include PVs such as:
HOSTNAMEVERSIONHEARTBEATUPTIMECPU_LOADstatusserververbosesleepcyclecycleTime
Writable PV values can be stored in an autosave file and restored on restart.
This makes epicsdev practical for interactive development and lab setups
where operator-tuned values should survive process restarts.
AI-assisted device support workflow
epicsdev is intentionally small and explicit, which makes it convenient for
AI-assisted code generation and device support prototyping.
Typical workflow:
- identify a device API or programming manual
- define PVs and their setter callbacks
- generate a first server implementation from an existing
epicsdevexample - review, test, and refine
One example built this way is epicsdev_tektronix.
Requirements
- Python 3.7+
p4p>=4.2.2psutil
Optional:
pypetopvplot- Phoebus for
.bobdisplay files
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file epicsdev-3.2.1.tar.gz.
File metadata
- Download URL: epicsdev-3.2.1.tar.gz
- Upload date:
- Size: 248.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ee46c3cf90b91f03f19618f95811d3ff58af331fc88d1a722be03c2d2de0c3b1
|
|
| MD5 |
c1f566396f3e341e312de51312ced6b8
|
|
| BLAKE2b-256 |
9f42133b633ac52dd36e2f7c38576ebbc26ac0f168d952f4e8cacc22eabbd37a
|
File details
Details for the file epicsdev-3.2.1-py3-none-any.whl.
File metadata
- Download URL: epicsdev-3.2.1-py3-none-any.whl
- Upload date:
- Size: 18.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b6a0e04c54ea4f6390e4cd2210b1a7d7ec7642153cd621a2244f6c9920b73391
|
|
| MD5 |
d7abab48e207ea5c0b2fabc23cf4f24d
|
|
| BLAKE2b-256 |
4c271b39d7515a4aaa1b37623425dd5edab2de35f9a9c606b71d24d8a4010326
|