This is an automated email from the ASF dual-hosted git repository.

chrisdutz pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git


The following commit(s) were added to refs/heads/develop by this push:
     new 7ac57b3ced feat: Add SLMP (MELSEC Communication 3E) protocol module 
(read-only wire layer) (#2597)
7ac57b3ced is described below

commit 7ac57b3cede971093167d72958868fd189b99efc
Author: LivingLikeKrillin <[email protected]>
AuthorDate: Thu Jul 9 05:34:24 2026 +0900

    feat: Add SLMP (MELSEC Communication 3E) protocol module (read-only wire 
layer) (#2597)
    
    * feat: Add SLMP (MELSEC Communication 3E) protocol module - read-only wire 
layer
    
    Adds the codegen-layer protocol module for SLMP / MELSEC Communication
    protocol (Mitsubishi PLCs), as proposed in the SLMP driver proposal issue:
    
    - slmp.mspec modelling the 3E binary frame (request/response), with
      Batch Read (0x0401), Random Read (0x0403) and Batch Read Multiple
      Blocks (0x0406) in word units, read-only
    - ParserSerializer test suite with vectors derived from the worked
      examples in the public Mitsubishi reference manual SH-080008
      (sections 8.1/8.3/8.4)
    - Root type declares the new-SPI encoding defaults (little-endian)
    
    The driver module (plc4j/drivers/slmp) will follow on top of the new
    SPI as a separate step.
    
    Signed-off-by: Jooyoung Jung <[email protected]>
    
    * fix(slmp): use canonical enum form for deviceCode in test vectors
    
    deviceCode is a numeric enum (SlmpDeviceCode), but the ParserSerializer
    test vectors used the shorthand <deviceCode>D</deviceCode> form. That
    does not round-trip through the generated parser/serializer, which
    expects the full enum element with its numeric value:
    
        <deviceCode>
          <SlmpDeviceCode dataType="uint" bitLength="8" 
stringRepresentation="D">168</SlmpDeviceCode>
        </deviceCode>
    
    Convert all deviceCode occurrences in ParserSerializerTestsuite.xml to
    the canonical form so the vectors round-trip once the generated driver
    types exercise them.
    
    ---------
    
    Signed-off-by: Jooyoung Jung <[email protected]>
---
 protocols/pom.xml                                  |   1 +
 protocols/slmp/pom.xml                             |  53 ++++
 .../apache/plc4x/protocol/slmp/SlmpProtocol.java   |  42 ++++
 ...e.plc4x.plugins.codegenerator.protocol.Protocol |  19 ++
 .../src/main/resources/protocols/slmp/slmp.mspec   | 167 ++++++++++++
 .../plc4x/protocol/slmp/SlmpProtocolTest.java      |  37 +++
 protocols/slmp/src/test/resources/logback-test.xml |  36 +++
 .../protocols/slmp/ParserSerializerTestsuite.xml   | 279 +++++++++++++++++++++
 8 files changed, 634 insertions(+)

diff --git a/protocols/pom.xml b/protocols/pom.xml
index aef6e7a883..07c5fa1003 100644
--- a/protocols/pom.xml
+++ b/protocols/pom.xml
@@ -59,6 +59,7 @@
     <module>profinet</module>
     <module>s7</module>
     <module>simulated</module>
+    <module>slmp</module>
     <module>socketcan</module>
     <module>umas</module>
   </modules>
diff --git a/protocols/slmp/pom.xml b/protocols/slmp/pom.xml
new file mode 100644
index 0000000000..91ebbc3b34
--- /dev/null
+++ b/protocols/slmp/pom.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      https://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.plc4x</groupId>
+    <artifactId>plc4x-protocols</artifactId>
+    <version>0.14.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>plc4x-protocols-slmp</artifactId>
+
+  <name>Protocols: SLMP</name>
+  <description>Base protocol specifications for the SLMP / MELSEC 
Communication protocol</description>
+
+  <properties>
+    
<project.build.outputTimestamp>2025-08-02T13:55:11Z</project.build.outputTimestamp>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.plc4x</groupId>
+      <artifactId>plc4x-code-generation-protocol-base-mspec</artifactId>
+      <version>0.14.0-SNAPSHOT</version>
+    </dependency>
+
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-classic</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+</project>
diff --git 
a/protocols/slmp/src/main/java/org/apache/plc4x/protocol/slmp/SlmpProtocol.java 
b/protocols/slmp/src/main/java/org/apache/plc4x/protocol/slmp/SlmpProtocol.java
new file mode 100644
index 0000000000..2c8959c98f
--- /dev/null
+++ 
b/protocols/slmp/src/main/java/org/apache/plc4x/protocol/slmp/SlmpProtocol.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.plc4x.protocol.slmp;
+
+import 
org.apache.plc4x.plugins.codegenerator.language.mspec.parser.MessageFormatParser;
+import 
org.apache.plc4x.plugins.codegenerator.language.mspec.protocol.ProtocolHelpers;
+import 
org.apache.plc4x.plugins.codegenerator.language.mspec.protocol.ValidatableTypeContext;
+import org.apache.plc4x.plugins.codegenerator.protocol.Protocol;
+import org.apache.plc4x.plugins.codegenerator.protocol.TypeContext;
+import 
org.apache.plc4x.plugins.codegenerator.types.exceptions.GenerationException;
+
+public class SlmpProtocol implements Protocol, ProtocolHelpers {
+
+    @Override
+    public String getName() {
+        return "slmp";
+    }
+
+    @Override
+    public TypeContext getTypeContext() throws GenerationException {
+        ValidatableTypeContext typeContext = new 
MessageFormatParser().parse(getMspecStream());
+        typeContext.validate();
+        return typeContext;
+    }
+
+}
diff --git 
a/protocols/slmp/src/main/resources/META-INF/services/org.apache.plc4x.plugins.codegenerator.protocol.Protocol
 
b/protocols/slmp/src/main/resources/META-INF/services/org.apache.plc4x.plugins.codegenerator.protocol.Protocol
new file mode 100644
index 0000000000..2195c2e214
--- /dev/null
+++ 
b/protocols/slmp/src/main/resources/META-INF/services/org.apache.plc4x.plugins.codegenerator.protocol.Protocol
@@ -0,0 +1,19 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+org.apache.plc4x.protocol.slmp.SlmpProtocol
diff --git a/protocols/slmp/src/main/resources/protocols/slmp/slmp.mspec 
b/protocols/slmp/src/main/resources/protocols/slmp/slmp.mspec
new file mode 100644
index 0000000000..20170095ae
--- /dev/null
+++ b/protocols/slmp/src/main/resources/protocols/slmp/slmp.mspec
@@ -0,0 +1,167 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// SLMP (Seamless Message Protocol) / MELSEC Communication protocol.
+//
+// Specification: Mitsubishi "MELSEC Communication Protocol Reference Manual"
+//   (SH(NA)-080008, public). All field layouts below are taken from that 
manual:
+//     - 3E frame message format ....... section 5.2
+//     - Subheader (50 00 / D0 00) ...... section 5.3
+//     - Access route (3E fixed value) .. chapter 6
+//     - Request/response data length ... section 5.3 (2-byte, little-endian)
+//     - Commands (Batch/Random/block Read) chapter 7 / 8.1 / 8.3 / 8.4
+//     - Device code list ............... section 8.1 (MELSEC-Q/L, 1-byte 
binary)
+//     - Batch Read data layout ......... section 8.1 (binary, word units)
+//     - Random Read data layout ........ section 8.3 (binary, word units)
+//     - Multi-block Read data layout ... section 8.4 (binary, word units)
+//
+// Scope of this initial version: 3E binary frame, read-only, Batch Read
+// (command 0x0401), Random Read (command 0x0403) and Batch Read Multiple 
Blocks
+// (command 0x0406) in word units (subcommand 0x0000). This is the wire layer
+// only; typed value decoding
+// (INT/WORD/DINT/REAL) and the device-addressing tag layer are intentionally
+// NOT modelled here yet and will follow once the driver logic is built.
+// Validated hardware-free via the ParserSerializer test suite.
+//
+// All multi-byte numeric fields are little-endian (transmitted 
least-significant byte first).
+// The 2-byte subheader (0x50/0xD0 then 0x00) is modelled as two single bytes 
so
+// its on-wire order is preserved regardless of the frame byte order.
+
+[constants
+    // Typical SLMP TCP port; the actual port is configured on the device and 
is
+    // overridable by the driver, so this is only a default.
+    [const uint 16 slmpDefaultPort 5007]
+]
+
+// Device codes for MELSEC-Q/L series commands (subcommand 0x0000 / 0x0001),
+// 1-byte binary, from the device code list in SH-080008 section 8.1.
+// Only the word/bit devices needed by the read-only road-map are listed.
+//
+// These 1-byte binary device codes are confirmed identical in the Mitsubishi
+// MELSEC iQ-F FX5 SLMP manual (JY997D56001) -- D=A8 W=B4 R=AF M=90 X=9C Y=9D
+// B=A0 -- so the same frame works on FX5 hardware (e.g. FX5S) as well as
+// MELSEC-Q/L. (FX5 also offers a 2-byte/extended code form via subcommand
+// 0x0002/0x0003 for ZR and large device numbers, which is out of scope here.)
+[enum uint 8 SlmpDeviceCode
+    ['0xA8' D]  // Data register   (word, decimal addressing)
+    ['0xB4' W]  // Link register   (word, hex addressing)
+    ['0xAF' R]  // File register    (word, decimal addressing)
+    ['0xC2' TN] // Timer, current value (word, decimal addressing) -- used by 
the
+                // Random Read worked example in SH-080008 section 8.3
+    ['0x90' M]  // Internal relay  (bit,  decimal addressing)
+    ['0x9C' X]  // Input            (bit,  hex addressing)
+    ['0x9D' Y]  // Output          (bit,  hex addressing)
+    ['0xA0' B]  // Link relay      (bit,  hex addressing)
+]
+
+// 3E frame. The Ethernet/TCP header is added by the transport and is not part
+// of this message. Request and response are distinguished by the subheader 
byte
+// (0x50 request / 0xD0 response).
+[discriminatedType SlmpMessage byteOrder='"LITTLE_ENDIAN"' 
unsignedIntegerEncoding='"unsigned-binary"' 
signedIntegerEncoding='"twos-complement"' floatEncoding='"IEEE754"' 
stringEncoding='"UTF8"'
+    [discriminator uint 8 subHeader]                  // 0x50 request, 0xD0 
response
+    [const         uint 8 subHeaderReserved 0x00]     // second subheader byte 
is always 0x00
+    [typeSwitch subHeader
+        ['0x50' SlmpRequestFrame3E
+            // Access route - fixed value for 3E frame (chapter 6): 00 FF FF 
03 00
+            [const    uint 8  network                  0x00]
+            [const    uint 8  pcNumber                 0xFF]
+            [const    uint 16 requestDestModuleIoNo    0x03FF]
+            [const    uint 8  requestDestModuleStation 0x00]
+            // Number of bytes from the monitoring timer up to the end of the 
request data.
+            // = monitoringTimer(2) + command(2) + subCommand(2) + requestData
+            [implicit uint 16 requestDataLength        '6 + 
requestData.lengthInBytes']
+            [simple   uint 16 monitoringTimer]                 // 0x0000 = 
wait infinitely
+            [simple   uint 16 command]                         // 0x0401 = 
Batch Read
+            [simple   uint 16 subCommand]                      // 0x0000 = 
word units
+            [simple   SlmpRequestData('command') requestData]
+        ]
+        ['0xD0' SlmpResponseFrame3E
+            [const    uint 8  network                  0x00]
+            [const    uint 8  pcNumber                 0xFF]
+            [const    uint 16 requestDestModuleIoNo    0x03FF]
+            [const    uint 8  requestDestModuleStation 0x00]
+            // Number of bytes from the end code up to the end of the response 
data.
+            // = endCode(2) + responseData
+            [implicit uint 16 responseDataLength       '2 + 
COUNT(responseData)']
+            [simple   uint 16 endCode]                         // 0x0000 = 
normal completion
+            // Raw payload. On normal completion this is the read words 
(little-endian,
+            // 2 bytes per point); on abnormal completion it carries error 
information.
+            // Typed decoding is left to the driver layer.
+            [array    byte    responseData             count 
'responseDataLength - 2']
+        ]
+    ]
+]
+
+// Request data, dispatched by command. Batch Read (0x0401) and Random Read
+// (0x0403) are modelled here; both are read-only, word units (subcommand 
0x0000).
+[discriminatedType SlmpRequestData(uint 16 command)
+    [typeSwitch command
+        ['0x0401' SlmpReadRequest
+            // Binary, MELSEC-Q/L series: device number (3 bytes, 
little-endian)
+            // then device code (1 byte). See SH-080008 section 8.1.
+            [simple uint 24        headDeviceNumber]
+            [simple SlmpDeviceCode deviceCode]
+            // Number of points to read. In word units this is the number of 
16-bit words.
+            [simple uint 16        numberOfPoints]
+        ]
+        ['0x0403' SlmpRandomReadRequest
+            // Random Read in word units (SH-080008 section 8.3): read 
discontinuous
+            // devices, given as a list of word-access points followed by a 
list of
+            // double-word-access points. The point counts are single bytes; 
each
+            // device is a 3-byte device number + 1-byte device code 
(SlmpDeviceSpec).
+            [simple uint 8         numberOfWordAccessPoints]
+            [simple uint 8         numberOfDoubleWordAccessPoints]
+            [array  SlmpDeviceSpec wordAccessDevices       count 
'numberOfWordAccessPoints']
+            [array  SlmpDeviceSpec doubleWordAccessDevices count 
'numberOfDoubleWordAccessPoints']
+        ]
+        ['0x0406' SlmpMultiBlockReadRequest
+            // Batch Read multiple blocks in word units (SH-080008 section 
8.4): read a
+            // number of word-device blocks followed by a number of bit-device 
blocks,
+            // where each block is a run of consecutive devices. The two block 
counts are
+            // single bytes; each block (SlmpDeviceBlock) is a 3-byte head 
device number,
+            // a 1-byte device code and a 2-byte number of points. Bit-device 
blocks are
+            // read in 16-bit word units (one point = 16 bits), so the wire 
layout of a
+            // bit-device block is identical to that of a word-device block.
+            [simple uint 8          numberOfWordDeviceBlocks]
+            [simple uint 8          numberOfBitDeviceBlocks]
+            [array  SlmpDeviceBlock wordDeviceBlocks count 
'numberOfWordDeviceBlocks']
+            [array  SlmpDeviceBlock bitDeviceBlocks  count 
'numberOfBitDeviceBlocks']
+        ]
+    ]
+]
+
+// A single device specification used by commands that address discontinuous
+// devices (e.g. Random Read 0x0403): a device number (3 bytes, little-endian)
+// followed by the 1-byte device code. See SH-080008 section 8.1 / 8.3.
+[type SlmpDeviceSpec
+    [simple uint 24        deviceNumber]
+    [simple SlmpDeviceCode deviceCode]
+]
+
+// A single block of consecutive devices used by commands that read whole 
blocks
+// (e.g. Batch Read Multiple Blocks 0x0406): a head device number (3 bytes,
+// little-endian) and 1-byte device code identifying the start of the run,
+// followed by the 2-byte number of points (consecutive devices) in the block.
+// This is the same field layout as a single-block Batch Read request
+// (SlmpReadRequest). See SH-080008 section 8.4.
+[type SlmpDeviceBlock
+    [simple uint 24        headDeviceNumber]
+    [simple SlmpDeviceCode deviceCode]
+    [simple uint 16        numberOfPoints]
+]
diff --git 
a/protocols/slmp/src/test/java/org/apache/plc4x/protocol/slmp/SlmpProtocolTest.java
 
