| Crates.io | epicars |
| lib.rs | epicars |
| version | 0.1.2 |
| created_at | 2025-08-06 22:40:55.659657+00 |
| updated_at | 2025-08-06 22:48:43.49982+00 |
| description | Standalone, pure rust implementation of EPICS CA protocol |
| homepage | |
| repository | https://github.com/ndevenish/epicars |
| max_upload_size | |
| id | 1784411 |
| size | 167,987 |
Rust implementation of EPICS CA protocol and basic variable access layers.
This crate is a pure-rust implementation of the EPICS CA protocol. It does not depend on the C-based epics-base project at all.
[!WARNING] This is a very early version of this library. Interfaces or structure may be changed around wildly between versions until a comfortable final design is settled upon.
Whereas the full model of IOC and the EPICS database is extremely flexible and expansive, that comes at a complexity and tooling cost that is not necessary for a lot of smaller projects that just want to expose the ability to have a couple of variables exposed via what is likely the designated control layer for the facility.
EPICArs approaches the problem by separating:
Provider - a trait that the Server uses to talk to values in your application.Basic example (but fully functional) providers are included:
IntercomProvider: Provides access objects to access record
data as a natively mapped data type. The access objects can be cloned and
passed across thread boundaries, and retain access to the same data.Here is an example of exposing a basic single i32 via the IntercomProvider.
You can run this and then caget NUMERIC_VALUE or caput NUMERIC_VALUE <new_value>
from anywhere inside the same broadcast network:
use epicars::{ServerBuilder, providers::IntercomProvider};
#[tokio::main]
async fn main() {
let mut provider = IntercomProvider::new();
let mut value = provider.add_pv("NUMERIC_VALUE", 42i32).unwrap();
let _server = ServerBuilder::new(provider).start().await.unwrap();
loop {
value.store(&(value.load() + 1));
println!("Value is now: {}", value.load());
tokio::time::sleep(Duration::from_secs(3)).await;
}
}
There are more examples in the example/ folder of the repository.
What is currently present:
camonitor functionality to receive updates of PV values.caget an
e.g. i8 as an i32 and this will automatically convert. You can also do the
inverse, and this will work as long as the data are representable as the target
type without loss.Provider trait, it's reasonable simple to run the server
asynchronously (currently required, and using tokio) but still allow access the
the current values synchronously. The built-in example providers do this.String to CA CHAR arrays back and forth.What this doesn't do (yet):
Work as a client to connect to repeaters, other CA servers, and IOCs. This will be worked on when the server portions are satisfactorily working and ergonomic "enough" to use (this was the reason this implementaiton was written).
Match exact behaviours of epics-base in terms of translation, error handling, and what it allows. This requires careful study of the EPICS code, and the building of an exhaustive test suite - this has not yet become a priority, but it may just be left as "good enough" until PVAccess becomes common eough that we don't need the CA interface any more.
Completely implement data types. Notably, ENUM types are not well handled, the
CTRL and GR data categories are not handled, and some of the precise behaviour
of STR have yet to be nailed down. These will be tackled when the use cases are
better understood.
Work at all without tokio. There are ambition to make this flexible over async runtime, specifically Embassy for embedded usage, but the only evidence of this so far is lightly in some of the design decisions.