Skip to content

Getting started

Start here

Use this page when you want the shortest path from a Rust program to a MELSEC PLC. The examples use TCP at 192.168.250.100:1025.

Prerequisites

Requirement Value
Rust 1.85 or newer (1.85 is the declared minimum supported compiler)
Async runtime tokio with macros and a runtime feature
PLC endpoint 192.168.250.100:1025
Profile used below SlmpPlcProfile::IqR

Add dependency

cargo add plc-comm-slmp
cargo add tokio --features macros,rt-multi-thread

Choose your PLC profile

The endpoint port, transport, target route, and exact SlmpPlcProfile are required. The library derives the SLMP frame and compatibility mode from the profile.

use plc_comm_slmp::{SlmpConnectionOptions, SlmpPlcProfile};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let options = SlmpConnectionOptions::new("192.168.250.100", 1025, plc_comm_slmp::SlmpTransportMode::Tcp, plc_comm_slmp::SlmpTargetAddress::default(), SlmpPlcProfile::IqR)?;
    println!("{:?}", options.plc_profile());

    Ok(())
}

First read

This reads D100 as an unsigned 16-bit word.

use plc_comm_slmp::{
    read_typed, SlmpAddress, SlmpClient, SlmpConnectionOptions, SlmpPlcProfile,
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let options = SlmpConnectionOptions::new("192.168.250.100", 1025, plc_comm_slmp::SlmpTransportMode::Tcp, plc_comm_slmp::SlmpTargetAddress::default(), SlmpPlcProfile::IqR)?;

    let client = SlmpClient::connect(options).await?;
    let value = read_typed(&client, SlmpAddress::parse("D100", SlmpPlcProfile::IqR)?, "U").await?;
    println!("{:?}", value);
    client.close().await?;

    Ok(())
}

Expected output shape:

U16(123)

First write

Only write to a test address that your PLC program allows you to change.

use plc_comm_slmp::{
    read_typed, write_typed, SlmpAddress, SlmpClient, SlmpConnectionOptions, SlmpPlcProfile,
    SlmpValue,
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let options = SlmpConnectionOptions::new("192.168.250.100", 1025, plc_comm_slmp::SlmpTransportMode::Tcp, plc_comm_slmp::SlmpTargetAddress::default(), SlmpPlcProfile::IqR)?;

    let client = SlmpClient::connect(options).await?;
    let address = SlmpAddress::parse("D600", SlmpPlcProfile::IqR)?;

    let original = read_typed(&client, address, "U").await?;
    write_typed(&client, address, "U", &SlmpValue::U16(42)).await?;
    let readback_result = read_typed(&client, address, "U").await;
    let restore_result = write_typed(&client, address, "U", &original).await;
    restore_result?;
    let value = readback_result?;
    println!("{:?}", value);
    client.close().await?;

    Ok(())
}

The readback result is not propagated until after restoration is attempted, so a readback failure cannot skip the confirmed-write cleanup. If the test write itself returns an outcome-unknown error, do not send an automatic restore or retry; reopen, inspect the test register, and reconcile it explicitly. If the restoration attempt fails, also inspect the test register and reconcile its value manually before continuing.

Confirm success

  1. The PLC IP address is reachable from your computer.
  2. TCP port 1025 is open on your PLC Ethernet module or built-in Ethernet port.
  3. The PLC-side communication data code is Binary and the port/open setting matches your transport; see the MELSEC SLMP PLC Setup Guide.
  4. PLC-side RUN-time write permission is enabled before you run a write example where the PLC exposes that setting.
  5. SlmpPlcProfile::IqR matches your real hardware, or you selected the correct variant from profiles.
  6. A read from D100 returns a SlmpValue without an SLMP end code error.
  7. Any write test uses a register reserved for testing and restores the original value.

If it does not work

Symptom Check
You get SLMP end code errors SlmpPlcProfile must match the actual hardware.
Connection opens but all requests fail Confirm Binary communication data code in the PLC setup guide.
Reads work but writes fail Confirm RUN-time write permission in the PLC setup guide and the selected profile write policy.
You are tempted to set the frame manually Do not override frame type manually; it is derived from the profile.
A special device family fails Start with D reads, not G, HG, LTN, or LCN.
X or Y addresses look different on iQ-F SlmpPlcProfile::IqF parses X and Y string addresses as octal.