Expand description
Async EtherNet/IP explicit messaging for simple PLC tag reads and writes.
This crate provides a small, crate-owned API around rust-ethernet-ip for the common
explicit-messaging workflow:
- connect to one target with
ExplicitSession::connect - read one or more tags as crate-owned
Values - write crate-owned
Values back to tags - use
ExplicitSession::read_tag_structandExplicitSession::write_tag_structfor caller-defined structured payloads - explicitly unregister the session with
ExplicitSession::close
The public API intentionally hides backend transport types so callers can work with a
stable interface centered on ExplicitSession, Value, and StructuredValue.
§Recovery behavior
The backend client automatically retries or falls back for some protocol-level transient
failures before an operation returns. If a read, batch read, or write still returns an
error that rust_ethernet_ip::EtherNetIpError::is_retriable marks retriable,
ExplicitSession drops the dead client. The failed operation is returned to the caller, and
the next read or write automatically reconnects with the same address and route path before
issuing the request.
§Features
By default, this crate exposes the async ExplicitSession API. Async callers provide their
own Tokio runtime by awaiting the session methods.
Enable the blocking feature to add blocking::ExplicitSession, a synchronous wrapper around
the async session. The blocking API supports the same connect, read, write, structured-value,
and close operations, and it drives them on a private shared Tokio runtime.
Do not call the blocking API from inside Tokio async code: it uses Handle::block_on, which
panics when invoked from an async execution context. Async callers should use the default
ExplicitSession API directly.
§Examples
Connect to a target, read a tag, write an updated value, then close the session:
use instro_ethernetip::{ExplicitSession, Result, Value};
let runtime = tokio::runtime::Runtime::new().expect("runtime should build");
runtime.block_on(async {
let mut session = ExplicitSession::connect("192.168.1.10:44818").await?;
let motor_running = session.read_tag("MotorRunning").await?;
assert!(matches!(motor_running, Value::Bool(_)));
session.write_tag("CommandSpeed", 1_500_i32.into()).await?;
session.close().await
})Convert Rust values into crate-owned PLC values without exposing backend types:
use instro_ethernetip::Value;
assert_eq!(Value::from(true), Value::Bool(true));
assert_eq!(Value::from(42_i32), Value::Dint(42));
assert_eq!(Value::from("ready"), Value::String("ready".to_owned()));Preserve a user-defined type payload as opaque bytes with StructuredValue:
use instro_ethernetip::{StructuredValue, Value};
let payload = StructuredValue {
symbol_id: Some(7),
data: vec![0xde, 0xad, 0xbe, 0xef],
};
assert_eq!(Value::from(payload.clone()), Value::Struct(payload));Structs§
- Explicit
Session - An active explicit-messaging EtherNet/IP session for a single target address.
- Structured
Value - User-facing wrapper for
rust_ethernet_ip::UdtData.
Enums§
- Batch
Read Error - Per-tag failure surfaced by a batched read.
- Error
- Errors returned by the explicit EtherNet/IP tag API.
- Value
- User-facing wrapper for
rust_ethernet_ip::PlcValuereturned by this crate.