You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cd...@apache.org on 2020/01/18 14:14:24 UTC
[plc4x] branch develop updated: - Started implementing the Modbus
protocol.
This is an automated email from the ASF dual-hosted git repository.
cdutz 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 3842331 - Started implementing the Modbus protocol.
3842331 is described below
commit 38423313e7c25e8b72cbe72c295c5b7b888135ad
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Sat Jan 18 15:14:16 2020 +0100
- Started implementing the Modbus protocol.
---
protocols/modbus/pom.xml | 43 ++++
.../plc4x/protocol/modbus/ModbusProtocol.java | 46 ++++
...e.plc4x.plugins.codegenerator.protocol.Protocol | 19 ++
.../main/resources/protocols/modbus/modbus.mspec | 269 +++++++++++++++++++++
protocols/pom.xml | 19 +-
5 files changed, 387 insertions(+), 9 deletions(-)
diff --git a/protocols/modbus/pom.xml b/protocols/modbus/pom.xml
new file mode 100644
index 0000000..d79335f
--- /dev/null
+++ b/protocols/modbus/pom.xml
@@ -0,0 +1,43 @@
+<?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
+
+ http://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.7.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>plc4x-protocols-modbus</artifactId>
+
+ <name>Protocols: Modbus</name>
+ <description>Base protocol specifications for the Modbus protocol</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4x-build-utils-protocol-base-mspec</artifactId>
+ <version>0.7.0-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/protocols/modbus/src/main/java/org/apache/plc4x/protocol/modbus/ModbusProtocol.java b/protocols/modbus/src/main/java/org/apache/plc4x/protocol/modbus/ModbusProtocol.java
new file mode 100644
index 0000000..2251995
--- /dev/null
+++ b/protocols/modbus/src/main/java/org/apache/plc4x/protocol/modbus/ModbusProtocol.java
@@ -0,0 +1,46 @@
+/*
+ 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
+
+ http://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.modbus;
+
+import org.apache.plc4x.plugins.codegenerator.language.mspec.parser.MessageFormatParser;
+import org.apache.plc4x.plugins.codegenerator.protocol.Protocol;
+import org.apache.plc4x.plugins.codegenerator.types.definitions.TypeDefinition;
+import org.apache.plc4x.plugins.codegenerator.types.exceptions.GenerationException;
+
+import java.io.InputStream;
+import java.util.Map;
+
+public class ModbusProtocol implements Protocol {
+
+ @Override
+ public String getName() {
+ return "modbus";
+ }
+
+ @Override
+ public Map<String, TypeDefinition> getTypeDefinitions() throws GenerationException {
+ InputStream schemaInputStream = ModbusProtocol.class.getResourceAsStream("/protocols/modbus/modbus.mspec");
+ if(schemaInputStream == null) {
+ throw new GenerationException("Error loading message-format schema for protocol '" + getName() + "'");
+ }
+ return new MessageFormatParser().parse(schemaInputStream);
+ }
+
+}
diff --git a/protocols/modbus/src/main/resources/META-INF/services/org.apache.plc4x.plugins.codegenerator.protocol.Protocol b/protocols/modbus/src/main/resources/META-INF/services/org.apache.plc4x.plugins.codegenerator.protocol.Protocol
new file mode 100644
index 0000000..b5211ef
--- /dev/null
+++ b/protocols/modbus/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
+#
+# http://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.modbus.ModbusProtocol
diff --git a/protocols/modbus/src/main/resources/protocols/modbus/modbus.mspec b/protocols/modbus/src/main/resources/protocols/modbus/modbus.mspec
new file mode 100644
index 0000000..b23a810
--- /dev/null
+++ b/protocols/modbus/src/main/resources/protocols/modbus/modbus.mspec
@@ -0,0 +1,269 @@
+//
+// 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
+//
+// http://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.
+//
+
+// Remark: The different fields are encoded in Big-endian.
+
+[type 'ModbusConstants'
+ [const uint 16 'modbusTcpDefaultPort' '502']
+]
+
+[type 'ModbusTcpADU' [bit 'response']
+ // It is used for transaction pairing, the MODBUS server copies in the response the transaction
+ // identifier of the request.
+ [simple uint 16 'transactionIdentifier']
+
+ // It is used for intra-system multiplexing. The MODBUS protocol is identified by the value 0.
+ [const uint 16 'protocolIdentifier' '0x0000']
+
+ // The length field is a byte count of the following fields, including the Unit Identifier and
+ // data fields.
+ [simple uint 16 'length']
+
+ // This field is used for intra-system routing purpose. It is typically used to communicate to
+ // a MODBUS+ or a MODBUS serial line slave through a gateway between an Ethernet TCP-IP network
+ // and a MODBUS serial line. This field is set by the MODBUS Client in the request and must be
+ // returned with the same value in the response by the server.
+ [simple uint 8 'unitItendifier']
+
+ // The actual modbus payload
+ [simple ModbusPDU 'pdu' ['response']]
+]
+
+[type 'ModbusSerialADU' [bit 'response']
+ [simple uint 16 'transactionId']
+ [reserved uint 16 '0x0000']
+ [simple uint 16 'length']
+ [simple uint 8 'address']
+
+ // The actual modbus payload
+ [simple ModbusPDU 'pdu' ['response']]
+]
+
+[discriminatedType 'ModbusPDU' [bit 'response']
+ [discriminator uint 7 'function']
+ [simple bit 'error']
+ [typeSwitch 'error','function','response'
+ ['true' ModbusPduError
+ [simple uint 8 'exceptionCode']
+ ]
+
+ // Bit Access
+ ['false','0x02','false' ModbusPduReadDiscreteInputsRequest
+ [simple uint 16 'startingAddress']
+ [simple uint 16 'quantity']
+ ]
+ ['false','0x02','true' ModbusPduReadDiscreteInputsResponse
+ [implicit uint 8 'byteCount' 'value.lengthInBytes']
+ [array int 8 'value' count 'byteCount']
+ ]
+
+ ['false','0x01','false' ModbusPduReadCoilsRequest
+ [simple uint 16 'startingAddress']
+ [simple uint 16 'quantity']
+ ]
+ ['false','0x01','true' ModbusPduReadCoilsResponse
+ [implicit uint 8 'byteCount' 'value.lengthInBytes']
+ [array int 8 'value' count 'byteCount']
+ ]
+
+ ['false','0x05','false' ModbusPduWriteSingleCoilRequest
+ [simple uint 16 'address']
+ [simple uint 16 'value']
+ ]
+ ['false','0x05','true' ModbusPduWriteSingleCoilResponse
+ [simple uint 16 'address']
+ [simple uint 16 'value']
+ ]
+
+ ['false','0x0F','false' ModbusPduWriteMultipleCoilsRequest
+ [simple uint 16 'startingAddress']
+ [simple uint 16 'quantity']
+ [implicit uint 8 'byteCount' 'value.lengthInBytes']
+ [array int 8 'value' count 'byteCount']
+ ]
+ ['false','0x0F','true' ModbusPduWriteMultipleCoilsResponse
+ [simple uint 16 'startingAddress']
+ [simple uint 16 'quantity']
+ ]
+
+ // Uint 16 Access (short)
+ ['false','0x04','false' ModbusPduReadInputRegistersRequest
+ [simple uint 16 'startingAddress']
+ [simple uint 16 'quantity']
+ ]
+ ['false','0x04','true' ModbusPduReadInputRegistersResponse
+ [implicit uint 8 'byteCount' 'value.lengthInBytes']
+ [array int 8 'value' count 'byteCount']
+ ]
+
+ ['false','0x03','false' ModbusPduReadHoldingRegistersRequest
+ [simple uint 16 'startingAddress']
+ [simple uint 16 'quantity']
+ ]
+ ['false','0x03','true' ModbusPduReadHoldingRegistersResponse
+ [implicit uint 8 'byteCount' 'value.lengthInBytes']
+ [array int 8 'value' count 'byteCount']
+ ]
+
+ ['false','0x06','false' ModbusPduWriteSingleRegisterRequest
+ [simple uint 16 'address']
+ [simple uint 16 'value']
+ ]
+ ['false','0x06','true' ModbusPduWriteSingleRegisterResponse
+ [simple uint 16 'address']
+ [simple uint 16 'value']
+ ]
+
+ ['false','0x10','false' ModbusPduWriteMultipleRegistersRequest
+ [simple uint 16 'startingAddress']
+ [simple uint 16 'quantity']
+ [implicit uint 8 'byteCount' 'value.lengthInBytes']
+ [array int 8 'value' count 'byteCount']
+ ]
+ ['false','0x10','true' ModbusPduWriteMultipleRegistersResponse
+ [simple uint 16 'startingAddress']
+ [simple uint 16 'quantity']
+ ]
+
+ ['false','0x17','false' ModbusPduReadWriteMultipleRegistersRequest
+ [simple uint 16 'readStartingAddress']
+ [simple uint 16 'readQuantity']
+ [simple uint 16 'writeStartingAddress']
+ [simple uint 16 'writeQuantity']
+ [implicit uint 8 'byteCount' 'value.lengthInBytes']
+ [array int 8 'value' count 'byteCount']
+ ]
+ ['false','0x17','true' ModbusPduReadWriteMultipleRegistersResponse
+ [implicit uint 8 'byteCount' 'value.lengthInBytes']
+ [array int 8 'value' count 'byteCount']
+ ]
+
+ ['false','0x16','false' ModbusPduMaskWriteRegisterRequest
+ [simple uint 16 'referenceAddress']
+ [simple uint 16 'andMask']
+ [simple uint 16 'orMask']
+ ]
+ ['false','0x16','true' ModbusPduMaskWriteRegisterResponse
+ [simple uint 16 'referenceAddress']
+ [simple uint 16 'andMask']
+ [simple uint 16 'orMask']
+ ]
+
+ ['false','0x18','false' ModbusPduReadFifoQueueRequest
+ [simple uint 16 'fifoPointerAddress']
+ ]
+ ['false','0x18','true' ModbusPduReadFifoQueueResponse
+ [implicit uint 16 'byteCount' 'fifoValue.lengthInBytes + 2']
+ [implicit uint 16 'fifoCount' 'fifoValue.lengthInBytes / 2']
+ [array uint 16 'fifoValue' count 'fifoCount']
+ ]
+
+ // File Record Access
+ ['false','0x14','false' ModbusPduReadFileRecordRequest
+ [implicit uint 8 'byteCount' 'items.lengthInBytes']
+ [array ModbusPduReadFileRecordRequestItem 'items' length 'byteCount']
+ ]
+ ['false','0x14','true' ModbusPduReadFileRecordResponse
+ [implicit uint 8 'byteCount' 'items.lengthInBytes']
+ [array ModbusPduReadFileRecordResponseItem 'items' length 'byteCount']
+ ]
+
+ ['false','0x15','false' ModbusPduWriteFileRecordRequest
+ [implicit uint 8 'byteCount' 'items.lengthInBytes']
+ [array ModbusPduWriteFileRecordRequestItem 'items' length 'byteCount']
+ ]
+ ['false','0x15','true' ModbusPduWriteFileRecordResponse
+ [implicit uint 8 'byteCount' 'items.lengthInBytes']
+ [array ModbusPduWriteFileRecordResponseItem 'items' length 'byteCount']
+ ]
+
+ // Diagnostics (Serial Line Only)
+ ['false','0x07','false' ModbusPduReadExceptionStatusRequest
+ ]
+ ['false','0x07','true' ModbusPduReadExceptionStatusResponse
+ [simple uint 8 'value']
+ ]
+
+ ['false','0x08','false' ModbusPduDiagnosticRequest
+ // TODO: Implement the sub-request discriminated type [simple uint 8 'subfunction']
+ ]
+ ['false','0x08','true' ModbusPduDiagnosticResponse
+ // TODO: Implement the sub-request discriminated type [simple uint 8 'subfunction']
+ ]
+
+ ['false','0x0B','false' ModbusPduGetComEventCounterRequest
+ ]
+ ['false','0x0B','true' ModbusPduGetComEventCounterResponse
+ [simple uint 16 'status']
+ [simple uint 16 'eventCount']
+ ]
+
+ ['false','0x0C','false' ModbusPduGetComEventLogRequest
+ ]
+ ['false','0x0C','true' ModbusPduGetComEventLogResponse
+ [implicit uint 8 'byteCount' 'events.lengthInBytes + 6']
+ [simple uint 16 'status']
+ [simple uint 16 'eventCount']
+ [simple uint 16 'messageCount']
+ [array int 8 'events' count 'byteCount - 6']
+ ]
+
+ ['false','0x11','false' ModbusPduReportServerIdRequest
+ ]
+ ['false','0x11','true' ModbusPduReportServerIdResponse
+ // TODO: This is not specified very well in the spec ... investigate.
+ [implicit uint 8 'byteCount' 'value.lengthInBytes']
+ [array int 8 'value' count 'byteCount']
+ ]
+
+ ['false','0x2B','false' ModbusPduReadDeviceIdentificationRequest
+ ]
+ ['false','0x2B','true' ModbusPduReadDeviceIdentificationResponse
+ ]
+ ]
+]
+
+[type 'ModbusPduReadFileRecordRequestItem'
+ [simple uint 8 'referenceType']
+ [simple uint 16 'fileNumber']
+ [simple uint 16 'recordNumber']
+ [simple uint 16 'recordLength']
+]
+
+[type 'ModbusPduReadFileRecordResponseItem'
+ [implicit uint 8 'dataLength' 'data.lengthInBytes + 1']
+ [simple uint 8 'referenceType']
+ [array uint 16 'data' length 'dataLength - 1']
+]
+
+[type 'ModbusPduWriteFileRecordRequestItem'
+ [simple uint 8 'referenceType']
+ [simple uint 16 'fileNumber']
+ [simple uint 16 'recordNumber']
+ [implicit uint 16 'recordLength' 'recordData.lengthInBytes / 2']
+ [array uint 16 'recordData' length 'recordLength * 2']
+]
+
+[type 'ModbusPduWriteFileRecordResponseItem'
+ [simple uint 8 'referenceType']
+ [simple uint 16 'fileNumber']
+ [simple uint 16 'recordNumber']
+ [implicit uint 16 'recordLength' 'recordData.lengthInBytes / 2']
+ [array uint 16 'recordData' length 'recordLength * 2']
+]
diff --git a/protocols/pom.xml b/protocols/pom.xml
index 8d3804c..c77fa40 100644
--- a/protocols/pom.xml
+++ b/protocols/pom.xml
@@ -33,6 +33,16 @@
<name>Protocols</name>
<description>Base protocol specifications.</description>
+ <modules>
+ <module>ab-eth</module>
+ <module>amsads</module>
+ <module>bacnetip</module>
+ <module>df1</module>
+ <module>knxnetip</module>
+ <module>modbus</module>
+ <module>s7</module>
+ </modules>
+
<build>
<plugins>
<!--
@@ -189,15 +199,6 @@
</plugins>
</build>
- <modules>
- <module>amsads</module>
- <module>ab-eth</module>
- <module>bacnetip</module>
- <module>df1</module>
- <module>knxnetip</module>
- <module>s7</module>
- </modules>
-
<profiles>
<profile>
<id>with-proxies</id>