6 releases
0.3.1 | Nov 14, 2022 |
---|---|
0.3.0 | Apr 16, 2022 |
0.2.1 | Mar 1, 2022 |
0.2.0 | Feb 25, 2022 |
0.1.1 | Dec 9, 2021 |
#306 in Asynchronous
31 downloads per month
275KB
7K
SLoC
rseip
Ethernet/IP (CIP) client in pure Rust, for generic CIP and AB PLC
Features
- Pure Rust Library
- Asynchronous
- Prefer static dispatch
- Extensible
- Explicit Messaging (Connected / Unconnected)
- Open Source
Services Supported for AB PLC
- Read Tag
- Write Tag
- Read Tag Fragmented
- Write Tag Fragmented
- Read Modify Write Tag
- Get Instance Attribute List (list tag)
- Read Template
How to use
Add rseip
to your cargo project's dependencies
rseip="0.3"
Please find detailed guides and examples from below sections.
Example
Tag Read/Write for Allen-bradley CompactLogIx device
use anyhow::Result;
use rseip::client::ab_eip::*;
use rseip::precludes::*;
#[tokio::main]
pub async fn main() -> Result<()> {
let mut client = AbEipClient::new_host_lookup("192.168.0.83")
.await?
.with_connection_path(PortSegment::default());
let tag = EPath::parse_tag("test_car1_x")?;
println!("read tag...");
let value: TagValue<i32> = client.read_tag(tag.clone()).await?;
println!("tag value: {:?}", value);
client.write_tag(tag, value).await?;
println!("write tag - done");
client.close().await?;
Ok(())
}
Please find more examples within examples.
Guides
Quick start
Add rseip
to your cargo project's dependencies
rseip="0.3"
Then, import modules of rseip
to your project
use rseip::client::ab_eip::*;
use rseip::precludes::*;
Then, create an unconnected client
let mut client = AbEipClient::new_host_lookup("192.168.0.83")
.await?
.with_connection_path(PortSegment::default());
or create a connection
let mut client =
AbEipConnection::new_host_lookup("192.168.0.83", OpenOptions::default()).await?;
Read from a tag
let tag = EPath::parse_tag("test_car1_x")?;
println!("read tag...");
let value: TagValue<i32> = client.read_tag(tag.clone()).await?;
Write to a tag
let tag = EPath::parse_tag("test_car1_x")?;
let value = TagValue {
tag_type: TagType::Dint,
value: 10_i32,
};
client.write_tag(tag, value).await?;
println!("write tag - done");
About TagValue
, Decode
, and Encode
As you may know, there are atomic types, structure types, and array type of tags. The library provides Encode
to encode values, Decode
to decode values, and TagValue
to manipulate tag data values. The library already implements Encode
and Decode
for some rust types: bool
,i8
,u8
,i16
,u16
,i32
,u32
,i64
,u64
,f32
,f64
,i128
,u128
,()
,Option
,Tuple
,Vec
,[T;N]
,SmallVec
. For structure type, you need to implement Encode
and Decode
by yourself.
Read
To get a single value (atomic/structure), and you know the exact mapped type, do like this
let value: TagValue<MyType> = client.read_tag(tag).await?;
println!("{:?}",value);
To get the tag type, and you do not care about the data part, do like this:
let value: TagValue<()> = client.read_tag(tag).await?;
println!("{:?}",value.tag_type);
To get the raw bytes whatever the data part holds, do like this:
let value: TagValue<Bytes> = client.read_tag(tag).await?;
To iterate values, and you know the exact mapped type, do like this:
let iter: TagValueTypedIter<MyType> = client.read_tag(tag).await?;
println!("{:?}", iter.tag_type());
while let Some(res) = iter.next(){
println!("{:?}", res);
}
To iterate values, and you do not know the exact mapped type, do like this:
let iter: TagValueIter = client.read_tag(tag).await?;
println!("{:?}", iter.tag_type());
let res = iter.next::<bool>().unwrap();
println!("{:?}", res);
let res = iter.next::<i32>().unwrap();
println!("{:?}", res);
let res = iter.next::<MyType>().unwrap();
println!("{:?}", res);
To read more than 1 elements of an Array
, do like this:
let value: TagValue<Vec<MyType>> = client.read_tag((tag,5_u16)).await?;
println!("{:?}",value);
Write
You must provide the tag type before you write to a tag. Normally, you can retrieve it by reading the tag. For structure type, you cannot reply on or persist the tag type (so called structure handle
), it might change because it is a calculated value (CRC based).
To write a single value (atomic/structure), do like this:
let value = TagValue {
tag_type: TagType::Dint,
value: 10_i32,
};
client.write_tag(tag, value).await?;
To write raw bytes, do like this:
let bytes:&[u8] = &[0,1,2,3];
let value = TagValue {
tag_type: TagType::Dint,
value: bytes,
};
client.write_tag(tag, value).await?;
To write multiple values to an array, do like this:
let items: Vec<MyType> = ...;
let value = TagValue {
tag_type: TagType::Dint,
value: items,
};
client.write_tag(tag, value).await?;
Moreover
For some reasons, TagValue
does not work for all type that implements Encode
or Decode
.
But you can work without TagValue
. You can define your own value holder, as long as it implements Encode
and Decode
.
For simple cases, Tuple
should be a good option.
let (tag_type,value):(TagType, i32) = client.read_tag(tag).await?;
client.write_tag(tag, (tag_type, 1_u16, value)).await?;
License
MIT
Dependencies
~4–13MB
~140K SLoC