Skip to main content

plc_comm_slmp/
lib.rs

1//! Async Rust client for Mitsubishi SLMP Binary 3E and 4E.
2//!
3//! This crate follows the same operation semantics as the sibling
4//! `plc-comm-slmp-python`, `.NET`, `C++`, `Node-RED`, and `cross-verify`
5//! projects in the same family. The intended flow is:
6//!
7//! 1. connect with [`SlmpConnectionOptions`] and [`SlmpClient`]
8//! 2. use raw device APIs for low-level control
9//! 3. use helper APIs such as [`read_named`] and [`write_named`] for
10//!    application-facing snapshots and typed values
11//! 4. validate behavior through `plc-comm-slmp-cross-verify`
12//!
13//! # Quick Start
14//!
15//! ```no_run
16//! use plc_comm_slmp::{
17//!     SlmpAddress, SlmpClient, SlmpCompatibilityMode, SlmpConnectionOptions, SlmpFrameType,
18//! };
19//!
20//! #[tokio::main]
21//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
22//!     let mut options = SlmpConnectionOptions::new("192.168.250.100");
23//!     options.port = 1025;
24//!     options.frame_type = SlmpFrameType::Frame4E;
25//!     options.compatibility_mode = SlmpCompatibilityMode::Iqr;
26//!
27//!     let client = SlmpClient::connect(options).await?;
28//!     let words = client.read_words_raw(SlmpAddress::parse("D100")?, 2).await?;
29//!     println!("{words:?}");
30//!     Ok(())
31//! }
32//! ```
33//!
34//! # Recommended High-Level Helpers
35//!
36//! ```no_run
37//! use plc_comm_slmp::{
38//!     NamedAddress, SlmpClient, SlmpCompatibilityMode, SlmpConnectionOptions, SlmpFrameType,
39//!     SlmpValue, read_named, write_named,
40//! };
41//!
42//! #[tokio::main]
43//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
44//!     let mut options = SlmpConnectionOptions::new("192.168.250.100");
45//!     options.port = 1025;
46//!     options.frame_type = SlmpFrameType::Frame4E;
47//!     options.compatibility_mode = SlmpCompatibilityMode::Iqr;
48//!     let client = SlmpClient::connect(options).await?;
49//!
50//!     let snapshot = read_named(
51//!         &client,
52//!         &["D100".into(), "D200:F".into(), "D50.3".into(), "LTN10:D".into()],
53//!     )
54//!     .await?;
55//!     println!("{snapshot:?}");
56//!
57//!     let mut updates = NamedAddress::new();
58//!     updates.insert("D300".into(), SlmpValue::U16(42));
59//!     updates.insert("D400:F".into(), SlmpValue::F32(3.14));
60//!     write_named(&client, &updates).await?;
61//!     Ok(())
62//! }
63//! ```
64//!
65//! # Address Notes
66//!
67//! - Plain word devices: `D100`, `R50`, `ZR0`
68//! - Plain bit devices: `M100`, `X20`, `Y20`, `B10`
69//! - Typed suffixes: `D200:F`, `D300:D`, `D400:L`
70//! - Bit-in-word form: `D50.3`
71//! - Long current values: `LTN10:D`, `LSTN20:D`, `LCN30:D`
72//! - Extended devices: `J1\\W10`, `U3\\G100`, `U1\\HG0`
73//!
74//! `.bit` notation is only valid for word devices. Long timer and long counter
75//! state reads (`LTS`, `LTC`, `LSTS`, `LSTC`, `LCS`, `LCC`) are normalized
76//! through the corresponding current-value block reads.
77//!
78//! # Examples
79//!
80//! The repository includes runnable examples under `examples/`:
81//!
82//! - `raw_read_write`
83//! - `named_helpers`
84//! - `advanced_operations`
85//!
86//! Run them with `cargo run --example <name>`.
87//!
88//! # Verification
89//!
90//! This crate is meant to participate in `plc-comm-slmp-cross-verify`.
91//! The canonical wrapper binary is `slmp_verify_client`.
92//!
93mod address;
94mod client;
95mod error;
96mod helpers;
97mod model;
98
99pub use address::{
100    SlmpAddress, normalize_named_address, parse_named_address, parse_named_target,
101    parse_qualified_device, parse_target_auto_number,
102};
103pub use client::{SlmpClient, encode_device_spec};
104pub use error::SlmpError;
105pub use helpers::{
106    NamedAddress, SlmpValue, parse_scalar_for_named, poll_named, read_dwords_chunked,
107    read_dwords_single_request, read_named, read_typed, read_words_chunked,
108    read_words_single_request, write_bit_in_word, write_dwords_chunked,
109    write_dwords_single_request, write_named, write_typed, write_words_chunked,
110    write_words_single_request,
111};
112pub use model::{
113    SlmpBlockRead, SlmpBlockReadResult, SlmpBlockWrite, SlmpBlockWriteOptions, SlmpCommand,
114    SlmpCompatibilityMode, SlmpConnectionOptions, SlmpDeviceAddress, SlmpDeviceCode,
115    SlmpExtensionSpec, SlmpFrameType, SlmpLongTimerResult, SlmpNamedTarget,
116    SlmpQualifiedDeviceAddress, SlmpRandomReadResult, SlmpTargetAddress, SlmpTraceDirection,
117    SlmpTransportMode, SlmpTypeNameInfo,
118};