b/protocols/slmp/src/test/java/org/apache/plc4x/protocol/slmp/SlmpProtocolTest.java
new file mode 100644
index 0000000000..06f0b490ec
--- /dev/null
+++ 
b/protocols/slmp/src/test/java/org/apache/plc4x/protocol/slmp/SlmpProtocolTest.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.plc4x.protocol.slmp;
+
+import org.apache.plc4x.plugins.codegenerator.protocol.TypeContext;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+
+class SlmpProtocolTest {
+
+    @Test
+    void getTypeContext() throws Exception {
+        TypeContext typeContext = new SlmpProtocol().getTypeContext();
+        assertNotNull(typeContext);
+        assertNotNull(typeContext.getUnresolvedTypeReferences());
+        assertSame(0, typeContext.getUnresolvedTypeReferences().size());
+    }
+
+}
diff --git a/protocols/slmp/src/test/resources/logback-test.xml 
b/protocols/slmp/src/test/resources/logback-test.xml
new file mode 100644
index 0000000000..0524f110fc
--- /dev/null
+++ b/protocols/slmp/src/test/resources/logback-test.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      https://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+  -->
+<configuration xmlns="http://ch.qos.logback/xml/ns/logback";
+               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+               xsi:schemaLocation="
+                  http://ch.qos.logback/xml/ns/logback
+                  
https://raw.githubusercontent.com/enricopulatzo/logback-XSD/master/src/main/xsd/logback.xsd";>
+
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <encoder>
+      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - 
%msg%n</pattern>
+    </encoder>
+  </appender>
+
+  <root level="error">
+    <appender-ref ref="STDOUT" />
+  </root>
+
+</configuration>
diff --git 
a/protocols/slmp/src/test/resources/protocols/slmp/ParserSerializerTestsuite.xml
 
