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)