纯Rust语言写的CIP客户端,支持CIP和AB PLC
- 纯Rust语言
- 异步支持
- 偏好静态派发
- 可扩展
- 显式CIP消息(无连接或有连接)
- 开源
- TAG 读操作
- TAG 写操作
- TAG 分片写操作 (Tag Read Fragmented)
- TAG 分片写操作 (Tag Write Fragmented)
- TAG 读修改写操作 (Tag Read Modify Write)
- TAG 遍历 (Tag List)
- 读取模板
添加 rseip 到 cargo 项目的依赖
rseip="0.3"继续往下查看更多示例和帮助。
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(())
}请到这里查看更多示例代码examples.
添加 rseip 到 cargo 项目的依赖
rseip="0.3"然后,导入 rseip 的模块到项目中
use rseip::client::ab_eip::*;
use rseip::precludes::*;然后, 创建一个无连接的客户端
let mut client = AbEipClient::new_host_lookup("192.168.0.83")
.await?
.with_connection_path(PortSegment::default());或者, 创建一个有连接的客户端
let mut client =
AbEipConnection::new_host_lookup("192.168.0.83", OpenOptions::default()).await?;let tag = EPath::parse_tag("test_car1_x")?;
println!("read tag...");
let value: TagValue<i32> = client.read_tag(tag.clone()).await?;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");AB PLC 有原子类型, 结构类型,以及数组。本项目提供了 Encode 来编码数据,Decode来解码数据,以及TagValue来辅助数据值的操作。此项目已经为以下类型实现了Encode and Decode: bool,i8,u8,i16,u16,i32,u32,i64,u64,f32,f64,i128,u128,(),Option,Tuple,Vec,[T;N],SmallVec。对于结构类型的数据你应该自己实现Encode and Decode。
想要读取单个值(原子类型或结构类型),并且你知道要映射到的类型,可以这样操作:
let value: TagValue<MyType> = client.read_tag(tag).await?;
println!("{:?}",value);想要读取 TAG 值类型,并且你不关心数据值,可以这样操作:
let value: TagValue<()> = client.read_tag(tag).await?;
println!("{:?}",value.tag_type);想要读取原始的字节数据,可以这样操作:
let value: TagValue<Bytes> = client.read_tag(tag).await?;想要遍历读取的数据值,可以这样操作:
let iter: TagValueTypedIter<MyType> = client.read_tag(tag).await?;
println!("{:?}", iter.tag_type());
while let Some(res) = iter.next(){
println!("{:?}", res);
}想要遍历读取的数据值,并且不知道具体类型,可以这样操作:
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);想要读取数组的多个元素,可以这样操作:
let value: TagValue<Vec<MyType>> = client.read_tag((tag,5_u16)).await?;
println!("{:?}",value);如果想要写数据,你必须知道TAG的类型。通常情况下,可以通过读的方式获得。但是对于结构类型,你不能持久的依赖所获得类型(structure handle),因为它是一个计算值(CRC),当结构的定义变化时,这个值可能改变。
想要写入单个值(原子类型或结构类型),可以这样操作:
let value = TagValue {
tag_type: TagType::Dint,
value: 10_i32,
};
client.write_tag(tag, value).await?;想要写入字节数据,可以这样操作:
let bytes:&[u8] = &[0,1,2,3];
let value = TagValue {
tag_type: TagType::Dint,
value: bytes,
};
client.write_tag(tag, value).await?;也支持写入bytes::Bytes。
想要向数组写入多个数据元素,可以这样操作:
let items: Vec<MyType> = ...;
let value = TagValue {
tag_type: TagType::Dint,
value: items,
};
client.write_tag(tag, value).await?;也支持写入[T;N]。
由于一些考虑,TagValue并不支持任意实现了Encode or Decode的类型的读写。
但是你可以不使用 TagValue,可以定义自己的值编解码器,只要实现了Encode和Decode。由于Encode需要计算字节数,自己实现的编码器比通用的实现性能会更好。
对于简单场景来说,Tuple应该足够应对了。
let (tag_type,value):(TagType, i32) = client.read_tag(tag).await?;
client.write_tag(tag, (tag_type, 1_u16, value)).await?;MIT