Skip to content

PLC profiles

The high-level API requires one explicit PLC profile. The selected profile controls frame type, low-level compatibility mode, string X and Y numbering rules, device-range catalog selection, and target-specific command guards.

For cross-profile capability and device-range details, see the SLMP Profile Reference.

Profile selection is intentionally not inferred from ReadTypeName, model text, or model code. Some PLCs and network paths cannot return reliable type name data, and a wrong inference can select the wrong address grammar or range catalog. Keep the final profile choice in the application, configuration UI, or operator workflow.

Use slmp::highlevel::plcProfileDescriptors(count) when a UI or configuration schema needs the canonical name, display name, connection availability, and base-profile relationship in one list. The abstract melsec:qcpu entry is included with connectable == false; a null base_profile means no declared base profile. Store canonical_name, not display_name.

Profile selection is the supported way to apply target-specific behavior. Pass the concrete profile to the SlmpClient constructor. Manual frame and compatibility settings do not imply a PLC model. setManualProfile exists only for controlled evidence collection and verification where the caller must select an explicit concrete profile, frame, and compatibility mode together. Normal runtime applications should use the profile-derived defaults.

When setManualProfile is used, the selected compatibility mode is the wire contract for ordinary and embedded module-buffer device specifications: Legacy permits device numbers through 0xFFFFFF, while iQR emits the 32-bit form. An unrepresentable Legacy address returns Error::InvalidArgument, even when the concrete profile normally defaults to iQR. Link-direct J device specifications remain fixed at 24 bits in either mode.

Verified hardware available for focused validation is maintained once in the shared MELSEC SLMP profile catalog.

Profiles table

Canonical profile Display name C++ selector Frame type Compatibility mode Notes
melsec:iq-f MELSEC iQ-F (built-in) slmp::highlevel::PlcProfile::IqF slmp::FrameType::Frame3E slmp::CompatibilityMode::Legacy iQ-F string X and Y addresses use octal notation; DX and DY are rejected.
melsec:iq-r MELSEC iQ-R (built-in) slmp::highlevel::PlcProfile::IqR slmp::FrameType::Frame4E slmp::CompatibilityMode::iQR Use for modern iQ-R targets.
melsec:iq-r:rj71en71 MELSEC iQ-R (RJ71EN71) slmp::highlevel::PlcProfile::IqRRj71En71 slmp::FrameType::Frame4E slmp::CompatibilityMode::iQR Ethernet-unit profile using iQ-R compatibility.
melsec:iq-l MELSEC iQ-L (built-in) slmp::highlevel::PlcProfile::IqL slmp::FrameType::Frame4E slmp::CompatibilityMode::iQR Use for MELSEC iQ-L targets.
melsec:mx-f MELSEC MX-F (built-in) slmp::highlevel::PlcProfile::MxF slmp::FrameType::Frame4E slmp::CompatibilityMode::iQR Use for MELSEC MX-F targets.
melsec:mx-r MELSEC MX-R (built-in) slmp::highlevel::PlcProfile::MxR slmp::FrameType::Frame4E slmp::CompatibilityMode::iQR Use for MELSEC MX-R targets.
melsec:mx-r:rj71en71 MELSEC MX-R (RJ71EN71) slmp::highlevel::PlcProfile::MxRRj71En71 slmp::FrameType::Frame4E slmp::CompatibilityMode::iQR Ethernet-unit profile using MX-R compatibility and melsec:mx-r address/range rules.
melsec:lcpu MELSEC-L (built-in) slmp::highlevel::PlcProfile::LCpu slmp::FrameType::Frame3E slmp::CompatibilityMode::Legacy Legacy L CPU profile.
melsec:lcpu:lj71e71-100 MELSEC-L (LJ71E71-100) slmp::highlevel::PlcProfile::LCpuLj71E71100 slmp::FrameType::Frame4E slmp::CompatibilityMode::Legacy Ethernet unit profile using Q/L compatibility.
melsec:qcpu:qj71e71-100 MELSEC-Q (QJ71E71-100) slmp::highlevel::PlcProfile::QCpuQj71E71100 slmp::FrameType::Frame4E slmp::CompatibilityMode::Legacy Ethernet unit profile for QCPU connections.
melsec:qnu MELSEC QnU (built-in) slmp::highlevel::PlcProfile::QnU slmp::FrameType::Frame3E slmp::CompatibilityMode::Legacy QnU profile. Use direct or random device commands for normal access.
melsec:qnu:qj71e71-100 MELSEC QnU (QJ71E71-100) slmp::highlevel::PlcProfile::QnUQj71E71100 slmp::FrameType::Frame4E slmp::CompatibilityMode::Legacy Ethernet unit profile using Q/L compatibility.
melsec:qnudv MELSEC QnUDV (built-in) slmp::highlevel::PlcProfile::QnUDV slmp::FrameType::Frame3E slmp::CompatibilityMode::Legacy QnUDV profile. Use direct or random device commands for normal access.
melsec:qnudv:qj71e71-100 MELSEC QnUDV (QJ71E71-100) slmp::highlevel::PlcProfile::QnUDVQj71E71100 slmp::FrameType::Frame4E slmp::CompatibilityMode::Legacy Ethernet unit profile using Q/L compatibility.

melsec:qcpu is base-only and remains for inherited address and range rules. Use melsec:qcpu:qj71e71-100 for QCPU Ethernet unit connections.

For configuration files, parsePlcProfile(text, profile) converts one exact canonical profile string to PlcProfile. It returns Error::InvalidArgument for unknown text and does not accept an empty or unspecified profile.

How to select

#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <thread>

#include <slmp_high_level.h>
#include <slmp_minimal.h>

class NoopTransport final : public slmp::ITransport {
  public:
    bool connect(const char*, uint16_t) override { return false; }
    void close() override {}
    bool connected() const override { return false; }
    size_t maximumRequestFrameSize() const override { return static_cast<size_t>(-1); }
    bool writeAll(const uint8_t*, size_t) override { return false; }
    bool readExact(uint8_t*, size_t, uint32_t) override { return false; }
    size_t write(const uint8_t*, size_t) override { return 0U; }
    size_t read(uint8_t*, size_t) override { return 0U; }
    size_t available() override { return 0U; }
    void cooperativeWait(uint32_t) override { std::this_thread::yield(); }
    bool currentDatagramBytesRemaining(size_t& bytes) const override {
        (void)bytes;
        return false;
    }
};

int main() {
    NoopTransport transport;
    uint8_t tx[64] = {};
    uint8_t rx[64] = {};
    constexpr auto profile = slmp::highlevel::PlcProfile::IqR;
    slmp::SlmpClient plc(transport, profile, slmp::TargetAddress{0x00, 0xFF, slmp::module_io::OwnStation, 0x00}, tx, sizeof(tx), rx, sizeof(rx));
    std::printf("%s\n", slmp::highlevel::plcProfileCanonicalName(profile));

    return plc.frameType() == slmp::FrameType::Frame4E ? 0 : 1;
}

Strict profile

SlmpClient enables strict profile checks by default. With a selected profile, operations known to be unavailable for that PLC are rejected before sending. Leave this enabled for normal applications.

setManualProfile is a controlled verification surface, not a general profile guard bypass. It retains the explicit profile and changes only the selected frame and compatibility encoding. Broader profile evidence collection uses separate maintainer tooling.