6 个版本
0.3.1 | 2022年11月14日 |
---|---|
0.3.0 | 2022年4月16日 |
0.2.1 | 2022年3月1日 |
0.2.0 | 2022年2月25日 |
0.1.1 | 2021年12月9日 |
#256 in 异步
每月 40 次下载
275KB
7K SLoC
rseip
纯Rust实现的Ethernet/IP (CIP) 客户端,适用于通用CIP和AB PLC
特性
- 纯Rust库
- 异步
- 优先静态调度
- 可扩展
- 显式消息(已连接/未连接)
- 开源
支持的AB PLC服务
- 读取标签
- 写入标签
- 读取碎片化标签
- 写入碎片化标签
- 读取/修改/写入标签
- 获取实例属性列表(标签列表)
- 读取模板
使用方法
将 rseip
添加到您的 cargo 项目的依赖中
rseip="0.3"
请从以下部分找到详细的指南和示例。
示例
Allen-bradley CompactLogIx 设备的标签读取/写入
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(())
}
请从 示例 中找到更多示例。
指南
快速入门
将 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");
关于 TagValue
、Decode
和 Encode
正如您所知,存在原子类型、结构类型和数组类型的标签。库提供了用于编码值的 Encode
、用于解码值的 Decode
以及用于操作标签数据值的 TagValue
。库已经为一些 Rust 类型实现了 Encode
和 Decode
:bool
、i8
、u8
、i16
、u16
、i32
、u32
、i64
、u64
、f32
、f64
、i128
、u128
、()
、Option
、Tuple
、Vec
、[T;N]
、SmallVec
。对于结构类型,您需要自行实现 Encode
和 Decode
。
读取
要获取单个值(原子/结构),并且您知道确切的映射类型,可以这样做
let value: TagValue<MyType> = client.read_tag(tag).await?;
println!("{:?}",value);
要获取标签类型,并且您不关心数据部分,可以这样做
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);
要读取 Array
的多个元素,可以这样做
let value: TagValue<Vec<MyType>> = client.read_tag((tag,5_u16)).await?;
println!("{:?}",value);
写入
在向标签写入之前,您必须提供标签类型。通常,您可以通过读取标签来检索它。对于结构类型,您不能依赖于或持久化标签类型(所谓 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?;
要将多个值写入数组,可以这样做
let items: Vec<MyType> = ...;
let value = TagValue {
tag_type: TagType::Dint,
value: items,
};
client.write_tag(tag, value).await?;
此外
由于某些原因,TagValue
并不适用于所有实现了 Encode
或 Decode
的类型。
但您可以在没有 TagValue
的情况下工作。您可以定义自己的值持有器,只要它实现了 Encode
和 Decode
。
对于简单的情况,Tuple
应该是一个不错的选择。
let (tag_type,value):(TagType, i32) = client.read_tag(tag).await?;
client.write_tag(tag, (tag_type, 1_u16, value)).await?;
许可
MIT
依赖项
~4–16MB
~157K SLoC