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 2021/12/03 17:01:45 UTC

[plc4x] branch develop updated: test(bacnet): Added tests for Who-Has and fixed bugs

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 87fb2db  test(bacnet): Added tests for Who-Has and fixed bugs
87fb2db is described below

commit 87fb2dbf3e4cc7ef60bab6439ced580f66fa3c74
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Fri Dec 3 18:01:36 2021 +0100

    test(bacnet): Added tests for Who-Has and fixed bugs
---
 .../BACnetConfirmedServiceRequestWriteProperty.go  | 185 ++++++---------
 .../plc4go/bacnetip/readwrite/model/BACnetError.go |   2 +
 .../model/BACnetErrorConfirmedEventNotification.go | 196 ++++++++++++++++
 .../readwrite/model/BACnetPropertyIdentifier.go    |  16 ++
 .../model/BACnetServiceAckAtomicWriteFile.go       |  38 +++-
 .../model/BACnetServiceAckReadProperty.go          | 249 ++++++---------------
 .../model/BACnetUnconfirmedServiceRequestWhoHas.go |  14 +-
 .../resources/protocols/bacnetip/bacnetip.mspec    |  10 +-
 .../plc4x/java/bacnetip/RandomPackagesTest.java    | 171 ++++++++++++--
 9 files changed, 547 insertions(+), 334 deletions(-)

diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetConfirmedServiceRequestWriteProperty.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetConfirmedServiceRequestWriteProperty.go
index 6addeec..217feea 100644
--- a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetConfirmedServiceRequestWriteProperty.go
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetConfirmedServiceRequestWriteProperty.go
@@ -28,20 +28,17 @@ import (
 // Code generated by code-generation. DO NOT EDIT.
 
 // Constant values.
-const BACnetConfirmedServiceRequestWriteProperty_OBJECTIDENTIFIERHEADER uint8 = 0x0C
-const BACnetConfirmedServiceRequestWriteProperty_PROPERTYIDENTIFIERHEADER uint8 = 0x03
 const BACnetConfirmedServiceRequestWriteProperty_OPENINGTAG uint8 = 0x3E
 const BACnetConfirmedServiceRequestWriteProperty_CLOSINGTAG uint8 = 0x3F
 
 // The data-structure of this message
 type BACnetConfirmedServiceRequestWriteProperty struct {
 	*BACnetConfirmedServiceRequest
-	ObjectType               uint16
-	ObjectInstanceNumber     uint32
-	PropertyIdentifierLength uint8
-	PropertyIdentifier       []int8
-	Value                    *BACnetTag
-	Priority                 *BACnetTag
+	ObjectIdentifier   *BACnetComplexTagObjectIdentifier
+	PropertyIdentifier *BACnetComplexTagPropertyIdentifier
+	ArrayIndex         *uint32
+	Value              *BACnetTag
+	Priority           *BACnetTag
 }
 
 // The corresponding interface
@@ -61,12 +58,11 @@ func (m *BACnetConfirmedServiceRequestWriteProperty) ServiceChoice() uint8 {
 func (m *BACnetConfirmedServiceRequestWriteProperty) InitializeParent(parent *BACnetConfirmedServiceRequest) {
 }
 
-func NewBACnetConfirmedServiceRequestWriteProperty(objectType uint16, objectInstanceNumber uint32, propertyIdentifierLength uint8, propertyIdentifier []int8, value *BACnetTag, priority *BACnetTag) *BACnetConfirmedServiceRequest {
+func NewBACnetConfirmedServiceRequestWriteProperty(objectIdentifier *BACnetComplexTagObjectIdentifier, propertyIdentifier *BACnetComplexTagPropertyIdentifier, arrayIndex *uint32, value *BACnetTag, priority *BACnetTag) *BACnetConfirmedServiceRequest {
 	child := &BACnetConfirmedServiceRequestWriteProperty{
-		ObjectType:                    objectType,
-		ObjectInstanceNumber:          objectInstanceNumber,
-		PropertyIdentifierLength:      propertyIdentifierLength,
+		ObjectIdentifier:              objectIdentifier,
 		PropertyIdentifier:            propertyIdentifier,
+		ArrayIndex:                    arrayIndex,
 		Value:                         value,
 		Priority:                      priority,
 		BACnetConfirmedServiceRequest: NewBACnetConfirmedServiceRequest(),
@@ -105,24 +101,15 @@ func (m *BACnetConfirmedServiceRequestWriteProperty) LengthInBits() uint16 {
 func (m *BACnetConfirmedServiceRequestWriteProperty) LengthInBitsConditional(lastItem bool) uint16 {
 	lengthInBits := uint16(m.ParentLengthInBits())
 
-	// Const Field (objectIdentifierHeader)
-	lengthInBits += 8
-
-	// Simple field (objectType)
-	lengthInBits += 10
-
-	// Simple field (objectInstanceNumber)
-	lengthInBits += 22
-
-	// Const Field (propertyIdentifierHeader)
-	lengthInBits += 5
+	// Simple field (objectIdentifier)
+	lengthInBits += m.ObjectIdentifier.LengthInBits()
 
-	// Simple field (propertyIdentifierLength)
-	lengthInBits += 3
+	// Simple field (propertyIdentifier)
+	lengthInBits += m.PropertyIdentifier.LengthInBits()
 
-	// Array field
-	if len(m.PropertyIdentifier) > 0 {
-		lengthInBits += 8 * uint16(len(m.PropertyIdentifier))
+	// Optional Field (arrayIndex)
+	if m.ArrayIndex != nil {
+		lengthInBits += 32
 	}
 
 	// Const Field (openingTag)
@@ -153,62 +140,40 @@ func BACnetConfirmedServiceRequestWritePropertyParse(readBuffer utils.ReadBuffer
 	var startPos = readBuffer.GetPos()
 	var curPos uint16
 
-	// Const Field (objectIdentifierHeader)
-	objectIdentifierHeader, _objectIdentifierHeaderErr := readBuffer.ReadUint8("objectIdentifierHeader", 8)
-	if _objectIdentifierHeaderErr != nil {
-		return nil, errors.Wrap(_objectIdentifierHeaderErr, "Error parsing 'objectIdentifierHeader' field")
-	}
-	if objectIdentifierHeader != BACnetConfirmedServiceRequestWriteProperty_OBJECTIDENTIFIERHEADER {
-		return nil, errors.New("Expected constant value " + fmt.Sprintf("%d", BACnetConfirmedServiceRequestWriteProperty_OBJECTIDENTIFIERHEADER) + " but got " + fmt.Sprintf("%d", objectIdentifierHeader))
+	// Simple Field (objectIdentifier)
+	if pullErr := readBuffer.PullContext("objectIdentifier"); pullErr != nil {
+		return nil, pullErr
 	}
-
-	// Simple Field (objectType)
-	_objectType, _objectTypeErr := readBuffer.ReadUint16("objectType", 10)
-	if _objectTypeErr != nil {
-		return nil, errors.Wrap(_objectTypeErr, "Error parsing 'objectType' field")
+	_objectIdentifier, _objectIdentifierErr := BACnetComplexTagParse(readBuffer, uint8(0), BACnetDataType_BACNET_OBJECT_IDENTIFIER)
+	if _objectIdentifierErr != nil {
+		return nil, errors.Wrap(_objectIdentifierErr, "Error parsing 'objectIdentifier' field")
 	}
-	objectType := _objectType
-
-	// Simple Field (objectInstanceNumber)
-	_objectInstanceNumber, _objectInstanceNumberErr := readBuffer.ReadUint32("objectInstanceNumber", 22)
-	if _objectInstanceNumberErr != nil {
-		return nil, errors.Wrap(_objectInstanceNumberErr, "Error parsing 'objectInstanceNumber' field")
+	objectIdentifier := CastBACnetComplexTagObjectIdentifier(_objectIdentifier)
+	if closeErr := readBuffer.CloseContext("objectIdentifier"); closeErr != nil {
+		return nil, closeErr
 	}
-	objectInstanceNumber := _objectInstanceNumber
 
-	// Const Field (propertyIdentifierHeader)
-	propertyIdentifierHeader, _propertyIdentifierHeaderErr := readBuffer.ReadUint8("propertyIdentifierHeader", 5)
-	if _propertyIdentifierHeaderErr != nil {
-		return nil, errors.Wrap(_propertyIdentifierHeaderErr, "Error parsing 'propertyIdentifierHeader' field")
+	// Simple Field (propertyIdentifier)
+	if pullErr := readBuffer.PullContext("propertyIdentifier"); pullErr != nil {
+		return nil, pullErr
 	}
-	if propertyIdentifierHeader != BACnetConfirmedServiceRequestWriteProperty_PROPERTYIDENTIFIERHEADER {
-		return nil, errors.New("Expected constant value " + fmt.Sprintf("%d", BACnetConfirmedServiceRequestWriteProperty_PROPERTYIDENTIFIERHEADER) + " but got " + fmt.Sprintf("%d", propertyIdentifierHeader))
+	_propertyIdentifier, _propertyIdentifierErr := BACnetComplexTagParse(readBuffer, uint8(1), BACnetDataType_BACNET_PROPERTY_IDENTIFIER)
+	if _propertyIdentifierErr != nil {
+		return nil, errors.Wrap(_propertyIdentifierErr, "Error parsing 'propertyIdentifier' field")
 	}
-
-	// Simple Field (propertyIdentifierLength)
-	_propertyIdentifierLength, _propertyIdentifierLengthErr := readBuffer.ReadUint8("propertyIdentifierLength", 3)
-	if _propertyIdentifierLengthErr != nil {
-		return nil, errors.Wrap(_propertyIdentifierLengthErr, "Error parsing 'propertyIdentifierLength' field")
+	propertyIdentifier := CastBACnetComplexTagPropertyIdentifier(_propertyIdentifier)
+	if closeErr := readBuffer.CloseContext("propertyIdentifier"); closeErr != nil {
+		return nil, closeErr
 	}
-	propertyIdentifierLength := _propertyIdentifierLength
 
-	// Array field (propertyIdentifier)
-	if pullErr := readBuffer.PullContext("propertyIdentifier", utils.WithRenderAsList(true)); pullErr != nil {
-		return nil, pullErr
-	}
-	// Count array
-	propertyIdentifier := make([]int8, propertyIdentifierLength)
-	{
-		for curItem := uint16(0); curItem < uint16(propertyIdentifierLength); curItem++ {
-			_item, _err := readBuffer.ReadInt8("", 8)
-			if _err != nil {
-				return nil, errors.Wrap(_err, "Error parsing 'propertyIdentifier' field")
-			}
-			propertyIdentifier[curItem] = _item
+	// Optional Field (arrayIndex) (Can be skipped, if a given expression evaluates to false)
+	var arrayIndex *uint32 = nil
+	if bool((propertyIdentifier.Value) == (BACnetPropertyIdentifier_VALUE_SOURCE_ARRAY)) {
+		_val, _err := readBuffer.ReadUint32("arrayIndex", 32)
+		if _err != nil {
+			return nil, errors.Wrap(_err, "Error parsing 'arrayIndex' field")
 		}
-	}
-	if closeErr := readBuffer.CloseContext("propertyIdentifier", utils.WithRenderAsList(true)); closeErr != nil {
-		return nil, closeErr
+		arrayIndex = &_val
 	}
 
 	// Const Field (openingTag)
@@ -270,10 +235,9 @@ func BACnetConfirmedServiceRequestWritePropertyParse(readBuffer utils.ReadBuffer
 
 	// Create a partially initialized instance
 	_child := &BACnetConfirmedServiceRequestWriteProperty{
-		ObjectType:                    objectType,
-		ObjectInstanceNumber:          objectInstanceNumber,
-		PropertyIdentifierLength:      propertyIdentifierLength,
-		PropertyIdentifier:            propertyIdentifier,
+		ObjectIdentifier:              CastBACnetComplexTagObjectIdentifier(objectIdentifier),
+		PropertyIdentifier:            CastBACnetComplexTagPropertyIdentifier(propertyIdentifier),
+		ArrayIndex:                    arrayIndex,
 		Value:                         CastBACnetTag(value),
 		Priority:                      CastBACnetTag(priority),
 		BACnetConfirmedServiceRequest: &BACnetConfirmedServiceRequest{},
@@ -288,52 +252,37 @@ func (m *BACnetConfirmedServiceRequestWriteProperty) Serialize(writeBuffer utils
 			return pushErr
 		}
 
-		// Const Field (objectIdentifierHeader)
-		_objectIdentifierHeaderErr := writeBuffer.WriteUint8("objectIdentifierHeader", 8, 0x0C)
-		if _objectIdentifierHeaderErr != nil {
-			return errors.Wrap(_objectIdentifierHeaderErr, "Error serializing 'objectIdentifierHeader' field")
+		// Simple Field (objectIdentifier)
+		if pushErr := writeBuffer.PushContext("objectIdentifier"); pushErr != nil {
+			return pushErr
 		}
-
-		// Simple Field (objectType)
-		objectType := uint16(m.ObjectType)
-		_objectTypeErr := writeBuffer.WriteUint16("objectType", 10, (objectType))
-		if _objectTypeErr != nil {
-			return errors.Wrap(_objectTypeErr, "Error serializing 'objectType' field")
+		_objectIdentifierErr := m.ObjectIdentifier.Serialize(writeBuffer)
+		if popErr := writeBuffer.PopContext("objectIdentifier"); popErr != nil {
+			return popErr
 		}
-
-		// Simple Field (objectInstanceNumber)
-		objectInstanceNumber := uint32(m.ObjectInstanceNumber)
-		_objectInstanceNumberErr := writeBuffer.WriteUint32("objectInstanceNumber", 22, (objectInstanceNumber))
-		if _objectInstanceNumberErr != nil {
-			return errors.Wrap(_objectInstanceNumberErr, "Error serializing 'objectInstanceNumber' field")
+		if _objectIdentifierErr != nil {
+			return errors.Wrap(_objectIdentifierErr, "Error serializing 'objectIdentifier' field")
 		}
 
-		// Const Field (propertyIdentifierHeader)
-		_propertyIdentifierHeaderErr := writeBuffer.WriteUint8("propertyIdentifierHeader", 5, 0x03)
-		if _propertyIdentifierHeaderErr != nil {
-			return errors.Wrap(_propertyIdentifierHeaderErr, "Error serializing 'propertyIdentifierHeader' field")
+		// Simple Field (propertyIdentifier)
+		if pushErr := writeBuffer.PushContext("propertyIdentifier"); pushErr != nil {
+			return pushErr
 		}
-
-		// Simple Field (propertyIdentifierLength)
-		propertyIdentifierLength := uint8(m.PropertyIdentifierLength)
-		_propertyIdentifierLengthErr := writeBuffer.WriteUint8("propertyIdentifierLength", 3, (propertyIdentifierLength))
-		if _propertyIdentifierLengthErr != nil {
-			return errors.Wrap(_propertyIdentifierLengthErr, "Error serializing 'propertyIdentifierLength' field")
+		_propertyIdentifierErr := m.PropertyIdentifier.Serialize(writeBuffer)
+		if popErr := writeBuffer.PopContext("propertyIdentifier"); popErr != nil {
+			return popErr
+		}
+		if _propertyIdentifierErr != nil {
+			return errors.Wrap(_propertyIdentifierErr, "Error serializing 'propertyIdentifier' field")
 		}
 
-		// Array Field (propertyIdentifier)
-		if m.PropertyIdentifier != nil {
-			if pushErr := writeBuffer.PushContext("propertyIdentifier", utils.WithRenderAsList(true)); pushErr != nil {
-				return pushErr
-			}
-			for _, _element := range m.PropertyIdentifier {
-				_elementErr := writeBuffer.WriteInt8("", 8, _element)
-				if _elementErr != nil {
-					return errors.Wrap(_elementErr, "Error serializing 'propertyIdentifier' field")
-				}
-			}
-			if popErr := writeBuffer.PopContext("propertyIdentifier", utils.WithRenderAsList(true)); popErr != nil {
-				return popErr
+		// Optional Field (arrayIndex) (Can be skipped, if the value is null)
+		var arrayIndex *uint32 = nil
+		if m.ArrayIndex != nil {
+			arrayIndex = m.ArrayIndex
+			_arrayIndexErr := writeBuffer.WriteUint32("arrayIndex", 32, *(arrayIndex))
+			if _arrayIndexErr != nil {
+				return errors.Wrap(_arrayIndexErr, "Error serializing 'arrayIndex' field")
 			}
 		}
 
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetError.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetError.go
index 77a6ffd..20db622 100644
--- a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetError.go
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetError.go
@@ -109,6 +109,8 @@ func BACnetErrorParse(readBuffer utils.ReadBuffer) (*BACnetError, error) {
 	switch {
 	case serviceChoice == 0x03: // BACnetErrorGetAlarmSummary
 		_parent, typeSwitchError = BACnetErrorGetAlarmSummaryParse(readBuffer)
+	case serviceChoice == 0x02: // BACnetErrorConfirmedEventNotification
+		_parent, typeSwitchError = BACnetErrorConfirmedEventNotificationParse(readBuffer)
 	case serviceChoice == 0x04: // BACnetErrorGetEnrollmentSummary
 		_parent, typeSwitchError = BACnetErrorGetEnrollmentSummaryParse(readBuffer)
 	case serviceChoice == 0x1D: // BACnetErrorGetEventInformation
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetErrorConfirmedEventNotification.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetErrorConfirmedEventNotification.go
new file mode 100644
index 0000000..2fe5d79
--- /dev/null
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetErrorConfirmedEventNotification.go
@@ -0,0 +1,196 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package model
+
+import (
+	"github.com/apache/plc4x/plc4go/internal/plc4go/spi/utils"
+	"github.com/pkg/errors"
+)
+
+// Code generated by code-generation. DO NOT EDIT.
+
+// The data-structure of this message
+type BACnetErrorConfirmedEventNotification struct {
+	*BACnetError
+	ErrorClass *BACnetTagApplicationEnumerated
+	ErrorCode  *BACnetTagApplicationEnumerated
+}
+
+// The corresponding interface
+type IBACnetErrorConfirmedEventNotification interface {
+	LengthInBytes() uint16
+	LengthInBits() uint16
+	Serialize(writeBuffer utils.WriteBuffer) error
+}
+
+///////////////////////////////////////////////////////////
+// Accessors for discriminator values.
+///////////////////////////////////////////////////////////
+func (m *BACnetErrorConfirmedEventNotification) ServiceChoice() uint8 {
+	return 0x02
+}
+
+func (m *BACnetErrorConfirmedEventNotification) InitializeParent(parent *BACnetError) {
+}
+
+func NewBACnetErrorConfirmedEventNotification(errorClass *BACnetTagApplicationEnumerated, errorCode *BACnetTagApplicationEnumerated) *BACnetError {
+	child := &BACnetErrorConfirmedEventNotification{
+		ErrorClass:  errorClass,
+		ErrorCode:   errorCode,
+		BACnetError: NewBACnetError(),
+	}
+	child.Child = child
+	return child.BACnetError
+}
+
+func CastBACnetErrorConfirmedEventNotification(structType interface{}) *BACnetErrorConfirmedEventNotification {
+	castFunc := func(typ interface{}) *BACnetErrorConfirmedEventNotification {
+		if casted, ok := typ.(BACnetErrorConfirmedEventNotification); ok {
+			return &casted
+		}
+		if casted, ok := typ.(*BACnetErrorConfirmedEventNotification); ok {
+			return casted
+		}
+		if casted, ok := typ.(BACnetError); ok {
+			return CastBACnetErrorConfirmedEventNotification(casted.Child)
+		}
+		if casted, ok := typ.(*BACnetError); ok {
+			return CastBACnetErrorConfirmedEventNotification(casted.Child)
+		}
+		return nil
+	}
+	return castFunc(structType)
+}
+
+func (m *BACnetErrorConfirmedEventNotification) GetTypeName() string {
+	return "BACnetErrorConfirmedEventNotification"
+}
+
+func (m *BACnetErrorConfirmedEventNotification) LengthInBits() uint16 {
+	return m.LengthInBitsConditional(false)
+}
+
+func (m *BACnetErrorConfirmedEventNotification) LengthInBitsConditional(lastItem bool) uint16 {
+	lengthInBits := uint16(m.ParentLengthInBits())
+
+	// Simple field (errorClass)
+	lengthInBits += m.ErrorClass.LengthInBits()
+
+	// Simple field (errorCode)
+	lengthInBits += m.ErrorCode.LengthInBits()
+
+	return lengthInBits
+}
+
+func (m *BACnetErrorConfirmedEventNotification) LengthInBytes() uint16 {
+	return m.LengthInBits() / 8
+}
+
+func BACnetErrorConfirmedEventNotificationParse(readBuffer utils.ReadBuffer) (*BACnetError, error) {
+	if pullErr := readBuffer.PullContext("BACnetErrorConfirmedEventNotification"); pullErr != nil {
+		return nil, pullErr
+	}
+
+	// Simple Field (errorClass)
+	if pullErr := readBuffer.PullContext("errorClass"); pullErr != nil {
+		return nil, pullErr
+	}
+	_errorClass, _errorClassErr := BACnetTagParse(readBuffer)
+	if _errorClassErr != nil {
+		return nil, errors.Wrap(_errorClassErr, "Error parsing 'errorClass' field")
+	}
+	errorClass := CastBACnetTagApplicationEnumerated(_errorClass)
+	if closeErr := readBuffer.CloseContext("errorClass"); closeErr != nil {
+		return nil, closeErr
+	}
+
+	// Simple Field (errorCode)
+	if pullErr := readBuffer.PullContext("errorCode"); pullErr != nil {
+		return nil, pullErr
+	}
+	_errorCode, _errorCodeErr := BACnetTagParse(readBuffer)
+	if _errorCodeErr != nil {
+		return nil, errors.Wrap(_errorCodeErr, "Error parsing 'errorCode' field")
+	}
+	errorCode := CastBACnetTagApplicationEnumerated(_errorCode)
+	if closeErr := readBuffer.CloseContext("errorCode"); closeErr != nil {
+		return nil, closeErr
+	}
+
+	if closeErr := readBuffer.CloseContext("BACnetErrorConfirmedEventNotification"); closeErr != nil {
+		return nil, closeErr
+	}
+
+	// Create a partially initialized instance
+	_child := &BACnetErrorConfirmedEventNotification{
+		ErrorClass:  CastBACnetTagApplicationEnumerated(errorClass),
+		ErrorCode:   CastBACnetTagApplicationEnumerated(errorCode),
+		BACnetError: &BACnetError{},
+	}
+	_child.BACnetError.Child = _child
+	return _child.BACnetError, nil
+}
+
+func (m *BACnetErrorConfirmedEventNotification) Serialize(writeBuffer utils.WriteBuffer) error {
+	ser := func() error {
+		if pushErr := writeBuffer.PushContext("BACnetErrorConfirmedEventNotification"); pushErr != nil {
+			return pushErr
+		}
+
+		// Simple Field (errorClass)
+		if pushErr := writeBuffer.PushContext("errorClass"); pushErr != nil {
+			return pushErr
+		}
+		_errorClassErr := m.ErrorClass.Serialize(writeBuffer)
+		if popErr := writeBuffer.PopContext("errorClass"); popErr != nil {
+			return popErr
+		}
+		if _errorClassErr != nil {
+			return errors.Wrap(_errorClassErr, "Error serializing 'errorClass' field")
+		}
+
+		// Simple Field (errorCode)
+		if pushErr := writeBuffer.PushContext("errorCode"); pushErr != nil {
+			return pushErr
+		}
+		_errorCodeErr := m.ErrorCode.Serialize(writeBuffer)
+		if popErr := writeBuffer.PopContext("errorCode"); popErr != nil {
+			return popErr
+		}
+		if _errorCodeErr != nil {
+			return errors.Wrap(_errorCodeErr, "Error serializing 'errorCode' field")
+		}
+
+		if popErr := writeBuffer.PopContext("BACnetErrorConfirmedEventNotification"); popErr != nil {
+			return popErr
+		}
+		return nil
+	}
+	return m.SerializeParent(writeBuffer, m, ser)
+}
+
+func (m *BACnetErrorConfirmedEventNotification) String() string {
+	if m == nil {
+		return "<nil>"
+	}
+	buffer := utils.NewBoxedWriteBufferWithOptions(true, true)
+	m.Serialize(buffer)
+	return buffer.GetBox().String()
+}
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetPropertyIdentifier.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetPropertyIdentifier.go
index c2033b9..3914d4d 100644
--- a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetPropertyIdentifier.go
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetPropertyIdentifier.go
@@ -379,6 +379,7 @@ const (
 	BACnetPropertyIdentifier_PROPORTIONAL_CONSTANT               BACnetPropertyIdentifier = 93
 	BACnetPropertyIdentifier_PROPORTIONAL_CONSTANT_UNITS         BACnetPropertyIdentifier = 94
 	BACnetPropertyIdentifier_PROTOCOL_LEVEL                      BACnetPropertyIdentifier = 482
+	BACnetPropertyIdentifier_PROTOCOL_CONFORMANCE_CLASS          BACnetPropertyIdentifier = 95
 	BACnetPropertyIdentifier_PROTOCOL_OBJECT_TYPES_SUPPORTED     BACnetPropertyIdentifier = 96
 	BACnetPropertyIdentifier_PROTOCOL_REVISION                   BACnetPropertyIdentifier = 139
 	BACnetPropertyIdentifier_PROTOCOL_SERVICES_SUPPORTED         BACnetPropertyIdentifier = 97
@@ -489,6 +490,7 @@ const (
 	BACnetPropertyIdentifier_ZONE_FROM                           BACnetPropertyIdentifier = 320
 	BACnetPropertyIdentifier_ZONE_MEMBERS                        BACnetPropertyIdentifier = 165
 	BACnetPropertyIdentifier_ZONE_TO                             BACnetPropertyIdentifier = 321
+	BACnetPropertyIdentifier_VENDOR_PROPRIETARY_VALUE            BACnetPropertyIdentifier = 9999
 )
 
 var BACnetPropertyIdentifierValues []BACnetPropertyIdentifier
@@ -842,6 +844,7 @@ func init() {
 		BACnetPropertyIdentifier_PROPORTIONAL_CONSTANT,
 		BACnetPropertyIdentifier_PROPORTIONAL_CONSTANT_UNITS,
 		BACnetPropertyIdentifier_PROTOCOL_LEVEL,
+		BACnetPropertyIdentifier_PROTOCOL_CONFORMANCE_CLASS,
 		BACnetPropertyIdentifier_PROTOCOL_OBJECT_TYPES_SUPPORTED,
 		BACnetPropertyIdentifier_PROTOCOL_REVISION,
 		BACnetPropertyIdentifier_PROTOCOL_SERVICES_SUPPORTED,
@@ -952,6 +955,7 @@ func init() {
 		BACnetPropertyIdentifier_ZONE_FROM,
 		BACnetPropertyIdentifier_ZONE_MEMBERS,
 		BACnetPropertyIdentifier_ZONE_TO,
+		BACnetPropertyIdentifier_VENDOR_PROPRIETARY_VALUE,
 	}
 }
 
@@ -1861,6 +1865,8 @@ func BACnetPropertyIdentifierByValue(value uint32) BACnetPropertyIdentifier {
 		return BACnetPropertyIdentifier_PROPORTIONAL_CONSTANT
 	case 94:
 		return BACnetPropertyIdentifier_PROPORTIONAL_CONSTANT_UNITS
+	case 95:
+		return BACnetPropertyIdentifier_PROTOCOL_CONFORMANCE_CLASS
 	case 96:
 		return BACnetPropertyIdentifier_PROTOCOL_OBJECT_TYPES_SUPPORTED
 	case 97:
@@ -1869,6 +1875,8 @@ func BACnetPropertyIdentifierByValue(value uint32) BACnetPropertyIdentifier {
 		return BACnetPropertyIdentifier_PROTOCOL_VERSION
 	case 99:
 		return BACnetPropertyIdentifier_READ_ONLY
+	case 9999:
+		return BACnetPropertyIdentifier_VENDOR_PROPRIETARY_VALUE
 	}
 	return 0
 }
@@ -2779,6 +2787,8 @@ func BACnetPropertyIdentifierByName(value string) BACnetPropertyIdentifier {
 		return BACnetPropertyIdentifier_PROPORTIONAL_CONSTANT
 	case "PROPORTIONAL_CONSTANT_UNITS":
 		return BACnetPropertyIdentifier_PROPORTIONAL_CONSTANT_UNITS
+	case "PROTOCOL_CONFORMANCE_CLASS":
+		return BACnetPropertyIdentifier_PROTOCOL_CONFORMANCE_CLASS
 	case "PROTOCOL_OBJECT_TYPES_SUPPORTED":
 		return BACnetPropertyIdentifier_PROTOCOL_OBJECT_TYPES_SUPPORTED
 	case "PROTOCOL_SERVICES_SUPPORTED":
@@ -2787,6 +2797,8 @@ func BACnetPropertyIdentifierByName(value string) BACnetPropertyIdentifier {
 		return BACnetPropertyIdentifier_PROTOCOL_VERSION
 	case "READ_ONLY":
 		return BACnetPropertyIdentifier_READ_ONLY
+	case "VENDOR_PROPRIETARY_VALUE":
+		return BACnetPropertyIdentifier_VENDOR_PROPRIETARY_VALUE
 	}
 	return 0
 }
@@ -3727,6 +3739,8 @@ func (e BACnetPropertyIdentifier) name() string {
 		return "PROPORTIONAL_CONSTANT"
 	case BACnetPropertyIdentifier_PROPORTIONAL_CONSTANT_UNITS:
 		return "PROPORTIONAL_CONSTANT_UNITS"
+	case BACnetPropertyIdentifier_PROTOCOL_CONFORMANCE_CLASS:
+		return "PROTOCOL_CONFORMANCE_CLASS"
 	case BACnetPropertyIdentifier_PROTOCOL_OBJECT_TYPES_SUPPORTED:
 		return "PROTOCOL_OBJECT_TYPES_SUPPORTED"
 	case BACnetPropertyIdentifier_PROTOCOL_SERVICES_SUPPORTED:
@@ -3735,6 +3749,8 @@ func (e BACnetPropertyIdentifier) name() string {
 		return "PROTOCOL_VERSION"
 	case BACnetPropertyIdentifier_READ_ONLY:
 		return "READ_ONLY"
+	case BACnetPropertyIdentifier_VENDOR_PROPRIETARY_VALUE:
+		return "VENDOR_PROPRIETARY_VALUE"
 	}
 	return ""
 }
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetServiceAckAtomicWriteFile.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetServiceAckAtomicWriteFile.go
index d74a053..505340d 100644
--- a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetServiceAckAtomicWriteFile.go
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetServiceAckAtomicWriteFile.go
@@ -21,6 +21,7 @@ package model
 
 import (
 	"github.com/apache/plc4x/plc4go/internal/plc4go/spi/utils"
+	"github.com/pkg/errors"
 )
 
 // Code generated by code-generation. DO NOT EDIT.
@@ -28,6 +29,7 @@ import (
 // The data-structure of this message
 type BACnetServiceAckAtomicWriteFile struct {
 	*BACnetServiceAck
+	FileStartPosition *BACnetComplexTagSignedInteger
 }
 
 // The corresponding interface
@@ -47,9 +49,10 @@ func (m *BACnetServiceAckAtomicWriteFile) ServiceChoice() uint8 {
 func (m *BACnetServiceAckAtomicWriteFile) InitializeParent(parent *BACnetServiceAck) {
 }
 
-func NewBACnetServiceAckAtomicWriteFile() *BACnetServiceAck {
+func NewBACnetServiceAckAtomicWriteFile(fileStartPosition *BACnetComplexTagSignedInteger) *BACnetServiceAck {
 	child := &BACnetServiceAckAtomicWriteFile{
-		BACnetServiceAck: NewBACnetServiceAck(),
+		FileStartPosition: fileStartPosition,
+		BACnetServiceAck:  NewBACnetServiceAck(),
 	}
 	child.Child = child
 	return child.BACnetServiceAck
@@ -85,6 +88,9 @@ func (m *BACnetServiceAckAtomicWriteFile) LengthInBits() uint16 {
 func (m *BACnetServiceAckAtomicWriteFile) LengthInBitsConditional(lastItem bool) uint16 {
 	lengthInBits := uint16(m.ParentLengthInBits())
 
+	// Simple field (fileStartPosition)
+	lengthInBits += m.FileStartPosition.LengthInBits()
+
 	return lengthInBits
 }
 
@@ -97,13 +103,27 @@ func BACnetServiceAckAtomicWriteFileParse(readBuffer utils.ReadBuffer) (*BACnetS
 		return nil, pullErr
 	}
 
+	// Simple Field (fileStartPosition)
+	if pullErr := readBuffer.PullContext("fileStartPosition"); pullErr != nil {
+		return nil, pullErr
+	}
+	_fileStartPosition, _fileStartPositionErr := BACnetComplexTagParse(readBuffer, uint8(0), BACnetDataType_SIGNED_INTEGER)
+	if _fileStartPositionErr != nil {
+		return nil, errors.Wrap(_fileStartPositionErr, "Error parsing 'fileStartPosition' field")
+	}
+	fileStartPosition := CastBACnetComplexTagSignedInteger(_fileStartPosition)
+	if closeErr := readBuffer.CloseContext("fileStartPosition"); closeErr != nil {
+		return nil, closeErr
+	}
+
 	if closeErr := readBuffer.CloseContext("BACnetServiceAckAtomicWriteFile"); closeErr != nil {
 		return nil, closeErr
 	}
 
 	// Create a partially initialized instance
 	_child := &BACnetServiceAckAtomicWriteFile{
-		BACnetServiceAck: &BACnetServiceAck{},
+		FileStartPosition: CastBACnetComplexTagSignedInteger(fileStartPosition),
+		BACnetServiceAck:  &BACnetServiceAck{},
 	}
 	_child.BACnetServiceAck.Child = _child
 	return _child.BACnetServiceAck, nil
@@ -115,6 +135,18 @@ func (m *BACnetServiceAckAtomicWriteFile) Serialize(writeBuffer utils.WriteBuffe
 			return pushErr
 		}
 
+		// Simple Field (fileStartPosition)
+		if pushErr := writeBuffer.PushContext("fileStartPosition"); pushErr != nil {
+			return pushErr
+		}
+		_fileStartPositionErr := m.FileStartPosition.Serialize(writeBuffer)
+		if popErr := writeBuffer.PopContext("fileStartPosition"); popErr != nil {
+			return popErr
+		}
+		if _fileStartPositionErr != nil {
+			return errors.Wrap(_fileStartPositionErr, "Error serializing 'fileStartPosition' field")
+		}
+
 		if popErr := writeBuffer.PopContext("BACnetServiceAckAtomicWriteFile"); popErr != nil {
 			return popErr
 		}
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetServiceAckReadProperty.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetServiceAckReadProperty.go
index 7530cd7..2ef3171 100644
--- a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetServiceAckReadProperty.go
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetServiceAckReadProperty.go
@@ -20,27 +20,18 @@
 package model
 
 import (
-	"fmt"
 	"github.com/apache/plc4x/plc4go/internal/plc4go/spi/utils"
 	"github.com/pkg/errors"
 )
 
 // Code generated by code-generation. DO NOT EDIT.
 
-// Constant values.
-const BACnetServiceAckReadProperty_OBJECTIDENTIFIERHEADER uint8 = 0x0C
-const BACnetServiceAckReadProperty_PROPERTYIDENTIFIERHEADER uint8 = 0x03
-const BACnetServiceAckReadProperty_OPENINGTAG uint8 = 0x3E
-const BACnetServiceAckReadProperty_CLOSINGTAG uint8 = 0x3F
-
 // The data-structure of this message
 type BACnetServiceAckReadProperty struct {
 	*BACnetServiceAck
-	ObjectType               uint16
-	ObjectInstanceNumber     uint32
-	PropertyIdentifierLength uint8
-	PropertyIdentifier       []int8
-	Value                    *BACnetTag
+	ObjectIdentifier   *BACnetComplexTagObjectIdentifier
+	PropertyIdentifier *BACnetComplexTagPropertyIdentifier
+	ArrayIndex         *uint32
 }
 
 // The corresponding interface
@@ -60,14 +51,12 @@ func (m *BACnetServiceAckReadProperty) ServiceChoice() uint8 {
 func (m *BACnetServiceAckReadProperty) InitializeParent(parent *BACnetServiceAck) {
 }
 
-func NewBACnetServiceAckReadProperty(objectType uint16, objectInstanceNumber uint32, propertyIdentifierLength uint8, propertyIdentifier []int8, value *BACnetTag) *BACnetServiceAck {
+func NewBACnetServiceAckReadProperty(objectIdentifier *BACnetComplexTagObjectIdentifier, propertyIdentifier *BACnetComplexTagPropertyIdentifier, arrayIndex *uint32) *BACnetServiceAck {
 	child := &BACnetServiceAckReadProperty{
-		ObjectType:               objectType,
-		ObjectInstanceNumber:     objectInstanceNumber,
-		PropertyIdentifierLength: propertyIdentifierLength,
-		PropertyIdentifier:       propertyIdentifier,
-		Value:                    value,
-		BACnetServiceAck:         NewBACnetServiceAck(),
+		ObjectIdentifier:   objectIdentifier,
+		PropertyIdentifier: propertyIdentifier,
+		ArrayIndex:         arrayIndex,
+		BACnetServiceAck:   NewBACnetServiceAck(),
 	}
 	child.Child = child
 	return child.BACnetServiceAck
@@ -103,35 +92,17 @@ func (m *BACnetServiceAckReadProperty) LengthInBits() uint16 {
 func (m *BACnetServiceAckReadProperty) LengthInBitsConditional(lastItem bool) uint16 {
 	lengthInBits := uint16(m.ParentLengthInBits())
 
-	// Const Field (objectIdentifierHeader)
-	lengthInBits += 8
-
-	// Simple field (objectType)
-	lengthInBits += 10
-
-	// Simple field (objectInstanceNumber)
-	lengthInBits += 22
+	// Simple field (objectIdentifier)
+	lengthInBits += m.ObjectIdentifier.LengthInBits()
 
-	// Const Field (propertyIdentifierHeader)
-	lengthInBits += 5
+	// Simple field (propertyIdentifier)
+	lengthInBits += m.PropertyIdentifier.LengthInBits()
 
-	// Simple field (propertyIdentifierLength)
-	lengthInBits += 3
-
-	// Array field
-	if len(m.PropertyIdentifier) > 0 {
-		lengthInBits += 8 * uint16(len(m.PropertyIdentifier))
+	// Optional Field (arrayIndex)
+	if m.ArrayIndex != nil {
+		lengthInBits += 32
 	}
 
-	// Const Field (openingTag)
-	lengthInBits += 8
-
-	// Simple field (value)
-	lengthInBits += m.Value.LengthInBits()
-
-	// Const Field (closingTag)
-	lengthInBits += 8
-
 	return lengthInBits
 }
 
@@ -144,93 +115,40 @@ func BACnetServiceAckReadPropertyParse(readBuffer utils.ReadBuffer) (*BACnetServ
 		return nil, pullErr
 	}
 
-	// Const Field (objectIdentifierHeader)
-	objectIdentifierHeader, _objectIdentifierHeaderErr := readBuffer.ReadUint8("objectIdentifierHeader", 8)
-	if _objectIdentifierHeaderErr != nil {
-		return nil, errors.Wrap(_objectIdentifierHeaderErr, "Error parsing 'objectIdentifierHeader' field")
-	}
-	if objectIdentifierHeader != BACnetServiceAckReadProperty_OBJECTIDENTIFIERHEADER {
-		return nil, errors.New("Expected constant value " + fmt.Sprintf("%d", BACnetServiceAckReadProperty_OBJECTIDENTIFIERHEADER) + " but got " + fmt.Sprintf("%d", objectIdentifierHeader))
-	}
-
-	// Simple Field (objectType)
-	_objectType, _objectTypeErr := readBuffer.ReadUint16("objectType", 10)
-	if _objectTypeErr != nil {
-		return nil, errors.Wrap(_objectTypeErr, "Error parsing 'objectType' field")
-	}
-	objectType := _objectType
-
-	// Simple Field (objectInstanceNumber)
-	_objectInstanceNumber, _objectInstanceNumberErr := readBuffer.ReadUint32("objectInstanceNumber", 22)
-	if _objectInstanceNumberErr != nil {
-		return nil, errors.Wrap(_objectInstanceNumberErr, "Error parsing 'objectInstanceNumber' field")
-	}
-	objectInstanceNumber := _objectInstanceNumber
-
-	// Const Field (propertyIdentifierHeader)
-	propertyIdentifierHeader, _propertyIdentifierHeaderErr := readBuffer.ReadUint8("propertyIdentifierHeader", 5)
-	if _propertyIdentifierHeaderErr != nil {
-		return nil, errors.Wrap(_propertyIdentifierHeaderErr, "Error parsing 'propertyIdentifierHeader' field")
-	}
-	if propertyIdentifierHeader != BACnetServiceAckReadProperty_PROPERTYIDENTIFIERHEADER {
-		return nil, errors.New("Expected constant value " + fmt.Sprintf("%d", BACnetServiceAckReadProperty_PROPERTYIDENTIFIERHEADER) + " but got " + fmt.Sprintf("%d", propertyIdentifierHeader))
-	}
-
-	// Simple Field (propertyIdentifierLength)
-	_propertyIdentifierLength, _propertyIdentifierLengthErr := readBuffer.ReadUint8("propertyIdentifierLength", 3)
-	if _propertyIdentifierLengthErr != nil {
-		return nil, errors.Wrap(_propertyIdentifierLengthErr, "Error parsing 'propertyIdentifierLength' field")
-	}
-	propertyIdentifierLength := _propertyIdentifierLength
-
-	// Array field (propertyIdentifier)
-	if pullErr := readBuffer.PullContext("propertyIdentifier", utils.WithRenderAsList(true)); pullErr != nil {
+	// Simple Field (objectIdentifier)
+	if pullErr := readBuffer.PullContext("objectIdentifier"); pullErr != nil {
 		return nil, pullErr
 	}
-	// Count array
-	propertyIdentifier := make([]int8, propertyIdentifierLength)
-	{
-		for curItem := uint16(0); curItem < uint16(propertyIdentifierLength); curItem++ {
-			_item, _err := readBuffer.ReadInt8("", 8)
-			if _err != nil {
-				return nil, errors.Wrap(_err, "Error parsing 'propertyIdentifier' field")
-			}
-			propertyIdentifier[curItem] = _item
-		}
+	_objectIdentifier, _objectIdentifierErr := BACnetComplexTagParse(readBuffer, uint8(0), BACnetDataType_BACNET_OBJECT_IDENTIFIER)
+	if _objectIdentifierErr != nil {
+		return nil, errors.Wrap(_objectIdentifierErr, "Error parsing 'objectIdentifier' field")
 	}
-	if closeErr := readBuffer.CloseContext("propertyIdentifier", utils.WithRenderAsList(true)); closeErr != nil {
+	objectIdentifier := CastBACnetComplexTagObjectIdentifier(_objectIdentifier)
+	if closeErr := readBuffer.CloseContext("objectIdentifier"); closeErr != nil {
 		return nil, closeErr
 	}
 
-	// Const Field (openingTag)
-	openingTag, _openingTagErr := readBuffer.ReadUint8("openingTag", 8)
-	if _openingTagErr != nil {
-		return nil, errors.Wrap(_openingTagErr, "Error parsing 'openingTag' field")
-	}
-	if openingTag != BACnetServiceAckReadProperty_OPENINGTAG {
-		return nil, errors.New("Expected constant value " + fmt.Sprintf("%d", BACnetServiceAckReadProperty_OPENINGTAG) + " but got " + fmt.Sprintf("%d", openingTag))
-	}
-
-	// Simple Field (value)
-	if pullErr := readBuffer.PullContext("value"); pullErr != nil {
+	// Simple Field (propertyIdentifier)
+	if pullErr := readBuffer.PullContext("propertyIdentifier"); pullErr != nil {
 		return nil, pullErr
 	}
-	_value, _valueErr := BACnetTagParse(readBuffer)
-	if _valueErr != nil {
-		return nil, errors.Wrap(_valueErr, "Error parsing 'value' field")
+	_propertyIdentifier, _propertyIdentifierErr := BACnetComplexTagParse(readBuffer, uint8(1), BACnetDataType_BACNET_PROPERTY_IDENTIFIER)
+	if _propertyIdentifierErr != nil {
+		return nil, errors.Wrap(_propertyIdentifierErr, "Error parsing 'propertyIdentifier' field")
 	}
-	value := CastBACnetTag(_value)
-	if closeErr := readBuffer.CloseContext("value"); closeErr != nil {
+	propertyIdentifier := CastBACnetComplexTagPropertyIdentifier(_propertyIdentifier)
+	if closeErr := readBuffer.CloseContext("propertyIdentifier"); closeErr != nil {
 		return nil, closeErr
 	}
 
-	// Const Field (closingTag)
-	closingTag, _closingTagErr := readBuffer.ReadUint8("closingTag", 8)
-	if _closingTagErr != nil {
-		return nil, errors.Wrap(_closingTagErr, "Error parsing 'closingTag' field")
-	}
-	if closingTag != BACnetServiceAckReadProperty_CLOSINGTAG {
-		return nil, errors.New("Expected constant value " + fmt.Sprintf("%d", BACnetServiceAckReadProperty_CLOSINGTAG) + " but got " + fmt.Sprintf("%d", closingTag))
+	// Optional Field (arrayIndex) (Can be skipped, if a given expression evaluates to false)
+	var arrayIndex *uint32 = nil
+	if bool((propertyIdentifier.Value) == (BACnetPropertyIdentifier_VALUE_SOURCE_ARRAY)) {
+		_val, _err := readBuffer.ReadUint32("arrayIndex", 32)
+		if _err != nil {
+			return nil, errors.Wrap(_err, "Error parsing 'arrayIndex' field")
+		}
+		arrayIndex = &_val
 	}
 
 	if closeErr := readBuffer.CloseContext("BACnetServiceAckReadProperty"); closeErr != nil {
@@ -239,12 +157,10 @@ func BACnetServiceAckReadPropertyParse(readBuffer utils.ReadBuffer) (*BACnetServ
 
 	// Create a partially initialized instance
 	_child := &BACnetServiceAckReadProperty{
-		ObjectType:               objectType,
-		ObjectInstanceNumber:     objectInstanceNumber,
-		PropertyIdentifierLength: propertyIdentifierLength,
-		PropertyIdentifier:       propertyIdentifier,
-		Value:                    CastBACnetTag(value),
-		BACnetServiceAck:         &BACnetServiceAck{},
+		ObjectIdentifier:   CastBACnetComplexTagObjectIdentifier(objectIdentifier),
+		PropertyIdentifier: CastBACnetComplexTagPropertyIdentifier(propertyIdentifier),
+		ArrayIndex:         arrayIndex,
+		BACnetServiceAck:   &BACnetServiceAck{},
 	}
 	_child.BACnetServiceAck.Child = _child
 	return _child.BACnetServiceAck, nil
@@ -256,77 +172,38 @@ func (m *BACnetServiceAckReadProperty) Serialize(writeBuffer utils.WriteBuffer)
 			return pushErr
 		}
 
-		// Const Field (objectIdentifierHeader)
-		_objectIdentifierHeaderErr := writeBuffer.WriteUint8("objectIdentifierHeader", 8, 0x0C)
-		if _objectIdentifierHeaderErr != nil {
-			return errors.Wrap(_objectIdentifierHeaderErr, "Error serializing 'objectIdentifierHeader' field")
-		}
-
-		// Simple Field (objectType)
-		objectType := uint16(m.ObjectType)
-		_objectTypeErr := writeBuffer.WriteUint16("objectType", 10, (objectType))
-		if _objectTypeErr != nil {
-			return errors.Wrap(_objectTypeErr, "Error serializing 'objectType' field")
-		}
-
-		// Simple Field (objectInstanceNumber)
-		objectInstanceNumber := uint32(m.ObjectInstanceNumber)
-		_objectInstanceNumberErr := writeBuffer.WriteUint32("objectInstanceNumber", 22, (objectInstanceNumber))
-		if _objectInstanceNumberErr != nil {
-			return errors.Wrap(_objectInstanceNumberErr, "Error serializing 'objectInstanceNumber' field")
-		}
-
-		// Const Field (propertyIdentifierHeader)
-		_propertyIdentifierHeaderErr := writeBuffer.WriteUint8("propertyIdentifierHeader", 5, 0x03)
-		if _propertyIdentifierHeaderErr != nil {
-			return errors.Wrap(_propertyIdentifierHeaderErr, "Error serializing 'propertyIdentifierHeader' field")
-		}
-
-		// Simple Field (propertyIdentifierLength)
-		propertyIdentifierLength := uint8(m.PropertyIdentifierLength)
-		_propertyIdentifierLengthErr := writeBuffer.WriteUint8("propertyIdentifierLength", 3, (propertyIdentifierLength))
-		if _propertyIdentifierLengthErr != nil {
-			return errors.Wrap(_propertyIdentifierLengthErr, "Error serializing 'propertyIdentifierLength' field")
+		// Simple Field (objectIdentifier)
+		if pushErr := writeBuffer.PushContext("objectIdentifier"); pushErr != nil {
+			return pushErr
 		}
-
-		// Array Field (propertyIdentifier)
-		if m.PropertyIdentifier != nil {
-			if pushErr := writeBuffer.PushContext("propertyIdentifier", utils.WithRenderAsList(true)); pushErr != nil {
-				return pushErr
-			}
-			for _, _element := range m.PropertyIdentifier {
-				_elementErr := writeBuffer.WriteInt8("", 8, _element)
-				if _elementErr != nil {
-					return errors.Wrap(_elementErr, "Error serializing 'propertyIdentifier' field")
-				}
-			}
-			if popErr := writeBuffer.PopContext("propertyIdentifier", utils.WithRenderAsList(true)); popErr != nil {
-				return popErr
-			}
+		_objectIdentifierErr := m.ObjectIdentifier.Serialize(writeBuffer)
+		if popErr := writeBuffer.PopContext("objectIdentifier"); popErr != nil {
+			return popErr
 		}
-
-		// Const Field (openingTag)
-		_openingTagErr := writeBuffer.WriteUint8("openingTag", 8, 0x3E)
-		if _openingTagErr != nil {
-			return errors.Wrap(_openingTagErr, "Error serializing 'openingTag' field")
+		if _objectIdentifierErr != nil {
+			return errors.Wrap(_objectIdentifierErr, "Error serializing 'objectIdentifier' field")
 		}
 
-		// Simple Field (value)
-		if pushErr := writeBuffer.PushContext("value"); pushErr != nil {
+		// Simple Field (propertyIdentifier)
+		if pushErr := writeBuffer.PushContext("propertyIdentifier"); pushErr != nil {
 			return pushErr
 		}
-		_valueErr := m.Value.Serialize(writeBuffer)
-		if popErr := writeBuffer.PopContext("value"); popErr != nil {
+		_propertyIdentifierErr := m.PropertyIdentifier.Serialize(writeBuffer)
+		if popErr := writeBuffer.PopContext("propertyIdentifier"); popErr != nil {
 			return popErr
 		}
-		if _valueErr != nil {
-			return errors.Wrap(_valueErr, "Error serializing 'value' field")
+		if _propertyIdentifierErr != nil {
+			return errors.Wrap(_propertyIdentifierErr, "Error serializing 'propertyIdentifier' field")
 		}
 
-		// Const Field (closingTag)
-		_closingTagErr := writeBuffer.WriteUint8("closingTag", 8, 0x3F)
-		if _closingTagErr != nil {
-			return errors.Wrap(_closingTagErr, "Error serializing 'closingTag' field")
+		// Optional Field (arrayIndex) (Can be skipped, if the value is null)
+		var arrayIndex *uint32 = nil
+		if m.ArrayIndex != nil {
+			arrayIndex = m.ArrayIndex
+			_arrayIndexErr := writeBuffer.WriteUint32("arrayIndex", 32, *(arrayIndex))
+			if _arrayIndexErr != nil {
+				return errors.Wrap(_arrayIndexErr, "Error serializing 'arrayIndex' field")
+			}
 		}
 
 		if popErr := writeBuffer.PopContext("BACnetServiceAckReadProperty"); popErr != nil {
diff --git a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequestWhoHas.go b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequestWhoHas.go
index c4dd879..1511b38 100644
--- a/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequestWhoHas.go
+++ b/plc4go/internal/plc4go/bacnetip/readwrite/model/BACnetUnconfirmedServiceRequestWhoHas.go
@@ -31,7 +31,7 @@ type BACnetUnconfirmedServiceRequestWhoHas struct {
 	*BACnetUnconfirmedServiceRequest
 	DeviceInstanceRangeLowLimit  *BACnetComplexTagUnsignedInteger
 	DeviceInstanceRangeHighLimit *BACnetComplexTagUnsignedInteger
-	ObjectIdentifier             *BACnetComplexTagOctetString
+	ObjectIdentifier             *BACnetComplexTagObjectIdentifier
 	ObjectName                   *BACnetComplexTagOctetString
 }
 
@@ -52,7 +52,7 @@ func (m *BACnetUnconfirmedServiceRequestWhoHas) ServiceChoice() uint8 {
 func (m *BACnetUnconfirmedServiceRequestWhoHas) InitializeParent(parent *BACnetUnconfirmedServiceRequest) {
 }
 
-func NewBACnetUnconfirmedServiceRequestWhoHas(deviceInstanceRangeLowLimit *BACnetComplexTagUnsignedInteger, deviceInstanceRangeHighLimit *BACnetComplexTagUnsignedInteger, objectIdentifier *BACnetComplexTagOctetString, objectName *BACnetComplexTagOctetString) *BACnetUnconfirmedServiceRequest {
+func NewBACnetUnconfirmedServiceRequestWhoHas(deviceInstanceRangeLowLimit *BACnetComplexTagUnsignedInteger, deviceInstanceRangeHighLimit *BACnetComplexTagUnsignedInteger, objectIdentifier *BACnetComplexTagObjectIdentifier, objectName *BACnetComplexTagOctetString) *BACnetUnconfirmedServiceRequest {
 	child := &BACnetUnconfirmedServiceRequestWhoHas{
 		DeviceInstanceRangeLowLimit:     deviceInstanceRangeLowLimit,
 		DeviceInstanceRangeHighLimit:    deviceInstanceRangeHighLimit,
@@ -169,20 +169,20 @@ func BACnetUnconfirmedServiceRequestWhoHasParse(readBuffer utils.ReadBuffer, len
 	}
 
 	// Optional Field (objectIdentifier) (Can be skipped, if a given expression evaluates to false)
-	var objectIdentifier *BACnetComplexTagOctetString = nil
+	var objectIdentifier *BACnetComplexTagObjectIdentifier = nil
 	{
 		currentPos := readBuffer.GetPos()
 		if pullErr := readBuffer.PullContext("objectIdentifier"); pullErr != nil {
 			return nil, pullErr
 		}
-		_val, _err := BACnetComplexTagParse(readBuffer, uint8(2), BACnetDataType_OCTET_STRING)
+		_val, _err := BACnetComplexTagParse(readBuffer, uint8(2), BACnetDataType_BACNET_OBJECT_IDENTIFIER)
 		switch {
 		case _err != nil && _err != utils.ParseAssertError:
 			return nil, errors.Wrap(_err, "Error parsing 'objectIdentifier' field")
 		case _err == utils.ParseAssertError:
 			readBuffer.SetPos(currentPos)
 		default:
-			objectIdentifier = CastBACnetComplexTagOctetString(_val)
+			objectIdentifier = CastBACnetComplexTagObjectIdentifier(_val)
 			if closeErr := readBuffer.CloseContext("objectIdentifier"); closeErr != nil {
 				return nil, closeErr
 			}
@@ -218,7 +218,7 @@ func BACnetUnconfirmedServiceRequestWhoHasParse(readBuffer utils.ReadBuffer, len
 	_child := &BACnetUnconfirmedServiceRequestWhoHas{
 		DeviceInstanceRangeLowLimit:     CastBACnetComplexTagUnsignedInteger(deviceInstanceRangeLowLimit),
 		DeviceInstanceRangeHighLimit:    CastBACnetComplexTagUnsignedInteger(deviceInstanceRangeHighLimit),
-		ObjectIdentifier:                CastBACnetComplexTagOctetString(objectIdentifier),
+		ObjectIdentifier:                CastBACnetComplexTagObjectIdentifier(objectIdentifier),
 		ObjectName:                      CastBACnetComplexTagOctetString(objectName),
 		BACnetUnconfirmedServiceRequest: &BACnetUnconfirmedServiceRequest{},
 	}
@@ -265,7 +265,7 @@ func (m *BACnetUnconfirmedServiceRequestWhoHas) Serialize(writeBuffer utils.Writ
 		}
 
 		// Optional Field (objectIdentifier) (Can be skipped, if the value is null)
-		var objectIdentifier *BACnetComplexTagOctetString = nil
+		var objectIdentifier *BACnetComplexTagObjectIdentifier = nil
 		if m.ObjectIdentifier != nil {
 			if pushErr := writeBuffer.PushContext("objectIdentifier"); pushErr != nil {
 				return pushErr
diff --git a/protocols/bacnetip/src/main/resources/protocols/bacnetip/bacnetip.mspec b/protocols/bacnetip/src/main/resources/protocols/bacnetip/bacnetip.mspec
index 3fa2240..05ab170 100644
--- a/protocols/bacnetip/src/main/resources/protocols/bacnetip/bacnetip.mspec
+++ b/protocols/bacnetip/src/main/resources/protocols/bacnetip/bacnetip.mspec
@@ -305,10 +305,10 @@
             [simple BACnetTagApplicationTime synchronizedTime]
         ]
         ['0x07' BACnetUnconfirmedServiceRequestWhoHas
-            [optional BACnetComplexTagUnsignedInteger('0', 'BACnetDataType.UNSIGNED_INTEGER')   deviceInstanceRangeLowLimit                                         ]
-            [optional BACnetComplexTagUnsignedInteger('1', 'BACnetDataType.UNSIGNED_INTEGER')   deviceInstanceRangeHighLimit  'deviceInstanceRangeLowLimit != null' ]
-            [optional BACnetComplexTagOctetString('2', 'BACnetDataType.OCTET_STRING')           objectIdentifier                                                    ]
-            [optional BACnetComplexTagOctetString('3', 'BACnetDataType.OCTET_STRING')           objectName                    'objectIdentifier == null'            ]
+            [optional BACnetComplexTagUnsignedInteger('0', 'BACnetDataType.UNSIGNED_INTEGER')           deviceInstanceRangeLowLimit                                         ]
+            [optional BACnetComplexTagUnsignedInteger('1', 'BACnetDataType.UNSIGNED_INTEGER')           deviceInstanceRangeHighLimit  'deviceInstanceRangeLowLimit != null' ]
+            [optional BACnetComplexTagObjectIdentifier('2', 'BACnetDataType.BACNET_OBJECT_IDENTIFIER')  objectIdentifier                                                    ]
+            [optional BACnetComplexTagOctetString('3', 'BACnetDataType.OCTET_STRING')                   objectName                    'objectIdentifier == null'            ]
         ]
         ['0x08' BACnetUnconfirmedServiceRequestWhoIs
             [optional BACnetComplexTagUnsignedInteger('0', 'BACnetDataType.UNSIGNED_INTEGER')   deviceInstanceRangeLowLimit                                         ]
@@ -340,7 +340,7 @@
 
         ]
         ['0x07' BACnetServiceAckAtomicWriteFile
-
+            [simple BACnetComplexTagSignedInteger('0', 'BACnetDataType.SIGNED_INTEGER') fileStartPosition]
         ]
 
         ['0x0A' BACnetServiceAckCreateObject
diff --git a/sandbox/test-java-bacnetip-driver/src/test/java/org/apache/plc4x/java/bacnetip/RandomPackagesTest.java b/sandbox/test-java-bacnetip-driver/src/test/java/org/apache/plc4x/java/bacnetip/RandomPackagesTest.java
index 32409c3..c42f61f 100644
--- a/sandbox/test-java-bacnetip-driver/src/test/java/org/apache/plc4x/java/bacnetip/RandomPackagesTest.java
+++ b/sandbox/test-java-bacnetip-driver/src/test/java/org/apache/plc4x/java/bacnetip/RandomPackagesTest.java
@@ -43,9 +43,7 @@ import java.io.File;
 import java.io.IOException;
 import java.net.URL;
 import java.nio.file.FileSystems;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Queue;
+import java.util.*;
 import java.util.concurrent.ConcurrentLinkedDeque;
 import java.util.stream.IntStream;
 
@@ -57,6 +55,8 @@ public class RandomPackagesTest {
 
     @BeforeAll
     static void setUp() {
+        // TODO: for mac only don't commit
+        System.getProperties().setProperty("jna.library.path", "/usr/local/Cellar/libpcap//1.10.1/lib");
         assumeTrue(() -> {
             try {
                 String version = Pcaps.libVersion();
@@ -4733,24 +4733,165 @@ public class RandomPackagesTest {
 
     @TestFactory
     @DisplayName("who-has")
-    Collection<DynamicTest> who_has() throws Exception {
+    Collection<DynamicNode> who_has() throws Exception {
         PCAPEvaluator pcapEvaluator = pcapEvaluator("who-has.cap");
         return Arrays.asList(
-            DynamicTest.dynamicTest("TODO",
+            DynamicTest.dynamicTest("Unconfirmed-REQ who-Is 133 133",
                 () -> {
-                    BVLC bvlc;
-                    bvlc = pcapEvaluator.nextBVLC();
+                    BVLC bvlc = pcapEvaluator.nextBVLC();
                     dump(bvlc);
-                    // TODO:
-                    assumeTrue(false, "not properly implemented. Check manually and add asserts");
+                    BVLCOriginalBroadcastNPDU bvlcOriginalBroadcastNPDU = (BVLCOriginalBroadcastNPDU) bvlc;
+                    APDUUnconfirmedRequest apduUnconfirmedRequest = (APDUUnconfirmedRequest) bvlcOriginalBroadcastNPDU.getNpdu().getApdu();
+                    BACnetUnconfirmedServiceRequestWhoIs baCnetUnconfirmedServiceRequestWhoIs = (BACnetUnconfirmedServiceRequestWhoIs) apduUnconfirmedRequest.getServiceRequest();
+                    assertEquals(133, baCnetUnconfirmedServiceRequestWhoIs.getDeviceInstanceRangeLowLimit().getActualValue());
+                    assertEquals(133, baCnetUnconfirmedServiceRequestWhoIs.getDeviceInstanceRangeLowLimit().getActualValue());
                 }),
-            DynamicTest.dynamicTest("TODO",
+            DynamicTest.dynamicTest("Unconfirmed-REQ who-Has device,133",
                 () -> {
-                    BVLC bvlc;
-                    bvlc = pcapEvaluator.nextBVLC();
+                    BVLC bvlc = pcapEvaluator.nextBVLC();
                     dump(bvlc);
-                    // TODO:
-                    assumeTrue(false, "not properly implemented. Check manually and add asserts");
+                    BVLCOriginalBroadcastNPDU bvlcOriginalBroadcastNPDU = (BVLCOriginalBroadcastNPDU) bvlc;
+                    APDUUnconfirmedRequest apduUnconfirmedRequest = (APDUUnconfirmedRequest) bvlcOriginalBroadcastNPDU.getNpdu().getApdu();
+                    BACnetUnconfirmedServiceRequestWhoHas baCnetUnconfirmedServiceRequestWhoHas = (BACnetUnconfirmedServiceRequestWhoHas) apduUnconfirmedRequest.getServiceRequest();
+                    assertEquals(133, baCnetUnconfirmedServiceRequestWhoHas.getDeviceInstanceRangeLowLimit().getActualValue());
+                    assertEquals(133, baCnetUnconfirmedServiceRequestWhoHas.getDeviceInstanceRangeLowLimit().getActualValue());
+                    // TODO: we should use a enum here
+                    assertEquals(8, baCnetUnconfirmedServiceRequestWhoHas.getObjectIdentifier().getObjectType());
+                    assertEquals(133, baCnetUnconfirmedServiceRequestWhoHas.getObjectIdentifier().getInstanceNumber());
+                }),
+            DynamicTest.dynamicTest("skip 2 LLC packages",
+                () -> {
+                    pcapEvaluator.skipPackages(2);
+                }),
+            DynamicTest.dynamicTest("Unconfirmed-REQ I-Am 133 133",
+                () -> {
+                    BVLC bvlc = pcapEvaluator.nextBVLC();
+                    dump(bvlc);
+                    BVLCOriginalBroadcastNPDU bvlcOriginalBroadcastNPDU = (BVLCOriginalBroadcastNPDU) bvlc;
+                    APDUUnconfirmedRequest apduUnconfirmedRequest = (APDUUnconfirmedRequest) bvlcOriginalBroadcastNPDU.getNpdu().getApdu();
+                    BACnetUnconfirmedServiceRequestIAm baCnetUnconfirmedServiceRequestIAm = (BACnetUnconfirmedServiceRequestIAm) apduUnconfirmedRequest.getServiceRequest();
+                    // TODO: we should use a enum here
+                    assertEquals(8, baCnetUnconfirmedServiceRequestIAm.getDeviceIdentifier().getObjectType());
+                    assertEquals(133, baCnetUnconfirmedServiceRequestIAm.getDeviceIdentifier().getInstanceNumber());
+                    assertEquals(480, baCnetUnconfirmedServiceRequestIAm.getMaximumApduLengthAcceptedLength().getActualValue());
+                    // TODO: we should use a enum here
+                    assertEquals(Arrays.asList((Byte) (byte) 0x0), baCnetUnconfirmedServiceRequestIAm.getSegmentationSupported().getData());
+                    assertEquals(42, baCnetUnconfirmedServiceRequestIAm.getVendorId().getActualValue());
+                }),
+            DynamicContainer.dynamicContainer("Confirmed-REQ atomicWriteFile 1-30", () -> {
+                Collection<DynamicNode> nodes = new LinkedList<>();
+                IntStream.range(1, 31).forEach(i -> {
+                    nodes.add(DynamicTest.dynamicTest("Confirmed-REQ atomicWriteFile [" + i + "] file,0", () -> {
+                        BVLC bvlc = pcapEvaluator.nextBVLC();
+                        dump(bvlc);
+                        BVLCOriginalUnicastNPDU bvlcOriginalUnicastNPDU = (BVLCOriginalUnicastNPDU) bvlc;
+                        APDUConfirmedRequest apduConfirmedRequest = (APDUConfirmedRequest) bvlcOriginalUnicastNPDU.getNpdu().getApdu();
+                        BACnetConfirmedServiceRequestAtomicWriteFile baCnetConfirmedServiceRequestAtomicWriteFile = (BACnetConfirmedServiceRequestAtomicWriteFile) apduConfirmedRequest.getServiceRequest();
+                        // TODO: we should use a enum here
+                        assertEquals(10, baCnetConfirmedServiceRequestAtomicWriteFile.getDeviceIdentifier().getObjectType());
+                        assertNotNull(baCnetConfirmedServiceRequestAtomicWriteFile.getFileStartPosition());
+                        assertNotNull(baCnetConfirmedServiceRequestAtomicWriteFile.getFileData());
+                    }));
+                    nodes.add(DynamicTest.dynamicTest("Confirmed-Ack     atomicWriteFile [" + i + "]", () -> {
+                        BVLC bvlc = pcapEvaluator.nextBVLC();
+                        dump(bvlc);
+                        BVLCOriginalUnicastNPDU bvlcOriginalUnicastNPDU = (BVLCOriginalUnicastNPDU) bvlc;
+                        APDUComplexAck apduComplexAck = (APDUComplexAck) bvlcOriginalUnicastNPDU.getNpdu().getApdu();
+                        BACnetServiceAckAtomicWriteFile baCnetServiceAckAtomicWriteFile = (BACnetServiceAckAtomicWriteFile) apduComplexAck.getServiceAck();
+                        assertNotNull(baCnetServiceAckAtomicWriteFile.getFileStartPosition());
+                    }));
+                });
+                return nodes.iterator();
+            }),
+            DynamicTest.dynamicTest("Unconfirmed-REQ who-Has device,133",
+                () -> {
+                    BVLC bvlc = pcapEvaluator.nextBVLC();
+                    dump(bvlc);
+                    BVLCOriginalBroadcastNPDU bvlcOriginalBroadcastNPDU = (BVLCOriginalBroadcastNPDU) bvlc;
+                    APDUUnconfirmedRequest apduUnconfirmedRequest = (APDUUnconfirmedRequest) bvlcOriginalBroadcastNPDU.getNpdu().getApdu();
+                    BACnetUnconfirmedServiceRequestWhoHas baCnetUnconfirmedServiceRequestWhoHas = (BACnetUnconfirmedServiceRequestWhoHas) apduUnconfirmedRequest.getServiceRequest();
+                    assertNull(baCnetUnconfirmedServiceRequestWhoHas.getDeviceInstanceRangeLowLimit());
+                    assertNull(baCnetUnconfirmedServiceRequestWhoHas.getDeviceInstanceRangeLowLimit());
+                    // TODO: we should use a enum here
+                    assertEquals(8, baCnetUnconfirmedServiceRequestWhoHas.getObjectIdentifier().getObjectType());
+                    assertEquals(133, baCnetUnconfirmedServiceRequestWhoHas.getObjectIdentifier().getInstanceNumber());
+                }),
+            DynamicTest.dynamicTest("skip 1 LLC packages",
+                () -> pcapEvaluator.skipPackages(1)),
+            DynamicTest.dynamicTest("Unconfirmed-REQ i-Have device,4194303 device,133",
+                () -> {
+                    BVLC bvlc = pcapEvaluator.nextBVLC();
+                    dump(bvlc);
+                    BVLCOriginalBroadcastNPDU bvlcOriginalBroadcastNPDU = (BVLCOriginalBroadcastNPDU) bvlc;
+                    APDUUnconfirmedRequest apduUnconfirmedRequest = (APDUUnconfirmedRequest) bvlcOriginalBroadcastNPDU.getNpdu().getApdu();
+                    BACnetUnconfirmedServiceRequestIHave baCnetUnconfirmedServiceRequestIHave = (BACnetUnconfirmedServiceRequestIHave) apduUnconfirmedRequest.getServiceRequest();
+                    // TODO: we should use a enum here
+                    assertEquals(8, baCnetUnconfirmedServiceRequestIHave.getDeviceIdentifier().getObjectType());
+                    assertEquals(4194303, baCnetUnconfirmedServiceRequestIHave.getDeviceIdentifier().getInstanceNumber());
+                    // TODO: we should use a enum here
+                    assertEquals(8, baCnetUnconfirmedServiceRequestIHave.getObjectIdentifier().getObjectType());
+                    assertEquals(133, baCnetUnconfirmedServiceRequestIHave.getObjectIdentifier().getInstanceNumber());
+                    assertEquals("Unknown", baCnetUnconfirmedServiceRequestIHave.getObjectName().getValue());
+                }),
+            DynamicTest.dynamicTest("Unconfirmed-REQ i-Have device,133 device,133",
+                () -> {
+                    BVLC bvlc = pcapEvaluator.nextBVLC();
+                    dump(bvlc);
+                    BVLCOriginalUnicastNPDU bvlcOriginalUnicastNPDU = (BVLCOriginalUnicastNPDU) bvlc;
+                    APDUUnconfirmedRequest apduUnconfirmedRequest = (APDUUnconfirmedRequest) bvlcOriginalUnicastNPDU.getNpdu().getApdu();
+                    BACnetUnconfirmedServiceRequestIHave baCnetUnconfirmedServiceRequestIHave = (BACnetUnconfirmedServiceRequestIHave) apduUnconfirmedRequest.getServiceRequest();
+                    // TODO: we should use a enum here
+                    assertEquals(8, baCnetUnconfirmedServiceRequestIHave.getDeviceIdentifier().getObjectType());
+                    assertEquals(133, baCnetUnconfirmedServiceRequestIHave.getDeviceIdentifier().getInstanceNumber());
+                    // TODO: we should use a enum here
+                    assertEquals(8, baCnetUnconfirmedServiceRequestIHave.getObjectIdentifier().getObjectType());
+                    assertEquals(133, baCnetUnconfirmedServiceRequestIHave.getObjectIdentifier().getInstanceNumber());
+                    assertEquals("SYNERGY", baCnetUnconfirmedServiceRequestIHave.getObjectName().getValue());
+                }),
+            DynamicTest.dynamicTest("Unconfirmed-REQ who-Has device,133",
+                () -> {
+                    BVLC bvlc = pcapEvaluator.nextBVLC();
+                    dump(bvlc);
+                    BVLCOriginalBroadcastNPDU bvlcOriginalBroadcastNPDU = (BVLCOriginalBroadcastNPDU) bvlc;
+                    APDUUnconfirmedRequest apduUnconfirmedRequest = (APDUUnconfirmedRequest) bvlcOriginalBroadcastNPDU.getNpdu().getApdu();
+                    BACnetUnconfirmedServiceRequestWhoHas baCnetUnconfirmedServiceRequestWhoHas = (BACnetUnconfirmedServiceRequestWhoHas) apduUnconfirmedRequest.getServiceRequest();
+                    assertNull(baCnetUnconfirmedServiceRequestWhoHas.getDeviceInstanceRangeLowLimit());
+                    assertNull(baCnetUnconfirmedServiceRequestWhoHas.getDeviceInstanceRangeLowLimit());
+                    // TODO: we should use a enum here
+                    assertEquals(8, baCnetUnconfirmedServiceRequestWhoHas.getObjectIdentifier().getObjectType());
+                    assertEquals(133, baCnetUnconfirmedServiceRequestWhoHas.getObjectIdentifier().getInstanceNumber());
+                }),
+            DynamicTest.dynamicTest("skip 1 LLC packages",
+                () -> pcapEvaluator.skipPackages(1)),
+            DynamicTest.dynamicTest("Unconfirmed-REQ i-Have device,4194303 device,133",
+                () -> {
+                    BVLC bvlc = pcapEvaluator.nextBVLC();
+                    dump(bvlc);
+                    BVLCOriginalBroadcastNPDU bvlcOriginalBroadcastNPDU = (BVLCOriginalBroadcastNPDU) bvlc;
+                    APDUUnconfirmedRequest apduUnconfirmedRequest = (APDUUnconfirmedRequest) bvlcOriginalBroadcastNPDU.getNpdu().getApdu();
+                    BACnetUnconfirmedServiceRequestIHave baCnetUnconfirmedServiceRequestIHave = (BACnetUnconfirmedServiceRequestIHave) apduUnconfirmedRequest.getServiceRequest();
+                    // TODO: we should use a enum here
+                    assertEquals(8, baCnetUnconfirmedServiceRequestIHave.getDeviceIdentifier().getObjectType());
+                    assertEquals(4194303, baCnetUnconfirmedServiceRequestIHave.getDeviceIdentifier().getInstanceNumber());
+                    // TODO: we should use a enum here
+                    assertEquals(8, baCnetUnconfirmedServiceRequestIHave.getObjectIdentifier().getObjectType());
+                    assertEquals(133, baCnetUnconfirmedServiceRequestIHave.getObjectIdentifier().getInstanceNumber());
+                    assertEquals("Unknown", baCnetUnconfirmedServiceRequestIHave.getObjectName().getValue());
+                }),
+            DynamicTest.dynamicTest("Unconfirmed-REQ i-Have device,133 device,133",
+                () -> {
+                    BVLC bvlc = pcapEvaluator.nextBVLC();
+                    dump(bvlc);
+                    BVLCOriginalUnicastNPDU bvlcOriginalUnicastNPDU = (BVLCOriginalUnicastNPDU) bvlc;
+                    APDUUnconfirmedRequest apduUnconfirmedRequest = (APDUUnconfirmedRequest) bvlcOriginalUnicastNPDU.getNpdu().getApdu();
+                    BACnetUnconfirmedServiceRequestIHave baCnetUnconfirmedServiceRequestIHave = (BACnetUnconfirmedServiceRequestIHave) apduUnconfirmedRequest.getServiceRequest();
+                    // TODO: we should use a enum here
+                    assertEquals(8, baCnetUnconfirmedServiceRequestIHave.getDeviceIdentifier().getObjectType());
+                    assertEquals(133, baCnetUnconfirmedServiceRequestIHave.getDeviceIdentifier().getInstanceNumber());
+                    // TODO: we should use a enum here
+                    assertEquals(8, baCnetUnconfirmedServiceRequestIHave.getObjectIdentifier().getObjectType());
+                    assertEquals(133, baCnetUnconfirmedServiceRequestIHave.getObjectIdentifier().getInstanceNumber());
+                    assertEquals("SYNERGY", baCnetUnconfirmedServiceRequestIHave.getObjectName().getValue());
                 })
         );
     }
@@ -5147,7 +5288,7 @@ public class RandomPackagesTest {
         }
 
         public void skipPackages(int numberOfPackages) {
-            IntStream.rangeClosed(1, numberOfPackages + 1).forEach(i -> {
+            IntStream.rangeClosed(1, numberOfPackages).forEach(i -> {
                 System.out.println("Skipping package " + i);
                 try {
                     pcapHandle.getNextPacket();