You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2022/07/18 13:32:22 UTC

[plc4x] branch develop updated: feat(cbus): implemented metering application

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

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


The following commit(s) were added to refs/heads/develop by this push:
     new ab42d2a95 feat(cbus): implemented metering application
ab42d2a95 is described below

commit ab42d2a951c64e7155871c4df0effd6cdb5a89b8
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Mon Jul 18 15:32:15 2022 +0200

    feat(cbus): implemented metering application
---
 plc4go/protocols/cbus/readwrite/ParserHelper.go    |   2 +
 plc4go/protocols/cbus/readwrite/XmlParserHelper.go |   2 +
 .../cbus/readwrite/model/MeteringCommandType.go    | 121 +++++++++
 .../model/MeteringCommandTypeContainer.go          | 278 ++++++++++++++++++++
 .../protocols/cbus/readwrite/model/MeteringData.go | 287 +++++++++++++++++++++
 .../model/MeteringDataDrinkingWaterConsumption.go  | 191 ++++++++++++++
 .../model/MeteringDataElectricityConsumption.go    | 191 ++++++++++++++
 .../readwrite/model/MeteringDataGasConsumption.go  | 191 ++++++++++++++
 .../model/MeteringDataMeasureDrinkingWater.go      | 155 +++++++++++
 .../model/MeteringDataMeasureElectricity.go        | 155 +++++++++++
 .../cbus/readwrite/model/MeteringDataMeasureGas.go | 155 +++++++++++
 .../cbus/readwrite/model/MeteringDataMeasureOil.go | 155 +++++++++++
 .../model/MeteringDataMeasureOtherWater.go         | 155 +++++++++++
 .../readwrite/model/MeteringDataOilConsumption.go  | 191 ++++++++++++++
 .../model/MeteringDataOtherWaterConsumption.go     | 191 ++++++++++++++
 .../cbus/readwrite/model/SALDataAccessControl.go   |   2 +-
 .../cbus/readwrite/model/SALDataAirConditioning.go |   2 +-
 .../cbus/readwrite/model/SALDataAudioAndVideo.go   |   2 +-
 .../readwrite/model/SALDataClockAndTimekeeping.go  |   2 +-
 .../cbus/readwrite/model/SALDataEnableControl.go   |   2 +-
 .../cbus/readwrite/model/SALDataFreeUsage.go       |   2 +-
 .../cbus/readwrite/model/SALDataHeating.go         |   2 +-
 .../readwrite/model/SALDataIrrigationControl.go    |   2 +-
 .../cbus/readwrite/model/SALDataMeasurement.go     |   2 +-
 .../cbus/readwrite/model/SALDataMetering.go        |  54 +++-
 .../model/SALDataPoolsSpasPondsFountainsControl.go |   2 +-
 .../cbus/readwrite/model/SALDataReserved.go        |   2 +-
 .../readwrite/model/SALDataRoomControlSystem.go    |   2 +-
 .../model/SALDataTelephonyStatusAndControl.go      |   2 +-
 .../readwrite/model/SALDataTemperatureBroadcast.go |   2 +-
 .../cbus/readwrite/model/SALDataTesting.go         |   2 +-
 .../cbus/readwrite/model/SALDataTriggerControl.go  |   2 +-
 .../cbus/readwrite/model/SALDataVentilation.go     |   2 +-
 .../protocols/cbus/readwrite/model/StaticHelper.go |  10 +
 .../java/cbus/readwrite/utils/StaticHelper.java    |  11 +
 .../org/apache/plc4x/java/cbus/ReferenceTest.java  |   2 -
 .../src/main/resources/protocols/cbus/c-bus.mspec  |  86 ++++--
 37 files changed, 2574 insertions(+), 43 deletions(-)

