iocmng — IOC Manager Framework
A pluggable task/job framework for EPICS soft IOC applications on Kubernetes. Provides base classes for continuous tasks and one-shot jobs, a declarative rule/transform engine, and a REST API for dynamic plugin management at runtime.
Key Features
TaskBase— base class for continuous, triggered, or reactive tasksJobBase— base class for one-shot jobs returning structured resultsDeclarativeTask— zero-code tasks driven entirely byconfig.yamlrules and transforms- Wired inputs/outputs — automatically read/write external PVs (poll or monitor)
- Connection tracking —
CONN_INP/CONN_OUTwaveform PVs show live CA/PVA connection state per port - Declarative rules — safe boolean expressions that fire actuators and set outputs
- Output latch —
latch: trueholds an output value until an operator writesCLEAR;latch_dirselects which transition latches (rise / fall / any) - ALARM severity —
alarm_on: MAJOR|MINORwires EPICS alarm fields directly from config - Transforms — computed outputs using built-in math/statistics/array functions
- Ring buffers —
buffer_sizeaccumulates time-series data for signal processing - Built-in function library —
mean,std,sqrt,clamp,moving_avg,derivative, and more - Safe expression evaluator — AST-validated expressions; no arbitrary code execution
- REST API — add/remove/restart plugins at runtime from git repos or local paths
- EPICS soft IOC PVs — every task gets STATUS, MESSAGE, ENABLE, VERSION, CYCLE_COUNT, CLEAR, RESET PVs
- Per-plugin
config.yaml— parameters, directional PVs, rules, transforms in one file - PV client abstraction — transparent PVA (p4p) or CA (PyEPICS) access; ENABLE/CLEAR/RESET polled each cycle to catch external writes
- Plugin validation — syntax, inheritance, abstract methods checked before acceptance
- Docker image — ready-to-run container with the REST API
- Standalone runner —
iocmng-runfor local development without a server - Optional Ophyd — device abstraction via
ophyd/infn_ophyd_hal
Quick Start
Install
pip install iocmng
# With all optional dependencies
pip install iocmng[all]
Run the API Server
iocmng-server
# With configuration
IOCMNG_PORT=8080 IOCMNG_PREFIX=SPARC:CONTROL iocmng-server
Create a Task (Python)
my_monitor.py
from iocmng import TaskBase
class MyMonitor(TaskBase):
def initialize(self):
self.logger.info("Starting monitor")
def execute(self):
value = self.get_pv("READING")
if value and value > self.parameters.get("threshold", 75):
self.set_pv("ALARM", 1)
def cleanup(self):
pass
config.yaml
parameters:
mode: continuous
interval: 1.0
threshold: 75.0
arguments:
inputs:
SETPOINT:
type: float
value: 50.0
unit: "%"
prec: 2
low: 0
high: 100
outputs:
READING:
type: float
value: 0.0
ALARM:
type: bool
value: 0
znam: "OK"
onam: "ALARM"
Create a Declarative Task (Zero Code)
No Python needed — all logic lives in config.yaml:
my_interlock.py
from iocmng import DeclarativeTask
class MyInterlock(DeclarativeTask):
pass
config.yaml
parameters:
mode: continuous
interval: 1.0
pva: false
arguments:
inputs:
temp:
type: float
value: 0.0
link: "DEVICE:TEMP" # Wired to external PV
link_mode: monitor # monitor pushes values; poll reads each cycle
buffer_size: 100 # Keep last 100 readings
pressure:
type: float
value: 0.0
link: "DEVICE:PRESSURE"
link_mode: monitor
outputs:
avg_temp:
type: float
value: 0.0
alarm:
type: bool
value: 0
znam: "OK"
onam: "ALARM"
latch: true # Hold value until CLEAR is written
latch_dir: "rise" # Latch on 0→1 transition (default)
alarm_on: MAJOR # EPICS ALARM severity when output is 1
transforms:
- output: avg_temp
expression: "mean(temp_buf)"
rule_defaults:
alarm: 0
rules:
- id: OVER_TEMP
condition: "mean(temp_buf) > 80 or pressure > 2.0"
message: "Temperature or pressure limit exceeded"
outputs:
alarm: 1
Run Standalone (no server)
iocmng-run -m my_interlock --config config.yaml --prefix MY:IOC --name interlock
Deploy via REST API
curl -X POST http://localhost:8080/api/v1/plugins \
-H "Content-Type: application/json" \
-d '{
"name": "my-interlock",
"git_url": "https://github.com/org/my-tasks.git",
"path": "plugins/interlock/",
"auto_start": true
}'
Documentation
| Document | Description |
|---|---|
| MANUAL.md | Complete reference: architecture, API, configuration, all features |
| HOWTO.md | Step-by-step recipes for common tasks |
| INSTALL.md | Installation and environment setup |
Task Modes
| Mode | Behavior | Use Case |
|---|---|---|
continuous |
execute() loops with interval sleep |
Monitoring, polling, periodic updates |
triggered |
triggered() called when RUN PV is written |
Operator-driven actions from CS-Studio |
reactive |
on_input_changed() fires on wired input change |
Event-driven interlocks, fast response |
Built-in Functions
Available in rule conditions and transform expressions:
| Category | Functions |
|---|---|
| Math | abs, round, sqrt, log, exp, pow, floor, ceil, clamp |
| Statistics | mean, std, variance, median, rms, min, max |
| Logic | any_of, all_of, count_true |
| Array | length, sum_of, diff, last, moving_avg, derivative |
Extend with register("my_fn", callable) from iocmng.core.functions.
Default PVs
Every task automatically gets:
| PV | Type | Description |
|---|---|---|
ENABLE |
boolOut | Enable/disable the task (readable and writable from any CA/PVA client) |
STATUS |
mbbIn | INIT / RUN / PAUSED / END / ERROR |
MESSAGE |
stringIn | Human-readable status |
VERSION |
stringIn | Framework or plugin version string |
CYCLE_COUNT |
longIn | Cycle counter (continuous / reactive modes) |
RUN |
boolOut | Trigger execution (triggered mode) |
CLEAR |
boolOut | Release all latched outputs (write 1 to pulse) |
RESET |
boolOut | Clear latches + reset cycle counter + re-init connectivity (write 1 to pulse) |
CONN_INP |
WaveformIn | Per-port connection state for wired inputs (1=connected, 0=disconnected) |
CONN_OUT |
WaveformIn | Per-port connection state for wired outputs |
Environment Variables
| Variable | Default | Description |
|---|---|---|
IOCMNG_PREFIX |
— | Controller PV prefix |
IOCMNG_PORT |
8080 |
Server port |
IOCMNG_HOST |
0.0.0.0 |
Server bind address |
IOCMNG_PLUGINS_DIR |
/data/plugins |
Plugin clone directory |
IOCMNG_PLUGINS_CONFIG |
— | Startup plugins YAML |
IOCMNG_LOG_LEVEL |
info |
Logging level |
IOCMNG_PVA |
true |
Use PVA (true) or CA (false) |
IOCMNG_DISABLE_OPHYD |
true |
Skip ophyd initialization |
Project Structure
src/iocmng/
├── __init__.py # Exports: TaskBase, JobBase, DeclarativeTask, pv_client, run_ioc
├── declarative.py # DeclarativeTask (zero-code tasks)
├── runner.py # Standalone CLI runner (iocmng-run)
├── base/
│ ├── task.py # TaskBase — continuous/triggered/reactive tasks
│ └── job.py # JobBase — one-shot jobs
├── core/
│ ├── controller.py # Central plugin manager
│ ├── loader.py # Git clone + config loading
│ ├── validator.py # Plugin validation
│ ├── plugin_spec.py # PvArgumentSpec, PluginSpec, RuleSpec, TransformSpec
│ ├── safe_eval.py # AST-validated expression evaluator
│ ├── functions.py # Built-in function registry
│ └── pv_client.py # PVA/CA abstraction layer
├── api/
│ ├── app.py # FastAPI application
│ ├── routes.py # REST endpoints
│ └── models.py # Pydantic models
└── ophyd/
└── factory.py # Optional ophyd device creation
Development
pip install -e ".[dev]"
pytest tests/ -v
black .
flake8 .
License
MIT
Metadata
Release files for iocmng 2.7.9
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| iocmng-2.7.9.tar.gz | 79.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| iocmng-2.7.9-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 141.7 kB
Release files / iocmng-2.7.9.tar.gz
| Download URL | iocmng-2.7.9.tar.gz |
|---|---|
| Size | 79.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
baf17cf54cf2cdb44de2c73ad816a185db4becc6b1427d2b232fbb7563307e0f
|
|
BLAKE2b-256 checksum How to use checksums |
0ece57e0a724fb771a6949770e2ea9f211c13e8d3a976868db0b9549e0a1c1dc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Release files / iocmng-2.7.9-py3-none-any.whl
| Download URL | iocmng-2.7.9-py3-none-any.whl |
|---|---|
| Size | 62.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7554f29e21915a5ae7e388108333ac85cd77bf98fa04a77ea46e42438ce90d09
|
|
BLAKE2b-256 checksum How to use checksums |
2efb50830809f1aa2bdf7b9e1f1ab6299570ee7c7bb8fe7892c04a1fb99c8faf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|