A pluggable task/job framework for IOC Manager applications with REST API
Project description
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
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 iocmng-2.7.3.tar.gz.
File metadata
- Download URL: iocmng-2.7.3.tar.gz
- Upload date:
- Size: 76.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a3e33a1129f8a6e884bb837498511616b524e42879d502278421ffbba322651b
|
|
| MD5 |
b7dca7b1fe7bd2201df5beb2a1330cd8
|
|
| BLAKE2b-256 |
f0b6a2e0921732e542895d4d68ac55752da27dd3daa110b4d99868ea9b5d2afc
|
File details
Details for the file iocmng-2.7.3-py3-none-any.whl.
File metadata
- Download URL: iocmng-2.7.3-py3-none-any.whl
- Upload date:
- Size: 60.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5c2253cd876f470316863c9156866ef0af1f7b14c209faf1f92e29713cee5aea
|
|
| MD5 |
47e08603f1c3dc75736e0179adb241cc
|
|
| BLAKE2b-256 |
bfec880f0c0214883bf66f3015cda277a548159cb10ca96e0aded5412291f08a
|