diff --git a/plc4go/protocols/cbus/readwrite/ParserHelper.go b/plc4go/protocols/cbus/readwrite/ParserHelper.go
index 74857ed4c..72a04d6bf 100644
--- a/plc4go/protocols/cbus/readwrite/ParserHelper.go
+++ b/plc4go/protocols/cbus/readwrite/ParserHelper.go
@@ -32,6 +32,8 @@ type CbusParserHelper struct {
 
 func (m CbusParserHelper) Parse(typeName string, arguments []string, io utils.ReadBuffer) (interface{}, error) {
 	switch typeName {
+	case "MeteringData":
+		return model.MeteringDataParse(io)
 	case "ApplicationAddress2":
 		return model.ApplicationAddress2Parse(io)
 	case "ApplicationAddress1":
diff --git a/plc4go/protocols/cbus/readwrite/XmlParserHelper.go b/plc4go/protocols/cbus/readwrite/XmlParserHelper.go
index 52eda8cc5..a90e54b7b 100644
--- a/plc4go/protocols/cbus/readwrite/XmlParserHelper.go
+++ b/plc4go/protocols/cbus/readwrite/XmlParserHelper.go
@@ -42,6 +42,8 @@ func init() {
 
 func (m CbusXmlParserHelper) Parse(typeName string, xmlString string, parserArguments ...string) (interface{}, error) {
 	switch typeName {
+	case "MeteringData":
+		return model.MeteringDataParse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)))
 	case "ApplicationAddress2":
 		return model.ApplicationAddress2Parse(utils.NewXmlReadBuffer(strings.NewReader(xmlString)))
 	case "ApplicationAddress1":
diff --git a/plc4go/protocols/cbus/readwrite/model/MeteringCommandType.go b/plc4go/protocols/cbus/readwrite/model/MeteringCommandType.go
new file mode 100644
index 000000000..5bb3788cf
--- /dev/null
+++ b/plc4go/protocols/cbus/readwrite/model/MeteringCommandType.go
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/spi/utils"
+	"github.com/pkg/errors"
+	"github.com/rs/zerolog/log"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// MeteringCommandType is an enum
+type MeteringCommandType uint8
+
+type IMeteringCommandType interface {
+	Serialize(writeBuffer utils.WriteBuffer) error
+}
+
+const (
+	MeteringCommandType_EVENT MeteringCommandType = 0x00
+)
+
+var MeteringCommandTypeValues []MeteringCommandType
+
+func init() {
+	_ = errors.New
+	MeteringCommandTypeValues = []MeteringCommandType{
+		MeteringCommandType_EVENT,
+	}
+}
+
+func MeteringCommandTypeByValue(value uint8) (enum MeteringCommandType, ok bool) {
+	switch value {
+	case 0x00:
+		return MeteringCommandType_EVENT, true
+	}
+	return 0, false
+}
+
+func MeteringCommandTypeByName(value string) (enum MeteringCommandType, ok bool) {
+	switch value {
+	case "EVENT":
+		return MeteringCommandType_EVENT, true
+	}
+	return 0, false
+}
+
+func MeteringCommandTypeKnows(value uint8) bool {
+	for _, typeValue := range MeteringCommandTypeValues {
+		if uint8(typeValue) == value {
+			return true
+		}
+	}
+	return false
+}
+
+func CastMeteringCommandType(structType interface{}) MeteringCommandType {
+	castFunc := func(typ interface{}) MeteringCommandType {
+		if sMeteringCommandType, ok := typ.(MeteringCommandType); ok {
+			return sMeteringCommandType
+		}
+		return 0
+	}
+	return castFunc(structType)
+}
+
+func (m MeteringCommandType) GetLengthInBits() uint16 {
+	return 4
+}
+
+func (m MeteringCommandType) GetLengthInBytes() uint16 {
+	return m.GetLengthInBits() / 8
+}
+
+func MeteringCommandTypeParse(readBuffer utils.ReadBuffer) (MeteringCommandType, error) {
+	val, err := readBuffer.ReadUint8("MeteringCommandType", 4)
+	if err != nil {
+		return 0, errors.Wrap(err, "error reading MeteringCommandType")
+	}
+	if enum, ok := MeteringCommandTypeByValue(val); !ok {
+		log.Debug().Msgf("no value %x found for RequestType", val)
+		return MeteringCommandType(val), nil
+	} else {
+		return enum, nil
+	}
+}
+
+func (e MeteringCommandType) Serialize(writeBuffer utils.WriteBuffer) error {
+	return writeBuffer.WriteUint8("MeteringCommandType", 4, uint8(e), utils.WithAdditionalStringRepresentation(e.PLC4XEnumName()))
+}
+
+// PLC4XEnumName returns the name that is used in code to identify this enum
+func (e MeteringCommandType) PLC4XEnumName() string {
+	switch e {
+	case MeteringCommandType_EVENT:
+		return "EVENT"
+	}
+	return ""
+}
+
+func (e MeteringCommandType) String() string {
+	return e.PLC4XEnumName()
+}
diff --git a/plc4go/protocols/cbus/readwrite/model/MeteringCommandTypeContainer.go b/plc4go/protocols/cbus/readwrite/model/MeteringCommandTypeContainer.go
new file mode 100644
index 000000000..a8388692c
--- /dev/null
+++ b/plc4go/protocols/cbus/readwrite/model/MeteringCommandTypeContainer.go
@@ -0,0 +1,278 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/spi/utils"
+	"github.com/pkg/errors"
+	"github.com/rs/zerolog/log"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// MeteringCommandTypeContainer is an enum
+type MeteringCommandTypeContainer uint8
+
+type IMeteringCommandTypeContainer interface {
+	NumBytes() uint8
+	CommandType() MeteringCommandType
+	Serialize(writeBuffer utils.WriteBuffer) error
+}
+
+const (
+	MeteringCommandTypeContainer_MeteringCommandEvent_0Bytes MeteringCommandTypeContainer = 0x08
+	MeteringCommandTypeContainer_MeteringCommandEvent_1Bytes MeteringCommandTypeContainer = 0x09
+	MeteringCommandTypeContainer_MeteringCommandEvent_2Bytes MeteringCommandTypeContainer = 0x0A
+	MeteringCommandTypeContainer_MeteringCommandEvent_3Bytes MeteringCommandTypeContainer = 0x0B
+	MeteringCommandTypeContainer_MeteringCommandEvent_4Bytes MeteringCommandTypeContainer = 0x0C
+	MeteringCommandTypeContainer_MeteringCommandEvent_5Bytes MeteringCommandTypeContainer = 0x0D
+	MeteringCommandTypeContainer_MeteringCommandEvent_6Bytes MeteringCommandTypeContainer = 0x0E
+	MeteringCommandTypeContainer_MeteringCommandEvent_7Bytes MeteringCommandTypeContainer = 0x0F
+)
+
+var MeteringCommandTypeContainerValues []MeteringCommandTypeContainer
+
+func init() {
+	_ = errors.New
+	MeteringCommandTypeContainerValues = []MeteringCommandTypeContainer{
+		MeteringCommandTypeContainer_MeteringCommandEvent_0Bytes,
+		MeteringCommandTypeContainer_MeteringCommandEvent_1Bytes,
+		MeteringCommandTypeContainer_MeteringCommandEvent_2Bytes,
+		MeteringCommandTypeContainer_MeteringCommandEvent_3Bytes,
+		MeteringCommandTypeContainer_MeteringCommandEvent_4Bytes,
+		MeteringCommandTypeContainer_MeteringCommandEvent_5Bytes,
+		MeteringCommandTypeContainer_MeteringCommandEvent_6Bytes,
+		MeteringCommandTypeContainer_MeteringCommandEvent_7Bytes,
+	}
+}
+
+func (e MeteringCommandTypeContainer) NumBytes() uint8 {
+	switch e {
+	case 0x08:
+		{ /* '0x08' */
+			return 0
+		}
+	case 0x09:
+		{ /* '0x09' */
+			return 1
+		}
+	case 0x0A:
+		{ /* '0x0A' */
+			return 2
+		}
+	case 0x0B:
+		{ /* '0x0B' */
+			return 3
+		}
+	case 0x0C:
+		{ /* '0x0C' */
+			return 4
+		}
+	case 0x0D:
+		{ /* '0x0D' */
+			return 5
+		}
+	case 0x0E:
+		{ /* '0x0E' */
+			return 6
+		}
+	case 0x0F:
+		{ /* '0x0F' */
+			return 7
+		}
+	default:
+		{
+			return 0
+		}
+	}
+}
+
+func MeteringCommandTypeContainerFirstEnumForFieldNumBytes(value uint8) (MeteringCommandTypeContainer, error) {
+	for _, sizeValue := range MeteringCommandTypeContainerValues {
+		if sizeValue.NumBytes() == value {
+			return sizeValue, nil
+		}
+	}
+	return 0, errors.Errorf("enum for %v describing NumBytes not found", value)
+}
+
+func (e MeteringCommandTypeContainer) CommandType() MeteringCommandType {
+	switch e {
+	case 0x08:
+		{ /* '0x08' */
+			return MeteringCommandType_EVENT
+		}
+	case 0x09:
+		{ /* '0x09' */
+			return MeteringCommandType_EVENT
+		}
+	case 0x0A:
+		{ /* '0x0A' */
+			return MeteringCommandType_EVENT
+		}
+	case 0x0B:
+		{ /* '0x0B' */
+			return MeteringCommandType_EVENT
+		}
+	case 0x0C:
+		{ /* '0x0C' */
+			return MeteringCommandType_EVENT
+		}
+	case 0x0D:
+		{ /* '0x0D' */
+			return MeteringCommandType_EVENT
+		}
+	case 0x0E:
+		{ /* '0x0E' */
+			return MeteringCommandType_EVENT
+		}
+	case 0x0F:
+		{ /* '0x0F' */
+			return MeteringCommandType_EVENT
+		}
+	default:
+		{
+			return 0
+		}
+	}
+}
+
+func MeteringCommandTypeContainerFirstEnumForFieldCommandType(value MeteringCommandType) (MeteringCommandTypeContainer, error) {
+	for _, sizeValue := range MeteringCommandTypeContainerValues {
+		if sizeValue.CommandType() == value {
+			return sizeValue, nil
+		}
+	}
+	return 0, errors.Errorf("enum for %v describing CommandType not found", value)
+}
+func MeteringCommandTypeContainerByValue(value uint8) (enum MeteringCommandTypeContainer, ok bool) {
+	switch value {
+	case 0x08:
+		return MeteringCommandTypeContainer_MeteringCommandEvent_0Bytes, true
+	case 0x09:
+		return MeteringCommandTypeContainer_MeteringCommandEvent_1Bytes, true
+	case 0x0A:
+		return MeteringCommandTypeContainer_MeteringCommandEvent_2Bytes, true
+	case 0x0B:
+		return MeteringCommandTypeContainer_MeteringCommandEvent_3Bytes, true
+	case 0x0C:
+		return MeteringCommandTypeContainer_MeteringCommandEvent_4Bytes, true
+	case 0x0D:
+		return MeteringCommandTypeContainer_MeteringCommandEvent_5Bytes, true
+	case 0x0E:
+		return MeteringCommandTypeContainer_MeteringCommandEvent_6Bytes, true
+	case 0x0F:
+		return MeteringCommandTypeContainer_MeteringCommandEvent_7Bytes, true
+	}
+	return 0, false
+}
+
+func MeteringCommandTypeContainerByName(value string) (enum MeteringCommandTypeContainer, ok bool) {
+	switch value {
+	case "MeteringCommandEvent_0Bytes":
+		return MeteringCommandTypeContainer_MeteringCommandEvent_0Bytes, true
+	case "MeteringCommandEvent_1Bytes":
+		return MeteringCommandTypeContainer_MeteringCommandEvent_1Bytes, true
+	case "MeteringCommandEvent_2Bytes":
+		return MeteringCommandTypeContainer_MeteringCommandEvent_2Bytes, true
+	case "MeteringCommandEvent_3Bytes":
+		return MeteringCommandTypeContainer_MeteringCommandEvent_3Bytes, true
+	case "MeteringCommandEvent_4Bytes":
+		return MeteringCommandTypeContainer_MeteringCommandEvent_4Bytes, true
+	case "MeteringCommandEvent_5Bytes":
+		return MeteringCommandTypeContainer_MeteringCommandEvent_5Bytes, true
+	case "MeteringCommandEvent_6Bytes":
+		return MeteringCommandTypeContainer_MeteringCommandEvent_6Bytes, true
+	case "MeteringCommandEvent_7Bytes":
+		return MeteringCommandTypeContainer_MeteringCommandEvent_7Bytes, true
+	}
+	return 0, false
+}
+
+func MeteringCommandTypeContainerKnows(value uint8) bool {
+	for _, typeValue := range MeteringCommandTypeContainerValues {
+		if uint8(typeValue) == value {
+			return true
+		}
+	}
+	return false
+}
+
+func CastMeteringCommandTypeContainer(structType interface{}) MeteringCommandTypeContainer {
+	castFunc := func(typ interface{}) MeteringCommandTypeContainer {
+		if sMeteringCommandTypeContainer, ok := typ.(MeteringCommandTypeContainer); ok {
+			return sMeteringCommandTypeContainer
+		}
+		return 0
+	}
+	return castFunc(structType)
+}
+
+func (m MeteringCommandTypeContainer) GetLengthInBits() uint16 {
+	return 8
+}
+
+func (m MeteringCommandTypeContainer) GetLengthInBytes() uint16 {
+	return m.GetLengthInBits() / 8
+}
+
+func MeteringCommandTypeContainerParse(readBuffer utils.ReadBuffer) (MeteringCommandTypeContainer, error) {
+	val, err := readBuffer.ReadUint8("MeteringCommandTypeContainer", 8)
+	if err != nil {
+		return 0, errors.Wrap(err, "error reading MeteringCommandTypeContainer")
+	}
+	if enum, ok := MeteringCommandTypeContainerByValue(val); !ok {
+		log.Debug().Msgf("no value %x found for RequestType", val)
+		return MeteringCommandTypeContainer(val), nil
+	} else {
+		return enum, nil
+	}
+}
+
+func (e MeteringCommandTypeContainer) Serialize(writeBuffer utils.WriteBuffer) error {
+	return writeBuffer.WriteUint8("MeteringCommandTypeContainer", 8, uint8(e), utils.WithAdditionalStringRepresentation(e.PLC4XEnumName()))
+}
+
+// PLC4XEnumName returns the name that is used in code to identify this enum
+func (e MeteringCommandTypeContainer) PLC4XEnumName() string {
+	switch e {
+	case MeteringCommandTypeContainer_MeteringCommandEvent_0Bytes:
+		return "MeteringCommandEvent_0Bytes"
+	case MeteringCommandTypeContainer_MeteringCommandEvent_1Bytes:
+		return "MeteringCommandEvent_1Bytes"
+	case MeteringCommandTypeContainer_MeteringCommandEvent_2Bytes:
+		return "MeteringCommandEvent_2Bytes"
+	case MeteringCommandTypeContainer_MeteringCommandEvent_3Bytes:
+		return "MeteringCommandEvent_3Bytes"
+	case MeteringCommandTypeContainer_MeteringCommandEvent_4Bytes:
+		return "MeteringCommandEvent_4Bytes"
+	case MeteringCommandTypeContainer_MeteringCommandEvent_5Bytes:
+		return "MeteringCommandEvent_5Bytes"
+	case MeteringCommandTypeContainer_MeteringCommandEvent_6Bytes:
+		return "MeteringCommandEvent_6Bytes"
+	case MeteringCommandTypeContainer_MeteringCommandEvent_7Bytes:
+		return "MeteringCommandEvent_7Bytes"
+	}
+	return ""
+}
+
+func (e MeteringCommandTypeContainer) String() string {
+	return e.PLC4XEnumName()
+}
diff --git a/plc4go/protocols/cbus/readwrite/model/MeteringData.go b/plc4go/protocols/cbus/readwrite/model/MeteringData.go
new file mode 100644
index 000000000..33542dd37
--- /dev/null
+++ b/plc4go/protocols/cbus/readwrite/model/MeteringData.go
@@ -0,0 +1,287 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/spi/utils"
+	"github.com/pkg/errors"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// MeteringData is the corresponding interface of MeteringData
+type MeteringData interface {
+	utils.LengthAware
+	utils.Serializable
+	// GetCommandTypeContainer returns CommandTypeContainer (property field)
+	GetCommandTypeContainer() MeteringCommandTypeContainer
+	// GetArgument returns Argument (property field)
+	GetArgument() byte
+	// GetCommandType returns CommandType (virtual field)
+	GetCommandType() MeteringCommandType
+}
+
+// MeteringDataExactly can be used when we want exactly this type and not a type which fulfills MeteringData.
+// This is useful for switch cases.
+type MeteringDataExactly interface {
+	MeteringData
+	isMeteringData() bool
+}
+
+// _MeteringData is the data-structure of this message
+type _MeteringData struct {
+	_MeteringDataChildRequirements
+	CommandTypeContainer MeteringCommandTypeContainer
+	Argument             byte
+}
+
+type _MeteringDataChildRequirements interface {
+	utils.Serializable
+	GetLengthInBits() uint16
+	GetLengthInBitsConditional(lastItem bool) uint16
+}
+
+type MeteringDataParent interface {
+	SerializeParent(writeBuffer utils.WriteBuffer, child MeteringData, serializeChildFunction func() error) error
+	GetTypeName() string
+}
+
+type MeteringDataChild interface {
+	utils.Serializable
+	InitializeParent(parent MeteringData, commandTypeContainer MeteringCommandTypeContainer, argument byte)
+	GetParent() *MeteringData
+
+	GetTypeName() string
+	MeteringData
+}
+
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for property fields.
+///////////////////////
+
+func (m *_MeteringData) GetCommandTypeContainer() MeteringCommandTypeContainer {
+	return m.CommandTypeContainer
+}
+
+func (m *_MeteringData) GetArgument() byte {
+	return m.Argument
+}
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for virtual fields.
+///////////////////////
+
+func (m *_MeteringData) GetCommandType() MeteringCommandType {
+	return CastMeteringCommandType(m.GetCommandTypeContainer().CommandType())
+}
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+
+// NewMeteringData factory function for _MeteringData
+func NewMeteringData(commandTypeContainer MeteringCommandTypeContainer, argument byte) *_MeteringData {
+	return &_MeteringData{CommandTypeContainer: commandTypeContainer, Argument: argument}
+}
+
+// Deprecated: use the interface for direct cast
+func CastMeteringData(structType interface{}) MeteringData {
+	if casted, ok := structType.(MeteringData); ok {
+		return casted
+	}
+	if casted, ok := structType.(*MeteringData); ok {
+		return *casted
+	}
+	return nil
+}
+
+func (m *_MeteringData) GetTypeName() string {
+	return "MeteringData"
+}
+
+func (m *_MeteringData) GetParentLengthInBits() uint16 {
+	lengthInBits := uint16(0)
+
+	// Simple field (commandTypeContainer)
+	lengthInBits += 8
+
+	// A virtual field doesn't have any in- or output.
+
+	// Simple field (argument)
+	lengthInBits += 8
+
+	return lengthInBits
+}
+
+func (m *_MeteringData) GetLengthInBytes() uint16 {
+	return m.GetLengthInBits() / 8
+}
+
+func MeteringDataParse(readBuffer utils.ReadBuffer) (MeteringData, error) {
+	positionAware := readBuffer
+	_ = positionAware
+	if pullErr := readBuffer.PullContext("MeteringData"); pullErr != nil {
+		return nil, errors.Wrap(pullErr, "Error pulling for MeteringData")
+	}
+	currentPos := positionAware.GetPos()
+	_ = currentPos
+
+	// Validation
+	if !(KnowsMeteringCommandTypeContainer(readBuffer)) {
+		return nil, errors.WithStack(utils.ParseAssertError{"no command type could be found"})
+	}
+
+	// Simple Field (commandTypeContainer)
+	if pullErr := readBuffer.PullContext("commandTypeContainer"); pullErr != nil {
+		return nil, errors.Wrap(pullErr, "Error pulling for commandTypeContainer")
+	}
+	_commandTypeContainer, _commandTypeContainerErr := MeteringCommandTypeContainerParse(readBuffer)
+	if _commandTypeContainerErr != nil {
+		return nil, errors.Wrap(_commandTypeContainerErr, "Error parsing 'commandTypeContainer' field of MeteringData")
+	}
+	commandTypeContainer := _commandTypeContainer
+	if closeErr := readBuffer.CloseContext("commandTypeContainer"); closeErr != nil {
+		return nil, errors.Wrap(closeErr, "Error closing for commandTypeContainer")
+	}
+
+	// Virtual field
+	_commandType := commandTypeContainer.CommandType()
+	commandType := MeteringCommandType(_commandType)
+	_ = commandType
+
+	// Simple Field (argument)
+	_argument, _argumentErr := readBuffer.ReadByte("argument")
+	if _argumentErr != nil {
+		return nil, errors.Wrap(_argumentErr, "Error parsing 'argument' field of MeteringData")
+	}
+	argument := _argument
+
+	// Switch Field (Depending on the discriminator values, passes the instantiation to a sub-type)
+	type MeteringDataChildSerializeRequirement interface {
+		MeteringData
+		InitializeParent(MeteringData, MeteringCommandTypeContainer, byte)
+		GetParent() MeteringData
+	}
+	var _childTemp interface{}
+	var _child MeteringDataChildSerializeRequirement
+	var typeSwitchError error
+	switch {
+	case commandType == MeteringCommandType_EVENT && argument == 0x01: // MeteringDataMeasureElectricity
+		_childTemp, typeSwitchError = MeteringDataMeasureElectricityParse(readBuffer)
+	case commandType == MeteringCommandType_EVENT && argument == 0x02: // MeteringDataMeasureGas
+		_childTemp, typeSwitchError = MeteringDataMeasureGasParse(readBuffer)
+	case commandType == MeteringCommandType_EVENT && argument == 0x03: // MeteringDataMeasureDrinkingWater
+		_childTemp, typeSwitchError = MeteringDataMeasureDrinkingWaterParse(readBuffer)
+	case commandType == MeteringCommandType_EVENT && argument == 0x04: // MeteringDataMeasureOtherWater
+		_childTemp, typeSwitchError = MeteringDataMeasureOtherWaterParse(readBuffer)
+	case commandType == MeteringCommandType_EVENT && argument == 0x05: // MeteringDataMeasureOil
+		_childTemp, typeSwitchError = MeteringDataMeasureOilParse(readBuffer)
+	case commandType == MeteringCommandType_EVENT && argument == 0x81: // MeteringDataElectricityConsumption
+		_childTemp, typeSwitchError = MeteringDataElectricityConsumptionParse(readBuffer)
+	case commandType == MeteringCommandType_EVENT && argument == 0x82: // MeteringDataGasConsumption
+		_childTemp, typeSwitchError = MeteringDataGasConsumptionParse(readBuffer)
+	case commandType == MeteringCommandType_EVENT && argument == 0x83: // MeteringDataDrinkingWaterConsumption
+		_childTemp, typeSwitchError = MeteringDataDrinkingWaterConsumptionParse(readBuffer)
+	case commandType == MeteringCommandType_EVENT && argument == 0x84: // MeteringDataOtherWaterConsumption
+		_childTemp, typeSwitchError = MeteringDataOtherWaterConsumptionParse(readBuffer)
+	case commandType == MeteringCommandType_EVENT && argument == 0x85: // MeteringDataOilConsumption
+		_childTemp, typeSwitchError = MeteringDataOilConsumptionParse(readBuffer)
+	default:
+		typeSwitchError = errors.Errorf("Unmapped type for parameters [commandType=%v, argument=%v]", commandType, argument)
+	}
+	if typeSwitchError != nil {
+		return nil, errors.Wrap(typeSwitchError, "Error parsing sub-type for type-switch of MeteringData")
+	}
+	_child = _childTemp.(MeteringDataChildSerializeRequirement)
+
+	if closeErr := readBuffer.CloseContext("MeteringData"); closeErr != nil {
+		return nil, errors.Wrap(closeErr, "Error closing for MeteringData")
+	}
+
+	// Finish initializing
+	_child.InitializeParent(_child, commandTypeContainer, argument)
+	return _child, nil
+}
+
+func (pm *_MeteringData) SerializeParent(writeBuffer utils.WriteBuffer, child MeteringData, serializeChildFunction func() error) error {
+	// We redirect all calls through client as some methods are only implemented there
+	m := child
+	_ = m
+	positionAware := writeBuffer
+	_ = positionAware
+	if pushErr := writeBuffer.PushContext("MeteringData"); pushErr != nil {
+		return errors.Wrap(pushErr, "Error pushing for MeteringData")
+	}
+
+	// Simple Field (commandTypeContainer)
+	if pushErr := writeBuffer.PushContext("commandTypeContainer"); pushErr != nil {
+		return errors.Wrap(pushErr, "Error pushing for commandTypeContainer")
+	}
+	_commandTypeContainerErr := writeBuffer.WriteSerializable(m.GetCommandTypeContainer())
+	if popErr := writeBuffer.PopContext("commandTypeContainer"); popErr != nil {
+		return errors.Wrap(popErr, "Error popping for commandTypeContainer")
+	}
+	if _commandTypeContainerErr != nil {
+		return errors.Wrap(_commandTypeContainerErr, "Error serializing 'commandTypeContainer' field")
+	}
+	// Virtual field
+	if _commandTypeErr := writeBuffer.WriteVirtual("commandType", m.GetCommandType()); _commandTypeErr != nil {
+		return errors.Wrap(_commandTypeErr, "Error serializing 'commandType' field")
+	}
+
+	// Simple Field (argument)
+	argument := byte(m.GetArgument())
+	_argumentErr := writeBuffer.WriteByte("argument", (argument))
+	if _argumentErr != nil {
+		return errors.Wrap(_argumentErr, "Error serializing 'argument' field")
+	}
+
+	// Switch field (Depending on the discriminator values, passes the serialization to a sub-type)
+	if _typeSwitchErr := serializeChildFunction(); _typeSwitchErr != nil {
+		return errors.Wrap(_typeSwitchErr, "Error serializing sub-type field")
+	}
+
+	if popErr := writeBuffer.PopContext("MeteringData"); popErr != nil {
+		return errors.Wrap(popErr, "Error popping for MeteringData")
+	}
+	return nil
+}
+
+func (m *_MeteringData) isMeteringData() bool {
+	return true
+}
+
+func (m *_MeteringData) String() string {
+	if m == nil {
+		return "<nil>"
+	}
+	writeBuffer := utils.NewBoxedWriteBufferWithOptions(true, true)
+	if err := writeBuffer.WriteSerializable(m); err != nil {
+		return err.Error()
+	}
+	return writeBuffer.GetBox().String()
+}
diff --git a/plc4go/protocols/cbus/readwrite/model/MeteringDataDrinkingWaterConsumption.go b/plc4go/protocols/cbus/readwrite/model/MeteringDataDrinkingWaterConsumption.go
new file mode 100644
index 000000000..078db91d0
--- /dev/null
+++ b/plc4go/protocols/cbus/readwrite/model/MeteringDataDrinkingWaterConsumption.go
@@ -0,0 +1,191 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/spi/utils"
+	"github.com/pkg/errors"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// MeteringDataDrinkingWaterConsumption is the corresponding interface of MeteringDataDrinkingWaterConsumption
+type MeteringDataDrinkingWaterConsumption interface {
+	utils.LengthAware
+	utils.Serializable
+	MeteringData
+	// GetKL returns KL (property field)
+	GetKL() uint32
+}
+
+// MeteringDataDrinkingWaterConsumptionExactly can be used when we want exactly this type and not a type which fulfills MeteringDataDrinkingWaterConsumption.
+// This is useful for switch cases.
+type MeteringDataDrinkingWaterConsumptionExactly interface {
+	MeteringDataDrinkingWaterConsumption
+	isMeteringDataDrinkingWaterConsumption() bool
+}
+
+// _MeteringDataDrinkingWaterConsumption is the data-structure of this message
+type _MeteringDataDrinkingWaterConsumption struct {
+	*_MeteringData
+	KL uint32
+}
+
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for discriminator values.
+///////////////////////
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+
+func (m *_MeteringDataDrinkingWaterConsumption) InitializeParent(parent MeteringData, commandTypeContainer MeteringCommandTypeContainer, argument byte) {
+	m.CommandTypeContainer = commandTypeContainer
+	m.Argument = argument
+}
+
+func (m *_MeteringDataDrinkingWaterConsumption) GetParent() MeteringData {
+	return m._MeteringData
+}
+
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for property fields.
+///////////////////////
+
+func (m *_MeteringDataDrinkingWaterConsumption) GetKL() uint32 {
+	return m.KL
+}
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+
+// NewMeteringDataDrinkingWaterConsumption factory function for _MeteringDataDrinkingWaterConsumption
+func NewMeteringDataDrinkingWaterConsumption(kL uint32, commandTypeContainer MeteringCommandTypeContainer, argument byte) *_MeteringDataDrinkingWaterConsumption {
+	_result := &_MeteringDataDrinkingWaterConsumption{
+		KL:            kL,
+		_MeteringData: NewMeteringData(commandTypeContainer, argument),
+	}
+	_result._MeteringData._MeteringDataChildRequirements = _result
+	return _result
+}
+
+// Deprecated: use the interface for direct cast
+func CastMeteringDataDrinkingWaterConsumption(structType interface{}) MeteringDataDrinkingWaterConsumption {
+	if casted, ok := structType.(MeteringDataDrinkingWaterConsumption); ok {
+		return casted
+	}
+	if casted, ok := structType.(*MeteringDataDrinkingWaterConsumption); ok {
+		return *casted
+	}
+	return nil
+}
+
+func (m *_MeteringDataDrinkingWaterConsumption) GetTypeName() string {
+	return "MeteringDataDrinkingWaterConsumption"
+}
+
+func (m *_MeteringDataDrinkingWaterConsumption) GetLengthInBits() uint16 {
+	return m.GetLengthInBitsConditional(false)
+}
+
+func (m *_MeteringDataDrinkingWaterConsumption) GetLengthInBitsConditional(lastItem bool) uint16 {
+	lengthInBits := uint16(m.GetParentLengthInBits())
+
+	// Simple field (kL)
+	lengthInBits += 32
+
+	return lengthInBits
+}
+
+func (m *_MeteringDataDrinkingWaterConsumption) GetLengthInBytes() uint16 {
+	return m.GetLengthInBits() / 8
+}
+
+func MeteringDataDrinkingWaterConsumptionParse(readBuffer utils.ReadBuffer) (MeteringDataDrinkingWaterConsumption, error) {
+	positionAware := readBuffer
+	_ = positionAware
+	if pullErr := readBuffer.PullContext("MeteringDataDrinkingWaterConsumption"); pullErr != nil {
+		return nil, errors.Wrap(pullErr, "Error pulling for MeteringDataDrinkingWaterConsumption")
+	}
+	currentPos := positionAware.GetPos()
+	_ = currentPos
+
+	// Simple Field (kL)
+	_kL, _kLErr := readBuffer.ReadUint32("kL", 32)
+	if _kLErr != nil {
+		return nil, errors.Wrap(_kLErr, "Error parsing 'kL' field of MeteringDataDrinkingWaterConsumption")
+	}
+	kL := _kL
+
+	if closeErr := readBuffer.CloseContext("MeteringDataDrinkingWaterConsumption"); closeErr != nil {
+		return nil, errors.Wrap(closeErr, "Error closing for MeteringDataDrinkingWaterConsumption")
+	}
+
+	// Create a partially initialized instance
+	_child := &_MeteringDataDrinkingWaterConsumption{
+		KL:            kL,
+		_MeteringData: &_MeteringData{},
+	}
+	_child._MeteringData._MeteringDataChildRequirements = _child
+	return _child, nil
+}
+
+func (m *_MeteringDataDrinkingWaterConsumption) Serialize(writeBuffer utils.WriteBuffer) error {
+	positionAware := writeBuffer
+	_ = positionAware
+	ser := func() error {
+		if pushErr := writeBuffer.PushContext("MeteringDataDrinkingWaterConsumption"); pushErr != nil {
+			return errors.Wrap(pushErr, "Error pushing for MeteringDataDrinkingWaterConsumption")
+		}
+
+		// Simple Field (kL)
+		kL := uint32(m.GetKL())
+		_kLErr := writeBuffer.WriteUint32("kL", 32, (kL))
+		if _kLErr != nil {
+			return errors.Wrap(_kLErr, "Error serializing 'kL' field")
+		}
+
+		if popErr := writeBuffer.PopContext("MeteringDataDrinkingWaterConsumption"); popErr != nil {
+			return errors.Wrap(popErr, "Error popping for MeteringDataDrinkingWaterConsumption")
+		}
+		return nil
+	}
+	return m.SerializeParent(writeBuffer, m, ser)
+}
+
+func (m *_MeteringDataDrinkingWaterConsumption) isMeteringDataDrinkingWaterConsumption() bool {
+	return true
+}
+
+func (m *_MeteringDataDrinkingWaterConsumption) String() string {
+	if m == nil {
+		return "<nil>"
+	}
+	writeBuffer := utils.NewBoxedWriteBufferWithOptions(true, true)
+	if err := writeBuffer.WriteSerializable(m); err != nil {
+		return err.Error()
+	}
+	return writeBuffer.GetBox().String()
+}
diff --git a/plc4go/protocols/cbus/readwrite/model/MeteringDataElectricityConsumption.go b/plc4go/protocols/cbus/readwrite/model/MeteringDataElectricityConsumption.go
new file mode 100644
index 000000000..82ee03f47
--- /dev/null
+++ b/plc4go/protocols/cbus/readwrite/model/MeteringDataElectricityConsumption.go
@@ -0,0 +1,191 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/spi/utils"
+	"github.com/pkg/errors"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// MeteringDataElectricityConsumption is the corresponding interface of MeteringDataElectricityConsumption
+type MeteringDataElectricityConsumption interface {
+	utils.LengthAware
+	utils.Serializable
+	MeteringData
+	// GetKWhr returns KWhr (property field)
+	GetKWhr() uint32
+}
+
+// MeteringDataElectricityConsumptionExactly can be used when we want exactly this type and not a type which fulfills MeteringDataElectricityConsumption.
+// This is useful for switch cases.
+type MeteringDataElectricityConsumptionExactly interface {
+	MeteringDataElectricityConsumption
+	isMeteringDataElectricityConsumption() bool
+}
+
+// _MeteringDataElectricityConsumption is the data-structure of this message
+type _MeteringDataElectricityConsumption struct {
+	*_MeteringData
+	KWhr uint32
+}
+
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for discriminator values.
+///////////////////////
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+
+func (m *_MeteringDataElectricityConsumption) InitializeParent(parent MeteringData, commandTypeContainer MeteringCommandTypeContainer, argument byte) {
+	m.CommandTypeContainer = commandTypeContainer
+	m.Argument = argument
+}
+
+func (m *_MeteringDataElectricityConsumption) GetParent() MeteringData {
+	return m._MeteringData
+}
+
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for property fields.
+///////////////////////
+
+func (m *_MeteringDataElectricityConsumption) GetKWhr() uint32 {
+	return m.KWhr
+}
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+
+// NewMeteringDataElectricityConsumption factory function for _MeteringDataElectricityConsumption
+func NewMeteringDataElectricityConsumption(kWhr uint32, commandTypeContainer MeteringCommandTypeContainer, argument byte) *_MeteringDataElectricityConsumption {
+	_result := &_MeteringDataElectricityConsumption{
+		KWhr:          kWhr,
+		_MeteringData: NewMeteringData(commandTypeContainer, argument),
+	}
+	_result._MeteringData._MeteringDataChildRequirements = _result
+	return _result
+}
+
+// Deprecated: use the interface for direct cast
+func CastMeteringDataElectricityConsumption(structType interface{}) MeteringDataElectricityConsumption {
+	if casted, ok := structType.(MeteringDataElectricityConsumption); ok {
+		return casted
+	}
+	if casted, ok := structType.(*MeteringDataElectricityConsumption); ok {
+		return *casted
+	}
+	return nil
+}
+
+func (m *_MeteringDataElectricityConsumption) GetTypeName() string {
+	return "MeteringDataElectricityConsumption"
+}
+
+func (m *_MeteringDataElectricityConsumption) GetLengthInBits() uint16 {
+	return m.GetLengthInBitsConditional(false)
+}
+
+func (m *_MeteringDataElectricityConsumption) GetLengthInBitsConditional(lastItem bool) uint16 {
+	lengthInBits := uint16(m.GetParentLengthInBits())
+
+	// Simple field (kWhr)
+	lengthInBits += 32
+
+	return lengthInBits
+}
+
+func (m *_MeteringDataElectricityConsumption) GetLengthInBytes() uint16 {
+	return m.GetLengthInBits() / 8
+}
+
+func MeteringDataElectricityConsumptionParse(readBuffer utils.ReadBuffer) (MeteringDataElectricityConsumption, error) {
+	positionAware := readBuffer
+	_ = positionAware
+	if pullErr := readBuffer.PullContext("MeteringDataElectricityConsumption"); pullErr != nil {
+		return nil, errors.Wrap(pullErr, "Error pulling for MeteringDataElectricityConsumption")
+	}
+	currentPos := positionAware.GetPos()
+	_ = currentPos
+
+	// Simple Field (kWhr)
+	_kWhr, _kWhrErr := readBuffer.ReadUint32("kWhr", 32)
+	if _kWhrErr != nil {
+		return nil, errors.Wrap(_kWhrErr, "Error parsing 'kWhr' field of MeteringDataElectricityConsumption")
+	}
+	kWhr := _kWhr
+
+	if closeErr := readBuffer.CloseContext("MeteringDataElectricityConsumption"); closeErr != nil {
+		return nil, errors.Wrap(closeErr, "Error closing for MeteringDataElectricityConsumption")
+	}
+
+	// Create a partially initialized instance
+	_child := &_MeteringDataElectricityConsumption{
+		KWhr:          kWhr,
+		_MeteringData: &_MeteringData{},
+	}
+	_child._MeteringData._MeteringDataChildRequirements = _child
+	return _child, nil
+}
+
+func (m *_MeteringDataElectricityConsumption) Serialize(writeBuffer utils.WriteBuffer) error {
+	positionAware := writeBuffer
+	_ = positionAware
+	ser := func() error {
+		if pushErr := writeBuffer.PushContext("MeteringDataElectricityConsumption"); pushErr != nil {
+			return errors.Wrap(pushErr, "Error pushing for MeteringDataElectricityConsumption")
+		}
+
+		// Simple Field (kWhr)
+		kWhr := uint32(m.GetKWhr())
+		_kWhrErr := writeBuffer.WriteUint32("kWhr", 32, (kWhr))
+		if _kWhrErr != nil {
+			return errors.Wrap(_kWhrErr, "Error serializing 'kWhr' field")
+		}
+
+		if popErr := writeBuffer.PopContext("MeteringDataElectricityConsumption"); popErr != nil {
+			return errors.Wrap(popErr, "Error popping for MeteringDataElectricityConsumption")
+		}
+		return nil
+	}
+	return m.SerializeParent(writeBuffer, m, ser)
+}
+
+func (m *_MeteringDataElectricityConsumption) isMeteringDataElectricityConsumption() bool {
+	return true
+}
+
+func (m *_MeteringDataElectricityConsumption) String() string {
+	if m == nil {
+		return "<nil>"
+	}
+	writeBuffer := utils.NewBoxedWriteBufferWithOptions(true, true)
+	if err := writeBuffer.WriteSerializable(m); err != nil {
+		return err.Error()
+	}
+	return writeBuffer.GetBox().String()
+}
diff --git a/plc4go/protocols/cbus/readwrite/model/MeteringDataGasConsumption.go b/plc4go/protocols/cbus/readwrite/model/MeteringDataGasConsumption.go
new file mode 100644
index 000000000..492622c1d
--- /dev/null
+++ b/plc4go/protocols/cbus/readwrite/model/MeteringDataGasConsumption.go
@@ -0,0 +1,191 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/spi/utils"
+	"github.com/pkg/errors"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// MeteringDataGasConsumption is the corresponding interface of MeteringDataGasConsumption
+type MeteringDataGasConsumption interface {
+	utils.LengthAware
+	utils.Serializable
+	MeteringData
+	// GetMJ returns MJ (property field)
+	GetMJ() uint32
+}
+
+// MeteringDataGasConsumptionExactly can be used when we want exactly this type and not a type which fulfills MeteringDataGasConsumption.
+// This is useful for switch cases.
+type MeteringDataGasConsumptionExactly interface {
+	MeteringDataGasConsumption
+	isMeteringDataGasConsumption() bool
+}
+
+// _MeteringDataGasConsumption is the data-structure of this message
+type _MeteringDataGasConsumption struct {
+	*_MeteringData
+	MJ uint32
+}
+
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for discriminator values.
+///////////////////////
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+
+func (m *_MeteringDataGasConsumption) InitializeParent(parent MeteringData, commandTypeContainer MeteringCommandTypeContainer, argument byte) {
+	m.CommandTypeContainer = commandTypeContainer
+	m.Argument = argument
+}
+
+func (m *_MeteringDataGasConsumption) GetParent() MeteringData {
+	return m._MeteringData
+}
+
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for property fields.
+///////////////////////
+
+func (m *_MeteringDataGasConsumption) GetMJ() uint32 {
+	return m.MJ
+}
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+
+// NewMeteringDataGasConsumption factory function for _MeteringDataGasConsumption
+func NewMeteringDataGasConsumption(mJ uint32, commandTypeContainer MeteringCommandTypeContainer, argument byte) *_MeteringDataGasConsumption {
+	_result := &_MeteringDataGasConsumption{
+		MJ:            mJ,
+		_MeteringData: NewMeteringData(commandTypeContainer, argument),
+	}
+	_result._MeteringData._MeteringDataChildRequirements = _result
+	return _result
+}
+
+// Deprecated: use the interface for direct cast
+func CastMeteringDataGasConsumption(structType interface{}) MeteringDataGasConsumption {
+	if casted, ok := structType.(MeteringDataGasConsumption); ok {
+		return casted
+	}
+	if casted, ok := structType.(*MeteringDataGasConsumption); ok {
+		return *casted
+	}
+	return nil
+}
+
+func (m *_MeteringDataGasConsumption) GetTypeName() string {
+	return "MeteringDataGasConsumption"
+}
+
+func (m *_MeteringDataGasConsumption) GetLengthInBits() uint16 {
+	return m.GetLengthInBitsConditional(false)
+}
+
+func (m *_MeteringDataGasConsumption) GetLengthInBitsConditional(lastItem bool) uint16 {
+	lengthInBits := uint16(m.GetParentLengthInBits())
+
+	// Simple field (mJ)
+	lengthInBits += 32
+
+	return lengthInBits
+}
+
+func (m *_MeteringDataGasConsumption) GetLengthInBytes() uint16 {
+	return m.GetLengthInBits() / 8
+}
+
+func MeteringDataGasConsumptionParse(readBuffer utils.ReadBuffer) (MeteringDataGasConsumption, error) {
+	positionAware := readBuffer
+	_ = positionAware
+	if pullErr := readBuffer.PullContext("MeteringDataGasConsumption"); pullErr != nil {
+		return nil, errors.Wrap(pullErr, "Error pulling for MeteringDataGasConsumption")
+	}
+	currentPos := positionAware.GetPos()
+	_ = currentPos
+
+	// Simple Field (mJ)
+	_mJ, _mJErr := readBuffer.ReadUint32("mJ", 32)
+	if _mJErr != nil {
+		return nil, errors.Wrap(_mJErr, "Error parsing 'mJ' field of MeteringDataGasConsumption")
+	}
+	mJ := _mJ
+
+	if closeErr := readBuffer.CloseContext("MeteringDataGasConsumption"); closeErr != nil {
+		return nil, errors.Wrap(closeErr, "Error closing for MeteringDataGasConsumption")
+	}
+
+	// Create a partially initialized instance
+	_child := &_MeteringDataGasConsumption{
+		MJ:            mJ,
+		_MeteringData: &_MeteringData{},
+	}
+	_child._MeteringData._MeteringDataChildRequirements = _child
+	return _child, nil
+}
+
+func (m *_MeteringDataGasConsumption) Serialize(writeBuffer utils.WriteBuffer) error {
+	positionAware := writeBuffer
+	_ = positionAware
+	ser := func() error {
+		if pushErr := writeBuffer.PushContext("MeteringDataGasConsumption"); pushErr != nil {
+			return errors.Wrap(pushErr, "Error pushing for MeteringDataGasConsumption")
+		}
+
+		// Simple Field (mJ)
+		mJ := uint32(m.GetMJ())
+		_mJErr := writeBuffer.WriteUint32("mJ", 32, (mJ))
+		if _mJErr != nil {
+			return errors.Wrap(_mJErr, "Error serializing 'mJ' field")
+		}
+
+		if popErr := writeBuffer.PopContext("MeteringDataGasConsumption"); popErr != nil {
+			return errors.Wrap(popErr, "Error popping for MeteringDataGasConsumption")
+		}
+		return nil
+	}
+	return m.SerializeParent(writeBuffer, m, ser)
+}
+
+func (m *_MeteringDataGasConsumption) isMeteringDataGasConsumption() bool {
+	return true
+}
+
+func (m *_MeteringDataGasConsumption) String() string {
+	if m == nil {
+		return "<nil>"
+	}
+	writeBuffer := utils.NewBoxedWriteBufferWithOptions(true, true)
+	if err := writeBuffer.WriteSerializable(m); err != nil {
+		return err.Error()
+	}
+	return writeBuffer.GetBox().String()
+}
diff --git a/plc4go/protocols/cbus/readwrite/model/MeteringDataMeasureDrinkingWater.go b/plc4go/protocols/cbus/readwrite/model/MeteringDataMeasureDrinkingWater.go
new file mode 100644
index 000000000..58fa48447
--- /dev/null
+++ b/plc4go/protocols/cbus/readwrite/model/MeteringDataMeasureDrinkingWater.go
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/spi/utils"
+	"github.com/pkg/errors"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// MeteringDataMeasureDrinkingWater is the corresponding interface of MeteringDataMeasureDrinkingWater
+type MeteringDataMeasureDrinkingWater interface {
+	utils.LengthAware
+	utils.Serializable
+	MeteringData
+}
+
+// MeteringDataMeasureDrinkingWaterExactly can be used when we want exactly this type and not a type which fulfills MeteringDataMeasureDrinkingWater.
+// This is useful for switch cases.
+type MeteringDataMeasureDrinkingWaterExactly interface {
+	MeteringDataMeasureDrinkingWater
+	isMeteringDataMeasureDrinkingWater() bool
+}
+
+// _MeteringDataMeasureDrinkingWater is the data-structure of this message
+type _MeteringDataMeasureDrinkingWater struct {
+	*_MeteringData
+}
+
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for discriminator values.
+///////////////////////
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+
+func (m *_MeteringDataMeasureDrinkingWater) InitializeParent(parent MeteringData, commandTypeContainer MeteringCommandTypeContainer, argument byte) {
+	m.CommandTypeContainer = commandTypeContainer
+	m.Argument = argument
+}
+
+func (m *_MeteringDataMeasureDrinkingWater) GetParent() MeteringData {
+	return m._MeteringData
+}
+
+// NewMeteringDataMeasureDrinkingWater factory function for _MeteringDataMeasureDrinkingWater
+func NewMeteringDataMeasureDrinkingWater(commandTypeContainer MeteringCommandTypeContainer, argument byte) *_MeteringDataMeasureDrinkingWater {
+	_result := &_MeteringDataMeasureDrinkingWater{
+		_MeteringData: NewMeteringData(commandTypeContainer, argument),
+	}
+	_result._MeteringData._MeteringDataChildRequirements = _result
+	return _result
+}
+
+// Deprecated: use the interface for direct cast
+func CastMeteringDataMeasureDrinkingWater(structType interface{}) MeteringDataMeasureDrinkingWater {
+	if casted, ok := structType.(MeteringDataMeasureDrinkingWater); ok {
+		return casted
+	}
+	if casted, ok := structType.(*MeteringDataMeasureDrinkingWater); ok {
+		return *casted
+	}
+	return nil
+}
+
+func (m *_MeteringDataMeasureDrinkingWater) GetTypeName() string {
+	return "MeteringDataMeasureDrinkingWater"
+}
+
+func (m *_MeteringDataMeasureDrinkingWater) GetLengthInBits() uint16 {
+	return m.GetLengthInBitsConditional(false)
+}
+
+func (m *_MeteringDataMeasureDrinkingWater) GetLengthInBitsConditional(lastItem bool) uint16 {
+	lengthInBits := uint16(m.GetParentLengthInBits())
+
+	return lengthInBits
+}
+
+func (m *_MeteringDataMeasureDrinkingWater) GetLengthInBytes() uint16 {
+	return m.GetLengthInBits() / 8
+}
+
+func MeteringDataMeasureDrinkingWaterParse(readBuffer utils.ReadBuffer) (MeteringDataMeasureDrinkingWater, error) {
+	positionAware := readBuffer
+	_ = positionAware
+	if pullErr := readBuffer.PullContext("MeteringDataMeasureDrinkingWater"); pullErr != nil {
+		return nil, errors.Wrap(pullErr, "Error pulling for MeteringDataMeasureDrinkingWater")
+	}
+	currentPos := positionAware.GetPos()
+	_ = currentPos
+
+	if closeErr := readBuffer.CloseContext("MeteringDataMeasureDrinkingWater"); closeErr != nil {
+		return nil, errors.Wrap(closeErr, "Error closing for MeteringDataMeasureDrinkingWater")
+	}
+
+	// Create a partially initialized instance
+	_child := &_MeteringDataMeasureDrinkingWater{
+		_MeteringData: &_MeteringData{},
+	}
+	_child._MeteringData._MeteringDataChildRequirements = _child
+	return _child, nil
+}
+
+func (m *_MeteringDataMeasureDrinkingWater) Serialize(writeBuffer utils.WriteBuffer) error {
+	positionAware := writeBuffer
+	_ = positionAware
+	ser := func() error {
+		if pushErr := writeBuffer.PushContext("MeteringDataMeasureDrinkingWater"); pushErr != nil {
+			return errors.Wrap(pushErr, "Error pushing for MeteringDataMeasureDrinkingWater")
+		}
+
+		if popErr := writeBuffer.PopContext("MeteringDataMeasureDrinkingWater"); popErr != nil {
+			return errors.Wrap(popErr, "Error popping for MeteringDataMeasureDrinkingWater")
+		}
+		return nil
+	}
+	return m.SerializeParent(writeBuffer, m, ser)
+}
+
+func (m *_MeteringDataMeasureDrinkingWater) isMeteringDataMeasureDrinkingWater() bool {
+	return true
+}
+
+func (m *_MeteringDataMeasureDrinkingWater) String() string {
+	if m == nil {
+		return "<nil>"
+	}
+	writeBuffer := utils.NewBoxedWriteBufferWithOptions(true, true)
+	if err := writeBuffer.WriteSerializable(m); err != nil {
+		return err.Error()
+	}
+	return writeBuffer.GetBox().String()
+}
diff --git a/plc4go/protocols/cbus/readwrite/model/MeteringDataMeasureElectricity.go b/plc4go/protocols/cbus/readwrite/model/MeteringDataMeasureElectricity.go
new file mode 100644
index 000000000..c9bbec333
--- /dev/null
+++ b/plc4go/protocols/cbus/readwrite/model/MeteringDataMeasureElectricity.go
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/spi/utils"
+	"github.com/pkg/errors"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// MeteringDataMeasureElectricity is the corresponding interface of MeteringDataMeasureElectricity
+type MeteringDataMeasureElectricity interface {
+	utils.LengthAware
+	utils.Serializable
+	MeteringData
+}
+
+// MeteringDataMeasureElectricityExactly can be used when we want exactly this type and not a type which fulfills MeteringDataMeasureElectricity.
+// This is useful for switch cases.
+type MeteringDataMeasureElectricityExactly interface {
+	MeteringDataMeasureElectricity
+	isMeteringDataMeasureElectricity() bool
+}
+
+// _MeteringDataMeasureElectricity is the data-structure of this message
+type _MeteringDataMeasureElectricity struct {
+	*_MeteringData
+}
+
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for discriminator values.
+///////////////////////
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+
+func (m *_MeteringDataMeasureElectricity) InitializeParent(parent MeteringData, commandTypeContainer MeteringCommandTypeContainer, argument byte) {
+	m.CommandTypeContainer = commandTypeContainer
+	m.Argument = argument
+}
+
+func (m *_MeteringDataMeasureElectricity) GetParent() MeteringData {
+	return m._MeteringData
+}
+
+// NewMeteringDataMeasureElectricity factory function for _MeteringDataMeasureElectricity
+func NewMeteringDataMeasureElectricity(commandTypeContainer MeteringCommandTypeContainer, argument byte) *_MeteringDataMeasureElectricity {
+	_result := &_MeteringDataMeasureElectricity{
+		_MeteringData: NewMeteringData(commandTypeContainer, argument),
+	}
+	_result._MeteringData._MeteringDataChildRequirements = _result
+	return _result
+}
+
+// Deprecated: use the interface for direct cast
+func CastMeteringDataMeasureElectricity(structType interface{}) MeteringDataMeasureElectricity {
+	if casted, ok := structType.(MeteringDataMeasureElectricity); ok {
+		return casted
+	}
+	if casted, ok := structType.(*MeteringDataMeasureElectricity); ok {
+		return *casted
+	}
+	return nil
+}
+
+func (m *_MeteringDataMeasureElectricity) GetTypeName() string {
+	return "MeteringDataMeasureElectricity"
+}
+
+func (m *_MeteringDataMeasureElectricity) GetLengthInBits() uint16 {
+	return m.GetLengthInBitsConditional(false)
+}
+
+func (m *_MeteringDataMeasureElectricity) GetLengthInBitsConditional(lastItem bool) uint16 {
+	lengthInBits := uint16(m.GetParentLengthInBits())
+
+	return lengthInBits
+}
+
+func (m *_MeteringDataMeasureElectricity) GetLengthInBytes() uint16 {
+	return m.GetLengthInBits() / 8
+}
+
+func MeteringDataMeasureElectricityParse(readBuffer utils.ReadBuffer) (MeteringDataMeasureElectricity, error) {
+	positionAware := readBuffer
+	_ = positionAware
+	if pullErr := readBuffer.PullContext("MeteringDataMeasureElectricity"); pullErr != nil {
+		return nil, errors.Wrap(pullErr, "Error pulling for MeteringDataMeasureElectricity")
+	}
+	currentPos := positionAware.GetPos()
+	_ = currentPos
+
+	if closeErr := readBuffer.CloseContext("MeteringDataMeasureElectricity"); closeErr != nil {
+		return nil, errors.Wrap(closeErr, "Error closing for MeteringDataMeasureElectricity")
+	}
+
+	// Create a partially initialized instance
+	_child := &_MeteringDataMeasureElectricity{
+		_MeteringData: &_MeteringData{},
+	}
+	_child._MeteringData._MeteringDataChildRequirements = _child
+	return _child, nil
+}
+
+func (m *_MeteringDataMeasureElectricity) Serialize(writeBuffer utils.WriteBuffer) error {
+	positionAware := writeBuffer
+	_ = positionAware
+	ser := func() error {
+		if pushErr := writeBuffer.PushContext("MeteringDataMeasureElectricity"); pushErr != nil {
+			return errors.Wrap(pushErr, "Error pushing for MeteringDataMeasureElectricity")
+		}
+
+		if popErr := writeBuffer.PopContext("MeteringDataMeasureElectricity"); popErr != nil {
+			return errors.Wrap(popErr, "Error popping for MeteringDataMeasureElectricity")
+		}
+		return nil
+	}
+	return m.SerializeParent(writeBuffer, m, ser)
+}
+
+func (m *_MeteringDataMeasureElectricity) isMeteringDataMeasureElectricity() bool {
+	return true
+}
+
+func (m *_MeteringDataMeasureElectricity) String() string {
+	if m == nil {
+		return "<nil>"
+	}
+	writeBuffer := utils.NewBoxedWriteBufferWithOptions(true, true)
+	if err := writeBuffer.WriteSerializable(m); err != nil {
+		return err.Error()
+	}
+	return writeBuffer.GetBox().String()
+}
diff --git a/plc4go/protocols/cbus/readwrite/model/MeteringDataMeasureGas.go b/plc4go/protocols/cbus/readwrite/model/MeteringDataMeasureGas.go
new file mode 100644
index 000000000..3547707c3
--- /dev/null
+++ b/plc4go/protocols/cbus/readwrite/model/MeteringDataMeasureGas.go
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/spi/utils"
+	"github.com/pkg/errors"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// MeteringDataMeasureGas is the corresponding interface of MeteringDataMeasureGas
+type MeteringDataMeasureGas interface {
+	utils.LengthAware
+	utils.Serializable
+	MeteringData
+}
+
+// MeteringDataMeasureGasExactly can be used when we want exactly this type and not a type which fulfills MeteringDataMeasureGas.
+// This is useful for switch cases.
+type MeteringDataMeasureGasExactly interface {
+	MeteringDataMeasureGas
+	isMeteringDataMeasureGas() bool
+}
+
+// _MeteringDataMeasureGas is the data-structure of this message
+type _MeteringDataMeasureGas struct {
+	*_MeteringData
+}
+
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for discriminator values.
+///////////////////////
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+
+func (m *_MeteringDataMeasureGas) InitializeParent(parent MeteringData, commandTypeContainer MeteringCommandTypeContainer, argument byte) {
+	m.CommandTypeContainer = commandTypeContainer
+	m.Argument = argument
+}
+
+func (m *_MeteringDataMeasureGas) GetParent() MeteringData {
+	return m._MeteringData
+}
+
+// NewMeteringDataMeasureGas factory function for _MeteringDataMeasureGas
+func NewMeteringDataMeasureGas(commandTypeContainer MeteringCommandTypeContainer, argument byte) *_MeteringDataMeasureGas {
+	_result := &_MeteringDataMeasureGas{
+		_MeteringData: NewMeteringData(commandTypeContainer, argument),
+	}
+	_result._MeteringData._MeteringDataChildRequirements = _result
+	return _result
+}
+
+// Deprecated: use the interface for direct cast
+func CastMeteringDataMeasureGas(structType interface{}) MeteringDataMeasureGas {
+	if casted, ok := structType.(MeteringDataMeasureGas); ok {
+		return casted
+	}
+	if casted, ok := structType.(*MeteringDataMeasureGas); ok {
+		return *casted
+	}
+	return nil
+}
+
+func (m *_MeteringDataMeasureGas) GetTypeName() string {
+	return "MeteringDataMeasureGas"
+}
+
+func (m *_MeteringDataMeasureGas) GetLengthInBits() uint16 {
+	return m.GetLengthInBitsConditional(false)
+}
+
+func (m *_MeteringDataMeasureGas) GetLengthInBitsConditional(lastItem bool) uint16 {
+	lengthInBits := uint16(m.GetParentLengthInBits())
+
+	return lengthInBits
+}
+
+func (m *_MeteringDataMeasureGas) GetLengthInBytes() uint16 {
+	return m.GetLengthInBits() / 8
+}
+
+func MeteringDataMeasureGasParse(readBuffer utils.ReadBuffer) (MeteringDataMeasureGas, error) {
+	positionAware := readBuffer
+	_ = positionAware
+	if pullErr := readBuffer.PullContext("MeteringDataMeasureGas"); pullErr != nil {
+		return nil, errors.Wrap(pullErr, "Error pulling for MeteringDataMeasureGas")
+	}
+	currentPos := positionAware.GetPos()
+	_ = currentPos
+
+	if closeErr := readBuffer.CloseContext("MeteringDataMeasureGas"); closeErr != nil {
+		return nil, errors.Wrap(closeErr, "Error closing for MeteringDataMeasureGas")
+	}
+
+	// Create a partially initialized instance
+	_child := &_MeteringDataMeasureGas{
+		_MeteringData: &_MeteringData{},
+	}
+	_child._MeteringData._MeteringDataChildRequirements = _child
+	return _child, nil
+}
+
+func (m *_MeteringDataMeasureGas) Serialize(writeBuffer utils.WriteBuffer) error {
+	positionAware := writeBuffer
+	_ = positionAware
+	ser := func() error {
+		if pushErr := writeBuffer.PushContext("MeteringDataMeasureGas"); pushErr != nil {
+			return errors.Wrap(pushErr, "Error pushing for MeteringDataMeasureGas")
+		}
+
+		if popErr := writeBuffer.PopContext("MeteringDataMeasureGas"); popErr != nil {
+			return errors.Wrap(popErr, "Error popping for MeteringDataMeasureGas")
+		}
+		return nil
+	}
+	return m.SerializeParent(writeBuffer, m, ser)
+}
+
+func (m *_MeteringDataMeasureGas) isMeteringDataMeasureGas() bool {
+	return true
+}
+
+func (m *_MeteringDataMeasureGas) String() string {
+	if m == nil {
+		return "<nil>"
+	}
+	writeBuffer := utils.NewBoxedWriteBufferWithOptions(true, true)
+	if err := writeBuffer.WriteSerializable(m); err != nil {
+		return err.Error()
+	}
+	return writeBuffer.GetBox().String()
+}
diff --git a/plc4go/protocols/cbus/readwrite/model/MeteringDataMeasureOil.go b/plc4go/protocols/cbus/readwrite/model/MeteringDataMeasureOil.go
new file mode 100644
index 000000000..6bbcd5211
--- /dev/null
+++ b/plc4go/protocols/cbus/readwrite/model/MeteringDataMeasureOil.go
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/spi/utils"
+	"github.com/pkg/errors"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// MeteringDataMeasureOil is the corresponding interface of MeteringDataMeasureOil
+type MeteringDataMeasureOil interface {
+	utils.LengthAware
+	utils.Serializable
+	MeteringData
+}
+
+// MeteringDataMeasureOilExactly can be used when we want exactly this type and not a type which fulfills MeteringDataMeasureOil.
+// This is useful for switch cases.
+type MeteringDataMeasureOilExactly interface {
+	MeteringDataMeasureOil
+	isMeteringDataMeasureOil() bool
+}
+
+// _MeteringDataMeasureOil is the data-structure of this message
+type _MeteringDataMeasureOil struct {
+	*_MeteringData
+}
+
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for discriminator values.
+///////////////////////
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+
+func (m *_MeteringDataMeasureOil) InitializeParent(parent MeteringData, commandTypeContainer MeteringCommandTypeContainer, argument byte) {
+	m.CommandTypeContainer = commandTypeContainer
+	m.Argument = argument
+}
+
+func (m *_MeteringDataMeasureOil) GetParent() MeteringData {
+	return m._MeteringData
+}
+
+// NewMeteringDataMeasureOil factory function for _MeteringDataMeasureOil
+func NewMeteringDataMeasureOil(commandTypeContainer MeteringCommandTypeContainer, argument byte) *_MeteringDataMeasureOil {
+	_result := &_MeteringDataMeasureOil{
+		_MeteringData: NewMeteringData(commandTypeContainer, argument),
+	}
+	_result._MeteringData._MeteringDataChildRequirements = _result
+	return _result
+}
+
+// Deprecated: use the interface for direct cast
+func CastMeteringDataMeasureOil(structType interface{}) MeteringDataMeasureOil {
+	if casted, ok := structType.(MeteringDataMeasureOil); ok {
+		return casted
+	}
+	if casted, ok := structType.(*MeteringDataMeasureOil); ok {
+		return *casted
+	}
+	return nil
+}
+
+func (m *_MeteringDataMeasureOil) GetTypeName() string {
+	return "MeteringDataMeasureOil"
+}
+
+func (m *_MeteringDataMeasureOil) GetLengthInBits() uint16 {
+	return m.GetLengthInBitsConditional(false)
+}
+
+func (m *_MeteringDataMeasureOil) GetLengthInBitsConditional(lastItem bool) uint16 {
+	lengthInBits := uint16(m.GetParentLengthInBits())
+
+	return lengthInBits
+}
+
+func (m *_MeteringDataMeasureOil) GetLengthInBytes() uint16 {
+	return m.GetLengthInBits() / 8
+}
+
+func MeteringDataMeasureOilParse(readBuffer utils.ReadBuffer) (MeteringDataMeasureOil, error) {
+	positionAware := readBuffer
+	_ = positionAware
+	if pullErr := readBuffer.PullContext("MeteringDataMeasureOil"); pullErr != nil {
+		return nil, errors.Wrap(pullErr, "Error pulling for MeteringDataMeasureOil")
+	}
+	currentPos := positionAware.GetPos()
+	_ = currentPos
+
+	if closeErr := readBuffer.CloseContext("MeteringDataMeasureOil"); closeErr != nil {
+		return nil, errors.Wrap(closeErr, "Error closing for MeteringDataMeasureOil")
+	}
+
+	// Create a partially initialized instance
+	_child := &_MeteringDataMeasureOil{
+		_MeteringData: &_MeteringData{},
+	}
+	_child._MeteringData._MeteringDataChildRequirements = _child
+	return _child, nil
+}
+
+func (m *_MeteringDataMeasureOil) Serialize(writeBuffer utils.WriteBuffer) error {
+	positionAware := writeBuffer
+	_ = positionAware
+	ser := func() error {
+		if pushErr := writeBuffer.PushContext("MeteringDataMeasureOil"); pushErr != nil {
+			return errors.Wrap(pushErr, "Error pushing for MeteringDataMeasureOil")
+		}
+
+		if popErr := writeBuffer.PopContext("MeteringDataMeasureOil"); popErr != nil {
+			return errors.Wrap(popErr, "Error popping for MeteringDataMeasureOil")
+		}
+		return nil
+	}
+	return m.SerializeParent(writeBuffer, m, ser)
+}
+
+func (m *_MeteringDataMeasureOil) isMeteringDataMeasureOil() bool {
+	return true
+}
+
+func (m *_MeteringDataMeasureOil) String() string {
+	if m == nil {
+		return "<nil>"
+	}
+	writeBuffer := utils.NewBoxedWriteBufferWithOptions(true, true)
+	if err := writeBuffer.WriteSerializable(m); err != nil {
+		return err.Error()
+	}
+	return writeBuffer.GetBox().String()
+}
diff --git a/plc4go/protocols/cbus/readwrite/model/MeteringDataMeasureOtherWater.go b/plc4go/protocols/cbus/readwrite/model/MeteringDataMeasureOtherWater.go
new file mode 100644
index 000000000..2f6c447dd
--- /dev/null
+++ b/plc4go/protocols/cbus/readwrite/model/MeteringDataMeasureOtherWater.go
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/spi/utils"
+	"github.com/pkg/errors"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// MeteringDataMeasureOtherWater is the corresponding interface of MeteringDataMeasureOtherWater
+type MeteringDataMeasureOtherWater interface {
+	utils.LengthAware
+	utils.Serializable
+	MeteringData
+}
+
+// MeteringDataMeasureOtherWaterExactly can be used when we want exactly this type and not a type which fulfills MeteringDataMeasureOtherWater.
+// This is useful for switch cases.
+type MeteringDataMeasureOtherWaterExactly interface {
+	MeteringDataMeasureOtherWater
+	isMeteringDataMeasureOtherWater() bool
+}
+
+// _MeteringDataMeasureOtherWater is the data-structure of this message
+type _MeteringDataMeasureOtherWater struct {
+	*_MeteringData
+}
+
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for discriminator values.
+///////////////////////
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+
+func (m *_MeteringDataMeasureOtherWater) InitializeParent(parent MeteringData, commandTypeContainer MeteringCommandTypeContainer, argument byte) {
+	m.CommandTypeContainer = commandTypeContainer
+	m.Argument = argument
+}
+
+func (m *_MeteringDataMeasureOtherWater) GetParent() MeteringData {
+	return m._MeteringData
+}
+
+// NewMeteringDataMeasureOtherWater factory function for _MeteringDataMeasureOtherWater
+func NewMeteringDataMeasureOtherWater(commandTypeContainer MeteringCommandTypeContainer, argument byte) *_MeteringDataMeasureOtherWater {
+	_result := &_MeteringDataMeasureOtherWater{
+		_MeteringData: NewMeteringData(commandTypeContainer, argument),
+	}
+	_result._MeteringData._MeteringDataChildRequirements = _result
+	return _result
+}
+
+// Deprecated: use the interface for direct cast
+func CastMeteringDataMeasureOtherWater(structType interface{}) MeteringDataMeasureOtherWater {
+	if casted, ok := structType.(MeteringDataMeasureOtherWater); ok {
+		return casted
+	}
+	if casted, ok := structType.(*MeteringDataMeasureOtherWater); ok {
+		return *casted
+	}
+	return nil
+}
+
+func (m *_MeteringDataMeasureOtherWater) GetTypeName() string {
+	return "MeteringDataMeasureOtherWater"
+}
+
+func (m *_MeteringDataMeasureOtherWater) GetLengthInBits() uint16 {
+	return m.GetLengthInBitsConditional(false)
+}
+
+func (m *_MeteringDataMeasureOtherWater) GetLengthInBitsConditional(lastItem bool) uint16 {
+	lengthInBits := uint16(m.GetParentLengthInBits())
+
+	return lengthInBits
+}
+
+func (m *_MeteringDataMeasureOtherWater) GetLengthInBytes() uint16 {
+	return m.GetLengthInBits() / 8
+}
+
+func MeteringDataMeasureOtherWaterParse(readBuffer utils.ReadBuffer) (MeteringDataMeasureOtherWater, error) {
+	positionAware := readBuffer
+	_ = positionAware
+	if pullErr := readBuffer.PullContext("MeteringDataMeasureOtherWater"); pullErr != nil {
+		return nil, errors.Wrap(pullErr, "Error pulling for MeteringDataMeasureOtherWater")
+	}
+	currentPos := positionAware.GetPos()
+	_ = currentPos
+
+	if closeErr := readBuffer.CloseContext("MeteringDataMeasureOtherWater"); closeErr != nil {
+		return nil, errors.Wrap(closeErr, "Error closing for MeteringDataMeasureOtherWater")
+	}
+
+	// Create a partially initialized instance
+	_child := &_MeteringDataMeasureOtherWater{
+		_MeteringData: &_MeteringData{},
+	}
+	_child._MeteringData._MeteringDataChildRequirements = _child
+	return _child, nil
+}
+
+func (m *_MeteringDataMeasureOtherWater) Serialize(writeBuffer utils.WriteBuffer) error {
+	positionAware := writeBuffer
+	_ = positionAware
+	ser := func() error {
+		if pushErr := writeBuffer.PushContext("MeteringDataMeasureOtherWater"); pushErr != nil {
+			return errors.Wrap(pushErr, "Error pushing for MeteringDataMeasureOtherWater")
+		}
+
+		if popErr := writeBuffer.PopContext("MeteringDataMeasureOtherWater"); popErr != nil {
+			return errors.Wrap(popErr, "Error popping for MeteringDataMeasureOtherWater")
+		}
+		return nil
+	}
+	return m.SerializeParent(writeBuffer, m, ser)
+}
+
+func (m *_MeteringDataMeasureOtherWater) isMeteringDataMeasureOtherWater() bool {
+	return true
+}
+
+func (m *_MeteringDataMeasureOtherWater) String() string {
+	if m == nil {
+		return "<nil>"
+	}
+	writeBuffer := utils.NewBoxedWriteBufferWithOptions(true, true)
+	if err := writeBuffer.WriteSerializable(m); err != nil {
+		return err.Error()
+	}
+	return writeBuffer.GetBox().String()
+}
diff --git a/plc4go/protocols/cbus/readwrite/model/MeteringDataOilConsumption.go b/plc4go/protocols/cbus/readwrite/model/MeteringDataOilConsumption.go
new file mode 100644
index 000000000..756a17cad
--- /dev/null
+++ b/plc4go/protocols/cbus/readwrite/model/MeteringDataOilConsumption.go
@@ -0,0 +1,191 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/spi/utils"
+	"github.com/pkg/errors"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// MeteringDataOilConsumption is the corresponding interface of MeteringDataOilConsumption
+type MeteringDataOilConsumption interface {
+	utils.LengthAware
+	utils.Serializable
+	MeteringData
+	// GetL returns L (property field)
+	GetL() uint32
+}
+
+// MeteringDataOilConsumptionExactly can be used when we want exactly this type and not a type which fulfills MeteringDataOilConsumption.
+// This is useful for switch cases.
+type MeteringDataOilConsumptionExactly interface {
+	MeteringDataOilConsumption
+	isMeteringDataOilConsumption() bool
+}
+
+// _MeteringDataOilConsumption is the data-structure of this message
+type _MeteringDataOilConsumption struct {
+	*_MeteringData
+	L uint32
+}
+
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for discriminator values.
+///////////////////////
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+
+func (m *_MeteringDataOilConsumption) InitializeParent(parent MeteringData, commandTypeContainer MeteringCommandTypeContainer, argument byte) {
+	m.CommandTypeContainer = commandTypeContainer
+	m.Argument = argument
+}
+
+func (m *_MeteringDataOilConsumption) GetParent() MeteringData {
+	return m._MeteringData
+}
+
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for property fields.
+///////////////////////
+
+func (m *_MeteringDataOilConsumption) GetL() uint32 {
+	return m.L
+}
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+
+// NewMeteringDataOilConsumption factory function for _MeteringDataOilConsumption
+func NewMeteringDataOilConsumption(L uint32, commandTypeContainer MeteringCommandTypeContainer, argument byte) *_MeteringDataOilConsumption {
+	_result := &_MeteringDataOilConsumption{
+		L:             L,
+		_MeteringData: NewMeteringData(commandTypeContainer, argument),
+	}
+	_result._MeteringData._MeteringDataChildRequirements = _result
+	return _result
+}
+
+// Deprecated: use the interface for direct cast
+func CastMeteringDataOilConsumption(structType interface{}) MeteringDataOilConsumption {
+	if casted, ok := structType.(MeteringDataOilConsumption); ok {
+		return casted
+	}
+	if casted, ok := structType.(*MeteringDataOilConsumption); ok {
+		return *casted
+	}
+	return nil
+}
+
+func (m *_MeteringDataOilConsumption) GetTypeName() string {
+	return "MeteringDataOilConsumption"
+}
+
+func (m *_MeteringDataOilConsumption) GetLengthInBits() uint16 {
+	return m.GetLengthInBitsConditional(false)
+}
+
+func (m *_MeteringDataOilConsumption) GetLengthInBitsConditional(lastItem bool) uint16 {
+	lengthInBits := uint16(m.GetParentLengthInBits())
+
+	// Simple field (L)
+	lengthInBits += 32
+
+	return lengthInBits
+}
+
+func (m *_MeteringDataOilConsumption) GetLengthInBytes() uint16 {
+	return m.GetLengthInBits() / 8
+}
+
+func MeteringDataOilConsumptionParse(readBuffer utils.ReadBuffer) (MeteringDataOilConsumption, error) {
+	positionAware := readBuffer
+	_ = positionAware
+	if pullErr := readBuffer.PullContext("MeteringDataOilConsumption"); pullErr != nil {
+		return nil, errors.Wrap(pullErr, "Error pulling for MeteringDataOilConsumption")
+	}
+	currentPos := positionAware.GetPos()
+	_ = currentPos
+
+	// Simple Field (L)
+	_L, _LErr := readBuffer.ReadUint32("L", 32)
+	if _LErr != nil {
+		return nil, errors.Wrap(_LErr, "Error parsing 'L' field of MeteringDataOilConsumption")
+	}
+	L := _L
+
+	if closeErr := readBuffer.CloseContext("MeteringDataOilConsumption"); closeErr != nil {
+		return nil, errors.Wrap(closeErr, "Error closing for MeteringDataOilConsumption")
+	}
+
+	// Create a partially initialized instance
+	_child := &_MeteringDataOilConsumption{
+		L:             L,
+		_MeteringData: &_MeteringData{},
+	}
+	_child._MeteringData._MeteringDataChildRequirements = _child
+	return _child, nil
+}
+
+func (m *_MeteringDataOilConsumption) Serialize(writeBuffer utils.WriteBuffer) error {
+	positionAware := writeBuffer
+	_ = positionAware
+	ser := func() error {
+		if pushErr := writeBuffer.PushContext("MeteringDataOilConsumption"); pushErr != nil {
+			return errors.Wrap(pushErr, "Error pushing for MeteringDataOilConsumption")
+		}
+
+		// Simple Field (L)
+		L := uint32(m.GetL())
+		_LErr := writeBuffer.WriteUint32("L", 32, (L))
+		if _LErr != nil {
+			return errors.Wrap(_LErr, "Error serializing 'L' field")
+		}
+
+		if popErr := writeBuffer.PopContext("MeteringDataOilConsumption"); popErr != nil {
+			return errors.Wrap(popErr, "Error popping for MeteringDataOilConsumption")
+		}
+		return nil
+	}
+	return m.SerializeParent(writeBuffer, m, ser)
+}
+
+func (m *_MeteringDataOilConsumption) isMeteringDataOilConsumption() bool {
+	return true
+}
+
+func (m *_MeteringDataOilConsumption) String() string {
+	if m == nil {
+		return "<nil>"
+	}
+	writeBuffer := utils.NewBoxedWriteBufferWithOptions(true, true)
+	if err := writeBuffer.WriteSerializable(m); err != nil {
+		return err.Error()
+	}
+	return writeBuffer.GetBox().String()
+}
diff --git a/plc4go/protocols/cbus/readwrite/model/MeteringDataOtherWaterConsumption.go b/plc4go/protocols/cbus/readwrite/model/MeteringDataOtherWaterConsumption.go
new file mode 100644
index 000000000..d6a44f27d
--- /dev/null
+++ b/plc4go/protocols/cbus/readwrite/model/MeteringDataOtherWaterConsumption.go
@@ -0,0 +1,191 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/spi/utils"
+	"github.com/pkg/errors"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// MeteringDataOtherWaterConsumption is the corresponding interface of MeteringDataOtherWaterConsumption
+type MeteringDataOtherWaterConsumption interface {
+	utils.LengthAware
+	utils.Serializable
+	MeteringData
+	// GetKL returns KL (property field)
+	GetKL() uint32
+}
+
+// MeteringDataOtherWaterConsumptionExactly can be used when we want exactly this type and not a type which fulfills MeteringDataOtherWaterConsumption.
+// This is useful for switch cases.
+type MeteringDataOtherWaterConsumptionExactly interface {
+	MeteringDataOtherWaterConsumption
+	isMeteringDataOtherWaterConsumption() bool
+}
+
+// _MeteringDataOtherWaterConsumption is the data-structure of this message
+type _MeteringDataOtherWaterConsumption struct {
+	*_MeteringData
+	KL uint32
+}
+
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for discriminator values.
+///////////////////////
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+
+func (m *_MeteringDataOtherWaterConsumption) InitializeParent(parent MeteringData, commandTypeContainer MeteringCommandTypeContainer, argument byte) {
+	m.CommandTypeContainer = commandTypeContainer
+	m.Argument = argument
+}
+
+func (m *_MeteringDataOtherWaterConsumption) GetParent() MeteringData {
+	return m._MeteringData
+}
+
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for property fields.
+///////////////////////
+
+func (m *_MeteringDataOtherWaterConsumption) GetKL() uint32 {
+	return m.KL
+}
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+
+// NewMeteringDataOtherWaterConsumption factory function for _MeteringDataOtherWaterConsumption
+func NewMeteringDataOtherWaterConsumption(kL uint32, commandTypeContainer MeteringCommandTypeContainer, argument byte) *_MeteringDataOtherWaterConsumption {
+	_result := &_MeteringDataOtherWaterConsumption{
+		KL:            kL,
+		_MeteringData: NewMeteringData(commandTypeContainer, argument),
+	}
+	_result._MeteringData._MeteringDataChildRequirements = _result
+	return _result
+}
+
+// Deprecated: use the interface for direct cast
+func CastMeteringDataOtherWaterConsumption(structType interface{}) MeteringDataOtherWaterConsumption {
+	if casted, ok := structType.(MeteringDataOtherWaterConsumption); ok {
+		return casted
+	}
+	if casted, ok := structType.(*MeteringDataOtherWaterConsumption); ok {
+		return *casted
+	}
+	return nil
+}
+
+func (m *_MeteringDataOtherWaterConsumption) GetTypeName() string {
+	return "MeteringDataOtherWaterConsumption"
+}
+
+func (m *_MeteringDataOtherWaterConsumption) GetLengthInBits() uint16 {
+	return m.GetLengthInBitsConditional(false)
+}
+
+func (m *_MeteringDataOtherWaterConsumption) GetLengthInBitsConditional(lastItem bool) uint16 {
+	lengthInBits := uint16(m.GetParentLengthInBits())
+
+	// Simple field (kL)
+	lengthInBits += 32
+
+	return lengthInBits
+}
+
+func (m *_MeteringDataOtherWaterConsumption) GetLengthInBytes() uint16 {
+	return m.GetLengthInBits() / 8
+}
+
+func MeteringDataOtherWaterConsumptionParse(readBuffer utils.ReadBuffer) (MeteringDataOtherWaterConsumption, error) {
+	positionAware := readBuffer
+	_ = positionAware
+	if pullErr := readBuffer.PullContext("MeteringDataOtherWaterConsumption"); pullErr != nil {
+		return nil, errors.Wrap(pullErr, "Error pulling for MeteringDataOtherWaterConsumption")
+	}
+	currentPos := positionAware.GetPos()
+	_ = currentPos
+
+	// Simple Field (kL)
+	_kL, _kLErr := readBuffer.ReadUint32("kL", 32)
+	if _kLErr != nil {
+		return nil, errors.Wrap(_kLErr, "Error parsing 'kL' field of MeteringDataOtherWaterConsumption")
+	}
+	kL := _kL
+
+	if closeErr := readBuffer.CloseContext("MeteringDataOtherWaterConsumption"); closeErr != nil {
+		return nil, errors.Wrap(closeErr, "Error closing for MeteringDataOtherWaterConsumption")
+	}
+
+	// Create a partially initialized instance
+	_child := &_MeteringDataOtherWaterConsumption{
+		KL:            kL,
+		_MeteringData: &_MeteringData{},
+	}
+	_child._MeteringData._MeteringDataChildRequirements = _child
+	return _child, nil
+}
+
+func (m *_MeteringDataOtherWaterConsumption) Serialize(writeBuffer utils.WriteBuffer) error {
+	positionAware := writeBuffer
+	_ = positionAware
+	ser := func() error {
+		if pushErr := writeBuffer.PushContext("MeteringDataOtherWaterConsumption"); pushErr != nil {
+			return errors.Wrap(pushErr, "Error pushing for MeteringDataOtherWaterConsumption")
+		}
+
+		// Simple Field (kL)
+		kL := uint32(m.GetKL())
+		_kLErr := writeBuffer.WriteUint32("kL", 32, (kL))
+		if _kLErr != nil {
+			return errors.Wrap(_kLErr, "Error serializing 'kL' field")
+		}
+
+		if popErr := writeBuffer.PopContext("MeteringDataOtherWaterConsumption"); popErr != nil {
+			return errors.Wrap(popErr, "Error popping for MeteringDataOtherWaterConsumption")
+		}
+		return nil
+	}
+	return m.SerializeParent(writeBuffer, m, ser)
+}
+
+func (m *_MeteringDataOtherWaterConsumption) isMeteringDataOtherWaterConsumption() bool {
+	return true
+}
+
+func (m *_MeteringDataOtherWaterConsumption) String() string {
+	if m == nil {
+		return "<nil>"
+	}
+	writeBuffer := utils.NewBoxedWriteBufferWithOptions(true, true)
+	if err := writeBuffer.WriteSerializable(m); err != nil {
+		return err.Error()
+	}
+	return writeBuffer.GetBox().String()
+}
diff --git a/plc4go/protocols/cbus/readwrite/model/SALDataAccessControl.go b/plc4go/protocols/cbus/readwrite/model/SALDataAccessControl.go
index bf70bdff4..963be5b81 100644
--- a/plc4go/protocols/cbus/readwrite/model/SALDataAccessControl.go
+++ b/plc4go/protocols/cbus/readwrite/model/SALDataAccessControl.go
@@ -116,7 +116,7 @@ func SALDataAccessControlParse(readBuffer utils.ReadBuffer, applicationId Applic
 
 	// Validation
 	if !(bool((1) == (2))) {
-		return nil, errors.WithStack(utils.ParseValidationError{"Not yet implemented"})
+		return nil, errors.WithStack(utils.ParseValidationError{"ACCESS_CONTROL Not yet implemented"})
 	}
 
 	if closeErr := readBuffer.CloseContext("SALDataAccessControl"); closeErr != nil {
diff --git a/plc4go/protocols/cbus/readwrite/model/SALDataAirConditioning.go b/plc4go/protocols/cbus/readwrite/model/SALDataAirConditioning.go
index 3e15eaa40..f55e860df 100644
--- a/plc4go/protocols/cbus/readwrite/model/SALDataAirConditioning.go
+++ b/plc4go/protocols/cbus/readwrite/model/SALDataAirConditioning.go
@@ -116,7 +116,7 @@ func SALDataAirConditioningParse(readBuffer utils.ReadBuffer, applicationId Appl
 
 	// Validation
 	if !(bool((1) == (2))) {
-		return nil, errors.WithStack(utils.ParseValidationError{"Not yet implemented"})
+		return nil, errors.WithStack(utils.ParseValidationError{"AIR_CONDITIONING Not yet implemented"})
 	}
 
 	if closeErr := readBuffer.CloseContext("SALDataAirConditioning"); closeErr != nil {
diff --git a/plc4go/protocols/cbus/readwrite/model/SALDataAudioAndVideo.go b/plc4go/protocols/cbus/readwrite/model/SALDataAudioAndVideo.go
index 0b569f873..f63e0243e 100644
--- a/plc4go/protocols/cbus/readwrite/model/SALDataAudioAndVideo.go
+++ b/plc4go/protocols/cbus/readwrite/model/SALDataAudioAndVideo.go
@@ -116,7 +116,7 @@ func SALDataAudioAndVideoParse(readBuffer utils.ReadBuffer, applicationId Applic
 
 	// Validation
 	if !(bool((1) == (2))) {
-		return nil, errors.WithStack(utils.ParseValidationError{"Not yet implemented"})
+		return nil, errors.WithStack(utils.ParseValidationError{"AUDIO_AND_VIDEO Not yet implemented"})
 	}
 
 	if closeErr := readBuffer.CloseContext("SALDataAudioAndVideo"); closeErr != nil {
diff --git a/plc4go/protocols/cbus/readwrite/model/SALDataClockAndTimekeeping.go b/plc4go/protocols/cbus/readwrite/model/SALDataClockAndTimekeeping.go
index b5990a972..7ab9e4a92 100644
--- a/plc4go/protocols/cbus/readwrite/model/SALDataClockAndTimekeeping.go
+++ b/plc4go/protocols/cbus/readwrite/model/SALDataClockAndTimekeeping.go
@@ -116,7 +116,7 @@ func SALDataClockAndTimekeepingParse(readBuffer utils.ReadBuffer, applicationId
 
 	// Validation
 	if !(bool((1) == (2))) {
-		return nil, errors.WithStack(utils.ParseValidationError{"Not yet implemented"})
+		return nil, errors.WithStack(utils.ParseValidationError{"CLOCK_AND_TIMEKEEPING Not yet implemented"})
 	}
 
 	if closeErr := readBuffer.CloseContext("SALDataClockAndTimekeeping"); closeErr != nil {
diff --git a/plc4go/protocols/cbus/readwrite/model/SALDataEnableControl.go b/plc4go/protocols/cbus/readwrite/model/SALDataEnableControl.go
index 08663d9c9..eeee6f114 100644
--- a/plc4go/protocols/cbus/readwrite/model/SALDataEnableControl.go
+++ b/plc4go/protocols/cbus/readwrite/model/SALDataEnableControl.go
@@ -116,7 +116,7 @@ func SALDataEnableControlParse(readBuffer utils.ReadBuffer, applicationId Applic
 
 	// Validation
 	if !(bool((1) == (2))) {
-		return nil, errors.WithStack(utils.ParseValidationError{"Not yet implemented"})
+		return nil, errors.WithStack(utils.ParseValidationError{"ENABLE_CONTROL Not yet implemented"})
 	}
 
 	if closeErr := readBuffer.CloseContext("SALDataEnableControl"); closeErr != nil {
diff --git a/plc4go/protocols/cbus/readwrite/model/SALDataFreeUsage.go b/plc4go/protocols/cbus/readwrite/model/SALDataFreeUsage.go
index 0391d8683..3db33650d 100644
--- a/plc4go/protocols/cbus/readwrite/model/SALDataFreeUsage.go
+++ b/plc4go/protocols/cbus/readwrite/model/SALDataFreeUsage.go
@@ -116,7 +116,7 @@ func SALDataFreeUsageParse(readBuffer utils.ReadBuffer, applicationId Applicatio
 
 	// Validation
 	if !(bool((1) == (2))) {
-		return nil, errors.WithStack(utils.ParseValidationError{"Not yet implemented"})
+		return nil, errors.WithStack(utils.ParseValidationError{"FREE_USAGE Not yet implemented"})
 	}
 
 	if closeErr := readBuffer.CloseContext("SALDataFreeUsage"); closeErr != nil {
diff --git a/plc4go/protocols/cbus/readwrite/model/SALDataHeating.go b/plc4go/protocols/cbus/readwrite/model/SALDataHeating.go
index 8b177d2bf..41cb5e248 100644
--- a/plc4go/protocols/cbus/readwrite/model/SALDataHeating.go
+++ b/plc4go/protocols/cbus/readwrite/model/SALDataHeating.go
@@ -116,7 +116,7 @@ func SALDataHeatingParse(readBuffer utils.ReadBuffer, applicationId ApplicationI
 
 	// Validation
 	if !(bool((1) == (2))) {
-		return nil, errors.WithStack(utils.ParseValidationError{"Not yet implemented"})
+		return nil, errors.WithStack(utils.ParseValidationError{"HEATING Not yet implemented"})
 	}
 
 	if closeErr := readBuffer.CloseContext("SALDataHeating"); closeErr != nil {
diff --git a/plc4go/protocols/cbus/readwrite/model/SALDataIrrigationControl.go b/plc4go/protocols/cbus/readwrite/model/SALDataIrrigationControl.go
index 4cd6a1e72..bdcb03229 100644
--- a/plc4go/protocols/cbus/readwrite/model/SALDataIrrigationControl.go
+++ b/plc4go/protocols/cbus/readwrite/model/SALDataIrrigationControl.go
@@ -116,7 +116,7 @@ func SALDataIrrigationControlParse(readBuffer utils.ReadBuffer, applicationId Ap
 
 	// Validation
 	if !(bool((1) == (2))) {
-		return nil, errors.WithStack(utils.ParseValidationError{"Not yet implemented"})
+		return nil, errors.WithStack(utils.ParseValidationError{"IRRIGATION_CONTROL Not yet implemented"})
 	}
 
 	if closeErr := readBuffer.CloseContext("SALDataIrrigationControl"); closeErr != nil {
diff --git a/plc4go/protocols/cbus/readwrite/model/SALDataMeasurement.go b/plc4go/protocols/cbus/readwrite/model/SALDataMeasurement.go
index 62c94dab8..49ec1b55b 100644
--- a/plc4go/protocols/cbus/readwrite/model/SALDataMeasurement.go
+++ b/plc4go/protocols/cbus/readwrite/model/SALDataMeasurement.go
@@ -116,7 +116,7 @@ func SALDataMeasurementParse(readBuffer utils.ReadBuffer, applicationId Applicat
 
 	// Validation
 	if !(bool((1) == (2))) {
-		return nil, errors.WithStack(utils.ParseValidationError{"Not yet implemented"})
+		return nil, errors.WithStack(utils.ParseValidationError{"MEASUREMENT Not yet implemented"})
 	}
 
 	if closeErr := readBuffer.CloseContext("SALDataMeasurement"); closeErr != nil {
diff --git a/plc4go/protocols/cbus/readwrite/model/SALDataMetering.go b/plc4go/protocols/cbus/readwrite/model/SALDataMetering.go
index 4c7744096..0876664bb 100644
--- a/plc4go/protocols/cbus/readwrite/model/SALDataMetering.go
+++ b/plc4go/protocols/cbus/readwrite/model/SALDataMetering.go
@@ -31,6 +31,8 @@ type SALDataMetering interface {
 	utils.LengthAware
 	utils.Serializable
 	SALData
+	// GetMeteringData returns MeteringData (property field)
+	GetMeteringData() MeteringData
 }
 
 // SALDataMeteringExactly can be used when we want exactly this type and not a type which fulfills SALDataMetering.
@@ -43,6 +45,7 @@ type SALDataMeteringExactly interface {
 // _SALDataMetering is the data-structure of this message
 type _SALDataMetering struct {
 	*_SALData
+	MeteringData MeteringData
 }
 
 ///////////////////////////////////////////////////////////
@@ -67,10 +70,25 @@ func (m *_SALDataMetering) GetParent() SALData {
 	return m._SALData
 }
 
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+/////////////////////// Accessors for property fields.
+///////////////////////
+
+func (m *_SALDataMetering) GetMeteringData() MeteringData {
+	return m.MeteringData
+}
+
+///////////////////////
+///////////////////////
+///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////
+
 // NewSALDataMetering factory function for _SALDataMetering
-func NewSALDataMetering(salData SALData) *_SALDataMetering {
+func NewSALDataMetering(meteringData MeteringData, salData SALData) *_SALDataMetering {
 	_result := &_SALDataMetering{
-		_SALData: NewSALData(salData),
+		MeteringData: meteringData,
+		_SALData:     NewSALData(salData),
 	}
 	_result._SALData._SALDataChildRequirements = _result
 	return _result
@@ -98,6 +116,9 @@ func (m *_SALDataMetering) GetLengthInBits() uint16 {
 func (m *_SALDataMetering) GetLengthInBitsConditional(lastItem bool) uint16 {
 	lengthInBits := uint16(m.GetParentLengthInBits())
 
+	// Simple field (meteringData)
+	lengthInBits += m.MeteringData.GetLengthInBits()
+
 	return lengthInBits
 }
 
@@ -114,9 +135,17 @@ func SALDataMeteringParse(readBuffer utils.ReadBuffer, applicationId Application
 	currentPos := positionAware.GetPos()
 	_ = currentPos
 
-	// Validation
-	if !(bool((1) == (2))) {
-		return nil, errors.WithStack(utils.ParseValidationError{"Not yet implemented"})
+	// Simple Field (meteringData)
+	if pullErr := readBuffer.PullContext("meteringData"); pullErr != nil {
+		return nil, errors.Wrap(pullErr, "Error pulling for meteringData")
+	}
+	_meteringData, _meteringDataErr := MeteringDataParse(readBuffer)
+	if _meteringDataErr != nil {
+		return nil, errors.Wrap(_meteringDataErr, "Error parsing 'meteringData' field of SALDataMetering")
+	}
+	meteringData := _meteringData.(MeteringData)
+	if closeErr := readBuffer.CloseContext("meteringData"); closeErr != nil {
+		return nil, errors.Wrap(closeErr, "Error closing for meteringData")
 	}
 
 	if closeErr := readBuffer.CloseContext("SALDataMetering"); closeErr != nil {
@@ -125,7 +154,8 @@ func SALDataMeteringParse(readBuffer utils.ReadBuffer, applicationId Application
 
 	// Create a partially initialized instance
 	_child := &_SALDataMetering{
-		_SALData: &_SALData{},
+		MeteringData: meteringData,
+		_SALData:     &_SALData{},
 	}
 	_child._SALData._SALDataChildRequirements = _child
 	return _child, nil
@@ -139,6 +169,18 @@ func (m *_SALDataMetering) Serialize(writeBuffer utils.WriteBuffer) error {
 			return errors.Wrap(pushErr, "Error pushing for SALDataMetering")
 		}
 
+		// Simple Field (meteringData)
+		if pushErr := writeBuffer.PushContext("meteringData"); pushErr != nil {
+			return errors.Wrap(pushErr, "Error pushing for meteringData")
+		}
+		_meteringDataErr := writeBuffer.WriteSerializable(m.GetMeteringData())
+		if popErr := writeBuffer.PopContext("meteringData"); popErr != nil {
+			return errors.Wrap(popErr, "Error popping for meteringData")
+		}
+		if _meteringDataErr != nil {
+			return errors.Wrap(_meteringDataErr, "Error serializing 'meteringData' field")
+		}
+
 		if popErr := writeBuffer.PopContext("SALDataMetering"); popErr != nil {
 			return errors.Wrap(popErr, "Error popping for SALDataMetering")
 		}
diff --git a/plc4go/protocols/cbus/readwrite/model/SALDataPoolsSpasPondsFountainsControl.go b/plc4go/protocols/cbus/readwrite/model/SALDataPoolsSpasPondsFountainsControl.go
index 996d69b7a..4ae740f11 100644
--- a/plc4go/protocols/cbus/readwrite/model/SALDataPoolsSpasPondsFountainsControl.go
+++ b/plc4go/protocols/cbus/readwrite/model/SALDataPoolsSpasPondsFountainsControl.go
@@ -116,7 +116,7 @@ func SALDataPoolsSpasPondsFountainsControlParse(readBuffer utils.ReadBuffer, app
 
 	// Validation
 	if !(bool((1) == (2))) {
-		return nil, errors.WithStack(utils.ParseValidationError{"Not yet implemented"})
+		return nil, errors.WithStack(utils.ParseValidationError{"POOLS_SPAS_PONDS_FOUNTAINS_CONTROL Not yet implemented"})
 	}
 
 	if closeErr := readBuffer.CloseContext("SALDataPoolsSpasPondsFountainsControl"); closeErr != nil {
diff --git a/plc4go/protocols/cbus/readwrite/model/SALDataReserved.go b/plc4go/protocols/cbus/readwrite/model/SALDataReserved.go
index 4d34e265e..d352ae416 100644
--- a/plc4go/protocols/cbus/readwrite/model/SALDataReserved.go
+++ b/plc4go/protocols/cbus/readwrite/model/SALDataReserved.go
@@ -116,7 +116,7 @@ func SALDataReservedParse(readBuffer utils.ReadBuffer, applicationId Application
 
 	// Validation
 	if !(bool((1) == (2))) {
-		return nil, errors.WithStack(utils.ParseValidationError{"Not yet implemented"})
+		return nil, errors.WithStack(utils.ParseValidationError{"RESERVED Not yet implemented"})
 	}
 
 	if closeErr := readBuffer.CloseContext("SALDataReserved"); closeErr != nil {
diff --git a/plc4go/protocols/cbus/readwrite/model/SALDataRoomControlSystem.go b/plc4go/protocols/cbus/readwrite/model/SALDataRoomControlSystem.go
index 68cb2ae5a..cf0d0c881 100644
--- a/plc4go/protocols/cbus/readwrite/model/SALDataRoomControlSystem.go
+++ b/plc4go/protocols/cbus/readwrite/model/SALDataRoomControlSystem.go
@@ -116,7 +116,7 @@ func SALDataRoomControlSystemParse(readBuffer utils.ReadBuffer, applicationId Ap
 
 	// Validation
 	if !(bool((1) == (2))) {
-		return nil, errors.WithStack(utils.ParseValidationError{"Not yet implemented"})
+		return nil, errors.WithStack(utils.ParseValidationError{"ROOM_CONTROL_SYSTEM Not yet implemented"})
 	}
 
 	if closeErr := readBuffer.CloseContext("SALDataRoomControlSystem"); closeErr != nil {
diff --git a/plc4go/protocols/cbus/readwrite/model/SALDataTelephonyStatusAndControl.go b/plc4go/protocols/cbus/readwrite/model/SALDataTelephonyStatusAndControl.go
index f8380d838..12c84e581 100644
--- a/plc4go/protocols/cbus/readwrite/model/SALDataTelephonyStatusAndControl.go
+++ b/plc4go/protocols/cbus/readwrite/model/SALDataTelephonyStatusAndControl.go
@@ -116,7 +116,7 @@ func SALDataTelephonyStatusAndControlParse(readBuffer utils.ReadBuffer, applicat
 
 	// Validation
 	if !(bool((1) == (2))) {
-		return nil, errors.WithStack(utils.ParseValidationError{"Not yet implemented"})
+		return nil, errors.WithStack(utils.ParseValidationError{"TELEPHONY_STATUS_AND_CONTROL Not yet implemented"})
 	}
 
 	if closeErr := readBuffer.CloseContext("SALDataTelephonyStatusAndControl"); closeErr != nil {
diff --git a/plc4go/protocols/cbus/readwrite/model/SALDataTemperatureBroadcast.go b/plc4go/protocols/cbus/readwrite/model/SALDataTemperatureBroadcast.go
index a5275662d..7a821e3cb 100644
--- a/plc4go/protocols/cbus/readwrite/model/SALDataTemperatureBroadcast.go
+++ b/plc4go/protocols/cbus/readwrite/model/SALDataTemperatureBroadcast.go
@@ -116,7 +116,7 @@ func SALDataTemperatureBroadcastParse(readBuffer utils.ReadBuffer, applicationId
 
 	// Validation
 	if !(bool((1) == (2))) {
-		return nil, errors.WithStack(utils.ParseValidationError{"Not yet implemented"})
+		return nil, errors.WithStack(utils.ParseValidationError{"TEMPERATURE_BROADCAST Not yet implemented"})
 	}
 
 	if closeErr := readBuffer.CloseContext("SALDataTemperatureBroadcast"); closeErr != nil {
diff --git a/plc4go/protocols/cbus/readwrite/model/SALDataTesting.go b/plc4go/protocols/cbus/readwrite/model/SALDataTesting.go
index d227c296c..62e4bf9bf 100644
--- a/plc4go/protocols/cbus/readwrite/model/SALDataTesting.go
+++ b/plc4go/protocols/cbus/readwrite/model/SALDataTesting.go
@@ -116,7 +116,7 @@ func SALDataTestingParse(readBuffer utils.ReadBuffer, applicationId ApplicationI
 
 	// Validation
 	if !(bool((1) == (2))) {
-		return nil, errors.WithStack(utils.ParseValidationError{"Not yet implemented"})
+		return nil, errors.WithStack(utils.ParseValidationError{"TESTING Not yet implemented"})
 	}
 
 	if closeErr := readBuffer.CloseContext("SALDataTesting"); closeErr != nil {
diff --git a/plc4go/protocols/cbus/readwrite/model/SALDataTriggerControl.go b/plc4go/protocols/cbus/readwrite/model/SALDataTriggerControl.go
index d2284d2aa..ce1123fc0 100644
--- a/plc4go/protocols/cbus/readwrite/model/SALDataTriggerControl.go
+++ b/plc4go/protocols/cbus/readwrite/model/SALDataTriggerControl.go
@@ -116,7 +116,7 @@ func SALDataTriggerControlParse(readBuffer utils.ReadBuffer, applicationId Appli
 
 	// Validation
 	if !(bool((1) == (2))) {
-		return nil, errors.WithStack(utils.ParseValidationError{"Not yet implemented"})
+		return nil, errors.WithStack(utils.ParseValidationError{"TRIGGER_CONTROL Not yet implemented"})
 	}
 
 	if closeErr := readBuffer.CloseContext("SALDataTriggerControl"); closeErr != nil {
diff --git a/plc4go/protocols/cbus/readwrite/model/SALDataVentilation.go b/plc4go/protocols/cbus/readwrite/model/SALDataVentilation.go
index 5ea47d56b..4471e21ab 100644
--- a/plc4go/protocols/cbus/readwrite/model/SALDataVentilation.go
+++ b/plc4go/protocols/cbus/readwrite/model/SALDataVentilation.go
@@ -116,7 +116,7 @@ func SALDataVentilationParse(readBuffer utils.ReadBuffer, applicationId Applicat
 
 	// Validation
 	if !(bool((1) == (2))) {
-		return nil, errors.WithStack(utils.ParseValidationError{"Not yet implemented"})
+		return nil, errors.WithStack(utils.ParseValidationError{"VENTILATION Not yet implemented"})
 	}
 
 	if closeErr := readBuffer.CloseContext("SALDataVentilation"); closeErr != nil {
diff --git a/plc4go/protocols/cbus/readwrite/model/StaticHelper.go b/plc4go/protocols/cbus/readwrite/model/StaticHelper.go
index ab8b3a742..9b3d6c998 100644
--- a/plc4go/protocols/cbus/readwrite/model/StaticHelper.go
+++ b/plc4go/protocols/cbus/readwrite/model/StaticHelper.go
@@ -141,3 +141,13 @@ func KnowsSecurityCommandTypeContainer(readBuffer utils.ReadBuffer) bool {
 	}
 	return SecurityCommandTypeContainerKnows(readUint8)
 }
+
+func KnowsMeteringCommandTypeContainer(readBuffer utils.ReadBuffer) bool {
+	oldPos := readBuffer.GetPos()
+	defer readBuffer.Reset(oldPos)
+	readUint8, err := readBuffer.ReadUint8("", 8)
+	if err != nil {
+		return false
+	}
+	return MeteringCommandTypeContainerKnows(readUint8)
+}
diff --git a/plc4j/drivers/c-bus/src/main/java/org/apache/plc4x/java/cbus/readwrite/utils/StaticHelper.java b/plc4j/drivers/c-bus/src/main/java/org/apache/plc4x/java/cbus/readwrite/utils/StaticHelper.java
index 40e66e1e2..16a4fa25c 100644
--- a/plc4j/drivers/c-bus/src/main/java/org/apache/plc4x/java/cbus/readwrite/utils/StaticHelper.java
+++ b/plc4j/drivers/c-bus/src/main/java/org/apache/plc4x/java/cbus/readwrite/utils/StaticHelper.java
@@ -117,4 +117,15 @@ public class StaticHelper {
         }
     }
 
+    public static boolean knowsMeteringCommandTypeContainer(ReadBuffer readBuffer) {
+        int oldPos = readBuffer.getPos();
+        try {
+            return MeteringCommandTypeContainer.isDefined(readBuffer.readUnsignedShort(8));
+        } catch (ParseException ignore) {
+            return false;
+        } finally {
+            readBuffer.reset(oldPos);
+        }
+    }
+
 }
diff --git a/plc4j/drivers/c-bus/src/test/java/org/apache/plc4x/java/cbus/ReferenceTest.java b/plc4j/drivers/c-bus/src/test/java/org/apache/plc4x/java/cbus/ReferenceTest.java
index 915f6cc26..cfc64b0ab 100644
--- a/plc4j/drivers/c-bus/src/test/java/org/apache/plc4x/java/cbus/ReferenceTest.java
+++ b/plc4j/drivers/c-bus/src/test/java/org/apache/plc4x/java/cbus/ReferenceTest.java
@@ -874,7 +874,6 @@ public class ReferenceTest {
     }
 
 
-    @Disabled("needs to be implemented")
     // from: https://updates.clipsal.com/ClipsalSoftwareDownload/DL/downloads/OpenCBus/Chapter%2006%20-%20C-Bus%20Metering%20Application.pdf
     @Nested
     class MeteringApplicationsTest{
@@ -908,7 +907,6 @@ public class ReferenceTest {
 
         }
 
-        @Disabled("this application needs to be implemented")
         //6.11.2
         @Nested
         class MeterMeasurementDevicesendsElectricityUse{
diff --git a/protocols/c-bus/src/main/resources/protocols/cbus/c-bus.mspec b/protocols/c-bus/src/main/resources/protocols/cbus/c-bus.mspec
index 915e52c24..dcf49e3bd 100644
--- a/protocols/c-bus/src/main/resources/protocols/cbus/c-bus.mspec
+++ b/protocols/c-bus/src/main/resources/protocols/cbus/c-bus.mspec
@@ -1299,64 +1299,64 @@
 [type SALData(ApplicationId applicationId)
     [typeSwitch applicationId
         ['RESERVED'                             *Reserved
-            [validation '1==2' "Not yet implemented"] // TODO: implement me
+            [validation '1==2' "RESERVED Not yet implemented"] // TODO: implement me
         ]
         ['FREE_USAGE'                           *FreeUsage
-            [validation '1==2' "Not yet implemented"] // TODO: implement me
+            [validation '1==2' "FREE_USAGE Not yet implemented"] // TODO: implement me
         ]
         ['TEMPERATURE_BROADCAST'                *TemperatureBroadcast
-            [validation '1==2' "Not yet implemented"] // TODO: implement me
+            [validation '1==2' "TEMPERATURE_BROADCAST Not yet implemented"] // TODO: implement me
         ]
         ['ROOM_CONTROL_SYSTEM'                  *RoomControlSystem
-            [validation '1==2' "Not yet implemented"] // TODO: implement me
+            [validation '1==2' "ROOM_CONTROL_SYSTEM Not yet implemented"] // TODO: implement me
         ]
         ['LIGHTING'                             *Lighting
             [simple LightingData lightingData]
         ]
         ['VENTILATION'                          *Ventilation
-            [validation '1==2' "Not yet implemented"] // TODO: implement me
+            [validation '1==2' "VENTILATION Not yet implemented"] // TODO: implement me
         ]
         ['IRRIGATION_CONTROL'                   *IrrigationControl
-            [validation '1==2' "Not yet implemented"] // TODO: implement me
+            [validation '1==2' "IRRIGATION_CONTROL Not yet implemented"] // TODO: implement me
         ]
         ['POOLS_SPAS_PONDS_FOUNTAINS_CONTROL'   *PoolsSpasPondsFountainsControl
-            [validation '1==2' "Not yet implemented"] // TODO: implement me
+            [validation '1==2' "POOLS_SPAS_PONDS_FOUNTAINS_CONTROL Not yet implemented"] // TODO: implement me
         ]
         ['HEATING'                              *Heating
-            [validation '1==2' "Not yet implemented"] // TODO: implement me
+            [validation '1==2' "HEATING Not yet implemented"] // TODO: implement me
         ]
         ['AIR_CONDITIONING'                     *AirConditioning
-            [validation '1==2' "Not yet implemented"] // TODO: implement me
+            [validation '1==2' "AIR_CONDITIONING Not yet implemented"] // TODO: implement me
         ]
         ['TRIGGER_CONTROL'                      *TriggerControl
-            [validation '1==2' "Not yet implemented"] // TODO: implement me
+            [validation '1==2' "TRIGGER_CONTROL Not yet implemented"] // TODO: implement me
         ]
         ['ENABLE_CONTROL'                       *EnableControl
-            [validation '1==2' "Not yet implemented"] // TODO: implement me
+            [validation '1==2' "ENABLE_CONTROL Not yet implemented"] // TODO: implement me
         ]
         ['AUDIO_AND_VIDEO'                      *AudioAndVideo
-            [validation '1==2' "Not yet implemented"] // TODO: implement me
+            [validation '1==2' "AUDIO_AND_VIDEO Not yet implemented"] // TODO: implement me
         ]
         ['SECURITY'                             *Security
             [simple SecurityData securityData]
         ]
         ['METERING'                             *Metering
-            [validation '1==2' "Not yet implemented"] // TODO: implement me
+            [simple MeteringData meteringData]
         ]
         ['ACCESS_CONTROL'                       *AccessControl
-            [validation '1==2' "Not yet implemented"] // TODO: implement me
+            [validation '1==2' "ACCESS_CONTROL Not yet implemented"] // TODO: implement me
         ]
         ['CLOCK_AND_TIMEKEEPING'                *ClockAndTimekeeping
-            [validation '1==2' "Not yet implemented"] // TODO: implement me
+            [validation '1==2' "CLOCK_AND_TIMEKEEPING Not yet implemented"] // TODO: implement me
         ]
         ['TELEPHONY_STATUS_AND_CONTROL'         *TelephonyStatusAndControl
-            [validation '1==2' "Not yet implemented"] // TODO: implement me
+            [validation '1==2' "TELEPHONY_STATUS_AND_CONTROL Not yet implemented"] // TODO: implement me
         ]
         ['MEASUREMENT'                          *Measurement
-            [validation '1==2' "Not yet implemented"] // TODO: implement me
+            [validation '1==2' "MEASUREMENT Not yet implemented"] // TODO: implement me
         ]
         ['TESTING'                              *Testing
-            [validation '1==2' "Not yet implemented"] // TODO: implement me
+            [validation '1==2' "TESTING Not yet implemented"] // TODO: implement me
         ]
     ]
     // TODO: we need to check that we don't read the crc by accident
@@ -1865,6 +1865,56 @@
     ['0x3' ZONE_SHORT       ]
 ]
 
+[type MeteringData
+    //TODO: golang doesn't like checking for null so we use that static call to check that the enum is known
+    [validation 'STATIC_CALL("knowsMeteringCommandTypeContainer", readBuffer)' "no command type could be found" shouldFail=false]
+    [simple  MeteringCommandTypeContainer commandTypeContainer                                   ]
+    [virtual MeteringCommandType          commandType          'commandTypeContainer.commandType']
+    [simple byte argument                                                               ]
+    [typeSwitch commandType, argument
+        ['EVENT', '0x01'       *MeasureElectricity
+        ]
+        ['EVENT', '0x02'       *MeasureGas
+        ]
+        ['EVENT', '0x03'       *MeasureDrinkingWater
+        ]
+        ['EVENT', '0x04'       *MeasureOtherWater
+        ]
+        ['EVENT', '0x05'       *MeasureOil
+        ]
+        ['EVENT', '0x81'       *ElectricityConsumption
+            [simple uint 32 kWhr      ] // kilo watt hours
+        ]
+        ['EVENT', '0x82'       *GasConsumption
+            [simple uint 32 mJ        ] // mega joule
+        ]
+        ['EVENT', '0x83'       *DrinkingWaterConsumption
+            [simple uint 32 kL        ] // kilo litre
+        ]
+        ['EVENT', '0x84'       *OtherWaterConsumption
+            [simple uint 32 kL        ] // kilo litre
+        ]
+        ['EVENT', '0x85'       *OilConsumption
+            [simple uint 32 L         ] // litre
+        ]
+    ]
+]
+
+[enum uint 8 MeteringCommandTypeContainer(MeteringCommandType commandType, uint 5 numBytes)
+    ['0x08' MeteringCommandEvent_0Bytes                    ['EVENT',  '0']]
+    ['0x09' MeteringCommandEvent_1Bytes                    ['EVENT',  '1']]
+    ['0x0A' MeteringCommandEvent_2Bytes                    ['EVENT',  '2']]
+    ['0x0B' MeteringCommandEvent_3Bytes                    ['EVENT',  '3']]
+    ['0x0C' MeteringCommandEvent_4Bytes                    ['EVENT',  '4']]
+    ['0x0D' MeteringCommandEvent_5Bytes                    ['EVENT',  '5']]
+    ['0x0E' MeteringCommandEvent_6Bytes                    ['EVENT',  '6']]
+    ['0x0F' MeteringCommandEvent_7Bytes                    ['EVENT',  '7']]
+]
+
+[enum uint 4 MeteringCommandType
+    ['0x00' EVENT     ]
+]
+
 [type ReplyOrConfirmation(CBusOptions cBusOptions, uint 16 messageLength, RequestContext requestContext)
     [peek    byte peekedByte                                                ]
     [virtual bit  isAlpha '(peekedByte >= 0x67) && (peekedByte <= 0x7A)'    ]