2 Star 1 Fork 0

joylei / eip-rs

Create your Gitee Account
Explore and code with more than 12 million developers,Free private repositories !:)
Sign up
Clone or Download
contribute
Sync branch
Cancel
Notice: Creating folder will generate an empty file .keep, because not support in Git
Loading...
README
MIT

EN | 中文

rseip

crates.io docs build license

EIP&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.1"

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={git="https://github.com/Joylei/eip-rs.git"}

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 values into collections, do like this:

let value: TagValue<Vec<MyType>> = client.read_tag(tag).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 (or 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 collections, 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

MIT License Copyright (c) 2021 joylei <leingliu@gmail.com> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

About

rseip - 纯Rust语言写的CIP客户端,支持CIP和AB PLC expand collapse
Rust
MIT
Cancel

Releases

No release

Contributors

All

Activities

Load More
can not load any more
Rust
1
https://gitee.com/wowin/eip-rs.git
git@gitee.com:wowin/eip-rs.git
wowin
eip-rs
eip-rs
main

Search