Releases: XavSPM/RevpiEpics
RevPiEpics v0.2.1
Release Notes - RevPiEpics v0.2.1
What's New: Architecture, Flexibility, and Autosave
1. Internal Architecture Refactoring (IOMap)
The monolithic IOMap object has been refactored into a cleaner object-oriented hierarchy. Analog inputs/outputs now use the AnalogIOMap class, which reduces the memory footprint for simple binary signals and removes numerous redundant conditional checks.
2. Native Autosave Integration (softioc.autosave)
It is now possible to enable automatic backup of EPICS configuration states:
- Global Activation: In
RevPiEpics.init(..., autosave=True, autosave_dir="/tmp/save"). - Granular Control: When creating an analog PV, you can specify
autosave_multiplier=Trueorautosave_offset=Trueto specifically save these parameters to the.softsavfile. - The standard
autosave=...parameter for primary variables is fully supported out of the box (e.g.,autosave=["PREC", "EGU", "VAL"]).
3. Simplified Software Scaling (Float PVs)
The previous behavior that generated an integer "DIVISOR" PV has been safely removed. The system now strictly relies on a :MULTIPLIER and an :OFFSET. Both PVs are now exported as Floating-point Records (aOut). They fully accept standard decimal computations (e.g. 0.1 instead of dividing by 10) and negative values.
4. Direct Scaling Parameter Setup
When building an analog I/O, developers can disregard PiCtory's system hardware defaults and manually inject the soft EPICS startup configuration straight from python:
RevPiEpics.builder("IN1", initial_multiplier=1.5, initial_offset=20.0)
5. Enriched Object API
The RecordWrapper Python object returned by RevPiEpics.builder(...) when targeting an analog module now structurally integrates its child scaling records. You can dynamically drive tracking parameters from Python execution logic: my_sensor.offset.set(10).
AIO Engine Core Mechanics (Reminder)
Delegated Mathematical Computation (SoftIOC)
At initialization, the system imports the software parameters mapped in PiCtory to establish an absolute factory baseline. The new scalable conversion is managed entirely by live synchronized computations across the soft PV backend (pvsync.py).
Real-time EPICS Editing
An operator can freely modify the mapped Soft PVs (like caput IN2_1:MULTIPLIER 0.5) to instantly adjust the underlying behavior:
- Reading (IN): Inverse calculation from the initial raw binary value scaling back to base zero, subsequently layered dynamically beneath the new EPICS ratio.
- Writing (OUT): Resolves the SCADA request according to the EPICS layer, then translates and applies the factory hardware ratio to pipeline directly to the Digital-to-Analog hardware converter.
What's Changed
Full Changelog: 0.2.0...0.2.1
RevpiEpics v0.2.0
RevpiEpics v0.2.0 - Major API Refactor 🚀
🎉 What's New
This major release brings a complete API refactor for simpler and more intuitive usage, along with improved support for asynchronous programming.
✨ Key Improvements
- 🔄 API Refactor: Migration from instance-based API to static methods
- ⚡ Enhanced Asyncio Support: Native integration with AsyncioDispatcher
- ⏱️ Cycletime Control: Customizable configuration of IO loop cycle time
- 🔧 Custom Functions: Add user tasks to the main loop with add_loop_task()
- 📚 Enhanced Documentation: Complete examples for cothread and asyncio
- 🛠️ Simplified Installation: Detailed instructions for virtual environments
🆕 New Features
- add_loop_task(): Allows adding custom functions to the main IO loop
- Practical Examples: Complete implementations for cothread and asyncio
- RevPi Commander Compatibility: System installation with
--break-system-packages
📋 Usage Examples
Simple Usage
from softioc import builder
from revpiepics import RevPiEpics
builder.SetDeviceName("TEST")
RevPiEpics.init(debug=True, cycletime=200)
# Create PVs
ai1 = RevPiEpics.builder("OutputStatus_2_i06")
ai2 = RevPiEpics.builder("OutputStatus_1_i06", "Out1Status")
ao1 = RevPiEpics.builder(io_name="OutputValue_1_i06", pv_name="Out1", DESC="Output 1", EGU="mV")
# Start IOC and IO loop
RevPiEpics.start()With Custom Function (add_loop_task)
from softioc import builder
from revpiepics import RevPiEpics
builder.SetDeviceName("TEST")
RevPiEpics.init(debug=True, cycletime=200)
ai1 = RevPiEpics.builder(io_name="OutputValue_1_i06", pv_name="Out1")
ai2 = RevPiEpics.builder(io_name="InputValue_1_i06", pv_name="In1")
counter = builder.aIn('COUNTER')
def update_logic():
"""Function executed at each IO loop cycle"""
# Copy input value to output with offset
ai1.set(ai2.get() + 100)
# Increment counter
counter.set(counter.get() + 1)
# Add function to IO loop
RevPiEpics.add_loop_task(update_logic)
# Start IOC and IO loop with custom function
RevPiEpics.start()With Cothread
from softioc import builder
from revpiepics import RevPiEpics
import cothread
builder.SetDeviceName("TEST")
RevPiEpics.init()
ai1 = RevPiEpics.builder(io_name="OutputValue_1_i06", pv_name="Out1")
ai2 = RevPiEpics.builder(io_name="InputValue_1_i06", pv_name="Int1")
def update():
while True:
ai1.set(ai2.get() + 100)
cothread.Sleep(1)
cothread.Spawn(update)
RevPiEpics.start()With Asyncio
from softioc import builder, asyncio_dispatcher
from revpiepics import RevPiEpics
import asyncio
dispatcher = asyncio_dispatcher.AsyncioDispatcher()
builder.SetDeviceName("TEST")
RevPiEpics.init()
ai1 = RevPiEpics.builder(io_name="OutputValue_1_i06", pv_name="Out1")
ai2 = RevPiEpics.builder(io_name="InputValue_1_i06", pv_name="Int1")
async def update():
while True:
ai1.set(ai2.get() + 100)
await asyncio.sleep(1)
dispatcher(update)
RevPiEpics.start(dispatcher=dispatcher)⚠️ Breaking Changes
- Initialization is now done with
RevPiEpics.init()instead ofRevPiEpics() - The
start()method is now static - No need to manually call
builder.LoadDatabase()andsoftioc.iocInit()
🔧 Migration
- Replace
RevPiEpics()withRevPiEpics.init() - Use
RevPiEpics.builder()directly (static method) - Call
RevPiEpics.start()instead ofinstance.start() - Remove manual calls to
builder.LoadDatabase()andsoftioc.iocInit()
🐛 Bug Fixes
- Improved IO type management
- Optimized update loop
- Better initialization error handling
📖 Documentation
- Complete examples for cothread and asyncio
- Detailed installation instructions
- Advanced PV configuration
Compatibility: Revolution Pi (Connect 5/4/S/SE, Core S/SE) + AIO Extension Modules
Requirements: 64-bit OS, PiCtory configuration
Dependencies: pythonSoftIOC, revpimodio2