b/protocols/slmp/src/test/resources/protocols/slmp/ParserSerializerTestsuite.xml
new file mode 100644
index 0000000000..6054c1963b
--- /dev/null
+++ 
b/protocols/slmp/src/test/resources/protocols/slmp/ParserSerializerTestsuite.xml
@@ -0,0 +1,279 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      https://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+  -->
+<!--
+  Reference vectors derived from the worked examples in the Mitsubishi MELSEC
+  Communication Protocol Reference Manual (SH-080008). The full 3E binary frame
+  is assembled per section 5.2 / chapter 6.
+
+  Batch Read (0x0401) word-unit example reading the values stored in D350 and
+  D351 (section 8.1):
+    request data : 5E 01 00 A8 02 00      (head=D350, code=D, points=2)
+    response data: AB 56 0F 17            (D350=0x56AB, D351=0x170F)
+
+  Random Read (0x0403) word-unit example reading D0, T0, M100, X20 in word 
units
+  and D1500, Y160, M1111 in double-word units (section 8.3):
+    request data : 04 03                                          (4 word pts, 
3 dword pts)
+                   00 00 00 A8  00 00 00 C2  64 00 00 90  20 00 00 9C   (D0, 
T0, M100, X20)
+                   DC 05 00 A8  60 01 00 9D  57 04 00 90               (D1500, 
Y160, M1111)
+    response data: 95 19 02 12 30 20 49 48                            
(D0=0x1995, T0=0x1202, ...)
+                   4E 4F 54 4C AF B9 DE C3 B7 BC DD BA                 
(D1500/01=0x4F4E/0x4C54, ...)
+
+  Batch Read Multiple Blocks (0x0406) word-unit example reading two word-device
+  blocks (D0-D3, W100-W107) and three bit-device blocks (M0-M31, M128-M159,
+  B100-B12F), section 8.4:
+    request data : 02 03                              (2 word blocks, 3 bit 
blocks)
+                   00 00 00 A8 04 00                  (block D0,   4 points)
+                   00 01 00 B4 08 00                  (block W100, 8 points)
+                   00 00 00 90 02 00                  (block M0,   2 points)
+                   80 00 00 90 02 00                  (block M128, 2 points)
+                   00 01 00 A0 03 00                  (block B100, 3 points)
+  The response (per the manual: word-block data then bit-block data, 16 bits 
per
+  point) re-uses the generic SlmpResponseFrame3E raw-byte payload already 
covered
+  by the Batch/Random Read response cases above, so it is not duplicated here.
+  -->
+<test:testsuite 
xmlns:test="https://plc4x.apache.org/schemas/parser-serializer-testsuite.xsd";
+                byteOrder="LITTLE_ENDIAN">
+
+  <name>SLMP</name>
+
+  <protocol-name>slmp</protocol-name>
+  <output-flavor>read-write</output-flavor>
+
+  <testcase>
+    <name>3E Batch Read Request - D350, 2 words</name>
+    <raw>500000ffff03000c000000010400005e0100a80200</raw>
+    <root-type>SlmpMessage</root-type>
+    <xml>
+      <SlmpMessage>
+        <subHeader dataType="uint" bitLength="8">80</subHeader>
+        <subHeaderReserved dataType="uint" bitLength="8">0</subHeaderReserved>
+        <SlmpRequestFrame3E>
+          <network dataType="uint" bitLength="8">0</network>
+          <pcNumber dataType="uint" bitLength="8">255</pcNumber>
+          <requestDestModuleIoNo dataType="uint" 
bitLength="16">1023</requestDestModuleIoNo>
+          <requestDestModuleStation dataType="uint" 
bitLength="8">0</requestDestModuleStation>
+          <requestDataLength dataType="uint" 
bitLength="16">12</requestDataLength>
+          <monitoringTimer dataType="uint" bitLength="16">0</monitoringTimer>
+          <command dataType="uint" bitLength="16">1025</command>
+          <subCommand dataType="uint" bitLength="16">0</subCommand>
+          <requestData>
+            <SlmpRequestData>
+              <SlmpReadRequest>
+                <headDeviceNumber dataType="uint" 
bitLength="24">350</headDeviceNumber>
+                <deviceCode>
+                  <SlmpDeviceCode dataType="uint" bitLength="8" 
stringRepresentation="D">168</SlmpDeviceCode>
+                </deviceCode>
+                <numberOfPoints dataType="uint" 
bitLength="16">2</numberOfPoints>
+              </SlmpReadRequest>
+            </SlmpRequestData>
+          </requestData>
+        </SlmpRequestFrame3E>
+      </SlmpMessage>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>3E Batch Read Response - D350=0x56AB, D351=0x170F</name>
+    <raw>d00000ffff030006000000ab560f17</raw>
+    <root-type>SlmpMessage</root-type>
+    <xml>
+      <SlmpMessage>
+        <subHeader dataType="uint" bitLength="8">208</subHeader>
+        <subHeaderReserved dataType="uint" bitLength="8">0</subHeaderReserved>
+        <SlmpResponseFrame3E>
+          <network dataType="uint" bitLength="8">0</network>
+          <pcNumber dataType="uint" bitLength="8">255</pcNumber>
+          <requestDestModuleIoNo dataType="uint" 
bitLength="16">1023</requestDestModuleIoNo>
+          <requestDestModuleStation dataType="uint" 
bitLength="8">0</requestDestModuleStation>
+          <responseDataLength dataType="uint" 
bitLength="16">6</responseDataLength>
+          <endCode dataType="uint" bitLength="16">0</endCode>
+          <responseData dataType="byte" 
bitLength="32">0xab560f17</responseData>
+        </SlmpResponseFrame3E>
+      </SlmpMessage>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>3E Random Read Request - D0,T0,M100,X20 word + D1500,Y160,M1111 
dword</name>
+    
<raw>500000ffff030024000000030400000403000000a8000000c2640000902000009cdc0500a86001009d57040090</raw>
+    <root-type>SlmpMessage</root-type>
+    <xml>
+      <SlmpMessage>
+        <subHeader dataType="uint" bitLength="8">80</subHeader>
+        <subHeaderReserved dataType="uint" bitLength="8">0</subHeaderReserved>
+        <SlmpRequestFrame3E>
+          <network dataType="uint" bitLength="8">0</network>
+          <pcNumber dataType="uint" bitLength="8">255</pcNumber>
+          <requestDestModuleIoNo dataType="uint" 
bitLength="16">1023</requestDestModuleIoNo>
+          <requestDestModuleStation dataType="uint" 
bitLength="8">0</requestDestModuleStation>
+          <requestDataLength dataType="uint" 
bitLength="16">36</requestDataLength>
+          <monitoringTimer dataType="uint" bitLength="16">0</monitoringTimer>
+          <command dataType="uint" bitLength="16">1027</command>
+          <subCommand dataType="uint" bitLength="16">0</subCommand>
+          <requestData>
+            <SlmpRequestData>
+              <SlmpRandomReadRequest>
+                <numberOfWordAccessPoints dataType="uint" 
bitLength="8">4</numberOfWordAccessPoints>
+                <numberOfDoubleWordAccessPoints dataType="uint" 
bitLength="8">3</numberOfDoubleWordAccessPoints>
+                <wordAccessDevices isList="true">
+                  <SlmpDeviceSpec>
+                    <deviceNumber dataType="uint" 
bitLength="24">0</deviceNumber>
+                    <deviceCode>
+                      <SlmpDeviceCode dataType="uint" bitLength="8" 
stringRepresentation="D">168</SlmpDeviceCode>
+                    </deviceCode>
+                  </SlmpDeviceSpec>
+                  <SlmpDeviceSpec>
+                    <deviceNumber dataType="uint" 
bitLength="24">0</deviceNumber>
+                    <deviceCode>
+                      <SlmpDeviceCode dataType="uint" bitLength="8" 
stringRepresentation="TN">194</SlmpDeviceCode>
+                    </deviceCode>
+                  </SlmpDeviceSpec>
+                  <SlmpDeviceSpec>
+                    <deviceNumber dataType="uint" 
bitLength="24">100</deviceNumber>
+                    <deviceCode>
+                      <SlmpDeviceCode dataType="uint" bitLength="8" 
stringRepresentation="M">144</SlmpDeviceCode>
+                    </deviceCode>
+                  </SlmpDeviceSpec>
+                  <SlmpDeviceSpec>
+                    <deviceNumber dataType="uint" 
bitLength="24">32</deviceNumber>
+                    <deviceCode>
+                      <SlmpDeviceCode dataType="uint" bitLength="8" 
stringRepresentation="X">156</SlmpDeviceCode>
+                    </deviceCode>
+                  </SlmpDeviceSpec>
+                </wordAccessDevices>
+                <doubleWordAccessDevices isList="true">
+                  <SlmpDeviceSpec>
+                    <deviceNumber dataType="uint" 
bitLength="24">1500</deviceNumber>
+                    <deviceCode>
+                      <SlmpDeviceCode dataType="uint" bitLength="8" 
stringRepresentation="D">168</SlmpDeviceCode>
+                    </deviceCode>
+                  </SlmpDeviceSpec>
+                  <SlmpDeviceSpec>
+                    <deviceNumber dataType="uint" 
bitLength="24">352</deviceNumber>
+                    <deviceCode>
+                      <SlmpDeviceCode dataType="uint" bitLength="8" 
stringRepresentation="Y">157</SlmpDeviceCode>
+                    </deviceCode>
+                  </SlmpDeviceSpec>
+                  <SlmpDeviceSpec>
+                    <deviceNumber dataType="uint" 
bitLength="24">1111</deviceNumber>
+                    <deviceCode>
+                      <SlmpDeviceCode dataType="uint" bitLength="8" 
stringRepresentation="M">144</SlmpDeviceCode>
+                    </deviceCode>
+                  </SlmpDeviceSpec>
+                </doubleWordAccessDevices>
+              </SlmpRandomReadRequest>
+            </SlmpRequestData>
+          </requestData>
+        </SlmpRequestFrame3E>
+      </SlmpMessage>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>3E Random Read Response - 4 word + 3 dword values</name>
+    <raw>d00000ffff03001600000095190212302049484e4f544cafb9dec3b7bcddba</raw>
+    <root-type>SlmpMessage</root-type>
+    <xml>
+      <SlmpMessage>
+        <subHeader dataType="uint" bitLength="8">208</subHeader>
+        <subHeaderReserved dataType="uint" bitLength="8">0</subHeaderReserved>
+        <SlmpResponseFrame3E>
+          <network dataType="uint" bitLength="8">0</network>
+          <pcNumber dataType="uint" bitLength="8">255</pcNumber>
+          <requestDestModuleIoNo dataType="uint" 
bitLength="16">1023</requestDestModuleIoNo>
+          <requestDestModuleStation dataType="uint" 
bitLength="8">0</requestDestModuleStation>
+          <responseDataLength dataType="uint" 
bitLength="16">22</responseDataLength>
+          <endCode dataType="uint" bitLength="16">0</endCode>
+          <responseData dataType="byte" 
bitLength="160">0x95190212302049484e4f544cafb9dec3b7bcddba</responseData>
+        </SlmpResponseFrame3E>
+      </SlmpMessage>
+    </xml>
+  </testcase>
+
+  <testcase>
+    <name>3E Multi-block Read Request - 2 word blocks (D0-D3, W100-W107) + 3 
bit blocks (M0-M31, M128-M159, B100-B12F)</name>
+    
<raw>500000ffff030026000000060400000203000000a80400000100b40800000000900200800000900200000100a00300</raw>
+    <root-type>SlmpMessage</root-type>
+    <xml>
+      <SlmpMessage>
+        <subHeader dataType="uint" bitLength="8">80</subHeader>
+        <subHeaderReserved dataType="uint" bitLength="8">0</subHeaderReserved>
+        <SlmpRequestFrame3E>
+          <network dataType="uint" bitLength="8">0</network>
+          <pcNumber dataType="uint" bitLength="8">255</pcNumber>
+          <requestDestModuleIoNo dataType="uint" 
bitLength="16">1023</requestDestModuleIoNo>
+          <requestDestModuleStation dataType="uint" 
bitLength="8">0</requestDestModuleStation>
+          <requestDataLength dataType="uint" 
bitLength="16">38</requestDataLength>
+          <monitoringTimer dataType="uint" bitLength="16">0</monitoringTimer>
+          <command dataType="uint" bitLength="16">1030</command>
+          <subCommand dataType="uint" bitLength="16">0</subCommand>
+          <requestData>
+            <SlmpRequestData>
+              <SlmpMultiBlockReadRequest>
+                <numberOfWordDeviceBlocks dataType="uint" 
bitLength="8">2</numberOfWordDeviceBlocks>
+                <numberOfBitDeviceBlocks dataType="uint" 
bitLength="8">3</numberOfBitDeviceBlocks>
+                <wordDeviceBlocks isList="true">
+                  <SlmpDeviceBlock>
+                    <headDeviceNumber dataType="uint" 
bitLength="24">0</headDeviceNumber>
+                    <deviceCode>
+                      <SlmpDeviceCode dataType="uint" bitLength="8" 
stringRepresentation="D">168</SlmpDeviceCode>
+                    </deviceCode>
+                    <numberOfPoints dataType="uint" 
bitLength="16">4</numberOfPoints>
+                  </SlmpDeviceBlock>
+                  <SlmpDeviceBlock>
+                    <headDeviceNumber dataType="uint" 
bitLength="24">256</headDeviceNumber>
+                    <deviceCode>
+                      <SlmpDeviceCode dataType="uint" bitLength="8" 
stringRepresentation="W">180</SlmpDeviceCode>
+                    </deviceCode>
+                    <numberOfPoints dataType="uint" 
bitLength="16">8</numberOfPoints>
+                  </SlmpDeviceBlock>
+                </wordDeviceBlocks>
+                <bitDeviceBlocks isList="true">
+                  <SlmpDeviceBlock>
+                    <headDeviceNumber dataType="uint" 
bitLength="24">0</headDeviceNumber>
+                    <deviceCode>
+                      <SlmpDeviceCode dataType="uint" bitLength="8" 
stringRepresentation="M">144</SlmpDeviceCode>
+                    </deviceCode>
+                    <numberOfPoints dataType="uint" 
bitLength="16">2</numberOfPoints>
+                  </SlmpDeviceBlock>
+                  <SlmpDeviceBlock>
+                    <headDeviceNumber dataType="uint" 
bitLength="24">128</headDeviceNumber>
+                    <deviceCode>
+                      <SlmpDeviceCode dataType="uint" bitLength="8" 
stringRepresentation="M">144</SlmpDeviceCode>
+                    </deviceCode>
+                    <numberOfPoints dataType="uint" 
bitLength="16">2</numberOfPoints>
+                  </SlmpDeviceBlock>
+                  <SlmpDeviceBlock>
+                    <headDeviceNumber dataType="uint" 
bitLength="24">256</headDeviceNumber>
+                    <deviceCode>
+                      <SlmpDeviceCode dataType="uint" bitLength="8" 
stringRepresentation="B">160</SlmpDeviceCode>
+                    </deviceCode>
+                    <numberOfPoints dataType="uint" 
bitLength="16">3</numberOfPoints>
+                  </SlmpDeviceBlock>
+                </bitDeviceBlocks>
+              </SlmpMultiBlockReadRequest>
+            </SlmpRequestData>
+          </requestData>
+        </SlmpRequestFrame3E>
+      </SlmpMessage>
+    </xml>
+  </testcase>
+
+</test:testsuite>


Reply via email to