You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by ld...@apache.org on 2020/12/21 17:39:56 UTC
[plc4x] 01/01: PLC4X-266 Initial sketch of M-Bus spec.
This is an automated email from the ASF dual-hosted git repository.
ldywicki pushed a commit to branch feature/m-bus
in repository https://gitbox.apache.org/repos/asf/plc4x.git
commit d54a33723bd2b5b1d5a0dce8711fcb370d1ed804
Author: Ćukasz Dywicki <lu...@code-house.org>
AuthorDate: Mon Dec 21 18:39:32 2020 +0100
PLC4X-266 Initial sketch of M-Bus spec.
It works with sample frames without decoding data.
---
plc4j/drivers/mbus/pom.xml | 204 ++++++++++++++++++
.../org/apache/plc4x/java/mbus/MBusPlcDriver.java | 95 +++++++++
.../plc4x/java/mbus/field/MBusFieldHandler.java | 29 +++
.../apache/plc4x/java/mbus/helper/MBusHelper.java | 97 +++++++++
.../java/mbus/protocol/MBusProtocolLogic.java | 32 +++
.../services/org.apache.plc4x.java.api.PlcDriver | 19 ++
.../apache/plc4x/java/mbus/MBusPayloadTest.java | 29 +++
.../plc4x/java/mbus/helper/MBusHelperTest.java | 48 +++++
plc4j/drivers/pom.xml | 1 +
{plc4j/drivers => protocols/mbus}/pom.xml | 34 ++-
.../apache/plc4x/protocol/mbus/MBusProtocol.java | 46 ++++
...e.plc4x.plugins.codegenerator.protocol.Protocol | 19 ++
.../src/main/resources/protocols/mbus/mbus.mspec | 124 +++++++++++
.../test/resources/protocols/mbus/MBusDriverIT.xml | 129 +++++++++++
.../protocols/mbus/MBusPayloadTestSuite.xml | 236 +++++++++++++++++++++
protocols/pom.xml | 1 +
src/site/asciidoc/protocols/mbus/index.adoc | 26 +++
17 files changed, 1148 insertions(+), 21 deletions(-)
diff --git a/plc4j/drivers/mbus/pom.xml b/plc4j/drivers/mbus/pom.xml
new file mode 100644
index 0000000..ba58f9b
--- /dev/null
+++ b/plc4j/drivers/mbus/pom.xml
@@ -0,0 +1,204 @@
+<?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>plc4j-drivers</artifactId>
+ <version>0.8.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>plc4j-driver-mbus</artifactId>
+ <name>PLC4J: Driver: MBus</name>
+ <description>Implementation of MBus driver.</description>
+
+ <packaging>bundle</packaging>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.plc4x.plugins</groupId>
+ <artifactId>plc4x-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>canopen</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>generate-driver</goal>
+ </goals>
+ <configuration>
+ <protocolName>mbus</protocolName>
+ <languageName>java</languageName>
+ <outputFlavor>read-write</outputFlavor>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.karaf.tooling</groupId>
+ <artifactId>karaf-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>generate-feature-xml</id>
+ <phase>compile</phase>
+ <goals>
+ <!-- Generate the feature.xml -->
+ <goal>features-generate-descriptor</goal>
+ <!-- Check the feature.xml -->
+ <goal>verify</goal>
+ </goals>
+ <configuration>
+ <enableGeneration>true</enableGeneration>
+ <aggregateFeatures>true</aggregateFeatures>
+ </configuration>
+ </execution>
+ <execution>
+ <id>build-kar</id>
+ <phase>package</phase>
+ <goals>
+ <!--
+ Build a kar archive (Jar containing the feature.xml
+ as well as the module content and it's dependencies.
+ -->
+ <goal>kar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
+ <Bundle-Activator>org.apache.plc4x.java.osgi.DriverActivator</Bundle-Activator>
+ <Export-Service>org.apache.plc4x.java.api.PlcDriver,MBusPlcDriver</Export-Service>
+ <Import-Package>
+ com.fasterxml.jackson.annotation;resolution:=optional,
+ *
+ </Import-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <configuration>
+ <usedDependencies combine.children="append">
+ <usedDependency>org.apache.plc4x:plc4x-build-utils-language-java</usedDependency>
+ <usedDependency>org.apache.plc4x:plc4x-protocols-mbus</usedDependency>
+ </usedDependencies>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4j-api</artifactId>
+ <version>0.8.0-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4j-spi</artifactId>
+ <version>0.8.0-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4j-transport-serial</artifactId>
+ <version>0.8.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4j-transport-tcp</artifactId>
+ <version>0.8.0-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>io.netty</groupId>
+ <artifactId>netty-buffer</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.vavr</groupId>
+ <artifactId>vavr</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-annotations</artifactId>
+ </dependency>
+
+ <!-- Logging -->
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4j-utils-test-utils</artifactId>
+ <version>0.8.0-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4x-protocols-mbus</artifactId>
+ <version>0.8.0-SNAPSHOT</version>
+ <!-- Scope is 'provided' as this way it's not shipped with the driver -->
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4x-build-utils-language-java</artifactId>
+ <version>0.8.0-SNAPSHOT</version>
+ <!-- Scope is 'provided' as this way it's not shipped with the driver -->
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4x-protocols-mbus</artifactId>
+ <version>0.8.0-SNAPSHOT</version>
+ <classifier>tests</classifier>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/plc4j/drivers/mbus/src/main/java/org/apache/plc4x/java/mbus/MBusPlcDriver.java b/plc4j/drivers/mbus/src/main/java/org/apache/plc4x/java/mbus/MBusPlcDriver.java
new file mode 100644
index 0000000..6632531
--- /dev/null
+++ b/plc4j/drivers/mbus/src/main/java/org/apache/plc4x/java/mbus/MBusPlcDriver.java
@@ -0,0 +1,95 @@
+/*
+ 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.java.mbus;
+
+import io.netty.buffer.ByteBuf;
+import org.apache.plc4x.java.api.value.PlcValueHandler;
+import org.apache.plc4x.java.mbus.field.MBusFieldHandler;
+import org.apache.plc4x.java.mbus.protocol.MBusProtocolLogic;
+import org.apache.plc4x.java.mbus.readwrite.MBusFrame;
+import org.apache.plc4x.java.mbus.readwrite.io.MBusFrameIO;
+import org.apache.plc4x.java.spi.configuration.Configuration;
+import org.apache.plc4x.java.spi.connection.GeneratedDriverBase;
+import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
+import org.apache.plc4x.java.spi.connection.ProtocolStackConfigurer;
+import org.apache.plc4x.java.spi.connection.SingleProtocolStackConfigurer;
+
+import java.util.function.ToIntFunction;
+
+public class MBusPlcDriver extends GeneratedDriverBase<MBusFrame> {
+
+ @Override
+ public String getProtocolCode() {
+ return "mbus";
+ }
+
+ @Override
+ public String getProtocolName() {
+ return "Meter-Bus";
+ }
+
+ @Override
+ protected Class<? extends Configuration> getConfigurationType() {
+ return null;
+ }
+
+ @Override
+ protected PlcFieldHandler getFieldHandler() {
+ return new MBusFieldHandler();
+ }
+
+ @Override
+ protected PlcValueHandler getValueHandler() {
+ return null;
+ }
+
+ @Override
+ protected String getDefaultTransport() {
+ return null;
+ }
+
+ @Override
+ protected ProtocolStackConfigurer<MBusFrame> getStackConfigurer() {
+ return SingleProtocolStackConfigurer.builder(MBusFrame.class, MBusFrameIO.class)
+ .withPacketSizeEstimator(MBusEstimator.class)
+ .withProtocol(MBusProtocolLogic.class)
+ .littleEndian()
+ .build();
+ }
+
+ static class MBusEstimator implements ToIntFunction<ByteBuf> {
+ @Override
+ public int applyAsInt(ByteBuf byteBuf) {
+ if (byteBuf.readableBytes() >= 1) {
+ int type = byteBuf.getByte(byteBuf.readerIndex()) & 0xFF;
+ switch (type) {
+ case 0x68:
+ // length is sent as second filed right after frame type
+ return byteBuf.getByte(byteBuf.readerIndex() + 1) & 0xFF;
+ case 0xE5:
+ return 1;
+ case 0x10: // short frame
+ return 5;
+ }
+ }
+
+ return -1;
+ }
+ }
+}
diff --git a/plc4j/drivers/mbus/src/main/java/org/apache/plc4x/java/mbus/field/MBusFieldHandler.java b/plc4j/drivers/mbus/src/main/java/org/apache/plc4x/java/mbus/field/MBusFieldHandler.java
new file mode 100644
index 0000000..c200a48
--- /dev/null
+++ b/plc4j/drivers/mbus/src/main/java/org/apache/plc4x/java/mbus/field/MBusFieldHandler.java
@@ -0,0 +1,29 @@
+/*
+ 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.java.mbus.field;
+
+import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.spi.connection.PlcFieldHandler;
+
+public class MBusFieldHandler implements PlcFieldHandler {
+ @Override
+ public PlcField createField(String fieldQuery) {
+ return null;
+ }
+}
diff --git a/plc4j/drivers/mbus/src/main/java/org/apache/plc4x/java/mbus/helper/MBusHelper.java b/plc4j/drivers/mbus/src/main/java/org/apache/plc4x/java/mbus/helper/MBusHelper.java
new file mode 100644
index 0000000..4efedaf
--- /dev/null
+++ b/plc4j/drivers/mbus/src/main/java/org/apache/plc4x/java/mbus/helper/MBusHelper.java
@@ -0,0 +1,97 @@
+/*
+ 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.java.mbus.helper;
+
+import org.apache.plc4x.java.mbus.readwrite.DataInformationFieldExtension;
+import org.apache.plc4x.java.spi.generation.ParseException;
+import org.apache.plc4x.java.spi.generation.ReadBuffer;
+
+public class MBusHelper {
+
+ public static byte crc(byte[] frame) {
+ return crc(frame, 3);
+ }
+
+ public static byte crc(byte[] frame, int headerLength) {
+ return crc(frame, headerLength, 0);
+ }
+
+ public static byte crc(byte[] frame, int headerLength, int skipBytes) {
+ int checksum = 0;
+ for (int index = headerLength; index < (frame.length - skipBytes); index++) {
+ checksum += frame[index];
+ }
+ return (byte) (checksum & 0xff);
+ }
+
+ public static boolean isLastExtension(ReadBuffer io) throws ParseException {
+ return (io.peekByte(-1) & 0x80) != 0x80;
+ }
+
+ public static DataInformationFieldExtension mergeDife(int storage, DataInformationFieldExtension[] difes) {
+ DataInformationFieldExtension ext = null;
+ for (DataInformationFieldExtension dife : difes) {
+ if (ext == null) {
+ ext = dife;
+ } else {
+ /*
+ ext = new DataInformationFieldExtension(
+ (byte) (ext.getSubunit() + dife.getSubunit()),
+ (byte) (ext.getTariff() + dife.getTariff()),
+ ext.getStorage() + dife.getStorage()
+ );
+ */
+ }
+
+ }
+ return ext;
+ }
+
+ public static int difeSize(DataInformationFieldExtension dife) {
+ return 0;
+ }
+
+ public static DataInformationFieldExtension readDife(ReadBuffer io, boolean extension, long storage) throws ParseException {
+ if (!extension) {
+ return null;
+ }
+
+ int subunit = 0;
+ int tariff = 0;
+
+ int numDife = 0;
+ byte val;
+ do {
+ val = io.readByte(8);
+ subunit += (((val & 0x40) >> 6) << numDife);
+ tariff += ((val & 0x30) >> 4) << (numDife * 2);
+ storage += ((val & 0x0f) << ((numDife * 4) + 1));
+ numDife++;
+ } while ((val & 0x80) == 0x80);
+
+// return new DataInformationFieldExtension(
+// subunit, tariff, BigInteger.valueOf(storage)
+// );
+ return null;
+ }
+
+ public static void writeDife(Object value) {
+
+ }
+}
diff --git a/plc4j/drivers/mbus/src/main/java/org/apache/plc4x/java/mbus/protocol/MBusProtocolLogic.java b/plc4j/drivers/mbus/src/main/java/org/apache/plc4x/java/mbus/protocol/MBusProtocolLogic.java
new file mode 100644
index 0000000..43fff58
--- /dev/null
+++ b/plc4j/drivers/mbus/src/main/java/org/apache/plc4x/java/mbus/protocol/MBusProtocolLogic.java
@@ -0,0 +1,32 @@
+/*
+ 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.java.mbus.protocol;
+
+import org.apache.plc4x.java.mbus.readwrite.MBusFrame;
+import org.apache.plc4x.java.spi.ConversationContext;
+import org.apache.plc4x.java.spi.Plc4xProtocolBase;
+
+public class MBusProtocolLogic extends Plc4xProtocolBase<MBusFrame> {
+
+ @Override
+ public void close(ConversationContext<MBusFrame> context) {
+
+ }
+
+}
diff --git a/plc4j/drivers/mbus/src/main/resources/META-INF/services/org.apache.plc4x.java.api.PlcDriver b/plc4j/drivers/mbus/src/main/resources/META-INF/services/org.apache.plc4x.java.api.PlcDriver
new file mode 100644
index 0000000..a9e773b
--- /dev/null
+++ b/plc4j/drivers/mbus/src/main/resources/META-INF/services/org.apache.plc4x.java.api.PlcDriver
@@ -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.java.mbus.MBusPlcDriver
diff --git a/plc4j/drivers/mbus/src/test/java/org/apache/plc4x/java/mbus/MBusPayloadTest.java b/plc4j/drivers/mbus/src/test/java/org/apache/plc4x/java/mbus/MBusPayloadTest.java
new file mode 100644
index 0000000..bc5a151
--- /dev/null
+++ b/plc4j/drivers/mbus/src/test/java/org/apache/plc4x/java/mbus/MBusPayloadTest.java
@@ -0,0 +1,29 @@
+/*
+ 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.java.mbus;
+
+import org.apache.plc4x.test.parserserializer.ParserSerializerTestsuiteRunner;
+
+public class MBusPayloadTest extends ParserSerializerTestsuiteRunner {
+
+ public MBusPayloadTest() {
+ super("/protocols/mbus/MBusPayloadTestSuite.xml");
+ }
+
+}
diff --git a/plc4j/drivers/mbus/src/test/java/org/apache/plc4x/java/mbus/helper/MBusHelperTest.java b/plc4j/drivers/mbus/src/test/java/org/apache/plc4x/java/mbus/helper/MBusHelperTest.java
new file mode 100644
index 0000000..b58a2f1
--- /dev/null
+++ b/plc4j/drivers/mbus/src/test/java/org/apache/plc4x/java/mbus/helper/MBusHelperTest.java
@@ -0,0 +1,48 @@
+/*
+ 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.java.mbus.helper;
+
+import org.apache.commons.codec.DecoderException;
+import org.apache.commons.codec.binary.Hex;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class MBusHelperTest {
+
+ String FRAME = "681F1F680802727856341224400107550000000313153100DA023B13018B60043718021816";
+ /*
+ "68 1F 1F 68" + // header + len=31
+ "08 02 72" + // C=08 (RSP), node=2, CI=72
+ "78 56 34 12" + // identification=12345678
+ "24 40 01 07" + // manufacturer id=4024, version =1, device type = water meter
+ "55 00 00 00" +
+ "03 13 15 31 00" + // data block 1, unit 0, storage 0, instant value, volume = 123456 l
+ "DA 02 3B 13 01" + // data block 2, unit 0, storage 5, max value, volume flow = 113 l/h
+ "8B 60 04 37 18 02" + // data block 3, unit 1, storage 0, tariff 2, instant value, energy = 218,37 KwH
+ "18 16" // checksum, stop sign
+ */
+
+ @Test
+ void calculateChecksum() throws DecoderException {
+ byte[] frame = Hex.decodeHex(FRAME);
+ byte crc = MBusHelper.crc(frame, 4, 2);
+ assertThat(Integer.toHexString(crc)).isEqualTo("18");
+ }
+}
\ No newline at end of file
diff --git a/plc4j/drivers/pom.xml b/plc4j/drivers/pom.xml
index c57cb3c..092c169 100644
--- a/plc4j/drivers/pom.xml
+++ b/plc4j/drivers/pom.xml
@@ -40,6 +40,7 @@
<module>eip</module>
<module>firmata</module>
<module>knxnetip</module>
+ <module>mbus</module>
<module>mock</module>
<module>modbus</module>
<module>s7</module>
diff --git a/plc4j/drivers/pom.xml b/protocols/mbus/pom.xml
similarity index 65%
copy from plc4j/drivers/pom.xml
copy to protocols/mbus/pom.xml
index c57cb3c..789157d 100644
--- a/plc4j/drivers/pom.xml
+++ b/protocols/mbus/pom.xml
@@ -8,7 +8,7 @@
"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
+ 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
@@ -23,29 +23,21 @@
<parent>
<groupId>org.apache.plc4x</groupId>
- <artifactId>plc4j</artifactId>
+ <artifactId>plc4x-protocols</artifactId>
<version>0.8.0-SNAPSHOT</version>
</parent>
- <artifactId>plc4j-drivers</artifactId>
- <packaging>pom</packaging>
+ <artifactId>plc4x-protocols-mbus</artifactId>
- <name>PLC4J: Drivers</name>
- <description>Wrapper project for all PLC4J driver implementations.</description>
+ <name>Protocols: MBus</name>
+ <description>Base protocol specifications for the M-Bus/Meterbus, an european metering standard.</description>
- <modules>
- <module>ab-eth</module>
- <module>ads</module>
- <module>canopen</module>
- <module>eip</module>
- <module>firmata</module>
- <module>knxnetip</module>
- <module>mock</module>
- <module>modbus</module>
- <module>s7</module>
- <module>opcua</module>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4x-build-utils-protocol-base-mspec</artifactId>
+ <version>0.8.0-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
- <module>simulated</module>
- </modules>
-
-</project>
+</project>
\ No newline at end of file
diff --git a/protocols/mbus/src/main/java/org/apache/plc4x/protocol/mbus/MBusProtocol.java b/protocols/mbus/src/main/java/org/apache/plc4x/protocol/mbus/MBusProtocol.java
new file mode 100644
index 0000000..28d5395
--- /dev/null
+++ b/protocols/mbus/src/main/java/org/apache/plc4x/protocol/mbus/MBusProtocol.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.mbus;
+
+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 MBusProtocol implements Protocol {
+
+ @Override
+ public String getName() {
+ return "mbus";
+ }
+
+ @Override
+ public Map<String, TypeDefinition> getTypeDefinitions() throws GenerationException {
+ InputStream schemaInputStream = MBusProtocol.class.getResourceAsStream("/protocols/mbus/mbus.mspec");
+ if(schemaInputStream == null) {
+ throw new GenerationException("Error loading message-format schema for protocol '" + getName() + "'");
+ }
+ return new MessageFormatParser().parse(schemaInputStream);
+ }
+
+}
diff --git a/protocols/mbus/src/main/resources/META-INF/services/org.apache.plc4x.plugins.codegenerator.protocol.Protocol b/protocols/mbus/src/main/resources/META-INF/services/org.apache.plc4x.plugins.codegenerator.protocol.Protocol
new file mode 100644
index 0000000..0763b79
--- /dev/null
+++ b/protocols/mbus/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.mbus.MBusProtocol
\ No newline at end of file
diff --git a/protocols/mbus/src/main/resources/protocols/mbus/mbus.mspec b/protocols/mbus/src/main/resources/protocols/mbus/mbus.mspec
new file mode 100644
index 0000000..2787a96
--- /dev/null
+++ b/protocols/mbus/src/main/resources/protocols/mbus/mbus.mspec
@@ -0,0 +1,124 @@
+//
+// 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.
+//
+[discriminatedType 'MBusFrame'
+ [discriminator uint 8 'header' ]
+ [typeSwitch 'header'
+ ['0xE5' AcknowledgeFrame
+ ]
+ ['0x10' ShortFrame
+ ]
+ ['0x68' DataFrame
+ [simple uint 8 'len' ]
+ [padding uint 8 'lenCheck' 'len' '1' ]
+ [const uint 8 'headerCheck' '0x68' ]
+ [simple uint 8 'controlField' ]
+ [simple uint 8 'address' ]
+ [simple uint 8 'controlInformation' ]
+ [simple VariableDataStructure 'data' ['controlField', 'controlInformation', 'len'] ]
+ [checksum int 8 'crc' 'STATIC_CALL("org.apache.plc4x.java.mbus.helper.MBusHelper.crc", checksumRawData)']
+ [const uint 8 'endFlag' '0x16' ]
+ ]
+ ]
+]
+
+[type 'VariableDataStructure' [uint 8 'controlField', uint 8 'ci', uint 8 'len']
+ [typeSwitch 'ci'
+ ['0x72' LongHeaderDataFrame
+ [simple SecondaryAddress 'address']
+ [simple ShortHeader 'header']
+ ]
+ ]
+ [array DataRecord 'records' terminated 'curPos > len - 7']
+]
+
+[type 'SecondaryAddress'
+ [simple uint 32 'identifier']
+ [simple uint 16 'manufacturer']
+ [simple uint 8 'version']
+ [simple uint 8 'deviceType']
+]
+
+[type 'ShortHeader'
+ [simple uint 8 'accessNumber']
+ [simple uint 8 'status']
+ [simple uint 8 'encryptedBlocks']
+ [simple uint 8 'encryptionMode' ]
+]
+
+[type 'DataRecord'
+ [implicit bit 'extension' 'dife != null']
+ [simple uint 1 'storage']
+ [enum Function 'function']
+ [enum Coding 'coding']
+ [optional DataInformationFieldExtension 'dife' 'extension']
+ [simple ValueInformationBlock 'vif']
+ [array uint 8 'data' length 'coding.size / 8']
+]
+
+[type 'DataInformationField'
+ [implicit bit 'extension' 'dife != null']
+ [simple uint 1 'storage']
+ [enum Function 'function']
+ [enum Coding 'coding']
+ [optional DataInformationFieldExtension 'dife' 'extension']
+]
+
+[type 'DataInformationFieldExtension'
+ [implicit bit 'extension' 'dife != null']
+ [simple uint 1 'unit']
+ [simple uint 2 'tariff']
+ [simple uint 4 'storage']
+ [optional DataInformationFieldExtension 'dife' 'extension']
+]
+
+[type 'ValueInformationBlock'
+ [simple ValueInformationField 'vif']
+]
+
+[type 'ValueInformationField'
+ [implicit bit 'extension' 'vife != null']
+ [simple uint 7 'unitAndMultiplier']
+ [optional ValueInformationField 'vife' 'extension']
+]
+
+[enum uint 4 'Coding' [uint 8 'size']
+ ['0x00' NO_DATA ['0'] ]
+ ['0x01' INT8 ['8'] ]
+ ['0x02' INT16 ['16'] ]
+ ['0x03' INT24 ['24'] ]
+ ['0x04' INT32 ['32'] ]
+ ['0x05' REAL ['32'] ]
+ ['0x06' INT48 ['48'] ]
+ ['0x07' INT64 ['64'] ]
+ ['0x08' READOUT ['0'] ]
+ ['0x09' BCD_2_DIGIT ['8'] ]
+ ['0x0A' BCD_4_DIGIT ['16'] ]
+ ['0x0B' BCD_6_DIGIT ['24'] ]
+ ['0x0C' BCD_8_DIGIT ['32'] ]
+ ['0x0D' VARIABLE_LEN ['-1'] ]
+ ['0x0E' BCD_12_DIGIT ['48'] ]
+ ['0x0F' SPECIAL_FUNCTION ['-2'] ]
+]
+
+[enum uint 2 'Function'
+ ['0x00' INSTANT_VALUE]
+ ['0x01' MAXIMUM_VALUE]
+ ['0x02' MINIMUM_VALUE]
+ ['0x03' ERROR_VALUE]
+]
\ No newline at end of file
diff --git a/protocols/mbus/src/test/resources/protocols/mbus/MBusDriverIT.xml b/protocols/mbus/src/test/resources/protocols/mbus/MBusDriverIT.xml
new file mode 100644
index 0000000..eae89fd
--- /dev/null
+++ b/protocols/mbus/src/test/resources/protocols/mbus/MBusDriverIT.xml
@@ -0,0 +1,129 @@
+<?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.
+ -->
+<test:driver-testsuite xmlns:test="https://plc4x.apache.org/schemas/driver-testsuite.xsd" bigEndian="true">
+
+ <name>MBus Driver Test</name>
+
+ <driver-name>mbus</driver-name>
+
+ <!--
+ <driver-parameters>
+ </driver-parameters>
+ -->
+
+ <testcase>
+ <name>Bogus driver test</name>
+ <description>
+ Ignore for now
+ </description>
+ <!--
+ <steps>
+ <api-request name="Receive Read Request from application">
+ <TestReadRequest className="org.apache.plc4x.test.driver.model.api.TestReadRequest">
+ <fields>
+ <field className="org.apache.plc4x.test.driver.model.api.TestField">
+ <name>expeditedSdo</name>
+ <address>SDO:1:1000/22:UNSIGNED32</address>
+ </field>
+ </fields>
+ </TestReadRequest>
+ </api-request>
+ <outgoing-plc-message name="Send SDO Initialize Upload Request">
+ <CANOpenSocketCANFrame className="org.apache.plc4x.java.canopen.transport.socketcan.CANOpenSocketCANFrame">
+ <nodeId>1</nodeId>
+ <service>RECEIVE_SDO</service>
+ <payload className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDORequest">
+ <command>INITIATE_UPLOAD</command>
+ <request className="org.apache.plc4x.java.canopen.readwrite.SDOInitiateUploadRequest">
+ <address className="org.apache.plc4x.java.canopen.readwrite.IndexAddress">
+ <index>1000</index>
+ <subindex>22</subindex>
+ </address>
+ </request>
+ </payload>
+ </CANOpenSocketCANFrame>
+ </outgoing-plc-message>
+ <incoming-plc-message name="Receive SDO Initialize Upload Response for other node">
+ <CANOpenSocketCANFrame className="org.apache.plc4x.java.canopen.transport.socketcan.CANOpenSocketCANFrame">
+ <nodeId>1</nodeId>
+ <service>TRANSMIT_SDO</service>
+ <payload className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDOResponse">
+ <command>INITIATE_UPLOAD</command>
+ <response className="org.apache.plc4x.java.canopen.readwrite.SDOInitiateUploadResponse">
+ <expedited>true</expedited>
+ <indicated>true</indicated>
+ <address className="org.apache.plc4x.java.canopen.readwrite.IndexAddress">
+ <index>1001</index>
+ <subindex>22</subindex>
+ </address>
+ <payload className="org.apache.plc4x.java.canopen.readwrite.SDOInitiateExpeditedUploadResponse">
+ <data>YXNkZg==</data>
+ </payload>
+ </response>
+ </payload>
+ </CANOpenSocketCANFrame>
+ </incoming-plc-message>
+ <incoming-plc-message name="Receive SDO Initialize Upload Response for from requested node">
+ <CANOpenSocketCANFrame className="org.apache.plc4x.java.canopen.transport.socketcan.CANOpenSocketCANFrame">
+ <nodeId>1</nodeId>
+ <service>TRANSMIT_SDO</service>
+ <payload className="org.apache.plc4x.java.canopen.readwrite.CANOpenSDOResponse">
+ <command>INITIATE_UPLOAD</command>
+ <response className="org.apache.plc4x.java.canopen.readwrite.SDOInitiateUploadResponse">
+ <expedited>true</expedited>
+ <indicated>true</indicated>
+ <address className="org.apache.plc4x.java.canopen.readwrite.IndexAddress">
+ <index>1000</index>
+ <subindex>22</subindex>
+ </address>
+ <payload className="org.apache.plc4x.java.canopen.readwrite.SDOInitiateExpeditedUploadResponse">
+ <data>YXNkZg==</data>
+ </payload>
+ </response>
+ </payload>
+ </CANOpenSocketCANFrame>
+ </incoming-plc-message>
+ <api-response name="Report Read Response to application (expedited)">
+ <PlcReadResponse>
+ <PlcReadRequest>
+ <fields>
+ <expeditedSdo>
+ <CANOpenSDOField>
+ <node>1</node>
+ <index>1000</index>
+ <subIndex>22</subIndex>
+ <dataType>UNSIGNED32</dataType>
+ </CANOpenSDOField>
+ </expeditedSdo>
+ </fields>
+ </PlcReadRequest>
+ <values>
+ <expeditedSdo result="OK">
+ <PlcUDINT>1717859169</PlcUDINT>
+ </expeditedSdo>
+ </values>
+ </PlcReadResponse>
+ </api-response>
+ <delay>1000</delay>
+ </steps>
+ -->
+ </testcase>
+
+</test:driver-testsuite>
\ No newline at end of file
diff --git a/protocols/mbus/src/test/resources/protocols/mbus/MBusPayloadTestSuite.xml b/protocols/mbus/src/test/resources/protocols/mbus/MBusPayloadTestSuite.xml
new file mode 100644
index 0000000..fd90e3f
--- /dev/null
+++ b/protocols/mbus/src/test/resources/protocols/mbus/MBusPayloadTestSuite.xml
@@ -0,0 +1,236 @@
+<?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.
+ -->
+<test:testsuite xmlns:test="https://plc4x.apache.org/schemas/parser-serializer-testsuite.xsd" bigEndian="false">
+
+ <name>Tests of MBus frames payload.</name>
+
+ <testcase>
+ <name>DIF: 03</name>
+ <raw>03</raw>
+ <root-type>DataInformationField</root-type>
+ <xml>
+ <DataInformationField className="org.apache.plc4x.java.mbus.readwrite.DataInformationField">
+ <storage>0</storage>
+ <function>INSTANT_VALUE</function>
+ <coding>INT24</coding>
+ <dife/>
+ </DataInformationField>
+ </xml>
+ </testcase>
+
+ <testcase>
+ <name>DIF: DA02</name>
+ <raw>DA02</raw>
+ <root-type>DataInformationField</root-type>
+ <xml>
+ <DataInformationField className="org.apache.plc4x.java.mbus.readwrite.DataInformationField">
+ <storage>1</storage>
+ <function>MAXIMUM_VALUE</function>
+ <coding>BCD_4_DIGIT</coding>
+ <dife className="org.apache.plc4x.java.mbus.readwrite.DataInformationFieldExtension">
+ <unit>0</unit>
+ <tariff>0</tariff>
+ <storage>2</storage>
+ <dife/>
+ </dife>
+ </DataInformationField>
+ </xml>
+ </testcase>
+
+ <testcase>
+ <name>DIF: 8B60</name>
+ <raw>8B60</raw>
+ <root-type>DataInformationField</root-type>
+ <xml>
+ <DataInformationField className="org.apache.plc4x.java.mbus.readwrite.DataInformationField">
+ <storage>0</storage>
+ <function>INSTANT_VALUE</function>
+ <coding>BCD_6_DIGIT</coding>
+ <dife className="org.apache.plc4x.java.mbus.readwrite.DataInformationFieldExtension">
+ <unit>1</unit>
+ <tariff>2</tariff>
+ <storage>0</storage>
+ <dife/>
+ </dife>
+ </DataInformationField>
+ </xml>
+ </testcase>
+
+ <testcase>
+ <name>Data Record: DA023B1301</name>
+ <raw>DA023B1301</raw>
+ <root-type>DataRecord</root-type>
+ <xml>
+ <DataRecord className="org.apache.plc4x.java.mbus.readwrite.DataRecord">
+ <storage>1</storage>
+ <function>MAXIMUM_VALUE</function>
+ <coding>BCD_4_DIGIT</coding>
+ <dife className="org.apache.plc4x.java.mbus.readwrite.DataInformationFieldExtension">
+ <unit>0</unit>
+ <tariff>0</tariff>
+ <storage>2</storage>
+ <dife/>
+ </dife>
+ <vif className="org.apache.plc4x.java.mbus.readwrite.ValueInformationBlock">
+ <vif className="org.apache.plc4x.java.mbus.readwrite.ValueInformationField">
+ <unitAndMultiplier>59</unitAndMultiplier>
+ <vife/>
+ </vif>
+ </vif>
+ <data>
+ <data>19</data>
+ <data>1</data>
+ </data>
+ </DataRecord>
+ </xml>
+ </testcase>
+
+ <testcase>
+ <name>Data Record: 8B6004371802</name>
+ <raw>8B6004371802</raw>
+ <root-type>DataRecord</root-type>
+ <xml>
+ <DataRecord className="org.apache.plc4x.java.mbus.readwrite.DataRecord">
+ <storage>0</storage>
+ <function>INSTANT_VALUE</function>
+ <coding>BCD_6_DIGIT</coding>
+ <dife className="org.apache.plc4x.java.mbus.readwrite.DataInformationFieldExtension">
+ <unit>1</unit>
+ <tariff>2</tariff>
+ <storage>0</storage>
+ <dife/>
+ </dife>
+ <vif className="org.apache.plc4x.java.mbus.readwrite.ValueInformationBlock">
+ <vif className="org.apache.plc4x.java.mbus.readwrite.ValueInformationField">
+ <unitAndMultiplier>4</unitAndMultiplier>
+ <vife/>
+ </vif>
+ </vif>
+ <data>
+ <data>55</data>
+ <data>24</data>
+ <data>2</data>
+ </data>
+ </DataRecord>
+ </xml>
+ </testcase>
+
+ <testcase>
+ <name>Read out test</name>
+ <raw>681F1F680802727856341224400107550000000313153100DA023B13018B60043718021816</raw>
+ <root-type>MBusFrame</root-type>
+ <xml>
+ <DataFrame className="org.apache.plc4x.java.mbus.readwrite.DataFrame">
+ <len>31</len>
+ <controlField>8</controlField>
+ <address>2</address>
+ <controlInformation>114</controlInformation>
+ <data className="org.apache.plc4x.java.mbus.readwrite.LongHeaderDataFrame">
+ <records>
+ <records className="org.apache.plc4x.java.mbus.readwrite.DataRecord">
+ <storage>0</storage>
+ <function>INSTANT_VALUE</function>
+ <coding>INT24</coding>
+ <dife/>
+ <vif className="org.apache.plc4x.java.mbus.readwrite.ValueInformationBlock">
+ <vif className="org.apache.plc4x.java.mbus.readwrite.ValueInformationField">
+ <unitAndMultiplier>19</unitAndMultiplier>
+ <vife/>
+ </vif>
+ </vif>
+ <data>
+ <data>21</data>
+ <data>49</data>
+ <data>0</data>
+ </data>
+ </records>
+ <records className="org.apache.plc4x.java.mbus.readwrite.DataRecord">
+ <storage>1</storage>
+ <function>MAXIMUM_VALUE</function>
+ <coding>BCD_4_DIGIT</coding>
+ <dife className="org.apache.plc4x.java.mbus.readwrite.DataInformationFieldExtension">
+ <unit>0</unit>
+ <tariff>0</tariff>
+ <storage>2</storage>
+ <dife/>
+ </dife>
+ <vif className="org.apache.plc4x.java.mbus.readwrite.ValueInformationBlock">
+ <vif className="org.apache.plc4x.java.mbus.readwrite.ValueInformationField">
+ <unitAndMultiplier>59</unitAndMultiplier>
+ <vife/>
+ </vif>
+ </vif>
+ <data>
+ <data>19</data>
+ <data>1</data>
+ </data>
+ </records>
+ <records className="org.apache.plc4x.java.mbus.readwrite.DataRecord">
+ <storage>0</storage>
+ <function>INSTANT_VALUE</function>
+ <coding>BCD_6_DIGIT</coding>
+ <dife className="org.apache.plc4x.java.mbus.readwrite.DataInformationFieldExtension">
+ <unit>1</unit>
+ <tariff>2</tariff>
+ <storage>0</storage>
+ <dife/>
+ </dife>
+ <vif className="org.apache.plc4x.java.mbus.readwrite.ValueInformationBlock">
+ <vif className="org.apache.plc4x.java.mbus.readwrite.ValueInformationField">
+ <unitAndMultiplier>4</unitAndMultiplier>
+ <vife/>
+ </vif>
+ </vif>
+ <data>
+ <data>55</data>
+ <data>24</data>
+ <data>2</data>
+ </data>
+ </records>
+ </records>
+ <address className="org.apache.plc4x.java.mbus.readwrite.SecondaryAddress">
+ <identifier>305419896</identifier>
+ <manufacturer>16420</manufacturer>
+ <version>1</version>
+ <deviceType>7</deviceType>
+ </address>
+ <header className="org.apache.plc4x.java.mbus.readwrite.ShortHeader">
+ <accessNumber>85</accessNumber>
+ <status>0</status>
+ <encryptedBlocks>0</encryptedBlocks>
+ <encryptionMode>0</encryptionMode>
+ </header>
+ </data>
+ </DataFrame>
+ </xml>
+ </testcase>
+
+ <testcase>
+ <name>Read out test: SON heat meter</name>
+ <raw>68A7A76808017201004001EE4D04041D000000040673830100041440E526000322CC61000C7899090508046D0A12952C055BC0C41C42055F00D30242053E08707B3E052BACC8E54405FF013985553F05FF02E015243E02FD17000001741501703C01FF040001FD0F1702FD0D3E000DFD0C0F3530302D3831364D353352393335308C407994477073844013C69D0A00814092280A8C80407919531031848040141B97000081804093280A1F9016</raw>
+ <root-type>MBusFrame</root-type>
+ <xml>
+ <DataFrame className="org.apache.plc4x.java.mbus.readwrite.DataFrame">
+ </DataFrame>
+ </xml>
+ </testcase>
+
+
+</test:testsuite>
\ No newline at end of file
diff --git a/protocols/pom.xml b/protocols/pom.xml
index 46188a6..9a2b652 100644
--- a/protocols/pom.xml
+++ b/protocols/pom.xml
@@ -42,6 +42,7 @@
<module>eip</module>
<module>firmata</module>
<module>knxnetip</module>
+ <module>mbus</module>
<module>modbus</module>
<module>s7</module>
<module>simulated</module>
diff --git a/src/site/asciidoc/protocols/mbus/index.adoc b/src/site/asciidoc/protocols/mbus/index.adoc
new file mode 100644
index 0000000..b680ec5
--- /dev/null
+++ b/src/site/asciidoc/protocols/mbus/index.adoc
@@ -0,0 +1,26 @@
+//
+// 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.
+//
+
+== M-Bus
+
+M-Bus is often called MeterBus.
+Both names are alias for part of European Norm (EN) 1337.
+
+=== Links
+
+- Sample frames and implementation guide: https://www.evs.ee/cen-tr-17167-2018
+(be aware obtained PDF uses weird security/DRM mechanism)