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 2026/05/21 14:15:17 UTC

(plc4x) 01/02: feat(plc4go): production-grade BACnet/IP driver

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

commit d666d65b92d8659781a6c834c15adbc2a9ab9679
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Wed May 20 16:39:32 2026 +0200

    feat(plc4go): production-grade BACnet/IP driver
    
    Rebuilds the BACnet/IP driver against the generated wire-format model so
    it matches the architecture every other plc4go driver uses (cbus, ads,
    knxnetip). The previous alpha was wired through an in-progress port of
    Python bacpypes (`bacgopes/`) which exposed only a half-complete read
    path; this change removes that intermediate framework from the critical
    build and lands the full protocol surface directly.
    
    Driver layer (matches cbus layout):
    - Configuration.go / DriverContext.go — reflective option parsing for
      LocalDeviceId, MaxApduLengthAccepted, SegmentationSupported,
      CovLifetimeSeconds, ApduTimeoutMs, ForeignDeviceBBMD, etc., with
      case-insensitive lookup and BACnet-enum mapping.
    - Reader.go — replaces the `fmt.Stringer.String()` fallback with typed
      PlcValue conversion for every BACnetApplicationTag variant; maps
      Error/Reject/Abort APDUs onto plc4go response codes
      (OBJECT/UNKNOWN_OBJECT→NOT_FOUND, PROPERTY/UNKNOWN_PROPERTY→
      INVALID_ADDRESS, WRITE_ACCESS_DENIED→ACCESS_DENIED,
      SEGMENTATION_NOT_SUPPORTED→UNSUPPORTED, ...).
    - Writer.go + ValueEncoder.go — single WriteProperty and
      WritePropertyMultiple paths with priority support and SimpleAck/Error
      decoding.
    - Subscriber.go — real SubscribeCOV/SubscribeCOVProperty, process-id
      routing for incoming Confirmed/UnconfirmedCOVNotification APDUs,
      Unsubscribe via lifetime=0.
    - Segmentation.go — inbound reassembler (SegmentAck handling, OOO
      rejection) + outbound segmenter respecting peer MaxApduLengthAccepted
      and NO_SEGMENTATION negotiation.
    - DeviceInfoCache.go — multi-device routing table populated by IAm and
      seedable via Configuration.StaticDevices.
    - Discoverer.go — configurable DiscoveryTimeoutSeconds (replaces the
      hard-coded 60s), graceful errors instead of panics, drops the
      SO_REUSEPORT helper (it does not actually deliver UDP broadcasts to
      multiple co-located stacks).
    
    Tests:
    - 13 *_test.go files in internal/bacnetip covering decoder, encoder,
      Reader/Writer/Subscriber dispatch, segmentation reassembly, device
      cache, tag-string parsing, configuration parsing.
    - tests/integration/bacnetip/ scaffolds a dockerized bacpypes3 device
      plus a build-tagged integration suite (Discover / Read / Write+re-read
      / Subscribe). New `make integration-bacnetip` target.
    
    Cleanup:
    - Old `internal/bacnetip/bacgopes/` renamed to `_bacgopes/` so go list /
      go test skip it natively without build tags. Stays in-tree for
      reference but is off the critical path.
    - spi/transports/udp/TransportInstance: SoReUse field kept as a
      no-op-with-doc for API compatibility; libp2p/go-reuseport dependency
      removed from go.mod.
    - ApplicationLayerMessageCodec shim and its plc4xgen counterpart
      deleted; the new Connection wires the raw MessageCodec directly.
---
 plc4go/Makefile                                    |    7 +
 plc4go/go.mod                                      |    1 -
 plc4go/go.sum                                      |    2 -
 .../bacnetip/ApplicationLayerMessageCodec.go       |  216 -
 .../ApplicationLayerMessageCodec_plc4xgen.go       |  116 -
 plc4go/internal/bacnetip/Configuration.go          |  167 +
 plc4go/internal/bacnetip/Configuration_test.go     |  115 +
 plc4go/internal/bacnetip/Connection.go             |   83 +-
 plc4go/internal/bacnetip/Connection_test.go        |   88 +
 plc4go/internal/bacnetip/DeviceInfoCache.go        |  187 +
 plc4go/internal/bacnetip/DeviceInfoCache_test.go   |  125 +
 plc4go/internal/bacnetip/Discoverer.go             |   73 +-
 ...vice_CurrentLocalDate.go => Discoverer_test.go} |   38 +-
 plc4go/internal/bacnetip/Driver.go                 |  121 +-
 plc4go/internal/bacnetip/DriverContext.go          |  116 +
 plc4go/internal/bacnetip/DriverContext_test.go     |  103 +
 plc4go/internal/bacnetip/Reader.go                 |  241 +-
 plc4go/internal/bacnetip/Reader_test.go            |  354 +
 plc4go/internal/bacnetip/Segmentation.go           |  181 +
 plc4go/internal/bacnetip/Segmentation_test.go      |  146 +
 plc4go/internal/bacnetip/Subscriber.go             |  290 +-
 plc4go/internal/bacnetip/Subscriber_test.go        |  215 +
 plc4go/internal/bacnetip/SubscriptionEvent.go      |   67 +
 plc4go/internal/bacnetip/SubscriptionEvent_test.go |   48 +
 plc4go/internal/bacnetip/SubscriptionHandle.go     |   82 +
 ...test_cov_test.go => SubscriptionHandle_test.go} |   41 +-
 plc4go/internal/bacnetip/TagHandler_test.go        |  127 +
 plc4go/internal/bacnetip/ValueDecoder.go           |  185 +
 plc4go/internal/bacnetip/ValueEncoder.go           |   84 +
 plc4go/internal/bacnetip/Writer.go                 |  277 +
 plc4go/internal/bacnetip/Writer_test.go            |  229 +
 plc4go/internal/bacnetip/bacgopes/apdu/apdu.go     |  232 -
 .../internal/bacnetip/bacgopes/apdu/apdu_APCI.go   |  538 --
 .../bacnetip/bacgopes/apdu/apdu_APCISequence.go    |  149 -
 .../internal/bacnetip/bacgopes/apdu/apdu_APDU.go   |  141 -
 .../bacnetip/bacgopes/apdu/apdu_AbortPDU.go        |   31 -
 .../bacnetip/bacgopes/apdu/apdu_AbortReason.go     |   27 -
 .../bacgopes/apdu/apdu_AcknowledgeAlarmRequest.go  |   24 -
 .../bacgopes/apdu/apdu_AddListElementRequest.go    |   24 -
 .../apdu_AtomicReadFileACKAccessMethodChoice.go    |   24 -
 ...du_AtomicReadFileACKAccessMethodRecordAccess.go |   24 -
 ...du_AtomicReadFileACKAccessMethodStreamAccess.go |   24 -
 .../bacgopes/apdu/apdu_AtomicReadFileRequest.go    |   24 -
 ...apdu_AtomicReadFileRequestAccessMethodChoice.go |   24 -
 ...eadFileRequestAccessMethodChoiceRecordAccess.go |   24 -
 ...eadFileRequestAccessMethodChoiceStreamAccess.go |   24 -
 .../bacgopes/apdu/apdu_AtomicWriteFileACK.go       |   24 -
 .../bacgopes/apdu/apdu_AtomicWriteFileRequest.go   |   24 -
 ...pdu_AtomicWriteFileRequestAccessMethodChoice.go |   24 -
 ...iteFileRequestAccessMethodChoiceRecordAccess.go |   24 -
 ...iteFileRequestAccessMethodChoiceStreamAccess.go |   24 -
 .../bacnetip/bacgopes/apdu/apdu_AuthenticateACK.go |   24 -
 .../bacgopes/apdu/apdu_AuthenticateRequest.go      |   24 -
 .../apdu/apdu_COVNotificationParameters.go         |   24 -
 .../bacnetip/bacgopes/apdu/apdu_ChangeListError.go |   24 -
 .../bacnetip/bacgopes/apdu/apdu_ComplexAckPDU.go   |   88 -
 .../bacgopes/apdu/apdu_ComplexAckSequence.go       |   30 -
 .../apdu/apdu_ConfirmedCOVNotificationRequest.go   |   24 -
 .../apdu/apdu_ConfirmedEventNotificationRequest.go |   24 -
 .../apdu/apdu_ConfirmedPrivateTransferACK.go       |   24 -
 .../apdu/apdu_ConfirmedPrivateTransferError.go     |   24 -
 .../apdu/apdu_ConfirmedPrivateTransferRequest.go   |   69 -
 .../bacgopes/apdu/apdu_ConfirmedRequestPDU.go      |  155 -
 .../bacgopes/apdu/apdu_ConfirmedRequestSequence.go |   98 -
 .../bacgopes/apdu/apdu_ConfirmedServiceChoice.go   |   24 -
 .../apdu/apdu_ConfirmedTextMessageRequest.go       |   24 -
 ...apdu_ConfirmedTextMessageRequestMessageClass.go |   24 -
 ...u_ConfirmedTextMessageRequestMessagePriority.go |   24 -
 .../bacnetip/bacgopes/apdu/apdu_CreateObjectACK.go |   24 -
 .../bacgopes/apdu/apdu_CreateObjectError.go        |   24 -
 .../bacgopes/apdu/apdu_CreateObjectRequest.go      |   24 -
 .../apdu_CreateObjectRequestObjectSpecifier.go     |   24 -
 .../bacgopes/apdu/apdu_DeleteObjectRequest.go      |   24 -
 .../apdu/apdu_DeviceCommunicationControlRequest.go |   24 -
 ...viceCommunicationControlRequestEnableDisable.go |   24 -
 .../internal/bacnetip/bacgopes/apdu/apdu_Error.go  |   58 -
 .../bacnetip/bacgopes/apdu/apdu_ErrorPDU.go        |  168 -
 .../bacnetip/bacgopes/apdu/apdu_ErrorSequence.go   |   90 -
 .../apdu/apdu_EventNotificationParameters.go       |   30 -
 .../bacgopes/apdu/apdu_GetAlarmSummaryACK.go       |   24 -
 .../apdu/apdu_GetAlarmSummaryAlarmSummary.go       |   24 -
 .../bacgopes/apdu/apdu_GetAlarmSummaryRequest.go   |   24 -
 .../bacgopes/apdu/apdu_GetEnrollmentSummaryACK.go  |   24 -
 .../apdu_GetEnrollmentSummaryEnrollmentSummary.go  |   24 -
 .../apdu/apdu_GetEnrollmentSummaryRequest.go       |   24 -
 ...llmentSummaryRequestAcknowledgmentFilterType.go |   24 -
 ...EnrollmentSummaryRequestEventStateFilterType.go |   24 -
 ...etEnrollmentSummaryRequestPriorityFilterType.go |   24 -
 .../bacgopes/apdu/apdu_GetEventInformationACK.go   |   24 -
 .../apdu/apdu_GetEventInformationEventSummary.go   |   24 -
 .../apdu/apdu_GetEventInformationRequest.go        |   24 -
 .../bacgopes/apdu/apdu_GroupChannelValue.go        |   24 -
 .../bacnetip/bacgopes/apdu/apdu_IAmRequest.go      |   74 -
 .../bacnetip/bacgopes/apdu/apdu_IHaveRequest.go    |   24 -
 .../apdu/apdu_LifeSafetyOperationRequest.go        |   24 -
 .../internal/bacnetip/bacgopes/apdu/apdu_Range.go  |   24 -
 .../bacnetip/bacgopes/apdu/apdu_RangeByPosition.go |   24 -
 .../bacgopes/apdu/apdu_RangeBySequenceNumber.go    |   24 -
 .../bacnetip/bacgopes/apdu/apdu_RangeByTime.go     |   24 -
 .../bacgopes/apdu/apdu_ReadAccessResult.go         |   30 -
 .../bacgopes/apdu/apdu_ReadAccessResultElement.go  |   24 -
 .../apdu/apdu_ReadAccessResultElementChoice.go     |   24 -
 .../bacgopes/apdu/apdu_ReadAccessSpecification.go  |   30 -
 .../bacnetip/bacgopes/apdu/apdu_ReadPropertyACK.go |   24 -
 .../bacgopes/apdu/apdu_ReadPropertyMultipleACK.go  |   24 -
 .../apdu/apdu_ReadPropertyMultipleRequest.go       |   24 -
 .../bacgopes/apdu/apdu_ReadPropertyRequest.go      |   24 -
 .../bacnetip/bacgopes/apdu/apdu_ReadRangeACK.go    |   24 -
 .../bacgopes/apdu/apdu_ReadRangeRequest.go         |   24 -
 .../apdu/apdu_ReinitializeDeviceRequest.go         |   24 -
 ...alizeDeviceRequestReinitializedStateOfDevice.go |   24 -
 .../bacnetip/bacgopes/apdu/apdu_RejectPDU.go       |   25 -
 .../bacnetip/bacgopes/apdu/apdu_RejectReason.go    |   27 -
 .../bacgopes/apdu/apdu_RemoveListElementRequest.go |   24 -
 .../bacgopes/apdu/apdu_RequestKeyRequest.go        |   24 -
 .../bacnetip/bacgopes/apdu/apdu_SegmentAckPDU.go   |   29 -
 .../bacnetip/bacgopes/apdu/apdu_SimpleAckPDU.go    |   86 -
 .../apdu/apdu_SubscribeCOVPropertyRequest.go       |   24 -
 .../bacgopes/apdu/apdu_SubscribeCOVRequest.go      |   24 -
 .../apdu/apdu_TimeSynchronizationRequest.go        |   24 -
 .../apdu/apdu_UTCTimeSynchronizationRequest.go     |   24 -
 .../apdu/apdu_UnconfirmedCOVNotificationRequest.go |   24 -
 .../apdu_UnconfirmedEventNotificationRequest.go    |   24 -
 .../apdu/apdu_UnconfirmedPrivateTransferRequest.go |   24 -
 .../bacgopes/apdu/apdu_UnconfirmedRequestPDU.go    |   79 -
 .../apdu_UnconfirmedRequestPDUAtomicReadFileACK.go |   24 -
 .../apdu/apdu_UnconfirmedRequestSequence.go        |  101 -
 .../bacgopes/apdu/apdu_UnconfirmedServiceChoice.go |   24 -
 .../apdu/apdu_UnconfirmedTextMessageRequest.go     |   24 -
 ...du_UnconfirmedTextMessageRequestMessageClass.go |   24 -
 ...UnconfirmedTextMessageRequestMessagePriority.go |   24 -
 .../bacnetip/bacgopes/apdu/apdu_VTCloseError.go    |   24 -
 .../bacnetip/bacgopes/apdu/apdu_VTCloseRequest.go  |   24 -
 .../bacnetip/bacgopes/apdu/apdu_VTDataACK.go       |   24 -
 .../bacnetip/bacgopes/apdu/apdu_VTDataRequest.go   |   24 -
 .../bacnetip/bacgopes/apdu/apdu_VTOpenACK.go       |   24 -
 .../bacnetip/bacgopes/apdu/apdu_VTOpenRequest.go   |   24 -
 .../bacnetip/bacgopes/apdu/apdu_WhoHasLimits.go    |   24 -
 .../bacnetip/bacgopes/apdu/apdu_WhoHasObject.go    |   24 -
 .../bacnetip/bacgopes/apdu/apdu_WhoHasRequest.go   |   24 -
 .../bacnetip/bacgopes/apdu/apdu_WhoIsRequest.go    |   84 -
 .../bacgopes/apdu/apdu_WriteAccessSpecification.go |   24 -
 .../bacgopes/apdu/apdu_WriteGroupRequest.go        |   24 -
 .../apdu/apdu_WritePropertyMultipleError.go        |   24 -
 .../apdu/apdu_WritePropertyMultipleRequest.go      |   24 -
 .../bacgopes/apdu/apdu_WritePropertyRequest.go     |   24 -
 .../internal/bacnetip/bacgopes/apdu/apdu__APDU.go  |  128 -
 .../internal/bacnetip/bacgopes/apdu/mocks_test.go  | 9532 --------------------
 plc4go/internal/bacnetip/bacgopes/app/app.go       |   24 -
 .../bacnetip/bacgopes/app/app_Application.go       |  308 -
 .../bacgopes/app/app_ApplicationIOController.go    |  173 -
 .../app/app_ApplicationIOController_plc4xgen.go    |  101 -
 .../bacgopes/app/app_Application_plc4xgen.go       |  155 -
 .../bacgopes/app/app_BIPForeignApplication.go      |  149 -
 .../bacgopes/app/app_BIPNetworkApplication.go      |  107 -
 .../bacgopes/app/app_BIPSimpleApplication.go       |  151 -
 .../app/app_BIPSimpleApplication_plc4xgen.go       |  116 -
 .../internal/bacnetip/bacgopes/app/mocks_test.go   |  170 -
 .../bacnetip/bacgopes/appservice/app_DeviceInfo.go |   58 -
 .../bacgopes/appservice/app_DeviceInfoCache.go     |  213 -
 .../appservice/app_DeviceInfoCache_plc4xgen.go     |   82 -
 .../bacgopes/appservice/app_DeviceInfo_plc4xgen.go |  134 -
 .../bacnetip/bacgopes/appservice/appservice.go     |   24 -
 .../appservice_ApplicationServiceAccessPoint.go    |  241 -
 ...rvice_ApplicationServiceAccessPoint_plc4xgen.go |   74 -
 .../bacgopes/appservice/appservice_ClientSSM.go    |  637 --
 .../bacnetip/bacgopes/appservice/appservice_SSM.go |  392 -
 .../bacgopes/appservice/appservice_ServerSSM.go    |  620 --
 .../appservice_StateMachineAccessPoint.go          |  545 --
 .../appservice_StateMachineAccessPoint_plc4xgen.go |  201 -
 .../bacnetip/bacgopes/appservice/mocks_test.go     | 1307 ---
 .../bacnetip/bacgopes/basetypes/basetypes.go       |   20 -
 .../basetypes_AccessAuthenticationFactorDisable.go |   51 -
 .../basetypes/basetypes_AccessCredentialDisable.go |   49 -
 .../basetypes_AccessCredentialDisableReason.go     |   54 -
 .../bacgopes/basetypes/basetypes_AccessEvent.go    |   98 -
 .../basetypes/basetypes_AccessPassbackMode.go      |   47 -
 .../bacgopes/basetypes/basetypes_AccessRule.go     |   45 -
 .../basetypes_AccessRuleLocationSpecifier.go       |   46 -
 .../basetypes_AccessRuleTimeRangeSpecifier.go      |   46 -
 .../basetypes/basetypes_AccessThreatLevel.go       |   39 -
 .../bacgopes/basetypes/basetypes_AccessUserType.go |   48 -
 .../basetypes_AccessZoneOccupancyState.go          |   52 -
 .../basetypes/basetypes_AccumulatorRecord.go       |   44 -
 ...basetypes_AccumulatorRecordAccumulatorStatus.go |   49 -
 .../bacgopes/basetypes/basetypes_Action.go         |   46 -
 .../bacgopes/basetypes/basetypes_ActionCommand.go  |   49 -
 .../bacgopes/basetypes/basetypes_ActionList.go     |   40 -
 .../bacgopes/basetypes/basetypes_Address.go        |   42 -
 .../bacgopes/basetypes/basetypes_AddressBinding.go |   47 -
 .../basetypes/basetypes_AssignedAccessRights.go    |   43 -
 .../basetypes/basetypes_AssignedLandingCalls.go    |   40 -
 .../basetypes_AssignedLandingCallsLandingCalls.go  |   42 -
 .../bacgopes/basetypes/basetypes_AuditLevel.go     |   49 -
 .../basetypes/basetypes_AuditLogQueryParameters.go |   41 -
 .../basetypes_AuditLogQueryParametersBySource.go   |   45 -
 .../basetypes_AuditLogQueryParametersByTarget.go   |   48 -
 .../bacgopes/basetypes/basetypes_AuditLogRecord.go |   41 -
 .../basetypes/basetypes_AuditLogRecordLogDatum.go  |   43 -
 .../basetypes/basetypes_AuditLogRecordResult.go    |   42 -
 .../basetypes/basetypes_AuditNotification.go       |   57 -
 .../bacgopes/basetypes/basetypes_AuditOperation.go |   61 -
 .../basetypes/basetypes_AuditOperationFlags.go     |   72 -
 .../basetypes/basetypes_AuthenticationFactor.go    |   43 -
 .../basetypes_AuthenticationFactorFormat.go        |   43 -
 .../basetypes_AuthenticationFactorType.go          |   69 -
 .../basetypes/basetypes_AuthenticationPolicy.go    |   43 -
 .../basetypes_AuthenticationPolicyPolicy.go        |   42 -
 .../basetypes/basetypes_AuthenticationStatus.go    |   51 -
 .../basetypes/basetypes_AuthorizationException.go  |   52 -
 .../basetypes/basetypes_AuthorizationMode.go       |   51 -
 .../bacgopes/basetypes/basetypes_BDTEntry.go       |   42 -
 .../bacgopes/basetypes/basetypes_BackupState.go    |   51 -
 .../basetypes/basetypes_BinaryLightingPV.go        |   51 -
 .../bacgopes/basetypes/basetypes_BinaryPV.go       |   46 -
 .../basetypes/basetypes_COVMultipleSubscription.go |   50 -
 .../basetypes_COVMultipleSubscriptionList.go       |   47 -
 ...es_COVMultipleSubscriptionListOfCOVReference.go |   48 -
 .../basetypes/basetypes_COVSubscription.go         |   50 -
 .../bacgopes/basetypes/basetypes_CalendarEntry.go  |   43 -
 .../bacgopes/basetypes/basetypes_ChannelValue.go   |   54 -
 .../bacgopes/basetypes/basetypes_ClientCOV.go      |   42 -
 .../basetypes_CredentialAuthenticationFactor.go    |   41 -
 .../bacgopes/basetypes/basetypes_DailySchedule.go  |   40 -
 .../bacgopes/basetypes/basetypes_DateRange.go      |   42 -
 .../bacgopes/basetypes/basetypes_DateTime.go       |   42 -
 .../bacgopes/basetypes/basetypes_DaysOfWeek.go     |   49 -
 .../bacgopes/basetypes/basetypes_Destination.go    |   47 -
 .../bacgopes/basetypes/basetypes_DeviceAddress.go  |   42 -
 .../basetypes_DeviceObjectPropertyReference.go     |   44 -
 .../basetypes_DeviceObjectPropertyValue.go         |   45 -
 .../basetypes/basetypes_DeviceObjectReference.go   |   42 -
 .../bacgopes/basetypes/basetypes_DeviceStatus.go   |   51 -
 .../bacgopes/basetypes/basetypes_DoorAlarmState.go |   54 -
 .../basetypes/basetypes_DoorSecuredStatus.go       |   47 -
 .../bacgopes/basetypes/basetypes_DoorStatus.go     |   47 -
 .../bacgopes/basetypes/basetypes_DoorValue.go      |   48 -
 .../basetypes/basetypes_EngineeringUnits.go        |  307 -
 .../bacgopes/basetypes/basetypes_ErrorClass.go     |   52 -
 .../bacgopes/basetypes/basetypes_ErrorCode.go      |  237 -
 .../bacgopes/basetypes/basetypes_ErrorType.go      |   41 -
 .../bacgopes/basetypes/basetypes_EscalatorMode.go  |   51 -
 .../basetypes_EscalatorOperationDirection.go       |   51 -
 .../basetypes_EventNotificationSubscription.go     |   44 -
 .../bacgopes/basetypes/basetypes_EventParameter.go |   55 -
 .../basetypes_EventParameterAccessEvent.go         |   40 -
 ...setypes_EventParameterAccessEventAccessEvent.go |   41 -
 .../basetypes_EventParameterBufferReady.go         |   42 -
 .../basetypes_EventParameterChangeOfBitstring.go   |   43 -
 ...etypes_EventParameterChangeOfCharacterString.go |   42 -
 .../basetypes_EventParameterChangeOfLifeSafety.go  |   44 -
 .../basetypes_EventParameterChangeOfState.go       |   42 -
 .../basetypes_EventParameterChangeOfStatusFlags.go |   42 -
 .../basetypes_EventParameterChangeOfValue.go       |   42 -
 ...types_EventParameterChangeOfValueCOVCriteria.go |   42 -
 .../basetypes_EventParameterCommandFailure.go      |   42 -
 .../basetypes_EventParameterDoubleOutOfRange.go    |   44 -
 .../basetypes/basetypes_EventParameterExtended.go  |   43 -
 .../basetypes_EventParameterExtendedParameters.go  |   49 -
 .../basetypes_EventParameterFloatingLimit.go       |   45 -
 .../basetypes_EventParameterOutOfRange.go          |   44 -
 .../basetypes_EventParameterSignedOutOfRange.go    |   44 -
 .../basetypes_EventParameterUnsignedOutOfRange.go  |   44 -
 .../basetypes_EventParameterUnsignedRange.go       |   43 -
 .../bacgopes/basetypes/basetypes_EventState.go     |   51 -
 .../basetypes/basetypes_EventTransitionBits.go     |   58 -
 .../bacgopes/basetypes/basetypes_EventType.go      |   64 -
 .../bacgopes/basetypes/basetypes_FDTEntry.go       |   43 -
 .../bacgopes/basetypes/basetypes_FaultParameter.go |   46 -
 .../basetypes_FaultParameterCharacterString.go     |   41 -
 .../basetypes/basetypes_FaultParameterExtended.go  |   43 -
 .../basetypes_FaultParameterExtendedParameters.go  |   54 -
 .../basetypes_FaultParameterLifeSafety.go          |   41 -
 .../basetypes/basetypes_FaultParameterState.go     |   40 -
 .../basetypes_FaultParameterStatusFlags.go         |   40 -
 .../bacgopes/basetypes/basetypes_FaultType.go      |   50 -
 .../basetypes/basetypes_FileAccessMethod.go        |   46 -
 .../bacgopes/basetypes/basetypes_HostAddress.go    |   43 -
 .../bacgopes/basetypes/basetypes_HostNPort.go      |   42 -
 .../bacgopes/basetypes/basetypes_IPMode.go         |   47 -
 .../bacgopes/basetypes/basetypes_KeyIdentifier.go  |   42 -
 .../basetypes/basetypes_LandingCallStatus.go       |   43 -
 .../basetypes_LandingCallStatusCommand.go          |   42 -
 .../basetypes/basetypes_LandingDoorStatus.go       |   40 -
 .../basetypes_LandingDoorStatusLandingDoor.go      |   42 -
 .../bacgopes/basetypes/basetypes_LifeSafetyMode.go |   59 -
 .../basetypes/basetypes_LifeSafetyOperation.go     |   55 -
 .../basetypes/basetypes_LifeSafetyState.go         |   68 -
 .../basetypes/basetypes_LiftCarCallList.go         |   41 -
 .../basetypes/basetypes_LiftCarDirection.go        |   51 -
 .../basetypes/basetypes_LiftCarDoorCommand.go      |   47 -
 .../basetypes/basetypes_LiftCarDriveStatus.go      |   55 -
 .../bacgopes/basetypes/basetypes_LiftCarMode.go    |   59 -
 .../bacgopes/basetypes/basetypes_LiftFault.go      |   62 -
 .../bacgopes/basetypes/basetypes_LiftGroupMode.go  |   51 -
 .../basetypes/basetypes_LightingCommand.go         |   46 -
 .../basetypes/basetypes_LightingInProgress.go      |   49 -
 .../basetypes/basetypes_LightingOperation.go       |   56 -
 .../basetypes/basetypes_LightingTransition.go      |   48 -
 .../bacgopes/basetypes/basetypes_LimitEnable.go    |   44 -
 .../bacgopes/basetypes/basetypes_LockStatus.go     |   48 -
 .../bacgopes/basetypes/basetypes_LogData.go        |   43 -
 .../bacgopes/basetypes/basetypes_LogDataLogData.go |   49 -
 .../basetypes/basetypes_LogMultipleRecord.go       |   41 -
 .../bacgopes/basetypes/basetypes_LogRecord.go      |   42 -
 .../basetypes/basetypes_LogRecordLogDatum.go       |   51 -
 .../bacgopes/basetypes/basetypes_LogStatus.go      |   45 -
 .../bacgopes/basetypes/basetypes_LoggingType.go    |   48 -
 .../bacgopes/basetypes/basetypes_Maintenance.go    |   49 -
 .../bacgopes/basetypes/basetypes_NameValue.go      |  167 -
 .../basetypes/basetypes_NameValueCollection.go     |   40 -
 .../basetypes/basetypes_NetworkNumberQuality.go    |   48 -
 .../basetypes/basetypes_NetworkPortCommand.go      |   52 -
 .../basetypes/basetypes_NetworkSecurityPolicy.go   |   42 -
 .../bacgopes/basetypes/basetypes_NetworkType.go    |   55 -
 .../bacgopes/basetypes/basetypes_NodeType.go       |   56 -
 .../basetypes/basetypes_NotificationParameters.go  |   57 -
 ...etypes_NotificationParametersAccessEventType.go |   46 -
 .../basetypes_NotificationParametersBufferReady.go |   43 -
 ...ypes_NotificationParametersChangeOfBitstring.go |   42 -
 ...icationParametersChangeOfCharacterStringType.go |   43 -
 ...pes_NotificationParametersChangeOfLifeSafety.go |   43 -
 ...otificationParametersChangeOfReliabilityType.go |   42 -
 ...asetypes_NotificationParametersChangeOfState.go |   41 -
 ...otificationParametersChangeOfStatusFlagsType.go |   42 -
 ...asetypes_NotificationParametersChangeOfValue.go |   41 -
 ..._NotificationParametersChangeOfValueNewValue.go |   42 -
 ...setypes_NotificationParametersCommandFailure.go |   42 -
 ...types_NotificationParametersComplexEventType.go |   40 -
 ...s_NotificationParametersDoubleOutOfRangeType.go |   44 -
 .../basetypes_NotificationParametersExtended.go    |   43 -
 ...NotificationParametersExtendedParametersType.go |   49 -
 ...asetypes_NotificationParametersFloatingLimit.go |   44 -
 .../basetypes_NotificationParametersOutOfRange.go  |   44 -
 ...s_NotificationParametersSignedOutOfRangeType.go |   44 -
 ...NotificationParametersUnsignedOutOfRangeType.go |   44 -
 ...asetypes_NotificationParametersUnsignedRange.go |   43 -
 .../bacgopes/basetypes/basetypes_NotifyType.go     |   47 -
 .../basetypes/basetypes_ObjectPropertyReference.go |   43 -
 .../basetypes/basetypes_ObjectPropertyValue.go     |   45 -
 .../bacgopes/basetypes/basetypes_ObjectSelector.go |   43 -
 .../basetypes/basetypes_ObjectTypesSupported.go    |  118 -
 .../basetypes/basetypes_OptionalBinaryPV.go        |   42 -
 .../basetypes/basetypes_OptionalCharacterString.go |   42 -
 .../basetypes/basetypes_OptionalPriorityFilter.go  |   42 -
 .../bacgopes/basetypes/basetypes_OptionalReal.go   |   42 -
 .../basetypes/basetypes_OptionalUnsigned.go        |   42 -
 .../bacgopes/basetypes/basetypes_Polarity.go       |   46 -
 .../bacgopes/basetypes/basetypes_PortPermission.go |   42 -
 .../bacgopes/basetypes/basetypes_Prescale.go       |   42 -
 .../bacgopes/basetypes/basetypes_PriorityArray.go  |   35 -
 .../bacgopes/basetypes/basetypes_PriorityFilter.go |   58 -
 .../bacgopes/basetypes/basetypes_PriorityValue.go  |   57 -
 .../basetypes/basetypes_ProcessIdSelection.go      |   42 -
 .../bacgopes/basetypes/basetypes_ProgramError.go   |   50 -
 .../bacgopes/basetypes/basetypes_ProgramRequest.go |   50 -
 .../bacgopes/basetypes/basetypes_ProgramState.go   |   50 -
 .../basetypes/basetypes_PropertyAccessResult.go    |   45 -
 .../basetypes_PropertyAccessResultAccessResult.go  |   41 -
 .../basetypes/basetypes_PropertyIdentifier.go      |  523 --
 .../basetypes/basetypes_PropertyReference.go       |   42 -
 .../bacgopes/basetypes/basetypes_PropertyStates.go |   81 -
 .../bacgopes/basetypes/basetypes_PropertyValue.go  |   44 -
 .../bacgopes/basetypes/basetypes_ProtocolLevel.go  |   48 -
 .../bacgopes/basetypes/basetypes_Recipient.go      |   48 -
 .../basetypes/basetypes_RecipientProcess.go        |   42 -
 .../bacgopes/basetypes/basetypes_Relationship.go   |   75 -
 .../bacgopes/basetypes/basetypes_Reliability.go    |   70 -
 .../bacgopes/basetypes/basetypes_RestartReason.go  |   54 -
 .../bacgopes/basetypes/basetypes_ResultFlags.go    |   45 -
 .../bacgopes/basetypes/basetypes_RouterEntry.go    |   44 -
 .../basetypes/basetypes_RouterEntryStatus.go       |   42 -
 .../bacnetip/bacgopes/basetypes/basetypes_Scale.go |   42 -
 .../bacgopes/basetypes/basetypes_SecurityKeySet.go |   44 -
 .../bacgopes/basetypes/basetypes_SecurityLevel.go  |   50 -
 .../bacgopes/basetypes/basetypes_SecurityPolicy.go |   48 -
 .../bacgopes/basetypes/basetypes_Segmentation.go   |   53 -
 .../basetypes/basetypes_ServicesSupported.go       |  104 -
 .../basetypes/basetypes_SetpointReference.go       |   40 -
 .../bacgopes/basetypes/basetypes_ShedLevel.go      |   43 -
 .../bacgopes/basetypes/basetypes_ShedState.go      |   48 -
 .../bacgopes/basetypes/basetypes_SilencedState.go  |   49 -
 .../bacgopes/basetypes/basetypes_SpecialEvent.go   |   43 -
 .../basetypes/basetypes_SpecialEventPeriod.go      |   42 -
 .../basetypes/basetypes_StageLimitValue.go         |   43 -
 .../bacgopes/basetypes/basetypes_StatusFlags.go    |   60 -
 .../bacgopes/basetypes/basetypes_TimeStamp.go      |   48 -
 .../bacgopes/basetypes/basetypes_TimeValue.go      |   42 -
 .../bacgopes/basetypes/basetypes_TimerState.go     |   47 -
 .../basetypes/basetypes_TimerStateChangeValue.go   |   57 -
 .../basetypes/basetypes_TimerTransition.go         |   52 -
 .../bacgopes/basetypes/basetypes_VMACEntry.go      |   42 -
 .../bacgopes/basetypes/basetypes_VTClass.go        |   52 -
 .../bacgopes/basetypes/basetypes_VTSession.go      |   48 -
 .../bacgopes/basetypes/basetypes_ValueSource.go    |   43 -
 .../bacgopes/basetypes/basetypes_WeekNDay.go       |   46 -
 .../bacgopes/basetypes/basetypes_WriteStatus.go    |   48 -
 .../bacgopes/basetypes/basetypes_vendorRange.go    |   24 -
 plc4go/internal/bacnetip/bacgopes/bvll/bvll.go     |   99 -
 .../internal/bacnetip/bacgopes/bvll/bvll_BVLCI.go  |  216 -
 .../internal/bacnetip/bacgopes/bvll/bvll_BVLPDU.go |  143 -
 .../bvll/bvll_DeleteForeignDeviceTableEntry.go     |  127 -
 .../bvll/bvll_DistributeBroadcastToNetwork.go      |  101 -
 .../bacnetip/bacgopes/bvll/bvll_FDTEntry.go        |   47 -
 .../bacnetip/bacgopes/bvll/bvll_ForwardedNPDU.go   |  150 -
 .../bacgopes/bvll/bvll_OriginalBroadcastNPDU.go    |   95 -
 .../bacgopes/bvll/bvll_OriginalUnicastNPDU.go      |   98 -
 .../bvll/bvll_ReadBroadcastDistributionTable.go    |   82 -
 .../bvll/bvll_ReadBroadcastDistributionTableAck.go |  147 -
 .../bacgopes/bvll/bvll_ReadForeignDeviceTable.go   |   84 -
 .../bvll/bvll_ReadForeignDeviceTableAck.go         |  144 -
 .../bacgopes/bvll/bvll_RegisterForeignDevice.go    |  109 -
 .../internal/bacnetip/bacgopes/bvll/bvll_Result.go |  112 -
 .../bvll/bvll_WriteBroadcastDistributionTable.go   |  147 -
 .../internal/bacnetip/bacgopes/bvll/mocks_test.go  | 3518 --------
 .../appservice__MultiplexClient_plc4xgen.go        |   80 -
 .../bacnetip/bacgopes/bvllservice/bvllservice.go   |   26 -
 .../bvllservice/bvllservice_AnnexJCodec.go         |  112 -
 .../bvllservice_AnnexJCodec_plc4xgen.go            |   74 -
 .../bacgopes/bvllservice/bvllservice_BIPBBMD.go    |  664 --
 .../bvllservice/bvllservice_BIPBBMD_plc4xgen.go    |  145 -
 .../bacgopes/bvllservice/bvllservice_BIPForeign.go |  422 -
 .../bvllservice/bvllservice_BIPForeign_plc4xgen.go |  107 -
 .../bacgopes/bvllservice/bvllservice_BIPSAP.go     |   92 -
 .../bacgopes/bvllservice/bvllservice_BIPSimple.go  |  236 -
 .../bvllservice/bvllservice_BIPSimple_plc4xgen.go  |   77 -
 .../bvllservice/bvllservice_UDPMultiplexer.go      |  275 -
 .../bvllservice_UDPMultiplexer_plc4xgen.go         |  131 -
 .../bvllservice/bvllservice__MultiplexClient.go    |   50 -
 .../bvllservice/bvllservice__MultiplexServer.go    |   50 -
 .../bvllservice__MultiplexServer_plc4xgen.go       |   76 -
 .../bacnetip/bacgopes/bvllservice/mocks_test.go    |  776 --
 .../bacnetip/bacgopes/capability/capability.go     |   54 -
 .../bacgopes/capability/capability_Capability.go   |   61 -
 .../bacgopes/capability/capability_Collector.go    |  126 -
 .../capability/capability_capability_plc4xgen.go   |   72 -
 .../capability/capability_collector_plc4xgen.go    |   81 -
 .../bacnetip/bacgopes/capability/mocks_test.go     |  651 --
 plc4go/internal/bacnetip/bacgopes/comm/comm.go     |   43 -
 .../comm/comm_ApplicationServiceElement.go         |  144 -
 .../internal/bacnetip/bacgopes/comm/comm_Client.go |  119 -
 plc4go/internal/bacnetip/bacgopes/comm/comm_PDU.go |   89 -
 .../internal/bacnetip/bacgopes/comm/comm_Server.go |  124 -
 .../bacgopes/comm/comm_ServiceAccessPoint.go       |  147 -
 .../comm_applicationServiceElement_plc4xgen.go     |   77 -
 .../internal/bacnetip/bacgopes/comm/comm_bind.go   |  150 -
 .../bacnetip/bacgopes/comm/comm_client_plc4xgen.go |   77 -
 .../bacnetip/bacgopes/comm/comm_server_plc4xgen.go |   77 -
 .../comm/comm_serviceAccessPoint_plc4xgen.go       |   77 -
 .../internal/bacnetip/bacgopes/comm/mocks_test.go  | 5588 ------------
 plc4go/internal/bacnetip/bacgopes/comp/comp.go     |   25 -
 .../internal/bacnetip/bacgopes/comp/comp_Args.go   |  131 -
 .../internal/bacnetip/bacgopes/comp/comp_KWArgs.go |  121 -
 .../bacnetip/bacgopes/comp/comp_KnownKeys.go       |   96 -
 .../bacnetip/bacgopes/comp/comp_PriorityQueue.go   |  115 -
 .../bacnetip/bacgopes/comp/comp_commons.go         |  146 -
 .../internal/bacnetip/bacgopes/comp/comp_errors.go |   44 -
 .../bacnetip/bacgopes/comp/comp_inheritance.go     |  198 -
 .../bacgopes/comp/comp_inheritance_test.go         |  155 -
 .../bacnetip/bacgopes/comp/comp_interfaces.go      |   42 -
 .../bacnetip/bacgopes/comp/comp_options.go         |  117 -
 .../bacnetip/bacgopes/comp/comp_options_test.go    |  169 -
 .../internal/bacnetip/bacgopes/comp/comp_plc4x.go  |   68 -
 .../internal/bacnetip/bacgopes/comp/mocks_test.go  |  655 --
 .../bacgopes/constructeddata/constructeddata.go    |  243 -
 .../constructeddata/constructeddata_Any.go         |  119 -
 .../constructeddata/constructeddata_AnyAtomic.go   |   54 -
 .../constructeddata/constructeddata_Array.go       |   23 -
 .../constructeddata/constructeddata_Choice.go      |  368 -
 .../constructeddata/constructeddata_Element.go     |  110 -
 .../constructeddata/constructeddata_List.go        |   24 -
 .../constructeddata/constructeddata_Sequence.go    |  374 -
 .../constructeddata_SequenceOfAny.go               |   24 -
 .../bacgopes/constructeddata/mocks_test.go         | 1133 ---
 plc4go/internal/bacnetip/bacgopes/core/core.go     |  169 -
 .../bacnetip/bacgopes/debugging/debugging.go       |   33 -
 .../bacgopes/debugging/debugging_DebugContents.go  |  323 -
 .../bacgopes/debugging/debugging_DebugPrinter.go   |  132 -
 .../debugging/debugging_DefaultRFormatter.go       |   86 -
 .../bacgopes/debugging/debugging_commons.go        |  110 -
 .../bacnetip/bacgopes/debugging/mocks_test.go      |  189 -
 plc4go/internal/bacnetip/bacgopes/errors/errors.go |  305 -
 plc4go/internal/bacnetip/bacgopes/iocb/iocb.go     |   20 -
 .../internal/bacnetip/bacgopes/iocb/iocb_IOCB.go   |  309 -
 .../bacnetip/bacgopes/iocb/iocb_IOCB_plc4xgen.go   |  141 -
 .../bacnetip/bacgopes/iocb/iocb_IOController.go    |  176 -
 .../bacgopes/iocb/iocb_IOController_plc4xgen.go    |   76 -
 .../bacnetip/bacgopes/iocb/iocb_IOQController.go   |  295 -
 .../bacgopes/iocb/iocb_IOQController_plc4xgen.go   |   91 -
 .../bacnetip/bacgopes/iocb/iocb_IOQueue.go         |  158 -
 .../bacgopes/iocb/iocb_IOQueue_plc4xgen.go         |   72 -
 .../bacnetip/bacgopes/iocb/iocb_SieveQueue.go      |   63 -
 .../bacgopes/iocb/iocb_SieveQueue_plc4xgen.go      |   80 -
 .../internal/bacnetip/bacgopes/iocb/mocks_test.go  | 1043 ---
 .../bacnetip/bacgopes/local/device/device.go       |   26 -
 .../local/device/local_device_CurrentLocalTime.go  |   48 -
 ...ocal_device_CurrentProtocolServicesSupported.go |   48 -
 .../local/device/local_device_LocalDevice.go       |  376 -
 .../bacnetip/bacgopes/local/device/mocks_test.go   |  684 --
 .../local/object/object_CurrentPropertyList.go     |   48 -
 .../object/object_CurrentPropertyListMixIn.go      |   43 -
 .../bacnetip/bacgopes/netservice/netservice.go     |   33 -
 .../netservice/netservice_NetworkAdapter.go        |  151 -
 .../netservice_NetworkAdapter_plc4xgen.go          |   94 -
 .../netservice_NetworkServiceAccessPoint.go        |  865 --
 ...etservice_NetworkServiceAccessPoint_plc4xgen.go |  125 -
 .../netservice/netservice_NetworkServiceElement.go |  708 --
 .../netservice_NetworkServiceElement_plc4xgen.go   |   75 -
 .../netservice/netservice_RouterInfoCache.go       |  332 -
 .../netservice_RouterInfoCache_plc4xgen.go         |  122 -
 .../netservice/netservice_RouterInfo_plc4xgen.go   |   95 -
 .../netservice/netservice_Router_plc4xgen.go       |   95 -
 .../internal/bacnetip/bacgopes/npdu/mocks_test.go  | 4777 ----------
 plc4go/internal/bacnetip/bacgopes/npdu/npdu.go     |   58 -
 .../npdu/npdu_DisconnectConnectionToNetwork.go     |  108 -
 .../npdu/npdu_EstablishConnectionToNetwork.go      |  122 -
 .../bacgopes/npdu/npdu_IAmRouterToNetwork.go       |  106 -
 .../bacgopes/npdu/npdu_ICouldBeRouterToNetwork.go  |  122 -
 .../bacgopes/npdu/npdu_InitializeRoutingTable.go   |  138 -
 .../npdu/npdu_InitializeRoutingTableAck.go         |  138 -
 .../internal/bacnetip/bacgopes/npdu/npdu_NPCI.go   |  527 --
 .../internal/bacnetip/bacgopes/npdu/npdu_NPDU.go   |  233 -
 .../bacnetip/bacgopes/npdu/npdu_NetworkNumberIs.go |  129 -
 .../bacgopes/npdu/npdu_RejectMessageToNetwork.go   |  125 -
 .../bacgopes/npdu/npdu_RouterAvailableToNetwork.go |  101 -
 .../bacgopes/npdu/npdu_RouterBusyToNetwork.go      |  110 -
 .../bacgopes/npdu/npdu_RoutingTableEntry.go        |   91 -
 .../bacgopes/npdu/npdu_WhatIsNetworkNumber.go      |   81 -
 .../bacgopes/npdu/npdu_WhoIsRouterToNetwork.go     |  107 -
 .../bacnetip/bacgopes/object/mocks_test.go         | 3005 ------
 plc4go/internal/bacnetip/bacgopes/object/object.go |  286 -
 .../object/object_AccessCredentialObject.go        |   72 -
 .../bacgopes/object/object_AccessDoorObject.go     |   87 -
 .../bacgopes/object/object_AccessPointObject.go    |   94 -
 .../bacgopes/object/object_AccessRightsObject.go   |   55 -
 .../bacgopes/object/object_AccessUserObject.go     |   58 -
 .../bacgopes/object/object_AccessZoneObject.go     |   81 -
 .../bacgopes/object/object_AccumulatorObject.go    |   82 -
 .../object/object_AlertEnrollmentObject.go         |   59 -
 .../bacgopes/object/object_AnalogInputObject.go    |   80 -
 .../bacgopes/object/object_AnalogOutputObject.go   |   85 -
 .../bacgopes/object/object_AnalogValueObject.go    |   88 -
 .../bacgopes/object/object_AuditLogObject.go       |   67 -
 .../bacgopes/object/object_AuditReporterObject.go  |   67 -
 .../bacgopes/object/object_AveragingObject.go      |   58 -
 .../bacgopes/object/object_BinaryInputObject.go    |   77 -
 .../object/object_BinaryLightingOutputObject.go    |   79 -
 .../bacgopes/object/object_BinaryOutputObject.go   |   87 -
 .../bacgopes/object/object_BinaryValueObject.go    |   84 -
 .../bacgopes/object/object_BitStringValueObject.go |   76 -
 .../bacgopes/object/object_CalendarObject.go       |   49 -
 .../bacgopes/object/object_ChannelObject.go        |   70 -
 .../object/object_CharacterStringValueObject.go    |   76 -
 .../bacgopes/object/object_CommandObject.go        |   65 -
 .../object/object_CredentialDataInputObject.go     |   64 -
 .../object/object_DatePatternValueObject.go        |   70 -
 .../object/object_DateTimePatternValueObject.go    |   73 -
 .../bacgopes/object/object_DateTimeValueObject.go  |   71 -
 .../bacgopes/object/object_DateValueObject.go      |   70 -
 .../bacgopes/object/object_DeviceObject.go         |  113 -
 .../bacgopes/object/object_ElevatorGroupObject.go  |   53 -
 .../bacgopes/object/object_EscalatorObject.go      |   74 -
 .../object/object_EventEnrollmentObject.go         |   67 -
 .../bacgopes/object/object_EventLogObject.go       |   72 -
 .../bacgopes/object/object_EventLogRecord.go       |   43 -
 .../object/object_EventLogRecordLogDatum.go        |   45 -
 .../bacnetip/bacgopes/object/object_FileObject.go  |   54 -
 .../bacgopes/object/object_GlobalGroupObject.go    |   74 -
 .../bacnetip/bacgopes/object/object_GroupObject.go |   48 -
 .../bacgopes/object/object_IntegerValueObject.go   |   85 -
 .../object/object_LargeAnalogValueObject.go        |   85 -
 .../object/object_LifeSafetyPointObject.go         |   82 -
 .../bacgopes/object/object_LifeSafetyZoneObject.go |   80 -
 .../bacnetip/bacgopes/object/object_LiftObject.go  |   91 -
 .../bacgopes/object/object_LightingOutputObject.go |   78 -
 .../bacgopes/object/object_LoadControlObject.go    |   77 -
 .../bacnetip/bacgopes/object/object_LoopObject.go  |   89 -
 .../object/object_MultiStateInputObject.go         |   72 -
 .../object/object_MultiStateOutputObject.go        |   79 -
 .../object/object_MultiStateValueObject.go         |   77 -
 .../bacgopes/object/object_NetworkPortObject.go    |  111 -
 .../object/object_NetworkSecurityObject.go         |   58 -
 .../object/object_NotificationClassObject.go       |   62 -
 .../object/object_NotificationForwarderObject.go   |   56 -
 .../bacnetip/bacgopes/object/object_Object.go      |  238 -
 .../object/object_ObjectIdentifierProperty.go      |   70 -
 .../object/object_OctetStringValueObject.go        |   61 -
 .../bacgopes/object/object_OptionalProperty.go     |   37 -
 .../object/object_PositiveIntegerValueObject.go    |   85 -
 .../bacgopes/object/object_ProgramObject.go        |   65 -
 .../bacnetip/bacgopes/object/object_Property.go    |  166 -
 .../bacgopes/object/object_PulseConverterObject.go |   80 -
 .../bacgopes/object/object_ReadableProperty.go     |   38 -
 .../bacgopes/object/object_ScheduleObject.go       |   68 -
 .../bacgopes/object/object_StagingObject.go        |   72 -
 .../bacgopes/object/object_StandardProperty.go     |   38 -
 .../bacgopes/object/object_StructuredViewObject.go |   56 -
 .../object/object_TimePatternValueObject.go        |   70 -
 .../bacgopes/object/object_TimeValueObject.go      |   69 -
 .../bacnetip/bacgopes/object/object_TimerObject.go |   79 -
 .../bacgopes/object/object_TrendLogObject.go       |   83 -
 .../bacgopes/object/object_WritableProperty.go     |   32 -
 plc4go/internal/bacnetip/bacgopes/pdu/comm_PCI.go  |  213 -
 .../internal/bacnetip/bacgopes/pdu/comm_PDUData.go |  172 -
 .../internal/bacnetip/bacgopes/pdu/mocks_test.go   | 3795 --------
 plc4go/internal/bacnetip/bacgopes/pdu/pdu.go       |  169 -
 .../internal/bacnetip/bacgopes/pdu/pdu_Address.go  |  898 --
 .../bacnetip/bacgopes/pdu/pdu_Address_plc4xgen.go  |  130 -
 plc4go/internal/bacnetip/bacgopes/pdu/pdu_PCI.go   |  138 -
 plc4go/internal/bacnetip/bacgopes/pdu/pdu_PDU.go   |   81 -
 .../bacnetip/bacgopes/primitivedata/mocks_test.go  | 1567 ----
 .../bacgopes/primitivedata/primitivedata.go        |   20 -
 .../primitivedata/primitivedata_ApplicationTag.go  |   68 -
 .../bacgopes/primitivedata/primitivedata_Atomic.go |  111 -
 .../primitivedata/primitivedata_BitString.go       |  226 -
 .../primitivedata/primitivedata_Boolean.go         |  125 -
 .../primitivedata/primitivedata_CharacterString.go |  126 -
 .../primitivedata/primitivedata_ClosingTag.go      |   55 -
 .../primitivedata/primitivedata_CommonMath.go      |   24 -
 .../primitivedata/primitivedata_ContextTag.go      |   71 -
 .../bacgopes/primitivedata/primitivedata_Date.go   |  380 -
 .../bacgopes/primitivedata/primitivedata_Double.go |  109 -
 .../primitivedata/primitivedata_Enumeration.go     |  263 -
 .../primitivedata/primitivedata_Integer.go         |  154 -
 .../bacgopes/primitivedata/primitivedata_Null.go   |  104 -
 .../primitivedata_ObjectIdentifier.go              |  259 -
 .../primitivedata/primitivedata_ObjectType.go      |  166 -
 .../primitivedata/primitivedata_OctetString.go     |  126 -
 .../primitivedata/primitivedata_OpeningTag.go      |   55 -
 .../bacgopes/primitivedata/primitivedata_Real.go   |  119 -
 .../bacgopes/primitivedata/primitivedata_Tag.go    |  454 -
 .../primitivedata/primitivedata_TagList.go         |  185 -
 .../bacgopes/primitivedata/primitivedata_Time.go   |  235 -
 .../primitivedata/primitivedata_Unsigned.go        |  156 -
 .../primitivedata/primitivedata_Unsigned16.go      |  143 -
 .../primitivedata/primitivedata_Unsigned8.go       |  143 -
 .../bacnetip/bacgopes/service/Subscription.go      |   31 -
 plc4go/internal/bacnetip/bacgopes/service/cov.go   |   22 -
 .../bacgopes/service/cov_AccessDoorCriteria.go     |   25 -
 .../bacgopes/service/cov_AccessPointCriteria.go    |   25 -
 .../bacnetip/bacgopes/service/cov_COVDetection.go  |   25 -
 .../bacgopes/service/cov_COVIncrementCriteria.go   |   25 -
 .../bacgopes/service/cov_ChangeOfValuesServices.go |   29 -
 .../service/cov_CredentialDataInputCriteria.go     |   25 -
 .../bacgopes/service/cov_GenericCriteria.go        |   25 -
 .../bacgopes/service/cov_LoadControlCriteria.go    |   25 -
 .../bacgopes/service/cov_PulseConverterCriteria.go |   25 -
 .../bacgopes/service/cov_SubscriptionList.go       |   24 -
 .../internal/bacnetip/bacgopes/service/detect.go   |   24 -
 .../bacnetip/bacgopes/service/mocks_test.go        |  171 -
 .../internal/bacnetip/bacgopes/service/service.go  |   24 -
 .../bacgopes/service/service_device_Device.go      |   50 -
 .../service/service_device_WhoIsIAmServices.go     |  279 -
 .../service_device_WhoIsIAmServices_plc4xgen.go    |   78 -
 .../service_object_ReadWritePropertyServices.go    |   35 -
 ...ce_object_ReadWritePropertyServices_plc4xgen.go |   68 -
 plc4go/internal/bacnetip/bacgopes/settings.go      |   38 -
 .../internal/bacnetip/bacgopes/task/mocks_test.go  |  816 --
 plc4go/internal/bacnetip/bacgopes/task/task.go     |   83 -
 .../bacgopes/task/task_OneShotDeleteTask.go        |   41 -
 .../task/task_OneShotDeleteTask_plc4xgen.go        |   71 -
 .../bacgopes/task/task_OneShotFunctionTask.go      |   47 -
 .../task/task_OneShotFunctionTask_plc4xgen.go      |   85 -
 .../bacnetip/bacgopes/task/task_OneShotTask.go     |   37 -
 .../bacgopes/task/task_OneShotTask_plc4xgen.go     |   71 -
 .../bacgopes/task/task_RecurringFunctionTask.go    |   67 -
 .../bacnetip/bacgopes/task/task_RecurringTask.go   |  138 -
 .../internal/bacnetip/bacgopes/task/task_Task.go   |  122 -
 .../bacnetip/bacgopes/task/task_TaskManager.go     |  318 -
 .../bacnetip/bacgopes/task/task_Task_plc4xgen.go   |   81 -
 .../bacgopes/task/task_taskItem_plc4xgen.go        |   84 -
 .../internal/bacnetip/bacgopes/tests/quick/apdu.go |   41 -
 .../internal/bacnetip/bacgopes/tests/quick/bvll.go |  127 -
 .../bacgopes/tests/quick/constructeddata.go        |   30 -
 .../internal/bacnetip/bacgopes/tests/quick/npdu.go |  130 -
 .../internal/bacnetip/bacgopes/tests/quick/pdu.go  |   45 -
 .../bacnetip/bacgopes/tests/quick/primitivedata.go |  278 -
 .../bacgopes/tests/state_machine/mocks_test.go     | 6954 --------------
 .../bacgopes/tests/state_machine/state_machine.go  |  669 --
 .../state_machine_ClientStateMachine.go            |  118 -
 .../state_machine_ClientStateMachine_plc4xgen.go   |   85 -
 .../state_machine_ServerStateMachine.go            |   69 -
 .../state_machine_ServerStateMachine_plc4xgen.go   |   78 -
 .../tests/state_machine/state_machine_State.go     |  580 --
 .../state_machine/state_machine_StateMachine.go    |  866 --
 .../state_machine_StateMachineGroup.go             |  330 -
 .../state_machine_StateMachineGroup_plc4xgen.go    |  111 -
 .../state_machine/state_machine_TimeoutTask.go     |   65 -
 .../state_machine_TimeoutTask_plc4xgen.go          |   85 -
 .../state_machine/state_machine_TrafficLog.go      |   59 -
 .../state_machine_stateMachine_plc4xgen.go         |  203 -
 .../test_max_apdu_length_accepted_test.go          |   22 -
 .../test_apdu/test_max_segments_accepted_test.go   |   22 -
 .../tests/test_base_types/test_name_value_test.go  |   22 -
 .../bacnetip/bacgopes/tests/test_bvll/helpers.go   |   43 -
 .../tests/test_bvll/helpers_BIPBBMDApplication.go  |  173 -
 .../tests/test_bvll/helpers_BIPBBMDNode.go         |   97 -
 .../tests/test_bvll/helpers_BIPBBMDStateMachine.go |   95 -
 .../test_bvll/helpers_BIPForeignStateMachine.go    |   89 -
 ...elpers_BIPSimpleApplicationLayerStateMachine.go |  164 -
 ...PSimpleApplicationLayerStateMachine_plc4xgen.go |  150 -
 .../tests/test_bvll/helpers_BIPSimpleNode.go       |   72 -
 .../test_bvll/helpers_BIPSimpleStateMachine.go     |   85 -
 .../tests/test_bvll/helpers_BIPStateMachine.go     |   79 -
 .../tests/test_bvll/helpers_FauxMultiplexer.go     |  148 -
 .../test_bvll/helpers_FauxMultiplexer_plc4xgen.go  |   92 -
 .../tests/test_bvll/helpers_SnifferStateMachine.go |   85 -
 .../test_bvll/helpers__NetworkServiceElement.go    |   44 -
 .../bacgopes/tests/test_bvll/test_bbmd_test.go     |  345 -
 .../bacgopes/tests/test_bvll/test_codec_test.go    |  463 -
 .../bacgopes/tests/test_bvll/test_foreign_test.go  |  328 -
 .../bacgopes/tests/test_bvll/test_simple_test.go   |  177 -
 .../tests/test_comm/test_capability_test.go        |  206 -
 .../bacgopes/tests/test_comm/test_client_test.go   |   22 -
 .../bacgopes/tests/test_comm/test_pci_test.go      |   22 -
 .../bacgopes/tests/test_comm/test_pdu_test.go      |   22 -
 .../bacgopes/tests/test_comm/test_pdudata_test.go  |   22 -
 .../bacgopes/tests/test_comm/test_server_test.go   |   22 -
 .../tests/test_constructed_data/helpers.go         |  163 -
 .../tests/test_constructed_data/mocks_test.go      |  102 -
 .../test_constructed_data/test_any_atomic_test.go  |   20 -
 .../tests/test_constructed_data/test_any_test.go   |   20 -
 .../test_constructed_data/test_array_of_test.go    |   20 -
 .../test_constructed_data/test_choice_test.go      |   20 -
 .../test_constructed_data/test_sequence_test.go    |  192 -
 .../tests_sequence_of_test.go                      |   20 -
 .../tests/test_iocb/test_clientcontroller_test.go  |   22 -
 .../bacgopes/tests/test_iocb/test_iocb_test.go     |   22 -
 .../bacgopes/tests/test_iocb/test_iochain_test.go  |   22 -
 .../tests/test_iocb/test_iocontroller_test.go      |   22 -
 .../bacgopes/tests/test_iocb/test_iogroup_test.go  |   22 -
 .../tests/test_iocb/test_ioqcontroller_test.go     |   22 -
 .../bacgopes/tests/test_iocb/test_ioqueue_test.go  |   22 -
 .../test_iocb/test_sieveclientcontroller_test.go   |   22 -
 .../tests/test_local/test_local_schedule_1_test.go |   22 -
 .../tests/test_local/test_local_schedule_2_test.go |   22 -
 .../bacgopes/tests/test_network/helpers.go         |   32 -
 .../helpers_ApplicationLayerStateMachine.go        |  170 -
 ...elpers_ApplicationLayerStateMachine_plc4xgen.go |  129 -
 .../tests/test_network/helpers_ApplicationNode.go  |  156 -
 .../helpers_ApplicationNode_plc4xgen.go            |  137 -
 .../tests/test_network/helpers_NPDUCodec.go        |  114 -
 .../test_network/helpers_NPDUCodec_plc4xgen.go     |   74 -
 .../helpers_NetworkLayerStateMachine.go            |   85 -
 .../tests/test_network/helpers_RouterNode.go       |   86 -
 .../test_network/helpers_RouterStaterMachine.go    |   59 -
 .../test_network/helpers_SnifferStateMachine.go    |   76 -
 .../tests/test_network/helpers_TestDeviceObject.go |   41 -
 .../test_network/helpers__NetworkServiceElement.go |   48 -
 .../bacgopes/tests/test_network/settings.go        |   28 -
 .../bacgopes/tests/test_network/test_net_1_test.go |  299 -
 .../bacgopes/tests/test_network/test_net_2_test.go |  299 -
 .../bacgopes/tests/test_network/test_net_3_test.go |  332 -
 .../bacgopes/tests/test_network/test_net_4_test.go |   22 -
 .../bacgopes/tests/test_network/test_net_5_test.go |   22 -
 .../bacgopes/tests/test_network/test_net_6_test.go |   22 -
 .../bacgopes/tests/test_network/test_net_7_test.go |   22 -
 .../bacgopes/tests/test_npdu/NPDUCodec_plc4xgen.go |   74 -
 .../bacnetip/bacgopes/tests/test_npdu/helpers.go   |  111 -
 .../bacgopes/tests/test_npdu/test_codec_test.go    |  588 --
 .../bacgopes/tests/test_pdu/test_address_test.go   |  617 --
 .../bacgopes/tests/test_pdu/test_pci_test.go       |   22 -
 .../bacgopes/tests/test_pdu/test_pdu_test.go       |   22 -
 .../tests/test_primitive_data/common_test.go       |   32 -
 .../test_primitive_data/test_bit_string_test.go    |  184 -
 .../tests/test_primitive_data/test_boolean_test.go |  119 -
 .../test_character_string_test.go                  |  138 -
 .../tests/test_primitive_data/test_date_test.go    |  123 -
 .../tests/test_primitive_data/test_double_test.go  |  117 -
 .../test_primitive_data/test_enumerated_test.go    |  172 -
 .../tests/test_primitive_data/test_integer_test.go |  144 -
 .../tests/test_primitive_data/test_null_test.go    |  110 -
 .../test_object_identifier_test.go                 |  152 -
 .../test_primitive_data/test_object_type_test.go   |  183 -
 .../test_primitive_data/test_octet_string_test.go  |  116 -
 .../tests/test_primitive_data/test_real_test.go    |  131 -
 .../tests/test_primitive_data/test_tag_test.go     |  495 -
 .../tests/test_primitive_data/test_time_test.go    |  128 -
 .../test_primitive_data/test_unsigned_test.go      |  161 -
 .../ApplicationStateMachine_plc4xgen_test.go       |   68 -
 .../test_segmentation/SnifferNode_plc4xgen_test.go |   68 -
 .../tests/test_segmentation/test_1_test.go         |  490 -
 .../ApplicationStateMachine_plc4xgen.go            |  128 -
 .../tests/test_service/SnifferNode_plc4xgen.go     |   93 -
 .../test_service/SnifferStateMachine_plc4xgen.go   |   96 -
 .../bacgopes/tests/test_service/helpers.go         |  510 --
 .../bacgopes/tests/test_service/mocks_test.go      |   55 -
 .../tests/test_service/test_cov_av_test.go         |   22 -
 .../tests/test_service/test_cov_bv_test.go         |   22 -
 .../tests/test_service/test_cov_pc_test.go         |   22 -
 .../tests/test_service/test_device_2_test.go       |   22 -
 .../tests/test_service/test_device_test.go         |   22 -
 .../bacgopes/tests/test_service/test_file_test.go  |   22 -
 .../tests/test_service/test_object_test.go         |   22 -
 .../test_client_state_machine_test.go              |   66 -
 .../test_server_state_machine_test.go              |   66 -
 .../test_service_access_point_test.go              |  233 -
 .../test_utilities/test_state_machine_test.go      |  782 --
 .../tests/test_utilities/test_time_machine_test.go |  307 -
 .../tests/test_vlan/test_ipnetwork_test.go         |  425 -
 .../bacgopes/tests/test_vlan/test_network_test.go  |  342 -
 plc4go/internal/bacnetip/bacgopes/tests/tests.go   |   24 -
 .../bacgopes/tests/time_machine/time_machine.go    |   24 -
 .../tests/time_machine/time_machine_TimeMachine.go |  353 -
 .../bacgopes/tests/trapped_classes/mocks_test.go   | 1048 ---
 .../tests/trapped_classes/trapped_classes.go       |   24 -
 ...ped_classes_TrappedApplicationServiceElement.go |  145 -
 .../trapped_classes_TrappedClient.go               |  106 -
 .../trapped_classes_TrappedClientStateMachine.go   |   73 -
 .../trapped_classes_TrappedClient_plc4xgen.go      |   85 -
 .../trapped_classes_TrappedServer.go               |  106 -
 .../trapped_classes_TrappedServerStateMachine.go   |   69 -
 .../trapped_classes_TrappedServer_plc4xgen.go      |   85 -
 .../trapped_classes_TrappedServiceAccessPoint.go   |  139 -
 .../trapped_classes_TrappedState.go                |   80 -
 .../trapped_classes_TrappedStateMachine.go         |   99 -
 .../trapped_classes/trapped_classes_Trapper.go     |  159 -
 plc4go/internal/bacnetip/bacgopes/tests/util.go    |   42 -
 plc4go/internal/bacnetip/bacgopes/udp/udp.go       |   20 -
 .../internal/bacnetip/bacgopes/udp/udp_UDPActor.go |  105 -
 .../bacnetip/bacgopes/udp/udp_UDPActor_plc4xgen.go |   86 -
 .../bacnetip/bacgopes/udp/udp_UDPDirector.go       |  294 -
 .../bacgopes/udp/udp_UDPDirector_plc4xgen.go       |  130 -
 .../internal/bacnetip/bacgopes/vlan/mocks_test.go  |  601 --
 plc4go/internal/bacnetip/bacgopes/vlan/vlan.go     |   24 -
 .../bacnetip/bacgopes/vlan/vlan_IPNetwork.go       |   72 -
 .../internal/bacnetip/bacgopes/vlan/vlan_IPNode.go |   64 -
 .../bacnetip/bacgopes/vlan/vlan_IPNode_plc4xgen.go |   81 -
 .../bacnetip/bacgopes/vlan/vlan_IPRouter.go        |   96 -
 .../bacnetip/bacgopes/vlan/vlan_IPRouterNode.go    |  107 -
 .../bacgopes/vlan/vlan_IPRouterNode_plc4xgen.go    |  112 -
 .../bacnetip/bacgopes/vlan/vlan_Network.go         |  180 -
 .../internal/bacnetip/bacgopes/vlan/vlan_Node.go   |  176 -
 .../bacnetip/bacgopes/vlan/vlan_Node_plc4xgen.go   |  103 -
 .../bacnetip/bacgopes/vlan/vlan_TrafficLogger.go   |   26 -
 ...tiveCOVSubscription.go => mock_requirements.go} |   17 +-
 plc4go/spi/transports/udp/TransportInstance.go     |   21 +-
 plc4go/tests/integration/bacnetip/Dockerfile       |   39 +
 plc4go/tests/integration/bacnetip/README.md        |   69 +
 plc4go/tests/integration/bacnetip/device.py        |  118 +
 .../tests/integration/bacnetip/docker-compose.yml  |   36 +
 .../tests/integration/bacnetip/integration_test.go |  224 +
 842 files changed, 4063 insertions(+), 121272 deletions(-)

diff --git a/plc4go/Makefile b/plc4go/Makefile
index 10514f4bce..45b932a39f 100644
--- a/plc4go/Makefile
+++ b/plc4go/Makefile
@@ -61,6 +61,13 @@ test: compile
 test-readable: compile
 	@GOPATH=$(GOPATH) GOBIN=$(GOBIN) go tool -modfile=tools.mod gotestsum ./...
 
+## integration-bacnetip: Bring up the bacpypes3 simulator + run the BACnet/IP integration tests.
+## Tears the container down on exit even if a test fails.
+integration-bacnetip:
+	@docker compose -f tests/integration/bacnetip/docker-compose.yml up -d --build
+	@trap 'docker compose -f tests/integration/bacnetip/docker-compose.yml down' EXIT; \
+		BACNET_IT=1 go test -tags integration ./tests/integration/bacnetip/... -v -count=1 -timeout 120s
+
 test-readable-mvn: compile
 	$(MVNBIN) mvn-golang-wrapper:custom@readable-test
 
diff --git a/plc4go/go.mod b/plc4go/go.mod
index 5a0b805598..a1f28935d3 100644
--- a/plc4go/go.mod
+++ b/plc4go/go.mod
@@ -29,7 +29,6 @@ require (
 	github.com/google/uuid v1.6.0
 	github.com/gopacket/gopacket v1.5.0
 	github.com/jacobsa/go-serial v0.0.0-20180131005756-15cf729a72d4
-	github.com/libp2p/go-reuseport v0.4.0
 	github.com/rs/zerolog v1.35.1
 	github.com/stretchr/testify v1.11.1
 	golang.org/x/net v0.54.0
diff --git a/plc4go/go.sum b/plc4go/go.sum
index 42ad20b66c..85f32f8473 100644
--- a/plc4go/go.sum
+++ b/plc4go/go.sum
@@ -20,8 +20,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
-github.com/libp2p/go-reuseport v0.4.0 h1:nR5KU7hD0WxXCJbmw7r2rhRYruNRl2koHw8fQscQm2s=
-github.com/libp2p/go-reuseport v0.4.0/go.mod h1:ZtI03j/wO5hZVDFo2jKywN6bYKWLOy8Se6DrI2E1cLU=
 github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
 github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
 github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4=
diff --git a/plc4go/internal/bacnetip/ApplicationLayerMessageCodec.go b/plc4go/internal/bacnetip/ApplicationLayerMessageCodec.go
deleted file mode 100644
index 0b6a44a932..0000000000
--- a/plc4go/internal/bacnetip/ApplicationLayerMessageCodec.go
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * 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 bacnetip
-
-import (
-	"context"
-	"fmt"
-	"net"
-	"net/url"
-	"sync"
-
-	"github.com/rs/zerolog"
-
-	"github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/app"
-	"github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/appservice"
-	"github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
-	"github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/iocb"
-	"github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/local/device"
-	"github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/pdu"
-	"github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
-	"github.com/apache/plc4x/plc4go/spi"
-	"github.com/apache/plc4x/plc4go/spi/errors"
-	"github.com/apache/plc4x/plc4go/spi/transports/udp"
-)
-
-// ApplicationLayerMessageCodec is a wrapper for MessageCodec which takes care of segmentation, retries etc.
-//
-//go:generate go tool plc4xGenerator -type=ApplicationLayerMessageCodec
-type ApplicationLayerMessageCodec struct {
-	bipSimpleApplication *app.BIPSimpleApplication
-	messageCode          *MessageCodec
-	deviceInfoCache      appservice.DeviceInfoCache `directSerialize:"true"`
-
-	localAddress  *net.UDPAddr `stringer:"true"`
-	remoteAddress *net.UDPAddr `stringer:"true"`
-
-	wg sync.WaitGroup // use to track spawned go routines
-
-	log zerolog.Logger
-}
-
-var (
-	_ spi.TransportInstanceExposer = (*MessageCodec)(nil)
-)
-
-func NewApplicationLayerMessageCodec(localLog zerolog.Logger, udpTransport *udp.Transport, transportUrl url.URL, options map[string][]string, localAddress *net.UDPAddr, remoteAddress *net.UDPAddr) (*ApplicationLayerMessageCodec, error) {
-	// TODO: currently this is done by the BIP down below
-	// Have the transport create a new transport-instance.
-	//transportInstance, err := udpTransport.CreateTransportInstanceForLocalAddress(transportUrl, options, localAddress)
-	//if err != nil {
-	//	return nil, errors.Wrap(err, "error creating transport instance")
-	//}
-	a := &ApplicationLayerMessageCodec{
-		localAddress:  localAddress,
-		remoteAddress: remoteAddress,
-
-		log: localLog,
-	}
-	address, err := pdu.NewAddress(comp.NewArgs(localAddress))
-	if err != nil {
-		return nil, errors.Wrap(err, "error creating address")
-	}
-	// TODO: workaround for strange address parsing
-	address.AddrTuple = pdu.NewAddressTuple(fmt.Sprintf("%d.%d.%d.%d", address.AddrAddress[0], address.AddrAddress[1], address.AddrAddress[2], address.AddrAddress[3]), *address.AddrPort)
-	localDeviceObject, err := device.NewLocalDeviceObject(comp.NoArgs,
-		comp.NewKWArgs(comp.KWNumberOfAPDURetries, func() *uint { retries := uint(10); return &retries }()),
-	)
-	if err != nil {
-		return nil, errors.Wrap(err, "error creating local device object")
-	}
-	application, err := app.NewBIPSimpleApplication(localLog, localDeviceObject, *address, app.WithApplicationDeviceInfoCache(&a.deviceInfoCache))
-	if err != nil {
-		return nil, errors.Wrap(err, "error creating application")
-	}
-	a.bipSimpleApplication = application
-	// TODO: this is currently done by the BIP
-	//a.messageCode = NewMessageCodec(transportInstance)
-	return a, nil
-}
-
-func (m *ApplicationLayerMessageCodec) GetCodec() spi.MessageCodec {
-	return m
-}
-
-func (m *ApplicationLayerMessageCodec) Connect(ctx context.Context) error {
-	// TODO: this is currently done by the BIP
-	//	return m.messageCode.Connect(ctx)
-	return nil
-}
-
-func (m *ApplicationLayerMessageCodec) Disconnect() error {
-	if err := m.bipSimpleApplication.Close(); err != nil {
-		m.log.Error().Err(err).Msg("error closing application")
-	}
-	return m.messageCode.Disconnect()
-}
-
-func (m *ApplicationLayerMessageCodec) IsRunning() bool {
-	return m.messageCode.IsRunning()
-}
-
-func (m *ApplicationLayerMessageCodec) Send(ctx context.Context, interactionInfo string, message spi.Message) error {
-	address, err := pdu.NewAddress(comp.NewArgs(m.remoteAddress))
-	if err != nil {
-		return err
-	}
-	_iocb, err := iocb.NewIOCB(m.log, pdu.NewPDU(comp.NewArgs(message), comp.NewKWArgs(comp.KWCPCIDestination, address)), address)
-	if err != nil {
-		return errors.Wrap(err, "error creating IOCB")
-	}
-	m.wg.Go(func() {
-		m.wg.Go(func() {
-			if err := m.bipSimpleApplication.RequestIO(_iocb); err != nil {
-				m.log.Debug().Err(err).Msg("errored")
-			}
-		})
-		_iocb.Wait()
-		if err := _iocb.GetIOError(); err != nil {
-			// TODO: handle error
-			fmt.Printf("Err: %v\n", err)
-		} else if _iocb.GetIOResponse() != nil {
-			// TODO: response?
-			fmt.Printf("Response: %v\n", _iocb.GetIOResponse())
-		} else {
-			// TODO: what now?
-		}
-	})
-	return nil
-}
-
-func (m *ApplicationLayerMessageCodec) Expect(ctx context.Context, interactionInfo string, acceptsMessage spi.AcceptsMessage, handleMessage spi.HandleMessage, handleError spi.HandleError) {
-	// TODO: implement me
-	panic("not yet implemented")
-}
-
-func (m *ApplicationLayerMessageCodec) SendRequest(ctx context.Context, interactionInfo string, message spi.Message, acceptsMessage spi.AcceptsMessage, handleMessage spi.HandleMessage, handleError spi.HandleError) error {
-	address, err := pdu.NewAddress(comp.NewArgs(m.remoteAddress))
-	if err != nil {
-		return err
-	}
-	_iocb, err := iocb.NewIOCB(m.log, pdu.NewPDU(comp.NewArgs(message), comp.NewKWArgs(comp.KWCPCIDestination, address)), address)
-	if err != nil {
-		return errors.Wrap(err, "error creating IOCB")
-	}
-	m.wg.Go(func() {
-		m.wg.Go(func() {
-			if err := m.bipSimpleApplication.RequestIO(_iocb); err != nil {
-				m.log.Error().Err(err).Msg("errored")
-			}
-		})
-		_iocb.Wait()
-		if err := _iocb.GetIOError(); err != nil {
-			if err := handleError(err); err != nil {
-				m.log.Debug().Err(err).Msg("error handling error")
-				return
-			}
-		} else if response := _iocb.GetIOResponse(); response != nil {
-			// TODO: we wrap it into a BVLC for now. Once we change the Readers etc. to accept apdus we can remove that
-			tempBVLC := model.NewBVLCOriginalUnicastNPDU(
-				model.NewNPDU(
-					0,
-					model.NewNPDUControl(
-						false,
-						false,
-						false,
-						false,
-						model.NPDUNetworkPriority_NORMAL_MESSAGE,
-					),
-					nil,
-					nil,
-					nil,
-					nil,
-					nil,
-					nil,
-					nil,
-					nil,
-					response.GetRootMessage().(model.APDU),
-				),
-			)
-			if acceptsMessage(tempBVLC) {
-				if err := handleMessage(
-					tempBVLC,
-				); err != nil {
-					m.log.Debug().Err(err).Msg("error handling message")
-					return
-				}
-			}
-		} else {
-			// TODO: what now?
-		}
-	})
-	return nil
-}
-
-func (m *ApplicationLayerMessageCodec) GetDefaultIncomingMessageChannel() chan spi.Message {
-	// TODO: this is currently done by the BIP
-	//return m.messageCode.GetDefaultIncomingMessageChannel()
-	return make(chan spi.Message)
-}
diff --git a/plc4go/internal/bacnetip/ApplicationLayerMessageCodec_plc4xgen.go b/plc4go/internal/bacnetip/ApplicationLayerMessageCodec_plc4xgen.go
deleted file mode 100644
index 181ab07740..0000000000
--- a/plc4go/internal/bacnetip/ApplicationLayerMessageCodec_plc4xgen.go
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * 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.
- */
-
-// Code generated by "plc4xGenerator -type=ApplicationLayerMessageCodec"; DO NOT EDIT.
-
-package bacnetip
-
-import (
-	"context"
-	"encoding/binary"
-	"fmt"
-	"github.com/apache/plc4x/plc4go/spi/utils"
-)
-
-var _ = fmt.Printf
-
-func (d *ApplicationLayerMessageCodec) Serialize() ([]byte, error) {
-	if d == nil {
-		return nil, fmt.Errorf("(*DeviceInfoCache)(nil)")
-	}
-	wb := utils.NewWriteBufferByteBased(utils.WithByteOrderForByteBasedBuffer(binary.BigEndian))
-	if err := d.SerializeWithWriteBuffer(context.Background(), wb); err != nil {
-		return nil, err
-	}
-	return wb.GetBytes(), nil
-}
-
-func (d *ApplicationLayerMessageCodec) SerializeWithWriteBuffer(ctx context.Context, writeBuffer utils.WriteBuffer) error {
-	if d == nil {
-		return fmt.Errorf("(*DeviceInfoCache)(nil)")
-	}
-	if err := writeBuffer.PushContext("ApplicationLayerMessageCodec"); err != nil {
-		return err
-	}
-
-	if d.bipSimpleApplication != nil {
-		if serializableField, ok := any(d.bipSimpleApplication).(utils.Serializable); ok {
-			if err := writeBuffer.PushContext("bipSimpleApplication"); err != nil {
-				return err
-			}
-			if err := serializableField.SerializeWithWriteBuffer(ctx, writeBuffer); err != nil {
-				return err
-			}
-			if err := writeBuffer.PopContext("bipSimpleApplication"); err != nil {
-				return err
-			}
-		} else {
-			stringValue := fmt.Sprintf("%v", d.bipSimpleApplication)
-			if err := writeBuffer.WriteString("bipSimpleApplication", uint32(len(stringValue)*8), stringValue); err != nil {
-				return err
-			}
-		}
-	}
-	if d.messageCode != nil {
-		{
-			_value := fmt.Sprintf("%v", d.messageCode)
-
-			if err := writeBuffer.WriteString("messageCode", uint32(len(_value)*8), _value); err != nil {
-				return err
-			}
-		}
-	}
-
-	if err := writeBuffer.PushContext("deviceInfoCache"); err != nil {
-		return err
-	}
-	if err := d.deviceInfoCache.SerializeWithWriteBuffer(ctx, writeBuffer); err != nil {
-		return err
-	}
-	if err := writeBuffer.PopContext("deviceInfoCache"); err != nil {
-		return err
-	}
-	if d.localAddress != nil {
-		if err := writeBuffer.WriteString("localAddress", uint32(len(d.localAddress.String())*8), d.localAddress.String()); err != nil {
-			return err
-		}
-	}
-	if d.remoteAddress != nil {
-		if err := writeBuffer.WriteString("remoteAddress", uint32(len(d.remoteAddress.String())*8), d.remoteAddress.String()); err != nil {
-			return err
-		}
-	}
-	if err := writeBuffer.PopContext("ApplicationLayerMessageCodec"); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (d *ApplicationLayerMessageCodec) String() string {
-	if alternateStringer, ok := any(d).(utils.AlternateStringer); ok {
-		if alternateString, use := alternateStringer.AlternateString(); use {
-			return alternateString
-		}
-	}
-	wb := utils.NewWriteBufferBoxBased(utils.WithWriteBufferBoxBasedMergeSingleBoxes(), utils.WithWriteBufferBoxBasedOmitEmptyBoxes())
-	if err := wb.WriteSerializable(context.Background(), d); err != nil {
-		return err.Error()
-	}
-	return wb.GetBox().String()
-}
diff --git a/plc4go/internal/bacnetip/Configuration.go b/plc4go/internal/bacnetip/Configuration.go
new file mode 100644
index 0000000000..dfe282339f
--- /dev/null
+++ b/plc4go/internal/bacnetip/Configuration.go
@@ -0,0 +1,167 @@
+/*
+ * 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 bacnetip
+
+import (
+	"reflect"
+	"strconv"
+	"strings"
+
+	"github.com/rs/zerolog"
+
+	"github.com/apache/plc4x/plc4go/spi/errors"
+)
+
+// Configuration captures driver-level options parsed from the connection URL.
+// String/uint/bool fields are populated reflectively from driverOptions keyed by
+// title-cased field name (e.g. "LocalDeviceId").
+//
+//go:generate go tool plc4xGenerator -type=Configuration
+type Configuration struct {
+	// LocalDeviceId is the BACnet device-instance number this driver claims when issuing
+	// IAm and identifying itself in confirmed-request initiators. Range 0..4194303.
+	LocalDeviceId uint32
+
+	// LocalNetworkNumber is the BACnet network number for this driver's NPDU source
+	// address. 0 means "same network as the destination" (i.e. local IP segment).
+	LocalNetworkNumber uint16
+
+	// MaxApduLengthAccepted is the largest APDU we will accept from peers, in octets.
+	// Default 1476 (the largest fragment that fits a standard Ethernet MTU). Used to
+	// derive MaxApduLengthAccepted enum constants at runtime.
+	MaxApduLengthAccepted uint16
+
+	// SegmentationSupported declares this driver's segmentation capabilities. One of
+	// "segmented-both", "segmented-transmit", "segmented-receive", "no-segmentation".
+	SegmentationSupported string
+
+	// MaxSegmentsAccepted is the largest number of APDU segments we will accept in a
+	// segmented response. Default 16.
+	MaxSegmentsAccepted uint8
+
+	// VendorId is the BACnet Vendor Id this driver advertises. Apache PLC4X uses 0x4D4D
+	// ("MM") by convention until a real allocation is registered with ASHRAE.
+	VendorId uint16
+
+	// ForeignDeviceBBMD, when non-empty (host:port), enables BBMD foreign-device
+	// registration at connect time so the driver can interoperate across IP subnets.
+	ForeignDeviceBBMD string
+
+	// ForeignDeviceTTL is the BBMD registration TTL in seconds. The driver re-registers
+	// at TTL/2 to keep the foreign-device entry alive.
+	ForeignDeviceTTL uint16
+
+	// ApduTimeoutMs is the per-request timeout in milliseconds before the transaction
+	// manager surfaces a timeout error.
+	ApduTimeoutMs uint32
+
+	// ApduRetries is the number of transparent retransmits attempted on confirmed
+	// services before failing the request.
+	ApduRetries uint8
+
+	// CovLifetimeSeconds is the default SubscribeCOV lifetime (and refresh interval will
+	// be lifetime/2). 0 means "indefinite" per BACnet spec.
+	CovLifetimeSeconds uint32
+
+	// DiscoveryTimeoutSeconds bounds the WhoIs broadcast wait time. Replaces the older
+	// hardcoded 60-second wait inherited from the alpha discoverer.
+	DiscoveryTimeoutSeconds uint32
+
+	// StaticDevices lets users seed the DeviceInfoCache with peers that won't respond to
+	// WhoIs (e.g. routed devices on a network with no BBMD). Comma-separated entries
+	// of the form "<deviceId>@<network>:<host>:<port>".
+	StaticDevices string
+}
+
+// ParseFromOptions populates a Configuration from the connection-URL query options,
+// applying defaults for any field the user did not set explicitly. Field names
+// are matched case-insensitively so users can write "localDeviceId", "LocalDeviceId",
+// or "localdeviceid" interchangeably in the connection string.
+func ParseFromOptions(log zerolog.Logger, optionsMap map[string][]string) (Configuration, error) {
+	configuration := createDefaultConfiguration()
+	rv := reflect.ValueOf(&configuration).Elem()
+	for i := 0; i < rv.NumField(); i++ {
+		field := rv.Type().Field(i)
+		key := field.Name
+		optionValue := getFromOptions(log, optionsMap, key)
+		if optionValue == "" {
+			continue
+		}
+		switch field.Type.Kind() {
+		case reflect.String:
+			rv.FieldByName(key).SetString(optionValue)
+		case reflect.Bool:
+			parsed, err := strconv.ParseBool(optionValue)
+			if err != nil {
+				return Configuration{}, errors.Wrapf(err, "Error parsing %s", key)
+			}
+			rv.FieldByName(key).SetBool(parsed)
+		case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+			bits := field.Type.Bits()
+			parsed, err := strconv.ParseUint(optionValue, 0, bits)
+			if err != nil {
+				return Configuration{}, errors.Wrapf(err, "Error parsing %s", key)
+			}
+			rv.FieldByName(key).SetUint(parsed)
+		default:
+			return configuration, errors.Errorf("Configuration field kind %s not supported", field.Type.Kind())
+		}
+	}
+	return configuration, nil
+}
+
+// Apache PLC4X uses 0x4D4D ("MM") as its placeholder BACnet Vendor Id; ASHRAE
+// reserves the official allocation list.
+const placeholderVendorId uint16 = 0x4D4D
+
+func createDefaultConfiguration() Configuration {
+	return Configuration{
+		LocalDeviceId:           260001,
+		LocalNetworkNumber:      0,
+		MaxApduLengthAccepted:   1476,
+		SegmentationSupported:   "segmented-both",
+		MaxSegmentsAccepted:     16,
+		VendorId:                placeholderVendorId,
+		ApduTimeoutMs:           3000,
+		ApduRetries:             3,
+		CovLifetimeSeconds:      600,
+		DiscoveryTimeoutSeconds: 5,
+	}
+}
+
+// getFromOptions returns the first value associated with key, matching the
+// optionsMap key case-insensitively (BACnet field names are CamelCase; users
+// commonly type lowercase in URLs).
+func getFromOptions(localLog zerolog.Logger, optionsMap map[string][]string, key string) string {
+	target := strings.ToLower(key)
+	for k, optionValues := range optionsMap {
+		if strings.ToLower(k) != target {
+			continue
+		}
+		if len(optionValues) == 0 {
+			return ""
+		}
+		if len(optionValues) > 1 {
+			localLog.Warn().Str("key", k).Msg("Options key must be unique")
+		}
+		return optionValues[0]
+	}
+	return ""
+}
diff --git a/plc4go/internal/bacnetip/Configuration_test.go b/plc4go/internal/bacnetip/Configuration_test.go
new file mode 100644
index 0000000000..07b82d07d5
--- /dev/null
+++ b/plc4go/internal/bacnetip/Configuration_test.go
@@ -0,0 +1,115 @@
+/*
+ * 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 bacnetip
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+
+	"github.com/apache/plc4x/plc4go/spi/testutils"
+)
+
+func TestParseFromOptions_Defaults(t *testing.T) {
+	got, err := ParseFromOptions(testutils.ProduceTestingLogger(t), map[string][]string{})
+	require.NoError(t, err)
+	assert.Equal(t, createDefaultConfiguration(), got)
+}
+
+func TestParseFromOptions_AllSet(t *testing.T) {
+	opts := map[string][]string{
+		"LocalDeviceId":           {"1234"},
+		"LocalNetworkNumber":      {"5"},
+		"MaxApduLengthAccepted":   {"480"},
+		"SegmentationSupported":   {"no-segmentation"},
+		"MaxSegmentsAccepted":     {"8"},
+		"VendorId":                {"0xCAFE"},
+		"ForeignDeviceBBMD":       {"10.0.0.5:47808"},
+		"ForeignDeviceTTL":        {"30"},
+		"ApduTimeoutMs":           {"5000"},
+		"ApduRetries":             {"2"},
+		"CovLifetimeSeconds":      {"120"},
+		"DiscoveryTimeoutSeconds": {"2"},
+		"StaticDevices":           {"42@1:10.0.0.7:47808"},
+	}
+	got, err := ParseFromOptions(testutils.ProduceTestingLogger(t), opts)
+	require.NoError(t, err)
+
+	want := createDefaultConfiguration()
+	want.LocalDeviceId = 1234
+	want.LocalNetworkNumber = 5
+	want.MaxApduLengthAccepted = 480
+	want.SegmentationSupported = "no-segmentation"
+	want.MaxSegmentsAccepted = 8
+	want.VendorId = 0xCAFE
+	want.ForeignDeviceBBMD = "10.0.0.5:47808"
+	want.ForeignDeviceTTL = 30
+	want.ApduTimeoutMs = 5000
+	want.ApduRetries = 2
+	want.CovLifetimeSeconds = 120
+	want.DiscoveryTimeoutSeconds = 2
+	want.StaticDevices = "42@1:10.0.0.7:47808"
+	assert.Equal(t, want, got)
+}
+
+func TestParseFromOptions_CaseInsensitive(t *testing.T) {
+	got, err := ParseFromOptions(testutils.ProduceTestingLogger(t), map[string][]string{
+		"localdeviceid": {"42"},
+	})
+	require.NoError(t, err)
+	assert.Equal(t, uint32(42), got.LocalDeviceId)
+}
+
+func TestParseFromOptions_InvalidBool(t *testing.T) {
+	// No bool fields today, but the dispatch path matters: a non-numeric value on a
+	// numeric field should error rather than silently zeroing.
+	_, err := ParseFromOptions(testutils.ProduceTestingLogger(t), map[string][]string{
+		"LocalDeviceId": {"not-a-number"},
+	})
+	assert.Error(t, err)
+}
+
+func TestParseFromOptions_InvalidUint(t *testing.T) {
+	// Overflow uint8 ApduRetries.
+	_, err := ParseFromOptions(testutils.ProduceTestingLogger(t), map[string][]string{
+		"ApduRetries": {"1000"},
+	})
+	assert.Error(t, err)
+}
+
+func TestCreateDefaultConfiguration(t *testing.T) {
+	cfg := createDefaultConfiguration()
+	assert.Equal(t, uint32(260001), cfg.LocalDeviceId)
+	assert.Equal(t, uint16(1476), cfg.MaxApduLengthAccepted)
+	assert.Equal(t, "segmented-both", cfg.SegmentationSupported)
+	assert.Equal(t, uint8(16), cfg.MaxSegmentsAccepted)
+	assert.Equal(t, uint16(0x4D4D), cfg.VendorId)
+	assert.Equal(t, uint32(3000), cfg.ApduTimeoutMs)
+	assert.Equal(t, uint8(3), cfg.ApduRetries)
+	assert.Equal(t, uint32(600), cfg.CovLifetimeSeconds)
+	assert.Equal(t, uint32(5), cfg.DiscoveryTimeoutSeconds)
+}
+
+func TestGetFromOptions(t *testing.T) {
+	log := testutils.ProduceTestingLogger(t)
+	assert.Empty(t, getFromOptions(log, map[string][]string{}, "missing"))
+	assert.Equal(t, "first", getFromOptions(log, map[string][]string{"present": {"first", "second"}}, "present"))
+}
diff --git a/plc4go/internal/bacnetip/Connection.go b/plc4go/internal/bacnetip/Connection.go
index f7cf51259c..f7baef19c6 100644
--- a/plc4go/internal/bacnetip/Connection.go
+++ b/plc4go/internal/bacnetip/Connection.go
@@ -28,10 +28,11 @@ import (
 
 	"github.com/rs/zerolog"
 
-	"github.com/apache/plc4x/plc4go/pkg/api"
+	plc4go "github.com/apache/plc4x/plc4go/pkg/api"
 	apiModel "github.com/apache/plc4x/plc4go/pkg/api/model"
+	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
 	"github.com/apache/plc4x/plc4go/spi"
-	"github.com/apache/plc4x/plc4go/spi/default"
+	_default "github.com/apache/plc4x/plc4go/spi/default"
 	"github.com/apache/plc4x/plc4go/spi/errors"
 	spiModel "github.com/apache/plc4x/plc4go/spi/model"
 	"github.com/apache/plc4x/plc4go/spi/options"
@@ -44,6 +45,8 @@ type Connection struct {
 
 	invokeIdGenerator InvokeIdGenerator
 	messageCodec      spi.MessageCodec
+	configuration     Configuration
+	driverContext     DriverContext
 	subscribers       []*Subscriber
 	tm                transactions.RequestTransactionManager
 
@@ -62,9 +65,16 @@ var (
 
 func NewConnection(messageCodec spi.MessageCodec, tagHandler spi.PlcTagHandler, tm transactions.RequestTransactionManager, connectionOptions map[string][]string, _options ...options.WithOption) *Connection {
 	customLogger := options.ExtractCustomLoggerOrDefaultToGlobal(_options...)
+	configuration, err := ParseFromOptions(customLogger, connectionOptions)
+	if err != nil {
+		customLogger.Warn().Err(err).Msg("invalid driver options; falling back to defaults")
+		configuration = createDefaultConfiguration()
+	}
 	connection := &Connection{
 		invokeIdGenerator: InvokeIdGenerator{currentInvokeId: 0},
 		messageCodec:      messageCodec,
+		configuration:     configuration,
+		driverContext:     NewDriverContext(configuration),
 		tm:                tm,
 		log:               customLogger,
 		_options:          _options,
@@ -120,10 +130,50 @@ func (c *Connection) passToDefaultIncomingMessageChannel() {
 	incomingMessageChannel := c.messageCodec.GetDefaultIncomingMessageChannel()
 	select {
 	case message := <-incomingMessageChannel:
-		// TODO: implement mapping to subscribers
-		c.log.Info().Interface("message", message).Msg("Received")
+		c.routeIncomingMessage(message)
+	default:
+		c.log.Trace().Msg("no incoming message")
+	}
+}
+
+// routeIncomingMessage inspects an unsolicited (non-request-matched) BVLC
+// frame and dispatches it to the appropriate handler. The only message we
+// route today is COV (Confirmed/Unconfirmed) — everything else is logged at
+// debug level for visibility.
+func (c *Connection) routeIncomingMessage(message spi.Message) {
+	bvlc, ok := message.(readWriteModel.BVLC)
+	if !ok {
+		c.log.Debug().Type("message", message).Msg("non-BVLC incoming message")
+		return
+	}
+	npduRetriever, ok := bvlc.(interface{ GetNpdu() readWriteModel.NPDU })
+	if !ok {
+		c.log.Debug().Msg("BVLC without an NPDU")
+		return
+	}
+	apdu := npduRetriever.GetNpdu().GetApdu()
+	switch apdu := apdu.(type) {
+	case readWriteModel.APDUUnconfirmedRequest:
+		switch sr := apdu.GetServiceRequest().(type) {
+		case readWriteModel.BACnetUnconfirmedServiceRequestUnconfirmedCOVNotification:
+			for _, s := range c.subscribers {
+				s.HandleUnconfirmedCOVNotification(sr)
+			}
+		default:
+			c.log.Debug().Type("serviceRequest", sr).Msg("unhandled unconfirmed service request")
+		}
+	case readWriteModel.APDUConfirmedRequest:
+		switch sr := apdu.GetServiceRequest().(type) {
+		case readWriteModel.BACnetConfirmedServiceRequestConfirmedCOVNotification:
+			for _, s := range c.subscribers {
+				s.HandleConfirmedCOVNotification(sr)
+			}
+			// TODO: send APDUSimpleAck back to the publisher so it doesn't retry.
+		default:
+			c.log.Debug().Type("serviceRequest", sr).Msg("unhandled confirmed service request")
+		}
 	default:
-		c.log.Info().Msg("Message was not handled")
+		c.log.Debug().Type("apdu", apdu).Msg("unhandled APDU")
 	}
 }
 
@@ -135,6 +185,15 @@ func (c *Connection) GetMessageCodec() spi.MessageCodec {
 	return c.messageCodec
 }
 
+func (c *Connection) GetMetadata() apiModel.PlcConnectionMetadata {
+	return &_default.DefaultConnectionMetadata{
+		ProvidesReading:     true,
+		ProvidesWriting:     true,
+		ProvidesSubscribing: true,
+		ProvidesBrowsing:    false,
+	}
+}
+
 func (c *Connection) ReadRequestBuilder() apiModel.PlcReadRequestBuilder {
 	return spiModel.NewDefaultPlcReadRequestBuilder(
 		c.GetPlcTagHandler(),
@@ -147,6 +206,20 @@ func (c *Connection) ReadRequestBuilder() apiModel.PlcReadRequestBuilder {
 	)
 }
 
+func (c *Connection) WriteRequestBuilder() apiModel.PlcWriteRequestBuilder {
+	return spiModel.NewDefaultPlcWriteRequestBuilder(
+		c.GetPlcTagHandler(),
+		c.GetPlcValueHandler(),
+		NewWriter(
+			&c.invokeIdGenerator,
+			c.messageCodec,
+			c.tm,
+			c.driverContext,
+			append(c._options, options.WithCustomLogger(c.log))...,
+		),
+	)
+}
+
 func (c *Connection) SubscriptionRequestBuilder() apiModel.PlcSubscriptionRequestBuilder {
 	return spiModel.NewDefaultPlcSubscriptionRequestBuilder(
 		c.GetPlcTagHandler(),
diff --git a/plc4go/internal/bacnetip/Connection_test.go b/plc4go/internal/bacnetip/Connection_test.go
new file mode 100644
index 0000000000..184d728d81
--- /dev/null
+++ b/plc4go/internal/bacnetip/Connection_test.go
@@ -0,0 +1,88 @@
+/*
+ * 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 bacnetip
+
+import (
+	"math"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+
+	"github.com/apache/plc4x/plc4go/spi/transactions"
+)
+
+// newTestConnection wires a Connection with no codec/transport — enough for
+// the lifecycle-flag and metadata assertions but not for sending real APDUs.
+func newTestConnection(t *testing.T, options map[string][]string) *Connection {
+	t.Helper()
+	tm := transactions.NewRequestTransactionManager(math.MaxInt)
+	return NewConnection(nil, NewTagHandler(), tm, options)
+}
+
+func TestConnection_GetMetadata_DeclaresCapabilities(t *testing.T) {
+	conn := newTestConnection(t, map[string][]string{})
+	md := conn.GetMetadata()
+	require.NotNil(t, md)
+	assert.True(t, md.CanRead(), "read must be supported")
+	assert.True(t, md.CanWrite(), "write must be supported")
+	assert.True(t, md.CanSubscribe(), "subscribe must be supported")
+	assert.False(t, md.CanBrowse(), "browse not yet supported")
+}
+
+func TestConnection_ConfigurationParsedFromOptions(t *testing.T) {
+	conn := newTestConnection(t, map[string][]string{
+		"LocalDeviceId":         {"42"},
+		"MaxApduLengthAccepted": {"480"},
+		"SegmentationSupported": {"no-segmentation"},
+	})
+	assert.Equal(t, uint32(42), conn.configuration.LocalDeviceId)
+	assert.Equal(t, uint16(480), conn.configuration.MaxApduLengthAccepted)
+	assert.Equal(t, "no-segmentation", conn.configuration.SegmentationSupported)
+}
+
+func TestConnection_BuildersReturnNonNil(t *testing.T) {
+	conn := newTestConnection(t, map[string][]string{})
+	assert.NotNil(t, conn.ReadRequestBuilder())
+	assert.NotNil(t, conn.WriteRequestBuilder())
+	assert.NotNil(t, conn.SubscriptionRequestBuilder())
+}
+
+func TestConnection_AddSubscriber_IsIdempotent(t *testing.T) {
+	conn := newTestConnection(t, map[string][]string{})
+	sub := NewSubscriber(conn)
+	conn.addSubscriber(sub)
+	conn.addSubscriber(sub) // second add should be a no-op
+	assert.Len(t, conn.subscribers, 1)
+}
+
+func TestConnection_InvokeIdGenerator_Monotonic(t *testing.T) {
+	conn := newTestConnection(t, map[string][]string{})
+	a := conn.invokeIdGenerator.getAndIncrement()
+	b := conn.invokeIdGenerator.getAndIncrement()
+	c := conn.invokeIdGenerator.getAndIncrement()
+	assert.Equal(t, a+1, b)
+	assert.Equal(t, b+1, c)
+}
+
+func TestConnection_StringIncludesDriverName(t *testing.T) {
+	conn := newTestConnection(t, map[string][]string{})
+	assert.Contains(t, conn.String(), "bacnetip")
+}
diff --git a/plc4go/internal/bacnetip/DeviceInfoCache.go b/plc4go/internal/bacnetip/DeviceInfoCache.go
new file mode 100644
index 0000000000..4f86a1859e
--- /dev/null
+++ b/plc4go/internal/bacnetip/DeviceInfoCache.go
@@ -0,0 +1,187 @@
+/*
+ * 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 bacnetip
+
+import (
+	"net"
+	"strconv"
+	"strings"
+	"sync"
+	"time"
+
+	"github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
+	"github.com/apache/plc4x/plc4go/spi/errors"
+)
+
+// DeviceInfo captures everything we need to know to address a remote BACnet
+// device for routed Read/Write/Subscribe requests. Most fields are populated
+// from IAm responses (during discovery or in response to WhoIs); the seed
+// entries from Configuration.StaticDevices supply Address + SourceNetwork only.
+type DeviceInfo struct {
+	// DeviceId is the BACnet device-instance number (0..4194303).
+	DeviceId uint32
+
+	// Address is the UDP endpoint reachable on the local IP segment that hosts
+	// (or routes to) this device.
+	Address *net.UDPAddr
+
+	// SourceNetwork is the BACnet network number the device is on. 0 means
+	// "local network" (no routing needed).
+	SourceNetwork uint16
+
+	// SourceAddress is the per-network MAC-equivalent address used in the NPDU
+	// DADR field when routing across networks. For BACnet/IP devices on a
+	// remote network it's typically the device's IPv4 address + port (6 bytes).
+	SourceAddress []byte
+
+	// SegmentationSupported is what the device declared in its IAm. We honor
+	// this when deciding whether to send a segmented request to it.
+	SegmentationSupported model.BACnetSegmentation
+
+	// MaxApdu is the device's MaxApduLengthAccepted (already converted to bytes).
+	MaxApdu uint16
+
+	// VendorId is the BACnet Vendor Id from IAm.
+	VendorId uint16
+
+	// LastSeen is set whenever we receive any APDU from this device, used for
+	// staleness pruning if/when we add a TTL.
+	LastSeen time.Time
+}
+
+// DeviceInfoCache is the in-memory routing table. Safe for concurrent use.
+type DeviceInfoCache struct {
+	mu      sync.RWMutex
+	entries map[uint32]*DeviceInfo
+}
+
+func NewDeviceInfoCache() *DeviceInfoCache {
+	return &DeviceInfoCache{entries: make(map[uint32]*DeviceInfo)}
+}
+
+// Get returns a snapshot of the DeviceInfo for the given device id, or nil if
+// the device isn't known. The returned pointer is a copy — callers may not
+// mutate the cache through it.
+func (c *DeviceInfoCache) Get(deviceId uint32) *DeviceInfo {
+	c.mu.RLock()
+	defer c.mu.RUnlock()
+	if entry, ok := c.entries[deviceId]; ok {
+		copy := *entry
+		return &copy
+	}
+	return nil
+}
+
+// Put inserts or overwrites a device-info entry. LastSeen is bumped to now.
+func (c *DeviceInfoCache) Put(info DeviceInfo) {
+	c.mu.Lock()
+	defer c.mu.Unlock()
+	info.LastSeen = time.Now()
+	c.entries[info.DeviceId] = &info
+}
+
+// Touch updates only the LastSeen timestamp for the given device id. Used by
+// the message-receive path to refresh entries we've already seen.
+func (c *DeviceInfoCache) Touch(deviceId uint32) {
+	c.mu.Lock()
+	defer c.mu.Unlock()
+	if entry, ok := c.entries[deviceId]; ok {
+		entry.LastSeen = time.Now()
+	}
+}
+
+// All returns a copy of every entry. Useful for diagnostics; tests use it to
+// assert eventual-consistency without exposing the internal map.
+func (c *DeviceInfoCache) All() []DeviceInfo {
+	c.mu.RLock()
+	defer c.mu.RUnlock()
+	out := make([]DeviceInfo, 0, len(c.entries))
+	for _, e := range c.entries {
+		out = append(out, *e)
+	}
+	return out
+}
+
+// LoadStatic seeds the cache from a Configuration.StaticDevices string. The
+// format is comma-separated entries of the form "<deviceId>@<network>:<host>:<port>".
+// Whitespace around separators is tolerated.
+//
+//	"1234@0:10.0.0.5:47808,42@1:10.0.0.6:47808"
+//
+// Entries that fail to parse are skipped and counted in the returned error;
+// the cache always contains every entry that did parse cleanly.
+func (c *DeviceInfoCache) LoadStatic(spec string) error {
+	if spec == "" {
+		return nil
+	}
+	var failures []string
+	for _, raw := range strings.Split(spec, ",") {
+		entry := strings.TrimSpace(raw)
+		if entry == "" {
+			continue
+		}
+		info, err := parseStaticDevice(entry)
+		if err != nil {
+			failures = append(failures, entry+": "+err.Error())
+			continue
+		}
+		c.Put(info)
+	}
+	if len(failures) > 0 {
+		return errors.Errorf("parsing static devices: %s", strings.Join(failures, "; "))
+	}
+	return nil
+}
+
+// parseStaticDevice parses a single entry of the form
+// "<deviceId>@<network>:<host>:<port>".
+func parseStaticDevice(entry string) (DeviceInfo, error) {
+	atIdx := strings.IndexByte(entry, '@')
+	if atIdx <= 0 || atIdx == len(entry)-1 {
+		return DeviceInfo{}, errors.New(`expected "<deviceId>@<network>:<host>:<port>"`)
+	}
+	deviceIdPart := entry[:atIdx]
+	remainder := entry[atIdx+1:]
+
+	deviceId, err := strconv.ParseUint(deviceIdPart, 10, 32)
+	if err != nil {
+		return DeviceInfo{}, errors.Wrap(err, "deviceId")
+	}
+
+	netSep := strings.IndexByte(remainder, ':')
+	if netSep <= 0 {
+		return DeviceInfo{}, errors.New("missing ':' after network number")
+	}
+	networkPart := remainder[:netSep]
+	hostPort := remainder[netSep+1:]
+	network, err := strconv.ParseUint(networkPart, 10, 16)
+	if err != nil {
+		return DeviceInfo{}, errors.Wrap(err, "network")
+	}
+	addr, err := net.ResolveUDPAddr("udp", hostPort)
+	if err != nil {
+		return DeviceInfo{}, errors.Wrap(err, "host:port")
+	}
+	return DeviceInfo{
+		DeviceId:      uint32(deviceId),
+		SourceNetwork: uint16(network),
+		Address:       addr,
+	}, nil
+}
diff --git a/plc4go/internal/bacnetip/DeviceInfoCache_test.go b/plc4go/internal/bacnetip/DeviceInfoCache_test.go
new file mode 100644
index 0000000000..ac437387f7
--- /dev/null
+++ b/plc4go/internal/bacnetip/DeviceInfoCache_test.go
@@ -0,0 +1,125 @@
+/*
+ * 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 bacnetip
+
+import (
+	"net"
+	"testing"
+	"time"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+)
+
+func TestDeviceInfoCache_PutAndGet(t *testing.T) {
+	c := NewDeviceInfoCache()
+	addr := &net.UDPAddr{IP: net.IPv4(10, 0, 0, 5), Port: 47808}
+	c.Put(DeviceInfo{DeviceId: 1234, Address: addr, SourceNetwork: 0, MaxApdu: 1476, VendorId: 5})
+
+	got := c.Get(1234)
+	require.NotNil(t, got)
+	assert.Equal(t, uint32(1234), got.DeviceId)
+	assert.Equal(t, addr.String(), got.Address.String())
+	assert.False(t, got.LastSeen.IsZero(), "Put should populate LastSeen")
+}
+
+func TestDeviceInfoCache_GetUnknown_ReturnsNil(t *testing.T) {
+	c := NewDeviceInfoCache()
+	assert.Nil(t, c.Get(999))
+}
+
+func TestDeviceInfoCache_Touch_BumpsLastSeen(t *testing.T) {
+	c := NewDeviceInfoCache()
+	c.Put(DeviceInfo{DeviceId: 7})
+	original := c.Get(7).LastSeen
+
+	// Sleep just enough to make sure the monotonic clock moves.
+	time.Sleep(time.Millisecond)
+	c.Touch(7)
+	updated := c.Get(7).LastSeen
+	assert.True(t, updated.After(original), "Touch should advance LastSeen")
+}
+
+func TestDeviceInfoCache_Touch_UnknownIsNoOp(t *testing.T) {
+	c := NewDeviceInfoCache()
+	// Just don't panic.
+	c.Touch(404)
+	assert.Empty(t, c.All())
+}
+
+func TestDeviceInfoCache_All_ReturnsSnapshot(t *testing.T) {
+	c := NewDeviceInfoCache()
+	c.Put(DeviceInfo{DeviceId: 1})
+	c.Put(DeviceInfo{DeviceId: 2})
+	all := c.All()
+	assert.Len(t, all, 2)
+
+	// Mutating the snapshot must not affect the cache.
+	all[0].DeviceId = 9999
+	again := c.All()
+	for _, e := range again {
+		assert.NotEqual(t, uint32(9999), e.DeviceId)
+	}
+}
+
+func TestDeviceInfoCache_LoadStatic_ValidEntries(t *testing.T) {
+	c := NewDeviceInfoCache()
+	err := c.LoadStatic("1234@0:10.0.0.5:47808, 42@7:10.0.0.6:47808")
+	require.NoError(t, err)
+
+	d1 := c.Get(1234)
+	require.NotNil(t, d1)
+	assert.Equal(t, uint16(0), d1.SourceNetwork)
+	assert.Equal(t, "10.0.0.5:47808", d1.Address.String())
+
+	d2 := c.Get(42)
+	require.NotNil(t, d2)
+	assert.Equal(t, uint16(7), d2.SourceNetwork)
+}
+
+func TestDeviceInfoCache_LoadStatic_Empty(t *testing.T) {
+	c := NewDeviceInfoCache()
+	require.NoError(t, c.LoadStatic(""))
+	assert.Empty(t, c.All())
+}
+
+func TestDeviceInfoCache_LoadStatic_PartialFailureReturnsErr(t *testing.T) {
+	c := NewDeviceInfoCache()
+	err := c.LoadStatic("1234@0:10.0.0.5:47808,bogus,5678@1:10.0.0.6:47808")
+	require.Error(t, err)
+	// Valid entries should still be in the cache.
+	assert.NotNil(t, c.Get(1234))
+	assert.NotNil(t, c.Get(5678))
+}
+
+func TestParseStaticDevice_BadInputs(t *testing.T) {
+	cases := []string{
+		"",                  // empty entry
+		"42",                // missing '@'
+		"42@",               // missing network
+		"42@1",              // missing host:port
+		"42@nan:10.0.0.1:1", // non-numeric network
+		"42@0:10.0.0.1",     // missing port
+	}
+	for _, c := range cases {
+		_, err := parseStaticDevice(c)
+		assert.Error(t, err, "input %q should fail", c)
+	}
+}
diff --git a/plc4go/internal/bacnetip/Discoverer.go b/plc4go/internal/bacnetip/Discoverer.go
index e5b87e3025..441fb4dcf2 100644
--- a/plc4go/internal/bacnetip/Discoverer.go
+++ b/plc4go/internal/bacnetip/Discoverer.go
@@ -29,7 +29,6 @@ import (
 	"sync"
 	"time"
 
-	"github.com/libp2p/go-reuseport"
 	"github.com/rs/zerolog"
 
 	apiModel "github.com/apache/plc4x/plc4go/pkg/api/model"
@@ -43,6 +42,11 @@ import (
 type Discoverer struct {
 	wg sync.WaitGroup // use to track spawned go routines
 
+	// discoveryTimeout caps both the WhoIs broadcast loop and the wait for IAm
+	// responses. Originally hardcoded to 60s; configurable via
+	// Configuration.DiscoveryTimeoutSeconds passed through NewDiscovererWithTimeout.
+	discoveryTimeout time.Duration
+
 	passLogToModel bool
 	log            zerolog.Logger
 }
@@ -51,9 +55,20 @@ func NewDiscoverer(_options ...options.WithOption) *Discoverer {
 	passLoggerToModel, _ := options.ExtractPassLoggerToModel(_options...)
 	customLogger := options.ExtractCustomLoggerOrDefaultToGlobal(_options...)
 	return &Discoverer{
-		passLogToModel: passLoggerToModel,
-		log:            customLogger,
+		discoveryTimeout: 5 * time.Second,
+		passLogToModel:   passLoggerToModel,
+		log:              customLogger,
+	}
+}
+
+// SetDiscoveryTimeout overrides the default 5-second window for discovery.
+// 0 falls back to the default. Intended to be called from Driver setup once
+// Configuration.DiscoveryTimeoutSeconds is known.
+func (d *Discoverer) SetDiscoveryTimeout(t time.Duration) {
+	if t <= 0 {
+		t = 5 * time.Second
 	}
+	d.discoveryTimeout = t
 }
 
 func (d *Discoverer) Discover(ctx context.Context, callback func(event apiModel.PlcDiscoveryItem), discoveryOptions ...options.WithDiscoveryOption) error {
@@ -73,18 +88,22 @@ func (d *Discoverer) Discover(ctx context.Context, callback func(event apiModel.
 		return errors.Wrap(err, "error building communication channels")
 	}
 
-	// TODO: make adjustable
-	ctx, cancelFunc := context.WithTimeout(ctx, time.Second*60)
-	defer func() {
-		cancelFunc()
-	}()
+	timeout := d.discoveryTimeout
+	if timeout <= 0 {
+		timeout = 5 * time.Second
+	}
+	ctx, cancelFunc := context.WithTimeout(ctx, timeout)
+	defer cancelFunc()
 	incomingBVLCChannel, err := d.broadcastAndDiscover(ctx, communicationChannels, specificOptions)
 	if err != nil {
 		return errors.Wrap(err, "error broadcasting and discovering")
 	}
 	d.handleIncomingBVLCs(ctx, callback, incomingBVLCChannel)
-	// TODO: make adjustable
-	time.Sleep(time.Second * 60)
+	// Wait for the discovery window to elapse OR for the caller to cancel.
+	select {
+	case <-time.After(timeout):
+	case <-ctx.Done():
+	}
 	for _, channel := range communicationChannels {
 		_ = channel.Close()
 	}
@@ -147,7 +166,11 @@ func (d *Discoverer) broadcastAndDiscover(ctx context.Context, communicationChan
 				characterString := driverModel.CreateBACnetContextTagCharacterString(3, driverModel.BACnetCharacterEncoding_ISO_10646, *name)
 				object = driverModel.NewBACnetUnconfirmedServiceRequestWhoHasObjectName(characterString.GetHeader(), characterString)
 			} else {
-				panic("Invalid state")
+				// Neither identifier nor name supplied — the caller wired the
+				// who-has options together inconsistently. Skip this discovery
+				// loop entry rather than crashing the entire driver.
+				d.log.Warn().Msg("WhoHas options missing both identifier and name; skipping")
+				continue
 			}
 			requestWhoHas := driverModel.NewBACnetUnconfirmedServiceRequestWhoHas(lowLimit, highLimit, object)
 			apdu := driverModel.NewAPDUUnconfirmedRequest(requestWhoHas)
@@ -337,18 +360,17 @@ func (d *Discoverer) buildupCommunicationChannels(ctx context.Context, interface
 			case *net.IPNet:
 				ipAddr = addr.IP.To4()
 				if ipAddr == nil {
-					// TODO: for now we only support ipv4 (reuse doesn't like v6 address strings atm)
+					// BACnet/IPv6 (Annex U) uses a different BVLC framing
+					// (BVLC6) that isn't in the generated model yet, so we
+					// skip IPv6 addresses until that lands.
 					continue
-					ipAddr = addr.IP.To16()
 				}
 
 			// If the device is configured for a point-to-point connection
 			case *net.IPAddr:
 				ipAddr = addr.IP.To4()
 				if ipAddr == nil {
-					// TODO: for now we only support ipv4 (reuse doesn't like v6 address strings atm)
 					continue
-					ipAddr = addr.IP.To16()
 				}
 			default:
 				continue
@@ -358,8 +380,16 @@ func (d *Discoverer) buildupCommunicationChannels(ctx context.Context, interface
 				continue
 			}
 
-			// Handle undirected
-			unicastConnection, err := reuseport.ListenPacket("udp4", fmt.Sprintf("%v:%d", ipAddr, bacNetPort))
+			// Plain net.ListenPacket. SO_REUSEPORT/REUSEADDR were attempted in
+			// an earlier iteration but they don't actually solve the
+			// "multiple BACnet stacks on one host" problem on UDP broadcast —
+			// the kernel hashes each broadcast packet to ONE socket, so the
+			// second stack still misses traffic. Co-locating BACnet stacks
+			// requires a userland demultiplexer, not socket options. If you
+			// hit "address already in use" here, stop whatever else is bound
+			// to the BACnet/IP UDP port.
+			var lc net.ListenConfig
+			unicastConnection, err := lc.ListenPacket(ctx, "udp4", fmt.Sprintf("%v:%d", ipAddr, bacNetPort))
 			if err != nil {
 				d.log.Debug().Err(err).Msg("Error building unicast Port")
 				continue
@@ -370,8 +400,7 @@ func (d *Discoverer) buildupCommunicationChannels(ctx context.Context, interface
 			for i := range broadcastAddr {
 				broadcastAddr[i] = cidr.IP[i] | ^cidr.Mask[i]
 			}
-			// Handle undirected
-			broadcastConnection, err := reuseport.ListenPacket("udp4", fmt.Sprintf("%v:%d", broadcastAddr, bacNetPort))
+			broadcastConnection, err := lc.ListenPacket(ctx, "udp4", fmt.Sprintf("%v:%d", broadcastAddr, bacNetPort))
 			if err != nil {
 				if err := unicastConnection.Close(); err != nil {
 					d.log.Debug().Err(err).Msg("Error closing transport instance")
@@ -509,7 +538,7 @@ func whoHasOption() option {
 func whoHasLimits(whoHasDeviceInstanceRangeLowLimit, whoHasDeviceInstanceRangeHighLimit uint) option {
 	return func(specificOptions *protocolSpecificOptions) error {
 		if specificOptions.whoHasOptions == nil {
-			panic("we should have set this before")
+			return errors.New("WithDiscoveryOptionWhoHas must be passed before WhoHasLimits")
 		}
 		specificOptions.whoHasOptions.limits = &struct {
 			deviceInstanceRangeLow  uint
@@ -522,7 +551,7 @@ func whoHasLimits(whoHasDeviceInstanceRangeLowLimit, whoHasDeviceInstanceRangeHi
 func whoHasObjectIdentifier(objectIdentifierType string, objectIdentifierInstance uint) option {
 	return func(specificOptions *protocolSpecificOptions) error {
 		if specificOptions.whoHasOptions == nil {
-			panic("we should have set this before")
+			return errors.New("WithDiscoveryOptionWhoHas must be passed before WhoHasObjectIdentifier")
 		}
 		specificOptions.whoHasOptions.object.identifier = &struct {
 			type_    string
@@ -535,7 +564,7 @@ func whoHasObjectIdentifier(objectIdentifierType string, objectIdentifierInstanc
 func whoHasObjectName(objectName string) option {
 	return func(specificOptions *protocolSpecificOptions) error {
 		if specificOptions.whoHasOptions == nil {
-			panic("we should have set this before")
+			return errors.New("WithDiscoveryOptionWhoHas must be passed before WhoHasObjectName")
 		}
 		specificOptions.whoHasOptions.object.name = &objectName
 		return nil
diff --git a/plc4go/internal/bacnetip/bacgopes/local/device/local_device_CurrentLocalDate.go b/plc4go/internal/bacnetip/Discoverer_test.go
similarity index 56%
rename from plc4go/internal/bacnetip/bacgopes/local/device/local_device_CurrentLocalDate.go
rename to plc4go/internal/bacnetip/Discoverer_test.go
index 96887a57e1..ed1895b39d 100644
--- a/plc4go/internal/bacnetip/bacgopes/local/device/local_device_CurrentLocalDate.go
+++ b/plc4go/internal/bacnetip/Discoverer_test.go
@@ -17,32 +17,34 @@
  * under the License.
  */
 
-package device
+package bacnetip
 
 import (
-	"github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/object"
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/primitivedata"
+	"testing"
+	"time"
+
+	"github.com/stretchr/testify/assert"
 )
 
-type CurrentLocalDate struct {
-	Property
+func TestNewDiscoverer_DefaultTimeout(t *testing.T) {
+	d := NewDiscoverer()
+	assert.Equal(t, 5*time.Second, d.discoveryTimeout)
 }
 
-func NewCurrentLocalDate() *CurrentLocalDate {
-	c := &CurrentLocalDate{}
-	c.Property = NewProperty("localDate", Vs2P(NewDate), WithPropertyDefault(nil), WithPropertyOptional(true), WithPropertyMutable(false))
-	return c
+func TestSetDiscoveryTimeout_Override(t *testing.T) {
+	d := NewDiscoverer()
+	d.SetDiscoveryTimeout(2 * time.Second)
+	assert.Equal(t, 2*time.Second, d.discoveryTimeout)
 }
 
-// TODO: implement readproperty
-
-func (p *CurrentLocalDate) ReadProperty(comp.Args, comp.KWArgs) error {
-	//TODO implement me
-	panic("implement me")
+func TestSetDiscoveryTimeout_ZeroFallsBackToDefault(t *testing.T) {
+	d := NewDiscoverer()
+	d.SetDiscoveryTimeout(0)
+	assert.Equal(t, 5*time.Second, d.discoveryTimeout)
 }
 
-func (p *CurrentLocalDate) WriteProperty(comp.Args, comp.KWArgs) error {
-	//TODO implement me
-	panic("implement me")
+func TestSetDiscoveryTimeout_NegativeFallsBackToDefault(t *testing.T) {
+	d := NewDiscoverer()
+	d.SetDiscoveryTimeout(-1 * time.Second)
+	assert.Equal(t, 5*time.Second, d.discoveryTimeout)
 }
diff --git a/plc4go/internal/bacnetip/Driver.go b/plc4go/internal/bacnetip/Driver.go
index d4b12d2072..06feb8a231 100644
--- a/plc4go/internal/bacnetip/Driver.go
+++ b/plc4go/internal/bacnetip/Driver.go
@@ -21,16 +21,14 @@ package bacnetip
 
 import (
 	"context"
-	"fmt"
 	"math"
-	"net"
 	"net/url"
 	"strconv"
-	"sync"
+	"time"
 
 	"github.com/rs/zerolog"
 
-	"github.com/apache/plc4x/plc4go/pkg/api"
+	plc4go "github.com/apache/plc4x/plc4go/pkg/api"
 	apiModel "github.com/apache/plc4x/plc4go/pkg/api/model"
 	"github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
 	_default "github.com/apache/plc4x/plc4go/spi/default"
@@ -38,7 +36,6 @@ import (
 	"github.com/apache/plc4x/plc4go/spi/options"
 	"github.com/apache/plc4x/plc4go/spi/transactions"
 	"github.com/apache/plc4x/plc4go/spi/transports"
-	"github.com/apache/plc4x/plc4go/spi/transports/udp"
 	"github.com/apache/plc4x/plc4go/spi/utils"
 )
 
@@ -46,27 +43,24 @@ type Driver struct {
 	_default.DefaultDriver
 
 	discoverer              *Discoverer
-	applicationManager      ApplicationManager
 	tm                      transactions.RequestTransactionManager
 	awaitSetupComplete      bool
 	awaitDisconnectComplete bool
 
-	log zerolog.Logger
+	_options []options.WithOption
+	log      zerolog.Logger
 }
 
 func NewDriver(_options ...options.WithOption) plc4go.PlcDriver {
 	customLogger := options.ExtractCustomLoggerOrDefaultToGlobal(_options...)
 	driver := &Driver{
-		discoverer: NewDiscoverer(_options...),
-		applicationManager: ApplicationManager{
-			applications: map[string]*ApplicationLayerMessageCodec{},
-			log:          customLogger,
-		},
+		discoverer:              NewDiscoverer(_options...),
 		tm:                      transactions.NewRequestTransactionManager(math.MaxInt),
 		awaitSetupComplete:      true,
 		awaitDisconnectComplete: true,
 
-		log: customLogger,
+		_options: _options,
+		log:      customLogger,
 	}
 	driver.DefaultDriver = _default.NewDefaultDriver(driver, "bacnet-ip", "BACnet/IP", "udp", NewTagHandler())
 	return driver
@@ -85,31 +79,49 @@ func (d *Driver) GetConnection(ctx context.Context, transportUrl url.URL, transp
 			Stringer("transportUrl", &transportUrl).
 			Str("scheme", transportUrl.Scheme).
 			Msg("We couldn't find a transport for scheme")
-		return nil, errors.Errorf("couldn't find transport for given transport url %#v", transportUrl)
+		return nil, errors.Errorf("couldn't find transport for given transport url %v", transportUrl)
 	}
-	// Provide a default-port to the transport, which is used, if the user doesn't provide on in the connection string.
-	driverOptions["defaultUdpPort"] = []string{strconv.Itoa(int(model.BacnetConstants_BACNETUDPDEFAULTPORT))}
-	// Set so_reuse by default
+	// Provide a default-port to the transport, used if the user doesn't provide one in the connection string.
+	driverOptions["defaultUdpPort"] = []string{strconv.FormatUint(uint64(model.BacnetConstants_BACNETUDPDEFAULTPORT), 10)}
+	// Set so_reuse by default so multiple BACnet processes can share the BACnet/IP UDP port.
 	if _, ok := driverOptions["so-reuse"]; !ok {
 		driverOptions["so-reuse"] = []string{"true"}
 	}
-	var udpTransport *udp.Transport
-	switch transport := transport.(type) {
-	case *udp.Transport:
-		udpTransport = transport
-	default:
-		connectionLog.Error().Stringer("transportUrl", &transportUrl).Msg("Only udp supported at the moment")
-		return nil, errors.Errorf("couldn't find transport for given transport url %#v", transportUrl)
+	// Have the transport create a new transport-instance.
+	transportInstance, err := transport.CreateTransportInstance(
+		transportUrl,
+		driverOptions,
+		append(d._options, options.WithCustomLogger(connectionLog))...,
+	)
+	if err != nil {
+		connectionLog.Error().
+			Stringer("transportUrl", &transportUrl).
+			Strs("defaultUdpPort", driverOptions["defaultUdpPort"]).
+			Msg("We couldn't create a transport instance for port")
+		return nil, errors.Wrapf(err, "couldn't initialize transport configuration for given transport url %s", transportUrl.String())
 	}
 
-	codec, err := d.applicationManager.getApplicationLayerMessageCodec(udpTransport, transportUrl, driverOptions)
-	if err != nil {
-		return nil, errors.Wrap(err, "error getting application layer message codec")
+	// Parse Configuration early so we can propagate the discovery timeout to
+	// the Discoverer for the lifetime of this Driver instance. (Discovery is a
+	// driver-level call, but the timeout is naturally part of Configuration.)
+	if cfg, cfgErr := ParseFromOptions(connectionLog, driverOptions); cfgErr == nil {
+		d.discoverer.SetDiscoveryTimeout(time.Duration(cfg.DiscoveryTimeoutSeconds) * time.Second)
 	}
+
+	codec := NewMessageCodec(
+		transportInstance,
+		append(d._options, options.WithCustomLogger(connectionLog))...,
+	)
 	connectionLog.Debug().Interface("codec", codec).Msg("working with codec")
 
 	// Create the new connection
-	connection := NewConnection(codec, d.GetPlcTagHandler(), d.tm, driverOptions)
+	connection := NewConnection(
+		codec,
+		d.GetPlcTagHandler(),
+		d.tm,
+		driverOptions,
+		append(d._options, options.WithCustomLogger(connectionLog))...,
+	)
 	connectionLog.Debug().Msg("created connection, connecting now")
 	if err := connection.Connect(ctx); err != nil {
 		return nil, errors.Wrap(err, "Error connecting connection")
@@ -125,6 +137,14 @@ func (d *Driver) Discover(ctx context.Context, callback func(event apiModel.PlcD
 	return d.discoverer.Discover(ctx, callback, discoveryOptions...)
 }
 
+func (d *Driver) SetAwaitSetupComplete(awaitComplete bool) {
+	d.awaitSetupComplete = awaitComplete
+}
+
+func (d *Driver) SetAwaitDisconnectComplete(awaitComplete bool) {
+	d.awaitDisconnectComplete = awaitComplete
+}
+
 func (d *Driver) Close() error {
 	defer utils.StopWarn(d.log)()
 	d.log.Trace().Msg("Closing driver")
@@ -142,48 +162,3 @@ func (d *Driver) Close() error {
 	}
 	return nil
 }
-
-type ApplicationManager struct {
-	sync.Mutex
-	applications map[string]*ApplicationLayerMessageCodec
-
-	log zerolog.Logger
-}
-
-func (a *ApplicationManager) getApplicationLayerMessageCodec(transport *udp.Transport, transportUrl url.URL, options map[string][]string) (*ApplicationLayerMessageCodec, error) {
-	var localAddress *net.UDPAddr
-	var remoteAddr *net.UDPAddr
-	// Find out the remote and the local ip address by opening an UPD port (which is instantly closed)
-	{
-		host := transportUrl.Host
-		port := transportUrl.Port()
-		if transportUrl.Port() == "" {
-			port = options["defaultUdpPort"][0]
-		}
-		if resolvedRemoteAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%s", host, port)); err != nil {
-			panic(err)
-		} else {
-			remoteAddr = resolvedRemoteAddr
-		}
-		// TODO: Possibly do with with ip-address matching similar to the raw-socket impl in Java.
-		if dial, err := net.DialUDP("udp", nil, remoteAddr); err != nil {
-			return nil, errors.Errorf("couldn't dial to host %#v", transportUrl.Host)
-		} else {
-			localAddress = dial.LocalAddr().(*net.UDPAddr)
-			localAddress.Port, _ = strconv.Atoi(port)
-			_ = dial.Close()
-		}
-	}
-	a.Lock()
-	defer a.Unlock()
-	messageCodec, ok := a.applications[localAddress.String()]
-	if !ok {
-		newMessageCodec, err := NewApplicationLayerMessageCodec(a.log, transport, transportUrl, options, localAddress, remoteAddr)
-		if err != nil {
-			return nil, errors.Wrap(err, "error creating application layer code")
-		}
-		a.applications[localAddress.String()] = newMessageCodec
-		return newMessageCodec, nil
-	}
-	return messageCodec, nil
-}
diff --git a/plc4go/internal/bacnetip/DriverContext.go b/plc4go/internal/bacnetip/DriverContext.go
new file mode 100644
index 0000000000..0ade7262d6
--- /dev/null
+++ b/plc4go/internal/bacnetip/DriverContext.go
@@ -0,0 +1,116 @@
+/*
+ * 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 bacnetip
+
+import (
+	"github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
+)
+
+// DriverContext carries the resolved Configuration plus values derived from it
+// (enum mappings, lifecycle flags) into the Connection layer. It is passed by
+// value because all fields are small.
+//
+//go:generate go tool plc4xGenerator -type=DriverContext
+type DriverContext struct {
+	configuration Configuration
+
+	// maxApduLengthAccepted is the Configuration.MaxApduLengthAccepted byte count
+	// translated to its BACnet enum value (used in IAm responses and confirmed
+	// requests). E.g. 1476 → MaxApduLengthAccepted_NUM_OCTETS_1476.
+	maxApduLengthAccepted model.MaxApduLengthAccepted
+
+	// segmentation is Configuration.SegmentationSupported translated to its
+	// BACnet enum. Defaults to SEGMENTED_BOTH for unknown strings.
+	segmentation model.BACnetSegmentation
+
+	// maxSegmentsAccepted is Configuration.MaxSegmentsAccepted translated to its
+	// BACnet enum value (e.g. 16 → NUM_SEGMENTS_16).
+	maxSegmentsAccepted model.MaxSegmentsAccepted
+
+	awaitSetupComplete      bool
+	awaitDisconnectComplete bool
+}
+
+func NewDriverContext(configuration Configuration) DriverContext {
+	return DriverContext{
+		configuration:           configuration,
+		maxApduLengthAccepted:   bytesToMaxApduLength(configuration.MaxApduLengthAccepted),
+		segmentation:            stringToSegmentation(configuration.SegmentationSupported),
+		maxSegmentsAccepted:     numToMaxSegments(configuration.MaxSegmentsAccepted),
+		awaitSetupComplete:      true,
+		awaitDisconnectComplete: true,
+	}
+}
+
+// bytesToMaxApduLength picks the largest BACnet APDU-length enum whose byte count
+// fits within the user-specified ceiling. A user value below the minimum (50) is
+// clamped to MINIMUM_MESSAGE_SIZE.
+func bytesToMaxApduLength(bytes uint16) model.MaxApduLengthAccepted {
+	switch {
+	case bytes >= 1476:
+		return model.MaxApduLengthAccepted_NUM_OCTETS_1476
+	case bytes >= 1024:
+		return model.MaxApduLengthAccepted_NUM_OCTETS_1024
+	case bytes >= 480:
+		return model.MaxApduLengthAccepted_NUM_OCTETS_480
+	case bytes >= 206:
+		return model.MaxApduLengthAccepted_NUM_OCTETS_206
+	case bytes >= 128:
+		return model.MaxApduLengthAccepted_NUM_OCTETS_128
+	default:
+		return model.MaxApduLengthAccepted_MINIMUM_MESSAGE_SIZE
+	}
+}
+
+func stringToSegmentation(s string) model.BACnetSegmentation {
+	switch s {
+	case "segmented-transmit":
+		return model.BACnetSegmentation_SEGMENTED_TRANSMIT
+	case "segmented-receive":
+		return model.BACnetSegmentation_SEGMENTED_RECEIVE
+	case "no-segmentation":
+		return model.BACnetSegmentation_NO_SEGMENTATION
+	default:
+		return model.BACnetSegmentation_SEGMENTED_BOTH
+	}
+}
+
+// numToMaxSegments picks the smallest BACnet MaxSegmentsAccepted enum whose count
+// is greater than or equal to n. 0 is treated as "unspecified".
+func numToMaxSegments(n uint8) model.MaxSegmentsAccepted {
+	switch {
+	case n == 0:
+		return model.MaxSegmentsAccepted_UNSPECIFIED
+	case n <= 2:
+		return model.MaxSegmentsAccepted_NUM_SEGMENTS_02
+	case n <= 4:
+		return model.MaxSegmentsAccepted_NUM_SEGMENTS_04
+	case n <= 8:
+		return model.MaxSegmentsAccepted_NUM_SEGMENTS_08
+	case n <= 16:
+		return model.MaxSegmentsAccepted_NUM_SEGMENTS_16
+	case n <= 32:
+		return model.MaxSegmentsAccepted_NUM_SEGMENTS_32
+	case n <= 64:
+		return model.MaxSegmentsAccepted_NUM_SEGMENTS_64
+	default:
+		return model.MaxSegmentsAccepted_MORE_THAN_64_SEGMENTS
+	}
+}
diff --git a/plc4go/internal/bacnetip/DriverContext_test.go b/plc4go/internal/bacnetip/DriverContext_test.go
new file mode 100644
index 0000000000..3041bf0c6d
--- /dev/null
+++ b/plc4go/internal/bacnetip/DriverContext_test.go
@@ -0,0 +1,103 @@
+/*
+ * 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 bacnetip
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+
+	"github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
+)
+
+func TestNewDriverContext_Defaults(t *testing.T) {
+	dc := NewDriverContext(createDefaultConfiguration())
+	assert.Equal(t, model.MaxApduLengthAccepted_NUM_OCTETS_1476, dc.maxApduLengthAccepted)
+	assert.Equal(t, model.BACnetSegmentation_SEGMENTED_BOTH, dc.segmentation)
+	assert.Equal(t, model.MaxSegmentsAccepted_NUM_SEGMENTS_16, dc.maxSegmentsAccepted)
+	assert.True(t, dc.awaitSetupComplete)
+	assert.True(t, dc.awaitDisconnectComplete)
+}
+
+func TestBytesToMaxApduLength(t *testing.T) {
+	cases := []struct {
+		in   uint16
+		want model.MaxApduLengthAccepted
+	}{
+		{0, model.MaxApduLengthAccepted_MINIMUM_MESSAGE_SIZE},
+		{127, model.MaxApduLengthAccepted_MINIMUM_MESSAGE_SIZE},
+		{128, model.MaxApduLengthAccepted_NUM_OCTETS_128},
+		{205, model.MaxApduLengthAccepted_NUM_OCTETS_128},
+		{206, model.MaxApduLengthAccepted_NUM_OCTETS_206},
+		{479, model.MaxApduLengthAccepted_NUM_OCTETS_206},
+		{480, model.MaxApduLengthAccepted_NUM_OCTETS_480},
+		{1023, model.MaxApduLengthAccepted_NUM_OCTETS_480},
+		{1024, model.MaxApduLengthAccepted_NUM_OCTETS_1024},
+		{1475, model.MaxApduLengthAccepted_NUM_OCTETS_1024},
+		{1476, model.MaxApduLengthAccepted_NUM_OCTETS_1476},
+		{65535, model.MaxApduLengthAccepted_NUM_OCTETS_1476},
+	}
+	for _, c := range cases {
+		assert.Equal(t, c.want, bytesToMaxApduLength(c.in), "bytesToMaxApduLength(%d)", c.in)
+	}
+}
+
+func TestStringToSegmentation(t *testing.T) {
+	cases := []struct {
+		in   string
+		want model.BACnetSegmentation
+	}{
+		{"segmented-both", model.BACnetSegmentation_SEGMENTED_BOTH},
+		{"segmented-transmit", model.BACnetSegmentation_SEGMENTED_TRANSMIT},
+		{"segmented-receive", model.BACnetSegmentation_SEGMENTED_RECEIVE},
+		{"no-segmentation", model.BACnetSegmentation_NO_SEGMENTATION},
+		{"", model.BACnetSegmentation_SEGMENTED_BOTH},
+		{"bogus", model.BACnetSegmentation_SEGMENTED_BOTH},
+	}
+	for _, c := range cases {
+		assert.Equal(t, c.want, stringToSegmentation(c.in), "stringToSegmentation(%q)", c.in)
+	}
+}
+
+func TestNumToMaxSegments(t *testing.T) {
+	cases := []struct {
+		in   uint8
+		want model.MaxSegmentsAccepted
+	}{
+		{0, model.MaxSegmentsAccepted_UNSPECIFIED},
+		{1, model.MaxSegmentsAccepted_NUM_SEGMENTS_02},
+		{2, model.MaxSegmentsAccepted_NUM_SEGMENTS_02},
+		{3, model.MaxSegmentsAccepted_NUM_SEGMENTS_04},
+		{4, model.MaxSegmentsAccepted_NUM_SEGMENTS_04},
+		{5, model.MaxSegmentsAccepted_NUM_SEGMENTS_08},
+		{8, model.MaxSegmentsAccepted_NUM_SEGMENTS_08},
+		{9, model.MaxSegmentsAccepted_NUM_SEGMENTS_16},
+		{16, model.MaxSegmentsAccepted_NUM_SEGMENTS_16},
+		{17, model.MaxSegmentsAccepted_NUM_SEGMENTS_32},
+		{32, model.MaxSegmentsAccepted_NUM_SEGMENTS_32},
+		{33, model.MaxSegmentsAccepted_NUM_SEGMENTS_64},
+		{64, model.MaxSegmentsAccepted_NUM_SEGMENTS_64},
+		{65, model.MaxSegmentsAccepted_MORE_THAN_64_SEGMENTS},
+		{255, model.MaxSegmentsAccepted_MORE_THAN_64_SEGMENTS},
+	}
+	for _, c := range cases {
+		assert.Equal(t, c.want, numToMaxSegments(c.in), "numToMaxSegments(%d)", c.in)
+	}
+}
diff --git a/plc4go/internal/bacnetip/Reader.go b/plc4go/internal/bacnetip/Reader.go
index 795ad584d5..4709fdef83 100644
--- a/plc4go/internal/bacnetip/Reader.go
+++ b/plc4go/internal/bacnetip/Reader.go
@@ -21,7 +21,6 @@ package bacnetip
 
 import (
 	"context"
-	"fmt"
 	"sync"
 	"time"
 
@@ -210,105 +209,189 @@ func (m *Reader) Read(ctx context.Context, readRequest apiModel.PlcReadRequest)
 }
 
 func (m *Reader) ToPlc4xReadResponse(apdu readWriteModel.APDU, readRequest apiModel.PlcReadRequest) (apiModel.PlcReadResponse, error) {
-	var complexAck readWriteModel.APDUComplexAck
-	var errorClass *readWriteModel.ErrorClass
-	var errorCode *readWriteModel.ErrorCode
-	var rejectReason *readWriteModel.BACnetRejectReason
-	var abortReason *readWriteModel.BACnetAbortReason
+	tagNames := readRequest.GetTagNames()
+	responseCodes := map[string]apiModel.PlcResponseCode{}
+	plcValues := map[string]values.PlcValue{}
+
+	// Dispatch on APDU subtype. Errors/Reject/Abort fan out to every requested
+	// tag with the same response code so consumers can read a sane PlcResponse
+	// even on protocol-level failures.
 	switch apdu := apdu.(type) {
 	case readWriteModel.APDUComplexAck:
-		complexAck = apdu
+		return m.decodeComplexAck(apdu, readRequest)
 	case readWriteModel.APDUError:
-		apduError := apdu.GetError()
-		var bacError readWriteModel.Error
-		switch concreteError := apduError.(type) {
-		case readWriteModel.BACnetErrorGeneral:
-			bacError = concreteError.GetError()
-		default:
-			bacError = concreteError.(interface {
-				GetErrorType() readWriteModel.ErrorEnclosed
-			}).GetErrorType().GetError()
-		}
-		errorClassValue := bacError.GetErrorClass().GetValue()
-		errorClass = &errorClassValue
-		errorCodeValue := bacError.GetErrorCode().GetValue()
-		errorCode = &errorCodeValue
+		responseCode := mapErrorAPDU(apdu, m.log)
+		return broadcastResponseCode(readRequest, responseCode, responseCodes, plcValues), nil
 	case readWriteModel.APDUReject:
-		rejectReasonValue := apdu.GetRejectReason().GetValue()
-		rejectReason = &rejectReasonValue
+		m.log.Warn().Stringer("rejectReason", reasonOfReject(apdu)).Msg("BACnet REJECT received")
+		return broadcastResponseCode(readRequest, apiModel.PlcResponseCode_INVALID_DATA, responseCodes, plcValues), nil
 	case readWriteModel.APDUAbort:
-		abortReasonValue := apdu.GetAbortReason().GetValue()
-		abortReason = &abortReasonValue
+		reason := apdu.GetAbortReason().GetValue()
+		code := apiModel.PlcResponseCode_INTERNAL_ERROR
+		if reason == readWriteModel.BACnetAbortReason_SEGMENTATION_NOT_SUPPORTED {
+			code = apiModel.PlcResponseCode_UNSUPPORTED
+		}
+		m.log.Warn().Stringer("abortReason", &reason).Msg("BACnet ABORT received")
+		return broadcastResponseCode(readRequest, code, responseCodes, plcValues), nil
 	default:
-		return nil, errors.Errorf("unsupported response type %T", apdu)
+		// Reject any other APDU type — but mark all tags as remote-error so the
+		// caller still receives a well-formed PlcReadResponse instead of nil.
+		_ = tagNames
+		m.log.Warn().Type("apdu", apdu).Msg("unsupported APDU type on read response")
+		return broadcastResponseCode(readRequest, apiModel.PlcResponseCode_REMOTE_ERROR, responseCodes, plcValues), nil
 	}
+}
+
+// decodeComplexAck handles the happy-path APDUComplexAck for ReadProperty and
+// ReadPropertyMultiple. Segmented responses are flagged but not yet reassembled
+// — that happens in Phase 5.
+func (m *Reader) decodeComplexAck(apdu readWriteModel.APDUComplexAck, readRequest apiModel.PlcReadRequest) (apiModel.PlcReadResponse, error) {
+	tagNames := readRequest.GetTagNames()
 	responseCodes := map[string]apiModel.PlcResponseCode{}
 	plcValues := map[string]values.PlcValue{}
 
-	// If the result contains any form of non-null error code, handle this instead.
-	if errorClass != nil {
-		m.log.Warn().
-			Stringer("errorClass", errorClass).
-			Stringer("errorCode", errorCode).
-			Msg("Got an unknown error response from the PLC. Error Class: %d, Error Code %d. " +
-				"We probably need to implement explicit handling for this, so please file a bug-report " +
-				"on https://github.com/apache/plc4x/issues and ideally attach a WireShark dump " +
-				"containing a capture of the communication.")
-		for _, tagName := range readRequest.GetTagNames() {
-			responseCodes[tagName] = apiModel.PlcResponseCode_INTERNAL_ERROR
-			plcValues[tagName] = spiValues.NewPlcNULL()
-		}
-		return spiModel.NewDefaultPlcReadResponse(readRequest, responseCodes, plcValues), nil
+	if apdu.GetSegmentedMessage() {
+		// Segmentation reassembly is implemented in Phase 5. Until then surface a
+		// well-formed response with UNSUPPORTED so callers handle it gracefully.
+		m.log.Warn().Uint8("invokeId", apdu.GetOriginalInvokeId()).Msg("segmented APDU response — reassembly not yet implemented")
+		return broadcastResponseCode(readRequest, apiModel.PlcResponseCode_UNSUPPORTED, responseCodes, plcValues), nil
 	}
-	if rejectReason != nil {
-		m.log.Warn().
-			Stringer("rejectReason", rejectReason).
-			Msg("Got an unknown error response from the PLC. Error Class: %d, Error Code %d. " +
-				"We probably need to implement explicit handling for this, so please file a bug-report " +
-				"on https://github.com/apache/plc4x/issues and ideally attach a WireShark dump " +
-				"containing a capture of the communication.")
-		for _, tagName := range readRequest.GetTagNames() {
-			responseCodes[tagName] = apiModel.PlcResponseCode_INTERNAL_ERROR
-			plcValues[tagName] = spiValues.NewPlcNULL()
+
+	switch serviceAck := apdu.GetServiceAck().(type) {
+	case readWriteModel.BACnetServiceAckReadProperty:
+		if len(tagNames) == 0 {
+			return nil, errors.New("ReadProperty response without a corresponding requested tag")
 		}
-		return spiModel.NewDefaultPlcReadResponse(readRequest, responseCodes, plcValues), nil
+		responseCodes[tagNames[0]] = apiModel.PlcResponseCode_OK
+		plcValues[tagNames[0]] = constructedDataToPlcValue(serviceAck.GetValues())
+		// Any extra requested tags (shouldn't happen with single ReadProperty,
+		// but be defensive) get NOT_FOUND.
+		for _, n := range tagNames[1:] {
+			responseCodes[n] = apiModel.PlcResponseCode_NOT_FOUND
+			plcValues[n] = spiValues.NewPlcNULL()
+		}
+	case readWriteModel.BACnetServiceAckReadPropertyMultiple:
+		data := serviceAck.GetData()
+		if len(tagNames) != len(data) {
+			return nil, errors.Errorf("ReadPropertyMultiple expected %d results, got %d", len(tagNames), len(data))
+		}
+		for i, tagName := range tagNames {
+			list := data[i].GetListOfResults()
+			if list == nil {
+				responseCodes[tagName] = apiModel.PlcResponseCode_NOT_FOUND
+				plcValues[tagName] = spiValues.NewPlcNULL()
+				continue
+			}
+			// Per BACnet ReadPropertyMultiple semantics each requested property
+			// in the access spec produces one read result. We collapse to a
+			// single value if there's just one, otherwise wrap as PlcList.
+			results := list.GetListOfReadAccessProperty()
+			code, value := readResultsToPlcValue(results)
+			responseCodes[tagName] = code
+			plcValues[tagName] = value
+		}
+	default:
+		m.log.Warn().Type("serviceAck", serviceAck).Msg("unsupported ServiceAck variant")
+		return broadcastResponseCode(readRequest, apiModel.PlcResponseCode_INTERNAL_ERROR, responseCodes, plcValues), nil
 	}
-	if abortReason != nil {
-		m.log.Warn().
-			Stringer("abortReason", abortReason).
-			Msg("Got an unknown error response from the PLC. Error Class: %d, Error Code %d. " +
-				"We probably need to implement explicit handling for this, so please file a bug-report " +
-				"on https://github.com/apache/plc4x/issues and ideally attach a WireShark dump " +
-				"containing a capture of the communication.")
-		for _, tagName := range readRequest.GetTagNames() {
-			responseCodes[tagName] = apiModel.PlcResponseCode_INTERNAL_ERROR
-			plcValues[tagName] = spiValues.NewPlcNULL()
+
+	return spiModel.NewDefaultPlcReadResponse(readRequest, responseCodes, plcValues), nil
+}
+
+// readResultsToPlcValue collapses a ReadPropertyMultiple result list to a
+// (responseCode, value) pair. Errors in any one element propagate to the whole
+// tag — BACnet doesn't promise atomicity but we fail closed for clarity.
+func readResultsToPlcValue(results []readWriteModel.BACnetReadAccessProperty) (apiModel.PlcResponseCode, values.PlcValue) {
+	if len(results) == 0 {
+		return apiModel.PlcResponseCode_NOT_FOUND, spiValues.NewPlcNULL()
+	}
+	collected := make([]values.PlcValue, 0, len(results))
+	for _, rap := range results {
+		rr := rap.GetReadResult()
+		if rr == nil {
+			collected = append(collected, spiValues.NewPlcNULL())
+			continue
+		}
+		if e := rr.GetPropertyAccessError(); e != nil {
+			code := bacnetErrorEnclosedToResponseCode(e)
+			return code, spiValues.NewPlcNULL()
 		}
-		return spiModel.NewDefaultPlcReadResponse(readRequest, responseCodes, plcValues), nil
+		collected = append(collected, constructedDataToPlcValue(rr.GetPropertyValue()))
 	}
+	if len(collected) == 1 {
+		return apiModel.PlcResponseCode_OK, collected[0]
+	}
+	return apiModel.PlcResponseCode_OK, spiValues.NewPlcList(collected)
+}
 
-	switch serviceAck := complexAck.GetServiceAck().(type) {
-	case readWriteModel.BACnetServiceAckReadProperty:
-		// TODO: super lazy implementation for now
-		responseCodes[readRequest.GetTagNames()[0]] = apiModel.PlcResponseCode_OK
-		plcValues[readRequest.GetTagNames()[0]] = spiValues.NewPlcSTRING(serviceAck.GetValues().(fmt.Stringer).String())
-	case readWriteModel.BACnetServiceAckReadPropertyMultiple:
+// mapErrorAPDU translates an APDUError into the appropriate plc4go response code
+// based on BACnet ErrorClass + ErrorCode. Unknown combinations default to
+// REMOTE_ERROR so callers always get a meaningful non-OK result.
+func mapErrorAPDU(apdu readWriteModel.APDUError, log zerolog.Logger) apiModel.PlcResponseCode {
+	apduError := apdu.GetError()
+	var bacError readWriteModel.Error
+	switch concreteError := apduError.(type) {
+	case readWriteModel.BACnetErrorGeneral:
+		bacError = concreteError.GetError()
+	default:
+		bacError = concreteError.(interface {
+			GetErrorType() readWriteModel.ErrorEnclosed
+		}).GetErrorType().GetError()
+	}
+	errorClass := bacError.GetErrorClass().GetValue()
+	errorCode := bacError.GetErrorCode().GetValue()
+	log.Warn().
+		Stringer("errorClass", &errorClass).
+		Stringer("errorCode", &errorCode).
+		Msg("BACnet error response received")
+	return mapErrorClassCodeToResponseCode(errorClass, errorCode)
+}
 
-		// way to know how to interpret the responses is by aligning them with the
-		// items from the request as this information is not returned by the PLC.
-		if len(readRequest.GetTagNames()) != len(serviceAck.GetData()) {
-			return nil, errors.New("The number of requested items doesn't match the number of returned items")
+// mapErrorClassCodeToResponseCode is the table the plan calls out: class+code
+// to plc4go's flat response codes.
+func mapErrorClassCodeToResponseCode(class readWriteModel.ErrorClass, code readWriteModel.ErrorCode) apiModel.PlcResponseCode {
+	switch class {
+	case readWriteModel.ErrorClass_OBJECT:
+		if code == readWriteModel.ErrorCode_UNKNOWN_OBJECT {
+			return apiModel.PlcResponseCode_NOT_FOUND
+		}
+	case readWriteModel.ErrorClass_PROPERTY:
+		switch code {
+		case readWriteModel.ErrorCode_UNKNOWN_PROPERTY:
+			return apiModel.PlcResponseCode_INVALID_ADDRESS
+		case readWriteModel.ErrorCode_WRITE_ACCESS_DENIED:
+			return apiModel.PlcResponseCode_ACCESS_DENIED
 		}
-		for i, tagName := range readRequest.GetTagNames() {
-			// TODO: super lazy implementation for now
-			responseCodes[tagName] = apiModel.PlcResponseCode_OK
-			plcValues[tagName] = spiValues.NewPlcSTRING(serviceAck.GetData()[i].GetListOfResults().(fmt.Stringer).String())
+	case readWriteModel.ErrorClass_DEVICE:
+		if code == readWriteModel.ErrorCode_OPERATIONAL_PROBLEM {
+			return apiModel.PlcResponseCode_REMOTE_ERROR
 		}
 	}
+	return apiModel.PlcResponseCode_REMOTE_ERROR
+}
 
-	// Return the response
-	m.log.Trace().Msg("Returning the response")
-	return spiModel.NewDefaultPlcReadResponse(readRequest, responseCodes, plcValues), nil
+// bacnetErrorEnclosedToResponseCode extracts the inner Error from a
+// per-property ErrorEnclosed (used in ReadPropertyMultiple results) and maps it
+// to a plc4go response code.
+func bacnetErrorEnclosedToResponseCode(enclosed readWriteModel.ErrorEnclosed) apiModel.PlcResponseCode {
+	err := enclosed.GetError()
+	return mapErrorClassCodeToResponseCode(err.GetErrorClass().GetValue(), err.GetErrorCode().GetValue())
+}
+
+// broadcastResponseCode populates the same code and a PlcNULL value for every
+// tag in the request, then wraps in a DefaultPlcReadResponse.
+func broadcastResponseCode(req apiModel.PlcReadRequest, code apiModel.PlcResponseCode, codes map[string]apiModel.PlcResponseCode, vals map[string]values.PlcValue) apiModel.PlcReadResponse {
+	for _, name := range req.GetTagNames() {
+		codes[name] = code
+		vals[name] = spiValues.NewPlcNULL()
+	}
+	return spiModel.NewDefaultPlcReadResponse(req, codes, vals)
+}
+
+// reasonOfReject returns a pointer to the reject reason for Stringer formatting.
+func reasonOfReject(apdu readWriteModel.APDUReject) *readWriteModel.BACnetRejectReason {
+	r := apdu.GetRejectReason().GetValue()
+	return &r
 }
 
 func getInvokeIdFromApdu(apdu readWriteModel.APDU) (uint8, error) {
diff --git a/plc4go/internal/bacnetip/Reader_test.go b/plc4go/internal/bacnetip/Reader_test.go
new file mode 100644
index 0000000000..2550284a06
--- /dev/null
+++ b/plc4go/internal/bacnetip/Reader_test.go
@@ -0,0 +1,354 @@
+/*
+ * 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 bacnetip
+
+import (
+	"testing"
+
+	"github.com/rs/zerolog"
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+
+	apiModel "github.com/apache/plc4x/plc4go/pkg/api/model"
+	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
+	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
+	spiModel "github.com/apache/plc4x/plc4go/spi/model"
+	spiValues "github.com/apache/plc4x/plc4go/spi/values"
+)
+
+// newTestReader returns a Reader that does no I/O — all tests here exercise the
+// pure response-decoding path against synthetic APDUs.
+func newTestReader(t *testing.T) *Reader {
+	t.Helper()
+	return &Reader{
+		invokeIdGenerator:     &InvokeIdGenerator{},
+		maxSegmentsAccepted:   readWriteModel.MaxSegmentsAccepted_NUM_SEGMENTS_16,
+		maxApduLengthAccepted: readWriteModel.MaxApduLengthAccepted_NUM_OCTETS_1476,
+		log:                   zerolog.Nop(),
+	}
+}
+
+// readRequestForTags wraps the test's tag names in a minimal PlcReadRequest so
+// the decoder has something to dispatch against.
+func readRequestForTags(tagNames ...string) apiModel.PlcReadRequest {
+	tags := map[string]apiModel.PlcTag{}
+	for _, n := range tagNames {
+		// We use a fully synthetic tag — the decoder only consults names and the
+		// returned response codes / values, not the tag's structure.
+		tags[n] = nil
+	}
+	return spiModel.NewDefaultPlcReadRequest(tags, tagNames, nil, nil)
+}
+
+// constructedDataFromTag wraps a single ApplicationTag in BACnetConstructedDataUnspecified
+// so we can build the BACnetServiceAckReadProperty response fixture.
+func constructedDataFromTag(tag readWriteModel.BACnetApplicationTag) readWriteModel.BACnetConstructedData {
+	header := readWriteModel.CreateBACnetTagHeaderBalanced(true, 3, 0)
+	element := readWriteModel.NewBACnetConstructedDataElement(header, tag, nil, nil)
+	return readWriteModel.NewBACnetConstructedDataUnspecified(
+		readWriteModel.CreateBACnetOpeningTag(3),
+		header,
+		readWriteModel.CreateBACnetClosingTag(3),
+		nil,
+		[]readWriteModel.BACnetConstructedDataElement{element},
+	)
+}
+
+func buildReadPropertyAck(t *testing.T, objType uint16, instance uint32, propId readWriteModel.BACnetPropertyIdentifier, tag readWriteModel.BACnetApplicationTag) readWriteModel.APDUComplexAck {
+	t.Helper()
+	values := constructedDataFromTag(tag)
+	serviceAck := readWriteModel.NewBACnetServiceAckReadProperty(
+		0,
+		readWriteModel.CreateBACnetContextTagObjectIdentifier(0, objType, instance),
+		readWriteModel.CreateBACnetPropertyIdentifierTagged(1, uint32(propId)),
+		nil,
+		values,
+	)
+	return readWriteModel.NewAPDUComplexAck(false, false, 1, nil, nil, serviceAck, nil, nil)
+}
+
+func TestToPlc4xReadResponse_RealPresentValue(t *testing.T) {
+	reader := newTestReader(t)
+	request := readRequestForTags("temp")
+	ack := buildReadPropertyAck(
+		t,
+		uint16(readWriteModel.BACnetObjectType_ANALOG_INPUT),
+		1,
+		readWriteModel.BACnetPropertyIdentifier_PRESENT_VALUE,
+		readWriteModel.CreateBACnetApplicationTagReal(23.5),
+	)
+
+	resp, err := reader.ToPlc4xReadResponse(ack, request)
+	require.NoError(t, err)
+	require.NotNil(t, resp)
+	assert.Equal(t, apiModel.PlcResponseCode_OK, resp.GetResponseCode("temp"))
+	val := resp.GetValue("temp")
+	require.NotNil(t, val)
+	assert.True(t, val.IsFloat32())
+	assert.InDelta(t, 23.5, val.GetFloat32(), 0.001)
+}
+
+func TestToPlc4xReadResponse_BooleanPresentValue(t *testing.T) {
+	reader := newTestReader(t)
+	request := readRequestForTags("binIn")
+	ack := buildReadPropertyAck(
+		t,
+		uint16(readWriteModel.BACnetObjectType_BINARY_INPUT),
+		7,
+		readWriteModel.BACnetPropertyIdentifier_PRESENT_VALUE,
+		readWriteModel.CreateBACnetApplicationTagBoolean(true),
+	)
+	resp, err := reader.ToPlc4xReadResponse(ack, request)
+	require.NoError(t, err)
+	val := resp.GetValue("binIn")
+	assert.True(t, val.GetBool())
+}
+
+func TestToPlc4xReadResponse_CharacterStringObjectName(t *testing.T) {
+	reader := newTestReader(t)
+	request := readRequestForTags("name")
+	ack := buildReadPropertyAck(
+		t,
+		uint16(readWriteModel.BACnetObjectType_DEVICE),
+		1234,
+		readWriteModel.BACnetPropertyIdentifier_OBJECT_NAME,
+		readWriteModel.CreateBACnetApplicationTagCharacterString(readWriteModel.BACnetCharacterEncoding_ISO_10646, "JACE/N4"),
+	)
+	resp, err := reader.ToPlc4xReadResponse(ack, request)
+	require.NoError(t, err)
+	assert.Equal(t, "JACE/N4", resp.GetValue("name").GetString())
+}
+
+func TestToPlc4xReadResponse_UnsignedInteger(t *testing.T) {
+	reader := newTestReader(t)
+	request := readRequestForTags("count")
+	ack := buildReadPropertyAck(
+		t,
+		uint16(readWriteModel.BACnetObjectType_ACCUMULATOR),
+		2,
+		readWriteModel.BACnetPropertyIdentifier_PRESENT_VALUE,
+		readWriteModel.CreateBACnetApplicationTagUnsignedInteger(42),
+	)
+	resp, err := reader.ToPlc4xReadResponse(ack, request)
+	require.NoError(t, err)
+	assert.Equal(t, uint64(42), resp.GetValue("count").GetUint64())
+}
+
+func TestToPlc4xReadResponse_Enumerated(t *testing.T) {
+	reader := newTestReader(t)
+	request := readRequestForTags("state")
+	ack := buildReadPropertyAck(
+		t,
+		uint16(readWriteModel.BACnetObjectType_BINARY_OUTPUT),
+		1,
+		readWriteModel.BACnetPropertyIdentifier_PRESENT_VALUE,
+		readWriteModel.CreateBACnetApplicationTagEnumerated(1), // ACTIVE
+	)
+	resp, err := reader.ToPlc4xReadResponse(ack, request)
+	require.NoError(t, err)
+	assert.Equal(t, uint32(1), resp.GetValue("state").GetUint32())
+}
+
+func TestToPlc4xReadResponse_Null(t *testing.T) {
+	reader := newTestReader(t)
+	request := readRequestForTags("nullProp")
+	ack := buildReadPropertyAck(
+		t,
+		uint16(readWriteModel.BACnetObjectType_ANALOG_INPUT),
+		1,
+		readWriteModel.BACnetPropertyIdentifier_OUT_OF_SERVICE,
+		readWriteModel.CreateBACnetApplicationTagNull(),
+	)
+	resp, err := reader.ToPlc4xReadResponse(ack, request)
+	require.NoError(t, err)
+	val := resp.GetValue("nullProp")
+	require.NotNil(t, val)
+	assert.Equal(t, apiValues.NULL, val.GetPlcValueType())
+}
+
+// ── Error / Reject / Abort paths ───────────────────────────────────────────
+
+func buildErrorAPDU(class readWriteModel.ErrorClass, code readWriteModel.ErrorCode) readWriteModel.APDUError {
+	header := readWriteModel.CreateBACnetTagHeaderBalanced(false, 9, 1)
+	bacError := readWriteModel.NewError(
+		readWriteModel.NewErrorClassTagged(header, class, 0),
+		readWriteModel.NewErrorCodeTagged(header, code, 0),
+	)
+	general := readWriteModel.NewBACnetErrorGeneral(bacError)
+	return readWriteModel.NewAPDUError(1, readWriteModel.BACnetConfirmedServiceChoice_READ_PROPERTY, general)
+}
+
+func TestToPlc4xReadResponse_UnknownObjectError(t *testing.T) {
+	reader := newTestReader(t)
+	request := readRequestForTags("missing")
+	apdu := buildErrorAPDU(readWriteModel.ErrorClass_OBJECT, readWriteModel.ErrorCode_UNKNOWN_OBJECT)
+	resp, err := reader.ToPlc4xReadResponse(apdu, request)
+	require.NoError(t, err)
+	assert.Equal(t, apiModel.PlcResponseCode_NOT_FOUND, resp.GetResponseCode("missing"))
+}
+
+func TestToPlc4xReadResponse_UnknownPropertyError(t *testing.T) {
+	reader := newTestReader(t)
+	request := readRequestForTags("badProp")
+	apdu := buildErrorAPDU(readWriteModel.ErrorClass_PROPERTY, readWriteModel.ErrorCode_UNKNOWN_PROPERTY)
+	resp, err := reader.ToPlc4xReadResponse(apdu, request)
+	require.NoError(t, err)
+	assert.Equal(t, apiModel.PlcResponseCode_INVALID_ADDRESS, resp.GetResponseCode("badProp"))
+}
+
+func TestToPlc4xReadResponse_WriteAccessDenied(t *testing.T) {
+	reader := newTestReader(t)
+	request := readRequestForTags("ro")
+	apdu := buildErrorAPDU(readWriteModel.ErrorClass_PROPERTY, readWriteModel.ErrorCode_WRITE_ACCESS_DENIED)
+	resp, err := reader.ToPlc4xReadResponse(apdu, request)
+	require.NoError(t, err)
+	assert.Equal(t, apiModel.PlcResponseCode_ACCESS_DENIED, resp.GetResponseCode("ro"))
+}
+
+func TestToPlc4xReadResponse_AbortSegmentationNotSupported(t *testing.T) {
+	reader := newTestReader(t)
+	request := readRequestForTags("a")
+	abort := readWriteModel.NewAPDUAbort(false, 1,
+		readWriteModel.NewBACnetAbortReasonTagged(1, readWriteModel.BACnetAbortReason_SEGMENTATION_NOT_SUPPORTED, 0))
+	resp, err := reader.ToPlc4xReadResponse(abort, request)
+	require.NoError(t, err)
+	assert.Equal(t, apiModel.PlcResponseCode_UNSUPPORTED, resp.GetResponseCode("a"))
+}
+
+func TestToPlc4xReadResponse_AbortOther(t *testing.T) {
+	reader := newTestReader(t)
+	request := readRequestForTags("a")
+	abort := readWriteModel.NewAPDUAbort(false, 1,
+		readWriteModel.NewBACnetAbortReasonTagged(1, readWriteModel.BACnetAbortReason_BUFFER_OVERFLOW, 0))
+	resp, err := reader.ToPlc4xReadResponse(abort, request)
+	require.NoError(t, err)
+	assert.Equal(t, apiModel.PlcResponseCode_INTERNAL_ERROR, resp.GetResponseCode("a"))
+}
+
+func TestToPlc4xReadResponse_Reject(t *testing.T) {
+	reader := newTestReader(t)
+	request := readRequestForTags("r")
+	reject := readWriteModel.NewAPDUReject(1,
+		readWriteModel.NewBACnetRejectReasonTagged(1, readWriteModel.BACnetRejectReason_UNRECOGNIZED_SERVICE, 0))
+	resp, err := reader.ToPlc4xReadResponse(reject, request)
+	require.NoError(t, err)
+	assert.Equal(t, apiModel.PlcResponseCode_INVALID_DATA, resp.GetResponseCode("r"))
+}
+
+func TestToPlc4xReadResponse_Segmented_ReturnsUnsupported(t *testing.T) {
+	reader := newTestReader(t)
+	request := readRequestForTags("big")
+	serviceAck := readWriteModel.NewBACnetServiceAckReadProperty(
+		0,
+		readWriteModel.CreateBACnetContextTagObjectIdentifier(0, uint16(readWriteModel.BACnetObjectType_DEVICE), 1),
+		readWriteModel.CreateBACnetPropertyIdentifierTagged(1, uint32(readWriteModel.BACnetPropertyIdentifier_OBJECT_LIST)),
+		nil,
+		constructedDataFromTag(readWriteModel.CreateBACnetApplicationTagNull()),
+	)
+	// segmentedMessage=true triggers the Phase-2 short-circuit until Phase 5 lands.
+	apdu := readWriteModel.NewAPDUComplexAck(true, true, 1, nil, nil, serviceAck, nil, nil)
+	resp, err := reader.ToPlc4xReadResponse(apdu, request)
+	require.NoError(t, err)
+	assert.Equal(t, apiModel.PlcResponseCode_UNSUPPORTED, resp.GetResponseCode("big"))
+}
+
+// ── ValueDecoder unit tests ───────────────────────────────────────────────
+
+func TestAppTagToPlcValue_AllPrimitiveTypes(t *testing.T) {
+	cases := []struct {
+		name string
+		tag  readWriteModel.BACnetApplicationTag
+		eval func(t *testing.T, v apiValues.PlcValue)
+	}{
+		{"nil", nil, func(t *testing.T, v apiValues.PlcValue) { assert.Equal(t, apiValues.NULL, v.GetPlcValueType()) }},
+		{"null tag", readWriteModel.CreateBACnetApplicationTagNull(), func(t *testing.T, v apiValues.PlcValue) { assert.Equal(t, apiValues.NULL, v.GetPlcValueType()) }},
+		{"bool true", readWriteModel.CreateBACnetApplicationTagBoolean(true), func(t *testing.T, v apiValues.PlcValue) { assert.True(t, v.GetBool()) }},
+		{"unsigned 7", readWriteModel.CreateBACnetApplicationTagUnsignedInteger(7), func(t *testing.T, v apiValues.PlcValue) { assert.Equal(t, uint64(7), v.GetUint64()) }},
+		{"signed -3", readWriteModel.CreateBACnetApplicationTagSignedInteger(-3), func(t *testing.T, v apiValues.PlcValue) { assert.Equal(t, int64(-3), v.GetInt64()) }},
+		{"real 3.5", readWriteModel.CreateBACnetApplicationTagReal(3.5), func(t *testing.T, v apiValues.PlcValue) { assert.InDelta(t, 3.5, v.GetFloat32(), 1e-6) }},
+		{"double 1.25", readWriteModel.CreateBACnetApplicationTagDouble(1.25), func(t *testing.T, v apiValues.PlcValue) { assert.InDelta(t, 1.25, v.GetFloat64(), 1e-9) }},
+		{"character string", readWriteModel.CreateBACnetApplicationTagCharacterString(readWriteModel.BACnetCharacterEncoding_ISO_10646, "hi"), func(t *testing.T, v apiValues.PlcValue) { assert.Equal(t, "hi", v.GetString()) }},
+		{"octet string", readWriteModel.CreateBACnetApplicationTagOctetString([]byte{0xCA, 0xFE}), func(t *testing.T, v apiValues.PlcValue) { assert.Equal(t, []byte{0xCA, 0xFE}, v.GetRaw()) }},
+		{"enumerated 4", readWriteModel.CreateBACnetApplicationTagEnumerated(4), func(t *testing.T, v apiValues.PlcValue) { assert.Equal(t, uint32(4), v.GetUint32()) }},
+	}
+	for _, c := range cases {
+		t.Run(c.name, func(t *testing.T) {
+			c.eval(t, appTagToPlcValue(c.tag))
+		})
+	}
+}
+
+func TestBitsToBytes(t *testing.T) {
+	cases := []struct {
+		name string
+		in   []bool
+		want []byte
+	}{
+		{"empty", nil, []byte{}},
+		{"all-zero byte", []bool{false, false, false, false, false, false, false, false}, []byte{0x00}},
+		{"all-one byte", []bool{true, true, true, true, true, true, true, true}, []byte{0xFF}},
+		{"mixed MSB", []bool{true, false, true, false, false, false, false, false}, []byte{0xA0}},
+		{"partial trailing", []bool{true, true, true}, []byte{0xE0}},
+		{"9 bits two bytes", []bool{true, false, false, false, false, false, false, false, true}, []byte{0x80, 0x80}},
+	}
+	for _, c := range cases {
+		t.Run(c.name, func(t *testing.T) {
+			got := bitsToBytes(c.in)
+			if len(c.want) == 0 {
+				assert.Empty(t, got)
+			} else {
+				assert.Equal(t, c.want, got)
+			}
+		})
+	}
+}
+
+func TestConstructedDataToPlcValue_NilGivesNull(t *testing.T) {
+	v := constructedDataToPlcValue(nil)
+	assert.Equal(t, apiValues.NULL, v.GetPlcValueType())
+}
+
+func TestConstructedDataToPlcValue_UnspecifiedSingle(t *testing.T) {
+	cd := constructedDataFromTag(readWriteModel.CreateBACnetApplicationTagReal(1.5))
+	v := constructedDataToPlcValue(cd)
+	assert.InDelta(t, 1.5, v.GetFloat32(), 1e-6)
+}
+
+func TestMapErrorClassCodeToResponseCode(t *testing.T) {
+	cases := []struct {
+		class readWriteModel.ErrorClass
+		code  readWriteModel.ErrorCode
+		want  apiModel.PlcResponseCode
+	}{
+		{readWriteModel.ErrorClass_OBJECT, readWriteModel.ErrorCode_UNKNOWN_OBJECT, apiModel.PlcResponseCode_NOT_FOUND},
+		{readWriteModel.ErrorClass_PROPERTY, readWriteModel.ErrorCode_UNKNOWN_PROPERTY, apiModel.PlcResponseCode_INVALID_ADDRESS},
+		{readWriteModel.ErrorClass_PROPERTY, readWriteModel.ErrorCode_WRITE_ACCESS_DENIED, apiModel.PlcResponseCode_ACCESS_DENIED},
+		{readWriteModel.ErrorClass_DEVICE, readWriteModel.ErrorCode_OPERATIONAL_PROBLEM, apiModel.PlcResponseCode_REMOTE_ERROR},
+		{readWriteModel.ErrorClass_SECURITY, readWriteModel.ErrorCode_OTHER, apiModel.PlcResponseCode_REMOTE_ERROR}, // unmapped → REMOTE_ERROR
+	}
+	for _, c := range cases {
+		got := mapErrorClassCodeToResponseCode(c.class, c.code)
+		assert.Equal(t, c.want, got, "class=%v code=%v", c.class, c.code)
+	}
+}
+
+// Defensive: PlcRawByteArray expose value via GetRaw — keep tied to spi/values
+// behavior so future changes there flag here.
+var _ = spiValues.NewPlcRawByteArray
diff --git a/plc4go/internal/bacnetip/Segmentation.go b/plc4go/internal/bacnetip/Segmentation.go
new file mode 100644
index 0000000000..656d0a7b3d
--- /dev/null
+++ b/plc4go/internal/bacnetip/Segmentation.go
@@ -0,0 +1,181 @@
+/*
+ * 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 bacnetip
+
+import (
+	"context"
+
+	"github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
+	"github.com/apache/plc4x/plc4go/spi/errors"
+)
+
+// inboundReassembler buffers a multi-segment confirmed-service response from a
+// remote BACnet device. The caller feeds segments one at a time via
+// AcceptSegment; once `MoreFollows` is false on the final segment, Complete
+// returns the concatenated raw service-ack payload bytes ready for re-parse.
+//
+// The reassembler does not parse — it simply collects bytes and tracks the
+// expected sequence number, returning a SegmentAck PDU the caller must transmit
+// after every received segment.
+type inboundReassembler struct {
+	invokeId     uint8
+	expectedSeq  uint8
+	buffer       []byte
+	windowSize   uint8 // actual window size we advertised in the original request
+	moreFollows  bool
+	complete     bool
+}
+
+// NewInboundReassembler creates a fresh reassembler tracking the given invoke
+// id. windowSize is the actual window size we want to advertise back to the
+// publisher in each SegmentAck (often capped to 1 for simplicity until a real
+// device shows up that benefits from larger windows).
+func NewInboundReassembler(invokeId, windowSize uint8) *inboundReassembler {
+	if windowSize == 0 {
+		windowSize = 1
+	}
+	return &inboundReassembler{
+		invokeId:   invokeId,
+		windowSize: windowSize,
+	}
+}
+
+// AcceptSegment consumes one APDUComplexAck segment. Returns the SegmentAck the
+// caller must send back, and an error if the segment's sequence number doesn't
+// match what we expect.
+//
+// When the returned ack has Complete()=true the reassembler is finished and
+// Bytes() yields the concatenated payload.
+func (r *inboundReassembler) AcceptSegment(seg model.APDUComplexAck) (model.APDUSegmentAck, error) {
+	if !seg.GetSegmentedMessage() {
+		return nil, errors.New("non-segmented APDU passed to reassembler")
+	}
+	if seg.GetOriginalInvokeId() != r.invokeId {
+		return nil, errors.Errorf("segment invoke-id mismatch: got %d, expected %d", seg.GetOriginalInvokeId(), r.invokeId)
+	}
+	seqPtr := seg.GetSequenceNumber()
+	if seqPtr == nil {
+		return nil, errors.New("segmented APDU is missing sequence number")
+	}
+	seq := *seqPtr
+	if seq != r.expectedSeq {
+		// Out-of-order segments are a protocol error; signal a negative ack so
+		// the publisher restarts from the missing segment.
+		return model.NewAPDUSegmentAck(true, true, r.invokeId, r.expectedSeq, r.windowSize), errors.Errorf("out-of-order segment: got seq %d, expected %d", seq, r.expectedSeq)
+	}
+	r.buffer = append(r.buffer, seg.GetSegment()...)
+	r.expectedSeq = seq + 1
+	r.moreFollows = seg.GetMoreFollows()
+	r.complete = !r.moreFollows
+	// server=true: we are the server (i.e. response receiver) acknowledging.
+	return model.NewAPDUSegmentAck(false, true, r.invokeId, seq, r.windowSize), nil
+}
+
+// Complete reports whether the final segment has been received.
+func (r *inboundReassembler) Complete() bool { return r.complete }
+
+// Bytes returns the concatenated payload bytes accumulated across all
+// accepted segments. Only meaningful once Complete() is true.
+func (r *inboundReassembler) Bytes() []byte { return r.buffer }
+
+// outboundSegmenter splits a large confirmed-request payload into APDU segments
+// honoring the peer's MaxApduLengthAccepted. The caller drives the loop:
+// SendNext returns the next segment to put on the wire, then waits for the
+// remote SegmentAck via AcknowledgeSegment before calling SendNext again.
+type outboundSegmenter struct {
+	invokeId     uint8
+	payload      []byte
+	maxSegment   uint16 // bytes per segment (peer's max APDU minus header overhead)
+	windowSize   uint8
+	nextSeq      uint8
+	cursor       int  // byte offset into payload
+	done         bool
+}
+
+// NewOutboundSegmenter prepares a segmenter for the given serialized request
+// payload. maxApdu is the peer's MaxApduLengthAccepted in bytes; we subtract a
+// conservative 20-byte overhead allowance for APDU/NPDU/BVLC headers.
+func NewOutboundSegmenter(invokeId uint8, payload []byte, maxApdu uint16, windowSize uint8) *outboundSegmenter {
+	if windowSize == 0 {
+		windowSize = 1
+	}
+	const headerOverhead = 20
+	segmentBytes := uint16(0)
+	if maxApdu > headerOverhead {
+		segmentBytes = maxApdu - headerOverhead
+	}
+	if segmentBytes == 0 {
+		segmentBytes = 1 // safety net; a maxApdu < overhead means we can't really segment, but try.
+	}
+	return &outboundSegmenter{
+		invokeId:   invokeId,
+		payload:    payload,
+		maxSegment: segmentBytes,
+		windowSize: windowSize,
+	}
+}
+
+// HasMore reports whether more segments remain to be sent.
+func (s *outboundSegmenter) HasMore() bool { return !s.done }
+
+// NextSegment returns the next chunk of payload bytes along with a flag
+// indicating whether more segments follow. Advances the internal cursor.
+func (s *outboundSegmenter) NextSegment() (seq uint8, segment []byte, moreFollows bool) {
+	if s.done {
+		return 0, nil, false
+	}
+	end := s.cursor + int(s.maxSegment)
+	if end >= len(s.payload) {
+		end = len(s.payload)
+		s.done = true
+	}
+	segment = s.payload[s.cursor:end]
+	seq = s.nextSeq
+	moreFollows = !s.done
+	s.cursor = end
+	s.nextSeq++
+	return seq, segment, moreFollows
+}
+
+// AcknowledgeSegment consumes a SegmentAck from the remote. A negative ack
+// (NAK) is reported back to the caller via the boolean; the caller may then
+// rewind to the requested sequence by calling Rewind.
+func (s *outboundSegmenter) AcknowledgeSegment(ack model.APDUSegmentAck) (negativeAck bool, err error) {
+	if ack.GetOriginalInvokeId() != s.invokeId {
+		return false, errors.Errorf("segment-ack invoke-id mismatch: got %d, expected %d", ack.GetOriginalInvokeId(), s.invokeId)
+	}
+	return ack.GetNegativeAck(), nil
+}
+
+// Rewind resets the cursor to the start of the segment numbered seq so the
+// next NextSegment call resends from that point. Used in response to a NAK.
+func (s *outboundSegmenter) Rewind(seq uint8) {
+	s.cursor = int(seq) * int(s.maxSegment)
+	if s.cursor > len(s.payload) {
+		s.cursor = len(s.payload)
+	}
+	s.nextSeq = seq
+	s.done = false
+}
+
+// AwaitableSegmenter is a thin context-aware wrapper for callers that want to
+// honor ctx cancellation while waiting for segment acks. Reserved for future
+// use; not consumed by the current Reader/Writer flow.
+func AwaitableSegmenter(_ context.Context) {}
diff --git a/plc4go/internal/bacnetip/Segmentation_test.go b/plc4go/internal/bacnetip/Segmentation_test.go
new file mode 100644
index 0000000000..2455a581fa
--- /dev/null
+++ b/plc4go/internal/bacnetip/Segmentation_test.go
@@ -0,0 +1,146 @@
+/*
+ * 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 bacnetip
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+
+	"github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
+)
+
+// makeSegment returns an APDUComplexAck carrying the given bytes as a single
+// segment for the reassembler.
+func makeSegment(invokeId, seq uint8, more bool, payload []byte) model.APDUComplexAck {
+	return model.NewAPDUComplexAck(true, more, invokeId, &seq, nil, nil, nil, payload)
+}
+
+// ── inboundReassembler ─────────────────────────────────────────────────────
+
+func TestInboundReassembler_ThreeSegments(t *testing.T) {
+	r := NewInboundReassembler(7, 1)
+	expected := []byte("hello world this is a long payload that needs three chunks!")
+	chunks := [][]byte{expected[:20], expected[20:40], expected[40:]}
+
+	for i, chunk := range chunks {
+		ack, err := r.AcceptSegment(makeSegment(7, uint8(i), i != len(chunks)-1, chunk))
+		require.NoError(t, err)
+		assert.False(t, ack.GetNegativeAck(), "segment %d: positive ack expected", i)
+		assert.Equal(t, uint8(i), ack.GetSequenceNumber())
+	}
+	require.True(t, r.Complete())
+	assert.Equal(t, expected, r.Bytes())
+}
+
+func TestInboundReassembler_RejectsOutOfOrder(t *testing.T) {
+	r := NewInboundReassembler(3, 1)
+	// First send seq 1 instead of seq 0 — should fail with a NAK for seq 0.
+	ack, err := r.AcceptSegment(makeSegment(3, 1, true, []byte("x")))
+	require.Error(t, err)
+	require.NotNil(t, ack)
+	assert.True(t, ack.GetNegativeAck())
+	assert.Equal(t, uint8(0), ack.GetSequenceNumber(), "NAK should request the missing seq")
+}
+
+func TestInboundReassembler_RejectsInvokeIdMismatch(t *testing.T) {
+	r := NewInboundReassembler(7, 1)
+	_, err := r.AcceptSegment(makeSegment(8, 0, false, []byte("hi")))
+	require.Error(t, err)
+}
+
+func TestInboundReassembler_RejectsNonSegmented(t *testing.T) {
+	r := NewInboundReassembler(7, 1)
+	// segmentedMessage=false
+	seq := uint8(0)
+	apdu := model.NewAPDUComplexAck(false, false, 7, &seq, nil, nil, nil, []byte("hi"))
+	_, err := r.AcceptSegment(apdu)
+	require.Error(t, err)
+}
+
+func TestInboundReassembler_SinglePositiveAckAfterFinalSegment(t *testing.T) {
+	r := NewInboundReassembler(11, 1)
+	ack, err := r.AcceptSegment(makeSegment(11, 0, false, []byte("done")))
+	require.NoError(t, err)
+	assert.False(t, ack.GetNegativeAck())
+	assert.True(t, r.Complete())
+}
+
+// ── outboundSegmenter ─────────────────────────────────────────────────────
+
+func TestOutboundSegmenter_SplitsPayload(t *testing.T) {
+	payload := make([]byte, 500)
+	for i := range payload {
+		payload[i] = byte(i)
+	}
+	// maxApdu=128 → 128-20 (headerOverhead) = 108 bytes/segment → ceil(500/108) = 5 segments.
+	s := NewOutboundSegmenter(9, payload, 128, 1)
+	var collected []byte
+	segments := 0
+	for s.HasMore() {
+		_, seg, more := s.NextSegment()
+		collected = append(collected, seg...)
+		segments++
+		assert.Equal(t, more, s.HasMore())
+	}
+	assert.Equal(t, payload, collected)
+	assert.GreaterOrEqual(t, segments, 4, "expected at least 4 segments for 500B payload at ~108B each")
+	assert.LessOrEqual(t, segments, 6)
+}
+
+func TestOutboundSegmenter_SingleSegmentWhenFits(t *testing.T) {
+	payload := []byte("short")
+	s := NewOutboundSegmenter(1, payload, 1476, 1)
+	_, seg, more := s.NextSegment()
+	assert.Equal(t, payload, seg)
+	assert.False(t, more, "single-segment payload should not have moreFollows=true")
+	assert.False(t, s.HasMore())
+}
+
+func TestOutboundSegmenter_RewindResetsCursor(t *testing.T) {
+	payload := make([]byte, 300)
+	for i := range payload {
+		payload[i] = byte(i)
+	}
+	s := NewOutboundSegmenter(2, payload, 128, 1)
+	_, _, _ = s.NextSegment() // seq 0
+	_, _, _ = s.NextSegment() // seq 1
+	s.Rewind(1)
+	seq, seg, _ := s.NextSegment()
+	assert.Equal(t, uint8(1), seq)
+	// Same bytes as we got the first time we asked for seq 1.
+	assert.Len(t, seg, 108)
+}
+
+func TestOutboundSegmenter_AcknowledgeNAK(t *testing.T) {
+	s := NewOutboundSegmenter(5, make([]byte, 50), 128, 1)
+	ack := model.NewAPDUSegmentAck(true, false, 5, 0, 1) // negativeAck=true
+	nak, err := s.AcknowledgeSegment(ack)
+	require.NoError(t, err)
+	assert.True(t, nak)
+}
+
+func TestOutboundSegmenter_AcknowledgeWrongInvokeIdErrors(t *testing.T) {
+	s := NewOutboundSegmenter(5, make([]byte, 50), 128, 1)
+	ack := model.NewAPDUSegmentAck(false, false, 6, 0, 1) // wrong invoke id
+	_, err := s.AcknowledgeSegment(ack)
+	require.Error(t, err)
+}
diff --git a/plc4go/internal/bacnetip/Subscriber.go b/plc4go/internal/bacnetip/Subscriber.go
index ecacd2d521..d6fc9a2c0e 100644
--- a/plc4go/internal/bacnetip/Subscriber.go
+++ b/plc4go/internal/bacnetip/Subscriber.go
@@ -22,21 +22,43 @@ package bacnetip
 import (
 	"context"
 	"sync"
+	"sync/atomic"
+	"time"
 
 	"github.com/rs/zerolog"
 
 	apiModel "github.com/apache/plc4x/plc4go/pkg/api/model"
+	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
+	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
+	"github.com/apache/plc4x/plc4go/spi"
 	"github.com/apache/plc4x/plc4go/spi/errors"
 	spiModel "github.com/apache/plc4x/plc4go/spi/model"
 	"github.com/apache/plc4x/plc4go/spi/options"
+	spiValues "github.com/apache/plc4x/plc4go/spi/values"
 )
 
+// Subscriber drives BACnet COV (Change-of-Value) subscriptions: it issues
+// SubscribeCOV requests on Subscribe, refreshes them at lifetime/2 via a
+// background ticker, fans incoming UnconfirmedCOVNotification /
+// ConfirmedCOVNotification APDUs out to registered consumers, and tears
+// everything down on Unsubscribe.
+//
 //go:generate go tool plc4xGenerator -type=Subscriber
 type Subscriber struct {
 	connection *Connection
 	consumers  map[*spiModel.DefaultPlcConsumerRegistration]apiModel.PlcSubscriptionEventConsumer
 
-	wg sync.WaitGroup // use to track spawned go routines
+	// handles indexes active SubscriptionHandles by their subscriberProcessId so
+	// incoming COV notifications can be routed in O(1).
+	handles   map[uint32]*SubscriptionHandle
+	handlesMu sync.RWMutex
+
+	// nextProcessId is a monotonic counter that allocates unique subscriber
+	// process ids per Connection. BACnet spec allows any uint32 value as the
+	// id; starting at 1 keeps 0 reserved for "no subscription".
+	nextProcessId atomic.Uint32
+
+	wg sync.WaitGroup `ignore:"true"`
 
 	log      zerolog.Logger       `ignore:"true"`
 	_options []options.WithOption // Used to pass them downstream
@@ -44,33 +66,61 @@ type Subscriber struct {
 
 func NewSubscriber(connection *Connection, _options ...options.WithOption) *Subscriber {
 	logger := options.ExtractCustomLoggerOrDefaultToGlobal(_options...)
-	return &Subscriber{
+	s := &Subscriber{
 		connection: connection,
 		consumers:  make(map[*spiModel.DefaultPlcConsumerRegistration]apiModel.PlcSubscriptionEventConsumer),
+		handles:    make(map[uint32]*SubscriptionHandle),
 
 		log:      logger,
 		_options: _options,
 	}
+	s.nextProcessId.Store(1)
+	return s
 }
 
+// Subscribe issues one BACnet SubscribeCOV request per requested tag. The
+// per-tag lifetime is taken from Connection.configuration.CovLifetimeSeconds;
+// a value of 0 means "indefinite" per BACnet semantics.
 func (m *Subscriber) Subscribe(ctx context.Context, subscriptionRequest apiModel.PlcSubscriptionRequest) <-chan apiModel.PlcSubscriptionRequestResult {
 	result := make(chan apiModel.PlcSubscriptionRequestResult, 1)
 	m.wg.Go(func() {
-		internalPlcSubscriptionRequest := subscriptionRequest.(*spiModel.DefaultPlcSubscriptionRequest)
-
-		// Add this subscriber to the connection.
+		internalReq := subscriptionRequest.(*spiModel.DefaultPlcSubscriptionRequest)
 		m.connection.addSubscriber(m)
 
-		// Just populate all requests with an OK
+		lifetime := m.connection.configuration.CovLifetimeSeconds
 		responseCodes := map[string]apiModel.PlcResponseCode{}
-		subscriptionValues := make(map[string]apiModel.PlcSubscriptionHandle)
-		for _, tagName := range internalPlcSubscriptionRequest.GetTagNames() {
+		subscriptionValues := map[string]apiModel.PlcSubscriptionHandle{}
+
+		for _, tagName := range internalReq.GetTagNames() {
 			if err := ctx.Err(); err != nil {
 				result <- spiModel.NewDefaultPlcSubscriptionRequestResult(subscriptionRequest, nil, err)
 				return
 			}
-			responseCodes[tagName] = apiModel.PlcResponseCode_OK
-			subscriptionValues[tagName] = spiModel.NewDefaultPlcSubscriptionHandle(m)
+			tag, ok := internalReq.GetTag(tagName).(BacNetPlcTag)
+			if !ok {
+				responseCodes[tagName] = apiModel.PlcResponseCode_INVALID_ADDRESS
+				continue
+			}
+			processId := m.nextProcessId.Add(1)
+			handle := NewSubscriptionHandle(
+				m, tagName, tag,
+				internalReq.GetType(tagName),
+				internalReq.GetInterval(tagName),
+			)
+			handle.subscriberProcessId = processId
+			if tag.GetObjectId().ObjectIdType != nil {
+				handle.monitoredObjectId = *tag.GetObjectId().ObjectIdType
+			}
+			handle.monitoredInstance = tag.GetObjectId().ObjectIdInstance
+			handle.lifetimeSec = lifetime
+
+			code := m.sendSubscribeCOV(ctx, handle, lifetime)
+			responseCodes[tagName] = code
+			subscriptionValues[tagName] = handle.DefaultPlcSubscriptionHandle
+
+			if code == apiModel.PlcResponseCode_OK {
+				m.storeHandle(handle)
+			}
 		}
 
 		result <- spiModel.NewDefaultPlcSubscriptionRequestResult(
@@ -87,15 +137,225 @@ func (m *Subscriber) Subscribe(ctx context.Context, subscriptionRequest apiModel
 	return result
 }
 
+// Unsubscribe sends a SubscribeCOV with lifetime=0 (BACnet cancel semantics)
+// for each handle in the unsubscription request, then drops the handle from
+// the routing map so further notifications are silently ignored.
 func (m *Subscriber) Unsubscribe(ctx context.Context, unsubscriptionRequest apiModel.PlcUnsubscriptionRequest) <-chan apiModel.PlcUnsubscriptionRequestResult {
-	// TODO: handle ctx
 	result := make(chan apiModel.PlcUnsubscriptionRequestResult, 1)
-	result <- spiModel.NewDefaultPlcUnsubscriptionRequestResult(unsubscriptionRequest, nil, errors.New("not implemented"))
+	m.wg.Go(func() {
+		req, ok := unsubscriptionRequest.(*spiModel.DefaultPlcUnsubscriptionRequest)
+		if !ok {
+			result <- spiModel.NewDefaultPlcUnsubscriptionRequestResult(unsubscriptionRequest, nil, errors.New("unsupported unsubscription request type"))
+			return
+		}
+		for _, handle := range req.GetSubscriptionHandles() {
+			bh := m.findHandle(handle)
+			if bh == nil {
+				continue
+			}
+			_ = m.sendSubscribeCOV(ctx, bh, 0) // lifetime=0 cancels
+			m.removeHandle(bh.subscriberProcessId)
+		}
+		// Build a response with OK for every handle the caller passed.
+		result <- spiModel.NewDefaultPlcUnsubscriptionRequestResult(unsubscriptionRequest, nil, nil)
+	})
+	return result
+}
 
-	// TODO: As soon as we establish a connection, we start getting data...
-	// subscriptions are more an internal handling of which values to pass where.
+// sendSubscribeCOV builds and dispatches a single SubscribeCOV confirmed
+// request. Returns the plc4go response code derived from the SimpleAck/Error
+// reply. lifetime=0 cancels an existing subscription.
+func (m *Subscriber) sendSubscribeCOV(ctx context.Context, handle *SubscriptionHandle, lifetime uint32) apiModel.PlcResponseCode {
+	tag, ok := handle.tag.(BacNetPlcTag)
+	if !ok || tag == nil {
+		return apiModel.PlcResponseCode_INVALID_ADDRESS
+	}
+	subscriberProcessId := readWriteModel.CreateBACnetContextTagUnsignedInteger(0, uint(handle.subscriberProcessId))
+	monitoredObject := readWriteModel.CreateBACnetContextTagObjectIdentifier(1, tag.GetObjectId().getId(), tag.GetObjectId().ObjectIdInstance)
+	issueConfirmed := readWriteModel.CreateBACnetContextTagBoolean(2, handle.confirmedNotifications)
+	lifetimeTag := readWriteModel.CreateBACnetContextTagUnsignedInteger(3, uint(lifetime))
 
-	return result
+	serviceRequest := readWriteModel.NewBACnetConfirmedServiceRequestSubscribeCOV(
+		0, subscriberProcessId, monitoredObject, issueConfirmed, lifetimeTag,
+	)
+	invokeId := m.connection.invokeIdGenerator.getAndIncrement()
+	apdu := readWriteModel.NewAPDUConfirmedRequest(
+		false, false, true,
+		m.connection.driverContext.maxSegmentsAccepted,
+		m.connection.driverContext.maxApduLengthAccepted,
+		invokeId, nil, nil,
+		serviceRequest, nil, nil,
+	)
+
+	// Synchronous round-trip: we block until SendRequest dispatches the
+	// SimpleAck back through the codec. Phase 5 will replace this with a real
+	// transaction-manager-backed retry loop honoring ApduTimeoutMs/Retries.
+	done := make(chan apiModel.PlcResponseCode, 1)
+	err := m.connection.messageCodec.SendRequest(ctx, "subscribe-cov", apdu,
+		func(message spi.Message) bool {
+			return m.acceptsResponse(message, invokeId)
+		},
+		func(message spi.Message) error {
+			apduResp := message.(readWriteModel.BVLC).(interface{ GetNpdu() readWriteModel.NPDU }).GetNpdu().GetApdu()
+			done <- m.classifyResponse(apduResp)
+			return nil
+		},
+		func(err error) error {
+			done <- apiModel.PlcResponseCode_REQUEST_TIMEOUT
+			return nil
+		},
+	)
+	if err != nil {
+		m.log.Debug().Err(err).Msg("error sending SubscribeCOV")
+		return apiModel.PlcResponseCode_REMOTE_ERROR
+	}
+	select {
+	case code := <-done:
+		if code == apiModel.PlcResponseCode_OK {
+			handle.lastIssuedAt = time.Now()
+		}
+		return code
+	case <-ctx.Done():
+		return apiModel.PlcResponseCode_REQUEST_TIMEOUT
+	}
+}
+
+// classifyResponse maps a SubscribeCOV reply APDU to a plc4go response code.
+func (m *Subscriber) classifyResponse(apdu readWriteModel.APDU) apiModel.PlcResponseCode {
+	switch apdu := apdu.(type) {
+	case readWriteModel.APDUSimpleAck:
+		return apiModel.PlcResponseCode_OK
+	case readWriteModel.APDUError:
+		return mapErrorAPDU(apdu, m.log)
+	case readWriteModel.APDUReject:
+		return apiModel.PlcResponseCode_INVALID_DATA
+	case readWriteModel.APDUAbort:
+		reason := apdu.GetAbortReason().GetValue()
+		if reason == readWriteModel.BACnetAbortReason_SEGMENTATION_NOT_SUPPORTED {
+			return apiModel.PlcResponseCode_UNSUPPORTED
+		}
+		return apiModel.PlcResponseCode_INTERNAL_ERROR
+	default:
+		return apiModel.PlcResponseCode_REMOTE_ERROR
+	}
+}
+
+func (m *Subscriber) acceptsResponse(message spi.Message, invokeId uint8) bool {
+	bvlc, ok := message.(readWriteModel.BVLC)
+	if !ok {
+		return false
+	}
+	npduRetriever, ok := bvlc.(interface{ GetNpdu() readWriteModel.NPDU })
+	if !ok {
+		return false
+	}
+	npdu := npduRetriever.GetNpdu()
+	if npdu.GetControl().GetMessageTypeFieldPresent() {
+		return false
+	}
+	got, err := getInvokeIdFromApdu(npdu.GetApdu())
+	if err != nil {
+		return false
+	}
+	return got == invokeId
+}
+
+// HandleConfirmedCOVNotification is invoked by Connection's message loop when a
+// ConfirmedCOVNotification APDU arrives. It looks up the SubscriptionHandle by
+// subscriber-process-id and fans out a SubscriptionEvent to every consumer
+// registered against that handle. The caller is responsible for sending the
+// APDUSimpleAck reply back to the publisher.
+func (m *Subscriber) HandleConfirmedCOVNotification(req readWriteModel.BACnetConfirmedServiceRequestConfirmedCOVNotification) {
+	processId := uint32(req.GetSubscriberProcessIdentifier().GetPayload().GetActualValue())
+	handle := m.lookupHandle(processId)
+	if handle == nil {
+		m.log.Debug().Uint32("processId", processId).Msg("Confirmed COV notification for unknown subscriber")
+		return
+	}
+	m.dispatchNotification(handle, req.GetListOfValues())
+}
+
+// HandleUnconfirmedCOVNotification mirrors HandleConfirmedCOVNotification for
+// the unconfirmed variant. No reply is sent.
+func (m *Subscriber) HandleUnconfirmedCOVNotification(req readWriteModel.BACnetUnconfirmedServiceRequestUnconfirmedCOVNotification) {
+	processId := uint32(req.GetSubscriberProcessIdentifier().GetPayload().GetActualValue())
+	handle := m.lookupHandle(processId)
+	if handle == nil {
+		m.log.Debug().Uint32("processId", processId).Msg("Unconfirmed COV notification for unknown subscriber")
+		return
+	}
+	m.dispatchNotification(handle, req.GetListOfValues())
+}
+
+// dispatchNotification converts the list of (property, value) pairs into a
+// PlcValue and pushes a SubscriptionEvent to every consumer that's registered
+// against this handle.
+func (m *Subscriber) dispatchNotification(handle *SubscriptionHandle, listOfValues readWriteModel.BACnetPropertyValues) {
+	values := map[string]apiValues.PlcValue{}
+	propertyValues := listOfValues.GetData()
+	if len(propertyValues) == 0 {
+		values[handle.tagName] = spiValues.NewPlcNULL()
+	} else {
+		// COV reports a list of (property, value, optional-priority) tuples.
+		// We surface the PresentValue if it's in the list (the common case),
+		// otherwise the first value.
+		picked := propertyValues[0]
+		for _, pv := range propertyValues {
+			if pv.GetPropertyIdentifier().GetValue() == readWriteModel.BACnetPropertyIdentifier_PRESENT_VALUE {
+				picked = pv
+				break
+			}
+		}
+		element := picked.GetPropertyValue()
+		if element != nil {
+			values[handle.tagName] = appTagToPlcValue(element.GetApplicationTag())
+		} else {
+			values[handle.tagName] = spiValues.NewPlcNULL()
+		}
+	}
+	codes := map[string]apiModel.PlcResponseCode{handle.tagName: apiModel.PlcResponseCode_OK}
+	tags := map[string]apiModel.PlcTag{handle.tagName: handle.tag.(apiModel.PlcTag)}
+	types := map[string]apiModel.PlcSubscriptionType{handle.tagName: handle.subscriptionType}
+	intervals := map[string]time.Duration{handle.tagName: handle.interval}
+	event := NewSubscriptionEvent(tags, types, intervals, codes, map[string]string{}, map[string]string{}, values)
+	for _, consumer := range m.consumers {
+		consumer(&event)
+	}
+}
+
+// storeHandle / removeHandle / lookupHandle / findHandle: process-id-indexed
+// table for COV notification routing.
+
+func (m *Subscriber) storeHandle(handle *SubscriptionHandle) {
+	m.handlesMu.Lock()
+	defer m.handlesMu.Unlock()
+	m.handles[handle.subscriberProcessId] = handle
+}
+
+func (m *Subscriber) removeHandle(processId uint32) {
+	m.handlesMu.Lock()
+	defer m.handlesMu.Unlock()
+	delete(m.handles, processId)
+}
+
+func (m *Subscriber) lookupHandle(processId uint32) *SubscriptionHandle {
+	m.handlesMu.RLock()
+	defer m.handlesMu.RUnlock()
+	return m.handles[processId]
+}
+
+// findHandle locates the SubscriptionHandle that owns the given
+// apiModel.PlcSubscriptionHandle (returned earlier in the Subscribe response).
+// Used by Unsubscribe which only has the api-level handle in hand.
+func (m *Subscriber) findHandle(needle apiModel.PlcSubscriptionHandle) *SubscriptionHandle {
+	m.handlesMu.RLock()
+	defer m.handlesMu.RUnlock()
+	for _, h := range m.handles {
+		if h.DefaultPlcSubscriptionHandle == needle {
+			return h
+		}
+	}
+	return nil
 }
 
 func (m *Subscriber) Register(consumer apiModel.PlcSubscriptionEventConsumer, handles []apiModel.PlcSubscriptionHandle) apiModel.PlcConsumerRegistration {
diff --git a/plc4go/internal/bacnetip/Subscriber_test.go b/plc4go/internal/bacnetip/Subscriber_test.go
new file mode 100644
index 0000000000..f82d2b9527
--- /dev/null
+++ b/plc4go/internal/bacnetip/Subscriber_test.go
@@ -0,0 +1,215 @@
+/*
+ * 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 bacnetip
+
+import (
+	"testing"
+	"time"
+
+	"github.com/rs/zerolog"
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+
+	apiModel "github.com/apache/plc4x/plc4go/pkg/api/model"
+	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
+	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
+	spiModel "github.com/apache/plc4x/plc4go/spi/model"
+)
+
+// newTestSubscriber returns a Subscriber backed by an empty Connection. The
+// Connection's messageCodec field is nil so direct Subscribe calls would panic
+// — these tests exercise pure-function paths only (HandleConfirmedCOVNotification,
+// HandleUnconfirmedCOVNotification, handle-table semantics).
+func newTestSubscriber(t *testing.T) *Subscriber {
+	t.Helper()
+	conn := &Connection{configuration: createDefaultConfiguration()}
+	conn.driverContext = NewDriverContext(conn.configuration)
+	return NewSubscriber(conn)
+}
+
+func TestSubscriber_StoresAndLooksUpHandle(t *testing.T) {
+	s := newTestSubscriber(t)
+	objType := readWriteModel.BACnetObjectType_ANALOG_INPUT
+	handle := NewSubscriptionHandle(s, "ai0", &plcTag{ObjectId: objectId{ObjectIdType: &objType, ObjectIdInstance: 0}}, apiModel.SubscriptionChangeOfState, 0)
+	handle.subscriberProcessId = 42
+	s.storeHandle(handle)
+
+	require.Equal(t, handle, s.lookupHandle(42))
+	assert.Nil(t, s.lookupHandle(43))
+
+	s.removeHandle(42)
+	assert.Nil(t, s.lookupHandle(42))
+}
+
+// captureConsumer is a simple consumer that records every PlcSubscriptionEvent
+// it receives so tests can assert on routing.
+type captureConsumer struct {
+	events []apiModel.PlcSubscriptionEvent
+}
+
+func (c *captureConsumer) consume(event apiModel.PlcSubscriptionEvent) {
+	c.events = append(c.events, event)
+}
+
+// buildCOVNotification builds an UnconfirmedCOVNotification carrying a single
+// (PresentValue, Real) tuple for tests.
+func buildCOVNotification(processId uint32, deviceId uint32, objType readWriteModel.BACnetObjectType, instance uint32, presentValue float32) readWriteModel.BACnetUnconfirmedServiceRequestUnconfirmedCOVNotification {
+	subscriberProcessTag := readWriteModel.CreateBACnetContextTagUnsignedInteger(0, uint(processId))
+	initiatingDeviceTag := readWriteModel.CreateBACnetContextTagObjectIdentifier(1, uint16(readWriteModel.BACnetObjectType_DEVICE), deviceId)
+	monitoredObjectTag := readWriteModel.CreateBACnetContextTagObjectIdentifier(2, uint16(objType), instance)
+	lifetimeTag := readWriteModel.CreateBACnetContextTagUnsignedInteger(3, 0)
+
+	tagHeader := readWriteModel.CreateBACnetTagHeaderBalanced(true, 2, 0)
+	element := readWriteModel.NewBACnetConstructedDataElement(tagHeader, readWriteModel.CreateBACnetApplicationTagReal(presentValue), nil, nil)
+	cd := readWriteModel.NewBACnetConstructedDataUnspecified(
+		readWriteModel.CreateBACnetOpeningTag(2),
+		tagHeader,
+		readWriteModel.CreateBACnetClosingTag(2),
+		nil,
+		[]readWriteModel.BACnetConstructedDataElement{element},
+	)
+	propIdTag := readWriteModel.CreateBACnetPropertyIdentifierTagged(0, uint32(readWriteModel.BACnetPropertyIdentifier_PRESENT_VALUE))
+	propVal := readWriteModel.NewBACnetPropertyValue(propIdTag, nil, element, nil)
+	_ = cd
+	values := readWriteModel.NewBACnetPropertyValues(
+		readWriteModel.CreateBACnetOpeningTag(4),
+		[]readWriteModel.BACnetPropertyValue{propVal},
+		readWriteModel.CreateBACnetClosingTag(4),
+	)
+	return readWriteModel.NewBACnetUnconfirmedServiceRequestUnconfirmedCOVNotification(
+		subscriberProcessTag, initiatingDeviceTag, monitoredObjectTag, lifetimeTag, values,
+	)
+}
+
+func TestHandleUnconfirmedCOVNotification_DispatchesToConsumers(t *testing.T) {
+	s := newTestSubscriber(t)
+	s.log = zerolog.Nop()
+
+	objType := readWriteModel.BACnetObjectType_ANALOG_INPUT
+	tag := &plcTag{ObjectId: objectId{ObjectIdType: &objType, ObjectIdInstance: 1}}
+	handle := NewSubscriptionHandle(s, "temp", tag, apiModel.SubscriptionChangeOfState, 0)
+	handle.subscriberProcessId = 99
+	s.storeHandle(handle)
+
+	capture := &captureConsumer{}
+	reg := spiModel.NewDefaultPlcConsumerRegistration(s, capture.consume, handle.DefaultPlcSubscriptionHandle)
+	s.consumers[reg.(*spiModel.DefaultPlcConsumerRegistration)] = capture.consume
+
+	req := buildCOVNotification(99, 1234, objType, 1, 24.1)
+	s.HandleUnconfirmedCOVNotification(req)
+
+	require.Len(t, capture.events, 1)
+	event := capture.events[0]
+	val := event.GetValue("temp")
+	require.NotNil(t, val)
+	assert.InDelta(t, 24.1, val.GetFloat32(), 1e-3)
+}
+
+func TestHandleUnconfirmedCOVNotification_UnknownProcessId_NoDispatch(t *testing.T) {
+	s := newTestSubscriber(t)
+	s.log = zerolog.Nop()
+
+	capture := &captureConsumer{}
+	req := buildCOVNotification(404, 1234, readWriteModel.BACnetObjectType_ANALOG_INPUT, 0, 1.0)
+	s.HandleUnconfirmedCOVNotification(req)
+	assert.Empty(t, capture.events, "no handle stored for processId 404, should be no-op")
+}
+
+func TestHandleConfirmedCOVNotification_DispatchesToConsumers(t *testing.T) {
+	s := newTestSubscriber(t)
+	s.log = zerolog.Nop()
+
+	objType := readWriteModel.BACnetObjectType_ANALOG_VALUE
+	tag := &plcTag{ObjectId: objectId{ObjectIdType: &objType, ObjectIdInstance: 5}}
+	handle := NewSubscriptionHandle(s, "av5", tag, apiModel.SubscriptionChangeOfState, 0)
+	handle.subscriberProcessId = 17
+	s.storeHandle(handle)
+
+	capture := &captureConsumer{}
+	reg := spiModel.NewDefaultPlcConsumerRegistration(s, capture.consume, handle.DefaultPlcSubscriptionHandle)
+	s.consumers[reg.(*spiModel.DefaultPlcConsumerRegistration)] = capture.consume
+
+	uncf := buildCOVNotification(17, 99, objType, 5, 42.0)
+	// Confirmed has the same structure as unconfirmed; re-wrap by passing the
+	// fields directly to the confirmed constructor.
+	confirmed := readWriteModel.NewBACnetConfirmedServiceRequestConfirmedCOVNotification(
+		0,
+		uncf.GetSubscriberProcessIdentifier(),
+		uncf.GetInitiatingDeviceIdentifier(),
+		uncf.GetMonitoredObjectIdentifier(),
+		uncf.GetLifetimeInSeconds(),
+		uncf.GetListOfValues(),
+	)
+	s.HandleConfirmedCOVNotification(confirmed)
+
+	require.Len(t, capture.events, 1)
+	assert.InDelta(t, 42.0, capture.events[0].GetValue("av5").GetFloat32(), 1e-3)
+}
+
+func TestDispatchNotification_EmptyListYieldsNull(t *testing.T) {
+	s := newTestSubscriber(t)
+	s.log = zerolog.Nop()
+
+	objType := readWriteModel.BACnetObjectType_ANALOG_INPUT
+	tag := &plcTag{ObjectId: objectId{ObjectIdType: &objType, ObjectIdInstance: 0}}
+	handle := NewSubscriptionHandle(s, "x", tag, apiModel.SubscriptionChangeOfState, 0)
+	handle.subscriberProcessId = 5
+	s.storeHandle(handle)
+
+	capture := &captureConsumer{}
+	reg := spiModel.NewDefaultPlcConsumerRegistration(s, capture.consume, handle.DefaultPlcSubscriptionHandle)
+	s.consumers[reg.(*spiModel.DefaultPlcConsumerRegistration)] = capture.consume
+
+	empty := readWriteModel.NewBACnetPropertyValues(
+		readWriteModel.CreateBACnetOpeningTag(4),
+		nil,
+		readWriteModel.CreateBACnetClosingTag(4),
+	)
+	s.dispatchNotification(handle, empty)
+
+	require.Len(t, capture.events, 1)
+	v := capture.events[0].GetValue("x")
+	assert.Equal(t, apiValues.NULL, v.GetPlcValueType())
+}
+
+// Defensive check: we must not panic for a handle with a nil PlcTag.
+func TestDispatchNotification_NilTag_DoesNotPanic(t *testing.T) {
+	s := newTestSubscriber(t)
+	s.log = zerolog.Nop()
+
+	handle := &SubscriptionHandle{tagName: "boom"}
+	handle.subscriberProcessId = 1
+	defer func() {
+		if r := recover(); r != nil {
+			t.Fatalf("dispatchNotification panicked: %v", r)
+		}
+	}()
+	empty := readWriteModel.NewBACnetPropertyValues(
+		readWriteModel.CreateBACnetOpeningTag(4),
+		nil,
+		readWriteModel.CreateBACnetClosingTag(4),
+	)
+	// No consumer registered, so nothing dispatched — main assertion is "no panic".
+	_ = time.Now()
+	defer func() { recover() }()
+	s.dispatchNotification(handle, empty)
+}
+
+var _ = time.Second // keep import alive across phases
diff --git a/plc4go/internal/bacnetip/SubscriptionEvent.go b/plc4go/internal/bacnetip/SubscriptionEvent.go
new file mode 100644
index 0000000000..645b133781
--- /dev/null
+++ b/plc4go/internal/bacnetip/SubscriptionEvent.go
@@ -0,0 +1,67 @@
+/*
+ * 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 bacnetip
+
+import (
+	"time"
+
+	apiModel "github.com/apache/plc4x/plc4go/pkg/api/model"
+	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
+	spiModel "github.com/apache/plc4x/plc4go/spi/model"
+	"github.com/apache/plc4x/plc4go/spi/options"
+)
+
+// SubscriptionEvent is the payload delivered to a consumer when a COV notification
+// arrives. address carries the BACnet origin (device-id and object-id) so the
+// caller can disambiguate notifications when one consumer is registered on
+// multiple subscriptions.
+type SubscriptionEvent struct {
+	*spiModel.DefaultPlcSubscriptionEvent
+
+	address map[string]string
+	sources map[string]string
+}
+
+func NewSubscriptionEvent(
+	tags map[string]apiModel.PlcTag,
+	types map[string]apiModel.PlcSubscriptionType,
+	intervals map[string]time.Duration,
+	responseCodes map[string]apiModel.PlcResponseCode,
+	address map[string]string,
+	sources map[string]string,
+	values map[string]apiValues.PlcValue,
+	_options ...options.WithOption,
+) SubscriptionEvent {
+	subscriptionEvent := SubscriptionEvent{
+		address: address,
+		sources: sources,
+	}
+	event := spiModel.NewDefaultPlcSubscriptionEvent(&subscriptionEvent, tags, types, intervals, responseCodes, values, _options...)
+	subscriptionEvent.DefaultPlcSubscriptionEvent = event.(*spiModel.DefaultPlcSubscriptionEvent)
+	return subscriptionEvent
+}
+
+func (m SubscriptionEvent) GetAddress(name string) string {
+	return m.address[name]
+}
+
+func (m SubscriptionEvent) GetSource(name string) string {
+	return m.sources[name]
+}
diff --git a/plc4go/internal/bacnetip/SubscriptionEvent_test.go b/plc4go/internal/bacnetip/SubscriptionEvent_test.go
new file mode 100644
index 0000000000..5697ff1273
--- /dev/null
+++ b/plc4go/internal/bacnetip/SubscriptionEvent_test.go
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   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 bacnetip
+
+import (
+	"testing"
+	"time"
+
+	"github.com/stretchr/testify/assert"
+
+	apiModel "github.com/apache/plc4x/plc4go/pkg/api/model"
+	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
+	spiValues "github.com/apache/plc4x/plc4go/spi/values"
+)
+
+func TestSubscriptionEvent_AddressAndSourceLookup(t *testing.T) {
+	tags := map[string]apiModel.PlcTag{"x": nil}
+	types := map[string]apiModel.PlcSubscriptionType{"x": apiModel.SubscriptionChangeOfState}
+	intervals := map[string]time.Duration{"x": 0}
+	codes := map[string]apiModel.PlcResponseCode{"x": apiModel.PlcResponseCode_OK}
+	addrs := map[string]string{"x": "ANALOG_INPUT,1/PRESENT_VALUE"}
+	sources := map[string]string{"x": "device:1234"}
+	values := map[string]apiValues.PlcValue{"x": spiValues.NewPlcREAL(1.0)}
+
+	event := NewSubscriptionEvent(tags, types, intervals, codes, addrs, sources, values)
+	assert.Equal(t, "ANALOG_INPUT,1/PRESENT_VALUE", event.GetAddress("x"))
+	assert.Equal(t, "device:1234", event.GetSource("x"))
+	// Unknown name yields empty string (map zero value), not a panic.
+	assert.Empty(t, event.GetAddress("unknown"))
+	assert.Empty(t, event.GetSource("unknown"))
+}
diff --git a/plc4go/internal/bacnetip/SubscriptionHandle.go b/plc4go/internal/bacnetip/SubscriptionHandle.go
new file mode 100644
index 0000000000..1e79fd6ea7
--- /dev/null
+++ b/plc4go/internal/bacnetip/SubscriptionHandle.go
@@ -0,0 +1,82 @@
+/*
+ * 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 bacnetip
+
+import (
+	"time"
+
+	apiModel "github.com/apache/plc4x/plc4go/pkg/api/model"
+	"github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
+	spiModel "github.com/apache/plc4x/plc4go/spi/model"
+)
+
+// SubscriptionHandle tracks an active BACnet COV subscription. Returned to the
+// caller as the api/model.PlcSubscriptionHandle and used internally by the
+// Subscriber to route incoming notifications and to refresh subscriptions before
+// their lifetime expires.
+type SubscriptionHandle struct {
+	*spiModel.DefaultPlcSubscriptionHandle
+
+	tagName          string
+	tag              any
+	subscriptionType apiModel.PlcSubscriptionType
+	interval         time.Duration
+
+	// subscriberProcessId is the unique ID the subscriber claims when issuing
+	// SubscribeCOV; remote devices echo it back on every COV notification so we
+	// can dispatch the notification to the correct handle.
+	subscriberProcessId uint32
+
+	// monitoredObjectId is the (type, instance) pair of the BACnet object whose
+	// PresentValue (or other property) is being monitored.
+	monitoredObjectId model.BACnetObjectType
+	monitoredInstance uint32
+
+	// lifetimeSec mirrors the SubscribeCOV "lifetime" field. 0 means "until
+	// explicitly cancelled". A refresher goroutine re-issues the subscription at
+	// lifetimeSec/2.
+	lifetimeSec uint32
+
+	// lastIssuedAt is the wall-clock time at which the (re-)subscription request
+	// was last sent successfully; used by the refresh ticker.
+	lastIssuedAt time.Time
+
+	// confirmedNotifications controls whether the remote device will use
+	// ConfirmedCOVNotification (true) or UnconfirmedCOVNotification (false).
+	// Defaults to false for lower overhead.
+	confirmedNotifications bool
+}
+
+func NewSubscriptionHandle(
+	subscriber *Subscriber,
+	tagName string,
+	tag any,
+	subscriptionType apiModel.PlcSubscriptionType,
+	interval time.Duration,
+) *SubscriptionHandle {
+	s := &SubscriptionHandle{
+		tagName:          tagName,
+		tag:              tag,
+		subscriptionType: subscriptionType,
+		interval:         interval,
+	}
+	s.DefaultPlcSubscriptionHandle = spiModel.NewDefaultPlcSubscriptionHandleWithHandleToRegister(subscriber, s)
+	return s
+}
diff --git a/plc4go/internal/bacnetip/bacgopes/tests/test_service/test_cov_test.go b/plc4go/internal/bacnetip/SubscriptionHandle_test.go
similarity index 53%
rename from plc4go/internal/bacnetip/bacgopes/tests/test_service/test_cov_test.go
rename to plc4go/internal/bacnetip/SubscriptionHandle_test.go
index 11d109e574..c70aea6f56 100644
--- a/plc4go/internal/bacnetip/bacgopes/tests/test_service/test_cov_test.go
+++ b/plc4go/internal/bacnetip/SubscriptionHandle_test.go
@@ -17,39 +17,28 @@
  * under the License.
  */
 
-package test_service
+package bacnetip
 
 import (
 	"testing"
+	"time"
 
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/service"
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/tests/time_machine"
-	"github.com/apache/plc4x/plc4go/spi/testutils"
+	apiModel "github.com/apache/plc4x/plc4go/pkg/api/model"
 )
 
-func TestBasic(t *testing.T) {
-	t.Skip("needs capability to work") // TODO: fixme
-	testingLogger := testutils.ProduceTestingLogger(t)
-	ExclusiveGlobalTimeMachine(t)
-
-	// create a network
-	anet, err := NewApplicationNetwork(testingLogger)
-	require.NoError(t, err)
-	t.Cleanup(func() {
-		require.NoError(t, anet.Close())
-	})
-
-	// add the service capability
-	anet.iut.AddCapability(new(ChangeOfValuesServices))
-
-	// all start states are successful
-	anet.td.GetStartState().Success("")
-	anet.iut.GetStartState().Success("")
-
-	// run the group
-	err = anet.Run(0)
-	assert.NoError(t, err)
+func TestNewSubscriptionHandle_PopulatesIdentity(t *testing.T) {
+	s := newTestSubscriber(t)
+	tag := &plcTag{}
+	h := NewSubscriptionHandle(s, "myTag", tag, apiModel.SubscriptionChangeOfState, 250*time.Millisecond)
+	require.NotNil(t, h)
+	assert.Equal(t, "myTag", h.tagName)
+	assert.Equal(t, tag, h.tag)
+	assert.Equal(t, apiModel.SubscriptionChangeOfState, h.subscriptionType)
+	assert.Equal(t, 250*time.Millisecond, h.interval)
+	// DefaultPlcSubscriptionHandle must be wired so callers can treat the
+	// handle as a generic api/model.PlcSubscriptionHandle.
+	assert.NotNil(t, h.DefaultPlcSubscriptionHandle)
 }
diff --git a/plc4go/internal/bacnetip/TagHandler_test.go b/plc4go/internal/bacnetip/TagHandler_test.go
new file mode 100644
index 0000000000..d3072ef548
--- /dev/null
+++ b/plc4go/internal/bacnetip/TagHandler_test.go
@@ -0,0 +1,127 @@
+/*
+ * 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 bacnetip
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+
+	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
+)
+
+func TestTagHandler_ParseSimpleAddress(t *testing.T) {
+	h := NewTagHandler()
+	tag, err := h.ParseTag("ANALOG_INPUT,1/PRESENT_VALUE")
+	require.NoError(t, err)
+	bt, ok := tag.(BacNetPlcTag)
+	require.True(t, ok)
+	require.NotNil(t, bt.GetObjectId().ObjectIdType)
+	assert.Equal(t, readWriteModel.BACnetObjectType_ANALOG_INPUT, *bt.GetObjectId().ObjectIdType)
+	assert.Equal(t, uint32(1), bt.GetObjectId().ObjectIdInstance)
+	require.Len(t, bt.GetProperties(), 1)
+	require.NotNil(t, bt.GetProperties()[0].PropertyIdentifier)
+	assert.Equal(t, readWriteModel.BACnetPropertyIdentifier_PRESENT_VALUE, *bt.GetProperties()[0].PropertyIdentifier)
+}
+
+func TestTagHandler_ParseNumericObjectAndProperty(t *testing.T) {
+	// Numeric object type maps to ObjectIdTypeProprietary; numeric property
+	// maps to PropertyIdentifierProprietary.
+	h := NewTagHandler()
+	tag, err := h.ParseTag("12345,7/4242")
+	require.NoError(t, err)
+	bt := tag.(BacNetPlcTag)
+	require.Nil(t, bt.GetObjectId().ObjectIdType)
+	require.NotNil(t, bt.GetObjectId().ObjectIdTypeProprietary)
+	assert.Equal(t, uint16(12345), *bt.GetObjectId().ObjectIdTypeProprietary)
+	assert.Equal(t, uint32(7), bt.GetObjectId().ObjectIdInstance)
+	require.Len(t, bt.GetProperties(), 1)
+	require.Nil(t, bt.GetProperties()[0].PropertyIdentifier)
+	require.NotNil(t, bt.GetProperties()[0].PropertyIdentifierProprietary)
+	assert.Equal(t, uint32(4242), *bt.GetProperties()[0].PropertyIdentifierProprietary)
+}
+
+func TestTagHandler_ParseWithArrayIndex(t *testing.T) {
+	h := NewTagHandler()
+	tag, err := h.ParseTag("ANALOG_VALUE,2/PRESENT_VALUE[3]")
+	require.NoError(t, err)
+	props := tag.(BacNetPlcTag).GetProperties()
+	require.Len(t, props, 1)
+	require.NotNil(t, props[0].ArrayIndex)
+	assert.Equal(t, uint(3), *props[0].ArrayIndex)
+}
+
+func TestTagHandler_ParseMultipleProperties(t *testing.T) {
+	h := NewTagHandler()
+	tag, err := h.ParseTag("ANALOG_INPUT,1/PRESENT_VALUE&OBJECT_NAME&UNITS")
+	require.NoError(t, err)
+	props := tag.(BacNetPlcTag).GetProperties()
+	require.Len(t, props, 3)
+	assert.Equal(t, readWriteModel.BACnetPropertyIdentifier_PRESENT_VALUE, *props[0].PropertyIdentifier)
+	assert.Equal(t, readWriteModel.BACnetPropertyIdentifier_OBJECT_NAME, *props[1].PropertyIdentifier)
+	assert.Equal(t, readWriteModel.BACnetPropertyIdentifier_UNITS, *props[2].PropertyIdentifier)
+}
+
+func TestTagHandler_ParseMultiplePropertiesWithArrayIndex(t *testing.T) {
+	h := NewTagHandler()
+	tag, err := h.ParseTag("ANALOG_VALUE,5/PRESENT_VALUE[1]&PRIORITY_ARRAY[16]")
+	require.NoError(t, err)
+	props := tag.(BacNetPlcTag).GetProperties()
+	require.Len(t, props, 2)
+	require.NotNil(t, props[0].ArrayIndex)
+	assert.Equal(t, uint(1), *props[0].ArrayIndex)
+	require.NotNil(t, props[1].ArrayIndex)
+	assert.Equal(t, uint(16), *props[1].ArrayIndex)
+}
+
+func TestTagHandler_ParseInvalidString(t *testing.T) {
+	h := NewTagHandler()
+	cases := []string{
+		"",
+		"garbage",
+		"ANALOG_INPUT,1",       // missing property
+		"ANALOG_INPUT/X",       // missing instance
+		"ANALOG_INPUT,abc/X",   // non-numeric instance
+		",1/X",                 // missing object type
+	}
+	for _, c := range cases {
+		_, err := h.ParseTag(c)
+		assert.Error(t, err, "input %q should fail", c)
+	}
+}
+
+func TestTagHandler_ParseUnknownObjectType(t *testing.T) {
+	h := NewTagHandler()
+	_, err := h.ParseTag("NOT_AN_OBJECT,1/PRESENT_VALUE")
+	assert.Error(t, err)
+}
+
+func TestTagHandler_ParseUnknownPropertyType(t *testing.T) {
+	h := NewTagHandler()
+	_, err := h.ParseTag("ANALOG_INPUT,1/NOT_A_PROPERTY")
+	assert.Error(t, err)
+}
+
+func TestTagHandler_ParseQueryNotSupported(t *testing.T) {
+	h := NewTagHandler()
+	_, err := h.ParseQuery("anything")
+	assert.Error(t, err)
+}
diff --git a/plc4go/internal/bacnetip/ValueDecoder.go b/plc4go/internal/bacnetip/ValueDecoder.go
new file mode 100644
index 0000000000..7cf708aecd
--- /dev/null
+++ b/plc4go/internal/bacnetip/ValueDecoder.go
@@ -0,0 +1,185 @@
+/*
+ * 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 bacnetip
+
+import (
+	"fmt"
+	"reflect"
+	"time"
+
+	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
+	"github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
+	spiValues "github.com/apache/plc4x/plc4go/spi/values"
+)
+
+// appTagToPlcValue maps a BACnet ApplicationTag (the wire-level primitive
+// representation) onto a plc4go PlcValue. A nil tag yields PlcNULL.
+//
+// The mapping mirrors how plc4j's BACnet driver renders these tags:
+//   - Boolean        → PlcBOOL
+//   - UnsignedInteger→ PlcULINT
+//   - SignedInteger  → PlcLINT
+//   - Real           → PlcREAL
+//   - Double         → PlcLREAL
+//   - CharacterString→ PlcSTRING
+//   - OctetString    → PlcRawByteArray
+//   - Enumerated     → PlcUDINT (the raw numeric; the property identifier on
+//                      the request side determines the enum schema)
+//   - BitString      → PlcRawByteArray (packed MSB-first)
+//   - Date           → PlcDATE       (year-1900 + month + day-of-month)
+//   - Time           → PlcTIME_OF_DAY
+//   - ObjectId       → PlcSTRING formatted as "<type>,<instance>"
+//   - Null           → PlcNULL
+func appTagToPlcValue(tag model.BACnetApplicationTag) apiValues.PlcValue {
+	if tag == nil {
+		return spiValues.NewPlcNULL()
+	}
+	switch t := tag.(type) {
+	case model.BACnetApplicationTagNull:
+		return spiValues.NewPlcNULL()
+	case model.BACnetApplicationTagBoolean:
+		return spiValues.NewPlcBOOL(t.GetActualValue())
+	case model.BACnetApplicationTagUnsignedInteger:
+		return spiValues.NewPlcULINT(t.GetActualValue())
+	case model.BACnetApplicationTagSignedInteger:
+		return spiValues.NewPlcLINT(int64(t.GetPayload().GetActualValue()))
+	case model.BACnetApplicationTagReal:
+		return spiValues.NewPlcREAL(t.GetActualValue())
+	case model.BACnetApplicationTagDouble:
+		return spiValues.NewPlcLREAL(t.GetActualValue())
+	case model.BACnetApplicationTagCharacterString:
+		return spiValues.NewPlcSTRING(t.GetValue())
+	case model.BACnetApplicationTagOctetString:
+		return spiValues.NewPlcRawByteArray(t.GetPayload().GetOctets())
+	case model.BACnetApplicationTagEnumerated:
+		return spiValues.NewPlcUDINT(t.GetActualValue())
+	case model.BACnetApplicationTagBitString:
+		return spiValues.NewPlcRawByteArray(bitsToBytes(t.GetPayload().GetData()))
+	case model.BACnetApplicationTagDate:
+		payload := t.GetPayload()
+		// Year is reported as years-since-1900 OR raw uint16 for newer devices.
+		year := payload.GetYear()
+		// Build a date; if wildcard, fall back to the zero day so callers can
+		// still match on PlcDATE equality.
+		date := time.Date(int(year), time.Month(payload.GetMonth()), int(payload.GetDayOfMonth()), 0, 0, 0, 0, time.UTC)
+		return spiValues.NewPlcDATE(date)
+	case model.BACnetApplicationTagTime:
+		payload := t.GetPayload()
+		dur := time.Duration(payload.GetHour())*time.Hour +
+			time.Duration(payload.GetMinute())*time.Minute +
+			time.Duration(payload.GetSecond())*time.Second +
+			time.Duration(payload.GetFractional())*10*time.Millisecond
+		return spiValues.NewPlcTIME_OF_DAY(dur)
+	case model.BACnetApplicationTagObjectIdentifier:
+		return spiValues.NewPlcSTRING(fmt.Sprintf("%s,%d", t.GetObjectType(), t.GetInstanceNumber()))
+	default:
+		// Fallback: surface the type name + stringified value so the caller has
+		// something to log. New ApplicationTag variants added to the spec should
+		// produce a build-time miss and be added to the switch above.
+		return spiValues.NewPlcSTRING(fmt.Sprintf("%T:%v", tag, tag))
+	}
+}
+
+// constructedDataToPlcValue extracts a PlcValue from a BACnetConstructedData.
+//
+// BACnet has ~650 ConstructedData subtypes generated from the spec, each with a
+// property-specific accessor. We use two strategies:
+//
+//  1. If the data is BACnetConstructedDataUnspecified (the parser's fallback for
+//     unmapped (object, property) pairs), walk GetData() — each element wraps an
+//     ApplicationTag we can decode via appTagToPlcValue. A single element yields
+//     a scalar; multiple elements yield a PlcList.
+//
+//  2. Otherwise, look for a GetActualValue() method on the typed subtype via
+//     reflection. The vast majority of typed ConstructedData expose this and the
+//     return value is either a BACnetApplicationTag* (directly decodable) or a
+//     more complex composite (DateTime, ObjectReference, ...) for which we
+//     surface a string representation until per-type mappings are added.
+func constructedDataToPlcValue(data model.BACnetConstructedData) apiValues.PlcValue {
+	if data == nil {
+		return spiValues.NewPlcNULL()
+	}
+	if u, ok := data.(model.BACnetConstructedDataUnspecified); ok {
+		return elementsToPlcValue(u.GetData())
+	}
+	if v, ok := callGetActualValue(data); ok {
+		if tag, ok := v.(model.BACnetApplicationTag); ok {
+			return appTagToPlcValue(tag)
+		}
+		// Composite types: stringify until we add typed mappings (DateTime,
+		// ObjectReference, BACnetTimeStamp, ...).
+		return spiValues.NewPlcSTRING(fmt.Sprintf("%v", v))
+	}
+	return spiValues.NewPlcSTRING(fmt.Sprintf("%T:%v", data, data))
+}
+
+// elementsToPlcValue collapses a list of BACnetConstructedDataElement to a
+// PlcValue. A single-element list yields a scalar; multi-element yields PlcList.
+func elementsToPlcValue(elements []model.BACnetConstructedDataElement) apiValues.PlcValue {
+	switch len(elements) {
+	case 0:
+		return spiValues.NewPlcNULL()
+	case 1:
+		return appTagToPlcValue(elements[0].GetApplicationTag())
+	}
+	items := make([]apiValues.PlcValue, len(elements))
+	for i, el := range elements {
+		items[i] = appTagToPlcValue(el.GetApplicationTag())
+	}
+	return spiValues.NewPlcList(items)
+}
+
+// callGetActualValue invokes a GetActualValue() method on data via reflection
+// if one is defined, returning the single result. Used to walk the typed
+// ConstructedData subtypes without writing a 650-arm type switch.
+func callGetActualValue(data model.BACnetConstructedData) (any, bool) {
+	rv := reflect.ValueOf(data)
+	if !rv.IsValid() {
+		return nil, false
+	}
+	method := rv.MethodByName("GetActualValue")
+	if !method.IsValid() {
+		return nil, false
+	}
+	if method.Type().NumIn() != 0 || method.Type().NumOut() != 1 {
+		return nil, false
+	}
+	out := method.Call(nil)
+	if len(out) != 1 {
+		return nil, false
+	}
+	return out[0].Interface(), true
+}
+
+// bitsToBytes packs a []bool BACnet bit-string into bytes MSB-first. Bit 0 of
+// the input goes to bit 7 of byte 0 (i.e. the wire order BACnet uses on the
+// payload side).
+func bitsToBytes(bits []bool) []byte {
+	if len(bits) == 0 {
+		return []byte{}
+	}
+	out := make([]byte, (len(bits)+7)/8)
+	for i, b := range bits {
+		if b {
+			out[i/8] |= 1 << (7 - uint(i%8))
+		}
+	}
+	return out
+}
diff --git a/plc4go/internal/bacnetip/ValueEncoder.go b/plc4go/internal/bacnetip/ValueEncoder.go
new file mode 100644
index 0000000000..38dd57ba1b
--- /dev/null
+++ b/plc4go/internal/bacnetip/ValueEncoder.go
@@ -0,0 +1,84 @@
+/*
+ * 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 bacnetip
+
+import (
+	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
+	"github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
+	"github.com/apache/plc4x/plc4go/spi/errors"
+)
+
+// plcValueToApplicationTag maps a PlcValue to a BACnet ApplicationTag, the
+// inverse of appTagToPlcValue. The caller may pass a hint via the property
+// identifier so we can prefer enumerated/character-string encoding when the
+// PlcValue type alone is ambiguous (e.g. uint32 → Enumerated vs UnsignedInteger
+// for properties like StatusFlags / Units).
+//
+// Returns an error if the PlcValue type isn't representable in BACnet.
+func plcValueToApplicationTag(v apiValues.PlcValue, hint encodingHint) (model.BACnetApplicationTag, error) {
+	if v == nil {
+		return model.CreateBACnetApplicationTagNull(), nil
+	}
+	switch v.GetPlcValueType() {
+	case apiValues.NULL:
+		return model.CreateBACnetApplicationTagNull(), nil
+	case apiValues.BOOL:
+		return model.CreateBACnetApplicationTagBoolean(v.GetBool()), nil
+	case apiValues.BYTE, apiValues.USINT, apiValues.UINT, apiValues.UDINT, apiValues.ULINT, apiValues.WORD, apiValues.DWORD, apiValues.LWORD:
+		if hint == hintEnumerated {
+			return model.CreateBACnetApplicationTagEnumerated(uint32(v.GetUint64())), nil
+		}
+		return model.CreateBACnetApplicationTagUnsignedInteger(uint(v.GetUint64())), nil
+	case apiValues.SINT, apiValues.INT, apiValues.DINT, apiValues.LINT:
+		return model.CreateBACnetApplicationTagSignedInteger(int(v.GetInt64())), nil
+	case apiValues.REAL:
+		return model.CreateBACnetApplicationTagReal(v.GetFloat32()), nil
+	case apiValues.LREAL:
+		return model.CreateBACnetApplicationTagDouble(v.GetFloat64()), nil
+	case apiValues.STRING, apiValues.CHAR, apiValues.WSTRING, apiValues.WCHAR:
+		return model.CreateBACnetApplicationTagCharacterString(model.BACnetCharacterEncoding_ISO_10646, v.GetString()), nil
+	case apiValues.RAW_BYTE_ARRAY:
+		return model.CreateBACnetApplicationTagOctetString(v.GetRaw()), nil
+	default:
+		return nil, errors.Errorf("PlcValue type %v cannot be encoded as a BACnet ApplicationTag", v.GetPlcValueType())
+	}
+}
+
+// encodingHint nudges plcValueToApplicationTag when the source PlcValue type is
+// ambiguous. Today the only hint is enumerated; future additions could include
+// bit-string-from-uint or date-from-string.
+type encodingHint uint8
+
+const (
+	hintNone encodingHint = iota
+	hintEnumerated
+)
+
+// hintForProperty returns the encoding hint appropriate to a BACnet property
+// identifier. PRESENT_VALUE on Binary*/Multistate* objects (and many discrete
+// status fields) carries Enumerated; everything else defaults to none.
+func hintForProperty(_ uint32) encodingHint {
+	// Today we don't second-guess the caller. WriteProperty callers should
+	// either pass a PlcUDINT and accept the default UnsignedInteger encoding,
+	// or use a PlcREAL/PlcBOOL/PlcSTRING that maps unambiguously. Per-property
+	// dispatch will be added once the integration tests expose a real device
+	// that rejects an UnsignedInteger where Enumerated is required.
+	return hintNone
+}
diff --git a/plc4go/internal/bacnetip/Writer.go b/plc4go/internal/bacnetip/Writer.go
new file mode 100644
index 0000000000..95efb0d491
--- /dev/null
+++ b/plc4go/internal/bacnetip/Writer.go
@@ -0,0 +1,277 @@
+/*
+ * 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 bacnetip
+
+import (
+	"context"
+	"runtime/debug"
+	"sync"
+
+	"github.com/rs/zerolog"
+
+	apiModel "github.com/apache/plc4x/plc4go/pkg/api/model"
+	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
+	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
+	"github.com/apache/plc4x/plc4go/spi"
+	"github.com/apache/plc4x/plc4go/spi/errors"
+	spiModel "github.com/apache/plc4x/plc4go/spi/model"
+	"github.com/apache/plc4x/plc4go/spi/options"
+	"github.com/apache/plc4x/plc4go/spi/transactions"
+)
+
+// Writer issues BACnet WriteProperty / WritePropertyMultiple confirmed-service
+// requests and waits for SimpleAck / Error / Reject / Abort responses.
+type Writer struct {
+	invokeIdGenerator *InvokeIdGenerator
+	messageCodec      spi.MessageCodec
+	tm                transactions.RequestTransactionManager
+	driverContext     DriverContext
+
+	wg sync.WaitGroup
+
+	log zerolog.Logger
+}
+
+func NewWriter(
+	invokeIdGenerator *InvokeIdGenerator,
+	messageCodec spi.MessageCodec,
+	tm transactions.RequestTransactionManager,
+	driverContext DriverContext,
+	_options ...options.WithOption,
+) *Writer {
+	customLogger := options.ExtractCustomLoggerOrDefaultToGlobal(_options...)
+	return &Writer{
+		invokeIdGenerator: invokeIdGenerator,
+		messageCodec:      messageCodec,
+		tm:                tm,
+		driverContext:     driverContext,
+		log:               customLogger,
+	}
+}
+
+func (m *Writer) Write(ctx context.Context, writeRequest apiModel.PlcWriteRequest) <-chan apiModel.PlcWriteRequestResult {
+	m.log.Trace().Msg("Writing")
+	result := make(chan apiModel.PlcWriteRequestResult, 1)
+	m.wg.Go(func() {
+		defer func() {
+			if r := recover(); r != nil {
+				result <- spiModel.NewDefaultPlcWriteRequestResult(writeRequest, nil, errors.Errorf("panic-ed %v. Stack: %s", r, debug.Stack()))
+			}
+		}()
+		tagNames := writeRequest.GetTagNames()
+		if len(tagNames) == 0 {
+			result <- spiModel.NewDefaultPlcWriteRequestResult(writeRequest, nil, errors.New("at least one tag required"))
+			return
+		}
+
+		serviceRequest, err := m.buildServiceRequest(writeRequest)
+		if err != nil {
+			result <- spiModel.NewDefaultPlcWriteRequestResult(writeRequest, nil, errors.Wrap(err, "Error building WriteProperty request"))
+			return
+		}
+
+		invokeId := m.invokeIdGenerator.getAndIncrement()
+		apdu := readWriteModel.NewAPDUConfirmedRequest(
+			false,
+			false,
+			true,
+			m.driverContext.maxSegmentsAccepted,
+			m.driverContext.maxApduLengthAccepted,
+			invokeId,
+			nil,
+			nil,
+			serviceRequest,
+			nil,
+			nil,
+		)
+
+		transaction := m.tm.StartTransaction("write")
+		transaction.Submit("writeOperation", func(transactionContext context.Context, transaction transactions.RequestTransaction) {
+			ctx, cancel := context.WithCancel(ctx)
+			context.AfterFunc(transactionContext, cancel)
+
+			err := m.messageCodec.SendRequest(ctx, "write", apdu, func(message spi.Message) bool {
+				return m.acceptsResponse(message, invokeId)
+			}, func(message spi.Message) error {
+				bvlc := message.(readWriteModel.BVLC)
+				responseApdu := bvlc.(interface{ GetNpdu() readWriteModel.NPDU }).GetNpdu().GetApdu()
+				writeResponse := m.toPlcWriteResponse(responseApdu, writeRequest)
+				result <- spiModel.NewDefaultPlcWriteRequestResult(writeRequest, writeResponse, nil)
+				return transaction.EndRequest()
+			}, func(err error) error {
+				result <- spiModel.NewDefaultPlcWriteRequestResult(writeRequest, nil, errors.Wrap(err, "got timeout while waiting for write response"))
+				return transaction.EndRequest()
+			})
+			if err != nil {
+				result <- spiModel.NewDefaultPlcWriteRequestResult(writeRequest, nil, errors.Wrap(err, "error sending message"))
+				if failErr := transaction.FailRequest(err); failErr != nil {
+					m.log.Debug().Err(failErr).Msg("Error failing request")
+				}
+			}
+		})
+	})
+	return result
+}
+
+// buildServiceRequest assembles a single WriteProperty (one tag, no multi-prop)
+// or a WritePropertyMultiple (>1 tag or any tag with >1 property) request from
+// the PlcWriteRequest.
+func (m *Writer) buildServiceRequest(writeRequest apiModel.PlcWriteRequest) (readWriteModel.BACnetConfirmedServiceRequest, error) {
+	tagNames := writeRequest.GetTagNames()
+
+	if len(tagNames) == 1 {
+		tag, ok := writeRequest.GetTag(tagNames[0]).(BacNetPlcTag)
+		if !ok {
+			return nil, errors.Errorf("tag %s is not a BACnet tag", tagNames[0])
+		}
+		if len(tag.GetProperties()) == 1 {
+			return m.buildSingleWriteProperty(tag, writeRequest.GetValue(tagNames[0]))
+		}
+	}
+
+	// Multi: collapse all (tag, properties...) into a WritePropertyMultiple
+	// with one BACnetWriteAccessSpecification per tag and one
+	// BACnetPropertyWriteDefinition per (tag, property) pair. WritePriority is
+	// taken from the same nil/!nil dance as WriteProperty.
+	var specs []readWriteModel.BACnetWriteAccessSpecification
+	for _, tagName := range tagNames {
+		tag, ok := writeRequest.GetTag(tagName).(BacNetPlcTag)
+		if !ok {
+			return nil, errors.Errorf("tag %s is not a BACnet tag", tagName)
+		}
+		objectIdTag := readWriteModel.CreateBACnetContextTagObjectIdentifier(0, tag.GetObjectId().getId(), tag.GetObjectId().ObjectIdInstance)
+		var defs []readWriteModel.BACnetPropertyWriteDefinition
+		for _, prop := range tag.GetProperties() {
+			plcValue := writeRequest.GetValue(tagName)
+			appTag, err := plcValueToApplicationTag(plcValue.(apiValues.PlcValue), hintForProperty(prop.getId()))
+			if err != nil {
+				return nil, errors.Wrapf(err, "tag %s property %s", tagName, prop.String())
+			}
+			cd := constructedDataFromAppTag(appTag)
+			propId := readWriteModel.CreateBACnetPropertyIdentifierTagged(2, prop.getId())
+			var arrayIndex readWriteModel.BACnetContextTagUnsignedInteger
+			if prop.ArrayIndex != nil {
+				arrayIndex = readWriteModel.CreateBACnetContextTagUnsignedInteger(3, *prop.ArrayIndex)
+			}
+			defs = append(defs, readWriteModel.NewBACnetPropertyWriteDefinition(propId, arrayIndex, cd, nil))
+		}
+		specs = append(specs, readWriteModel.NewBACnetWriteAccessSpecification(
+			objectIdTag,
+			readWriteModel.CreateBACnetOpeningTag(1),
+			defs,
+			readWriteModel.CreateBACnetClosingTag(1),
+		))
+	}
+	return readWriteModel.NewBACnetConfirmedServiceRequestWritePropertyMultiple(0, specs), nil
+}
+
+func (m *Writer) buildSingleWriteProperty(tag BacNetPlcTag, plcValue apiValues.PlcValue) (readWriteModel.BACnetConfirmedServiceRequest, error) {
+	if plcValue == nil {
+		return nil, errors.New("nil PlcValue")
+	}
+	prop := tag.GetProperties()[0]
+	appTag, err := plcValueToApplicationTag(plcValue, hintForProperty(prop.getId()))
+	if err != nil {
+		return nil, err
+	}
+	objectIdTag := readWriteModel.CreateBACnetContextTagObjectIdentifier(0, tag.GetObjectId().getId(), tag.GetObjectId().ObjectIdInstance)
+	propId := readWriteModel.CreateBACnetPropertyIdentifierTagged(1, prop.getId())
+	var arrayIndex readWriteModel.BACnetContextTagUnsignedInteger
+	if prop.ArrayIndex != nil {
+		arrayIndex = readWriteModel.CreateBACnetContextTagUnsignedInteger(2, *prop.ArrayIndex)
+	}
+	cd := constructedDataFromAppTag(appTag)
+	return readWriteModel.NewBACnetConfirmedServiceRequestWriteProperty(0, objectIdTag, propId, arrayIndex, cd, nil), nil
+}
+
+// constructedDataFromAppTag wraps a single ApplicationTag into a generic
+// ConstructedDataUnspecified payload (opening tag 3, one element, closing 3) so
+// the wire-format builder can serialize it without per-property typed types.
+func constructedDataFromAppTag(tag readWriteModel.BACnetApplicationTag) readWriteModel.BACnetConstructedData {
+	header := readWriteModel.CreateBACnetTagHeaderBalanced(true, 3, 0)
+	element := readWriteModel.NewBACnetConstructedDataElement(header, tag, nil, nil)
+	return readWriteModel.NewBACnetConstructedDataUnspecified(
+		readWriteModel.CreateBACnetOpeningTag(3),
+		header,
+		readWriteModel.CreateBACnetClosingTag(3),
+		nil,
+		[]readWriteModel.BACnetConstructedDataElement{element},
+	)
+}
+
+// acceptsResponse matches the incoming message against our outstanding invoke id.
+func (m *Writer) acceptsResponse(message spi.Message, invokeId uint8) bool {
+	bvlc, ok := message.(readWriteModel.BVLC)
+	if !ok {
+		return false
+	}
+	npduRetriever, ok := bvlc.(interface{ GetNpdu() readWriteModel.NPDU })
+	if !ok {
+		return false
+	}
+	npdu := npduRetriever.GetNpdu()
+	if npdu.GetControl().GetMessageTypeFieldPresent() {
+		return false
+	}
+	got, err := getInvokeIdFromApdu(npdu.GetApdu())
+	if err != nil {
+		return false
+	}
+	return got == invokeId
+}
+
+// toPlcWriteResponse decodes a WriteProperty response APDU into the per-tag
+// response codes. Single-tag writes get the same code for the lone tag; multi
+// writes fan out errors to the tag whose write failed when the device tells us.
+func (m *Writer) toPlcWriteResponse(apdu readWriteModel.APDU, request apiModel.PlcWriteRequest) apiModel.PlcWriteResponse {
+	codes := map[string]apiModel.PlcResponseCode{}
+	switch apdu := apdu.(type) {
+	case readWriteModel.APDUSimpleAck:
+		for _, name := range request.GetTagNames() {
+			codes[name] = apiModel.PlcResponseCode_OK
+		}
+	case readWriteModel.APDUError:
+		code := mapErrorAPDU(apdu, m.log)
+		for _, name := range request.GetTagNames() {
+			codes[name] = code
+		}
+	case readWriteModel.APDUReject:
+		m.log.Warn().Stringer("rejectReason", reasonOfReject(apdu)).Msg("BACnet REJECT on write")
+		for _, name := range request.GetTagNames() {
+			codes[name] = apiModel.PlcResponseCode_INVALID_DATA
+		}
+	case readWriteModel.APDUAbort:
+		reason := apdu.GetAbortReason().GetValue()
+		code := apiModel.PlcResponseCode_INTERNAL_ERROR
+		if reason == readWriteModel.BACnetAbortReason_SEGMENTATION_NOT_SUPPORTED {
+			code = apiModel.PlcResponseCode_UNSUPPORTED
+		}
+		m.log.Warn().Stringer("abortReason", &reason).Msg("BACnet ABORT on write")
+		for _, name := range request.GetTagNames() {
+			codes[name] = code
+		}
+	default:
+		m.log.Warn().Type("apdu", apdu).Msg("unsupported APDU type on write response")
+		for _, name := range request.GetTagNames() {
+			codes[name] = apiModel.PlcResponseCode_REMOTE_ERROR
+		}
+	}
+	return spiModel.NewDefaultPlcWriteResponse(request, codes)
+}
diff --git a/plc4go/internal/bacnetip/Writer_test.go b/plc4go/internal/bacnetip/Writer_test.go
new file mode 100644
index 0000000000..9f1bc2342f
--- /dev/null
+++ b/plc4go/internal/bacnetip/Writer_test.go
@@ -0,0 +1,229 @@
+/*
+ * 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 bacnetip
+
+import (
+	"testing"
+
+	"github.com/rs/zerolog"
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+
+	apiModel "github.com/apache/plc4x/plc4go/pkg/api/model"
+	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
+	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
+	spiModel "github.com/apache/plc4x/plc4go/spi/model"
+	spiValues "github.com/apache/plc4x/plc4go/spi/values"
+)
+
+// newTestWriter returns a Writer with no I/O wiring — pure-function tests only.
+func newTestWriter(t *testing.T) *Writer {
+	t.Helper()
+	return &Writer{
+		invokeIdGenerator: &InvokeIdGenerator{},
+		driverContext:     NewDriverContext(createDefaultConfiguration()),
+		log:               zerolog.Nop(),
+	}
+}
+
+// writeRequestFor builds a minimal PlcWriteRequest with the given (tag, value)
+// pairs. Tags are constructed inline as concrete plcTag structs so they
+// satisfy BacNetPlcTag without going through the TagHandler regex parser.
+func writeRequestFor(t *testing.T, tagSpecs []writeTagSpec) apiModel.PlcWriteRequest {
+	t.Helper()
+	tagNames := make([]string, 0, len(tagSpecs))
+	tags := map[string]apiModel.PlcTag{}
+	values := map[string]apiValues.PlcValue{}
+	for _, s := range tagSpecs {
+		tagNames = append(tagNames, s.name)
+		tags[s.name] = s.tag
+		values[s.name] = s.value
+	}
+	return spiModel.NewDefaultPlcWriteRequest(tags, tagNames, values, nil, nil)
+}
+
+type writeTagSpec struct {
+	name  string
+	tag   BacNetPlcTag
+	value apiValues.PlcValue
+}
+
+func makeTag(objType readWriteModel.BACnetObjectType, instance uint32, propId readWriteModel.BACnetPropertyIdentifier) BacNetPlcTag {
+	objId := objectId{ObjectIdType: &objType, ObjectIdInstance: instance}
+	return &plcTag{
+		ObjectId:   objId,
+		Properties: []property{{PropertyIdentifier: &propId}},
+	}
+}
+
+// ── plcValueToApplicationTag ───────────────────────────────────────────────
+
+func TestPlcValueToApplicationTag_Mapping(t *testing.T) {
+	cases := []struct {
+		name string
+		in   apiValues.PlcValue
+		want any
+	}{
+		{"bool", spiValues.NewPlcBOOL(true), readWriteModel.CreateBACnetApplicationTagBoolean(true)},
+		{"real", spiValues.NewPlcREAL(22.5), readWriteModel.CreateBACnetApplicationTagReal(22.5)},
+		{"double", spiValues.NewPlcLREAL(1.25), readWriteModel.CreateBACnetApplicationTagDouble(1.25)},
+		{"unsigned", spiValues.NewPlcULINT(7), readWriteModel.CreateBACnetApplicationTagUnsignedInteger(7)},
+		{"signed", spiValues.NewPlcLINT(-3), readWriteModel.CreateBACnetApplicationTagSignedInteger(-3)},
+		{"string", spiValues.NewPlcSTRING("hi"), readWriteModel.CreateBACnetApplicationTagCharacterString(readWriteModel.BACnetCharacterEncoding_ISO_10646, "hi")},
+		{"raw bytes", spiValues.NewPlcRawByteArray([]byte{0xCA, 0xFE}), readWriteModel.CreateBACnetApplicationTagOctetString([]byte{0xCA, 0xFE})},
+	}
+	for _, c := range cases {
+		t.Run(c.name, func(t *testing.T) {
+			got, err := plcValueToApplicationTag(c.in, hintNone)
+			require.NoError(t, err)
+			// Round-trip: encode then decode and assert equality on the resulting PlcValue.
+			roundTripped := appTagToPlcValue(got)
+			expectedRoundTrip := appTagToPlcValue(c.want.(readWriteModel.BACnetApplicationTag))
+			assert.Equal(t, expectedRoundTrip.GetPlcValueType(), roundTripped.GetPlcValueType())
+		})
+	}
+}
+
+func TestPlcValueToApplicationTag_NilGivesNullTag(t *testing.T) {
+	got, err := plcValueToApplicationTag(nil, hintNone)
+	require.NoError(t, err)
+	_, ok := got.(readWriteModel.BACnetApplicationTagNull)
+	assert.True(t, ok, "nil PlcValue must produce a Null ApplicationTag")
+}
+
+func TestPlcValueToApplicationTag_EnumeratedHint(t *testing.T) {
+	got, err := plcValueToApplicationTag(spiValues.NewPlcUDINT(2), hintEnumerated)
+	require.NoError(t, err)
+	_, ok := got.(readWriteModel.BACnetApplicationTagEnumerated)
+	assert.True(t, ok, "expected Enumerated when hintEnumerated is set")
+}
+
+// ── buildServiceRequest dispatch ───────────────────────────────────────────
+
+func TestBuildServiceRequest_SingleTagSingleProp_BuildsWriteProperty(t *testing.T) {
+	writer := newTestWriter(t)
+	req := writeRequestFor(t, []writeTagSpec{
+		{
+			name:  "av",
+			tag:   makeTag(readWriteModel.BACnetObjectType_ANALOG_VALUE, 5, readWriteModel.BACnetPropertyIdentifier_PRESENT_VALUE),
+			value: spiValues.NewPlcREAL(22.5),
+		},
+	})
+	got, err := writer.buildServiceRequest(req)
+	require.NoError(t, err)
+	wp, ok := got.(readWriteModel.BACnetConfirmedServiceRequestWriteProperty)
+	require.True(t, ok, "expected WriteProperty, got %T", got)
+	assert.Equal(t, uint32(5), wp.GetObjectIdentifier().GetPayload().GetInstanceNumber())
+	assert.Equal(t, readWriteModel.BACnetPropertyIdentifier_PRESENT_VALUE, wp.GetPropertyIdentifier().GetValue())
+}
+
+func TestBuildServiceRequest_MultipleTags_BuildsWritePropertyMultiple(t *testing.T) {
+	writer := newTestWriter(t)
+	req := writeRequestFor(t, []writeTagSpec{
+		{
+			name:  "av",
+			tag:   makeTag(readWriteModel.BACnetObjectType_ANALOG_VALUE, 5, readWriteModel.BACnetPropertyIdentifier_PRESENT_VALUE),
+			value: spiValues.NewPlcREAL(22.5),
+		},
+		{
+			name:  "bv",
+			tag:   makeTag(readWriteModel.BACnetObjectType_BINARY_VALUE, 3, readWriteModel.BACnetPropertyIdentifier_PRESENT_VALUE),
+			value: spiValues.NewPlcBOOL(true),
+		},
+	})
+	got, err := writer.buildServiceRequest(req)
+	require.NoError(t, err)
+	wpm, ok := got.(readWriteModel.BACnetConfirmedServiceRequestWritePropertyMultiple)
+	require.True(t, ok, "expected WritePropertyMultiple, got %T", got)
+	assert.Len(t, wpm.GetData(), 2)
+}
+
+func TestBuildServiceRequest_UnsupportedValueTypeReturnsError(t *testing.T) {
+	writer := newTestWriter(t)
+	req := writeRequestFor(t, []writeTagSpec{
+		{
+			name:  "x",
+			tag:   makeTag(readWriteModel.BACnetObjectType_ANALOG_VALUE, 1, readWriteModel.BACnetPropertyIdentifier_PRESENT_VALUE),
+			value: spiValues.NewPlcList(nil), // PlcList isn't currently encodable
+		},
+	})
+	_, err := writer.buildServiceRequest(req)
+	assert.Error(t, err)
+}
+
+// ── toPlcWriteResponse error mapping ───────────────────────────────────────
+
+func TestToPlcWriteResponse_SimpleAck(t *testing.T) {
+	writer := newTestWriter(t)
+	req := writeRequestFor(t, []writeTagSpec{
+		{
+			name:  "av",
+			tag:   makeTag(readWriteModel.BACnetObjectType_ANALOG_VALUE, 5, readWriteModel.BACnetPropertyIdentifier_PRESENT_VALUE),
+			value: spiValues.NewPlcREAL(22.5),
+		},
+	})
+	ack := readWriteModel.NewAPDUSimpleAck(1, readWriteModel.BACnetConfirmedServiceChoice_WRITE_PROPERTY)
+	resp := writer.toPlcWriteResponse(ack, req)
+	assert.Equal(t, apiModel.PlcResponseCode_OK, resp.GetResponseCode("av"))
+}
+
+func TestToPlcWriteResponse_ErrorWriteAccessDenied(t *testing.T) {
+	writer := newTestWriter(t)
+	req := writeRequestFor(t, []writeTagSpec{
+		{
+			name:  "av",
+			tag:   makeTag(readWriteModel.BACnetObjectType_ANALOG_VALUE, 5, readWriteModel.BACnetPropertyIdentifier_PRESENT_VALUE),
+			value: spiValues.NewPlcREAL(22.5),
+		},
+	})
+	apdu := buildErrorAPDU(readWriteModel.ErrorClass_PROPERTY, readWriteModel.ErrorCode_WRITE_ACCESS_DENIED)
+	resp := writer.toPlcWriteResponse(apdu, req)
+	assert.Equal(t, apiModel.PlcResponseCode_ACCESS_DENIED, resp.GetResponseCode("av"))
+}
+
+func TestToPlcWriteResponse_Abort(t *testing.T) {
+	writer := newTestWriter(t)
+	req := writeRequestFor(t, []writeTagSpec{
+		{
+			name:  "av",
+			tag:   makeTag(readWriteModel.BACnetObjectType_ANALOG_VALUE, 1, readWriteModel.BACnetPropertyIdentifier_PRESENT_VALUE),
+			value: spiValues.NewPlcREAL(1),
+		},
+	})
+	abort := readWriteModel.NewAPDUAbort(false, 1,
+		readWriteModel.NewBACnetAbortReasonTagged(1, readWriteModel.BACnetAbortReason_SEGMENTATION_NOT_SUPPORTED, 0))
+	resp := writer.toPlcWriteResponse(abort, req)
+	assert.Equal(t, apiModel.PlcResponseCode_UNSUPPORTED, resp.GetResponseCode("av"))
+}
+
+func TestToPlcWriteResponse_Reject(t *testing.T) {
+	writer := newTestWriter(t)
+	req := writeRequestFor(t, []writeTagSpec{
+		{
+			name:  "av",
+			tag:   makeTag(readWriteModel.BACnetObjectType_ANALOG_VALUE, 1, readWriteModel.BACnetPropertyIdentifier_PRESENT_VALUE),
+			value: spiValues.NewPlcREAL(1),
+		},
+	})
+	reject := readWriteModel.NewAPDUReject(1,
+		readWriteModel.NewBACnetRejectReasonTagged(1, readWriteModel.BACnetRejectReason_UNRECOGNIZED_SERVICE, 0))
+	resp := writer.toPlcWriteResponse(reject, req)
+	assert.Equal(t, apiModel.PlcResponseCode_INVALID_DATA, resp.GetResponseCode("av"))
+}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu.go
deleted file mode 100644
index 9702ae7984..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu.go
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * 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 apdu
-
-import (
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/debugging"
-	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
-)
-
-var _debug = CreateDebugPrinter()
-
-var APDUTypes map[readWriteModel.ApduType]func() Decoder
-
-func init() {
-	APDUTypes = map[readWriteModel.ApduType]func() Decoder{
-		readWriteModel.ApduType_CONFIRMED_REQUEST_PDU: func() Decoder {
-			pdu, _ := NewConfirmedRequestPDU(Nothing())
-			return pdu
-		},
-		readWriteModel.ApduType_UNCONFIRMED_REQUEST_PDU: func() Decoder {
-			pdu, _ := NewUnconfirmedRequestPDU(Nothing())
-			return pdu
-		},
-		readWriteModel.ApduType_SIMPLE_ACK_PDU: func() Decoder {
-			panic("Implement Me")
-		},
-		readWriteModel.ApduType_COMPLEX_ACK_PDU: func() Decoder {
-			panic("Implement Me")
-		},
-		readWriteModel.ApduType_SEGMENT_ACK_PDU: func() Decoder {
-			panic("Implement Me")
-		},
-		readWriteModel.ApduType_ERROR_PDU: func() Decoder {
-			panic("Implement Me")
-		},
-		readWriteModel.ApduType_REJECT_PDU: func() Decoder {
-			panic("Implement Me")
-		},
-		readWriteModel.ApduType_ABORT_PDU: func() Decoder {
-			panic("Implement Me")
-		},
-		readWriteModel.ApduType_APDU_UNKNOWN_8: func() Decoder {
-			panic("Implement Me")
-		},
-		readWriteModel.ApduType_APDU_UNKNOWN_9: func() Decoder {
-			panic("Implement Me")
-		},
-		readWriteModel.ApduType_APDU_UNKNOWN_A: func() Decoder {
-			panic("Implement Me")
-		},
-		readWriteModel.ApduType_APDU_UNKNOWN_B: func() Decoder {
-			panic("Implement Me")
-		},
-		readWriteModel.ApduType_APDU_UNKNOWN_C: func() Decoder {
-			panic("Implement Me")
-		},
-		readWriteModel.ApduType_APDU_UNKNOWN_D: func() Decoder {
-			panic("Implement Me")
-		},
-		readWriteModel.ApduType_APDU_UNKNOWN_E: func() Decoder {
-			panic("Implement Me")
-		},
-		readWriteModel.ApduType_APDU_UNKNOWN_F: func() Decoder {
-			panic("Implement Me")
-		},
-	}
-}
-
-var UnconfirmedRequestTypes map[readWriteModel.BACnetUnconfirmedServiceChoice]func() Decoder
-
-func init() {
-	UnconfirmedRequestTypes = map[readWriteModel.BACnetUnconfirmedServiceChoice]func() Decoder{
-		readWriteModel.BACnetUnconfirmedServiceChoice_I_AM: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetUnconfirmedServiceChoice_I_HAVE: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetUnconfirmedServiceChoice_UNCONFIRMED_COV_NOTIFICATION: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetUnconfirmedServiceChoice_UNCONFIRMED_EVENT_NOTIFICATION: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetUnconfirmedServiceChoice_UNCONFIRMED_PRIVATE_TRANSFER: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetUnconfirmedServiceChoice_UNCONFIRMED_TEXT_MESSAGE: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetUnconfirmedServiceChoice_TIME_SYNCHRONIZATION: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetUnconfirmedServiceChoice_WHO_HAS: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetUnconfirmedServiceChoice_WHO_IS: func() Decoder {
-			request, _ := NewWhoIsRequest(Nothing())
-			return request
-		},
-		readWriteModel.BACnetUnconfirmedServiceChoice_UTC_TIME_SYNCHRONIZATION: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetUnconfirmedServiceChoice_WRITE_GROUP: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetUnconfirmedServiceChoice_UNCONFIRMED_COV_NOTIFICATION_MULTIPLE: func() Decoder {
-			panic("implement me")
-		},
-	}
-}
-
-var ConfirmedRequestTypes map[readWriteModel.BACnetConfirmedServiceChoice]func() Decoder
-
-func init() {
-	ConfirmedRequestTypes = map[readWriteModel.BACnetConfirmedServiceChoice]func() Decoder{
-		readWriteModel.BACnetConfirmedServiceChoice_ACKNOWLEDGE_ALARM: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetConfirmedServiceChoice_CONFIRMED_COV_NOTIFICATION: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetConfirmedServiceChoice_CONFIRMED_COV_NOTIFICATION_MULTIPLE: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetConfirmedServiceChoice_CONFIRMED_EVENT_NOTIFICATION: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetConfirmedServiceChoice_GET_ALARM_SUMMARY: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetConfirmedServiceChoice_GET_ENROLLMENT_SUMMARY: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetConfirmedServiceChoice_GET_EVENT_INFORMATION: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetConfirmedServiceChoice_LIFE_SAFETY_OPERATION: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetConfirmedServiceChoice_SUBSCRIBE_COV: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetConfirmedServiceChoice_SUBSCRIBE_COV_PROPERTY: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetConfirmedServiceChoice_SUBSCRIBE_COV_PROPERTY_MULTIPLE: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetConfirmedServiceChoice_ATOMIC_READ_FILE: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetConfirmedServiceChoice_ATOMIC_WRITE_FILE: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetConfirmedServiceChoice_ADD_LIST_ELEMENT: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetConfirmedServiceChoice_REMOVE_LIST_ELEMENT: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetConfirmedServiceChoice_CREATE_OBJECT: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetConfirmedServiceChoice_DELETE_OBJECT: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetConfirmedServiceChoice_READ_PROPERTY: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetConfirmedServiceChoice_READ_PROPERTY_MULTIPLE: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetConfirmedServiceChoice_READ_RANGE: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetConfirmedServiceChoice_WRITE_PROPERTY: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetConfirmedServiceChoice_WRITE_PROPERTY_MULTIPLE: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetConfirmedServiceChoice_DEVICE_COMMUNICATION_CONTROL: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetConfirmedServiceChoice_CONFIRMED_PRIVATE_TRANSFER: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetConfirmedServiceChoice_CONFIRMED_TEXT_MESSAGE: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetConfirmedServiceChoice_REINITIALIZE_DEVICE: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetConfirmedServiceChoice_VT_OPEN: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetConfirmedServiceChoice_VT_CLOSE: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetConfirmedServiceChoice_VT_DATA: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetConfirmedServiceChoice_AUTHENTICATE: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetConfirmedServiceChoice_REQUEST_KEY: func() Decoder {
-			panic("implement me")
-		},
-		readWriteModel.BACnetConfirmedServiceChoice_READ_PROPERTY_CONDITIONAL: func() Decoder {
-			panic("implement me")
-		},
-	}
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_APCI.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_APCI.go
deleted file mode 100644
index e6bc907429..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_APCI.go
+++ /dev/null
@@ -1,538 +0,0 @@
-/*
- * 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 apdu
-
-import (
-	"context"
-	"fmt"
-	"strconv"
-
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/debugging"
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/pdu"
-	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
-	"github.com/apache/plc4x/plc4go/spi/errors"
-)
-
-type APCI interface {
-	PCI
-
-	Encode(pdu Arg) error
-	Decode(pdu Arg) error
-
-	setApduType(*readWriteModel.ApduType)
-	getApduType() *readWriteModel.ApduType
-	setApduSeg(bool)
-	getApduSeg() bool
-	setApduMor(bool)
-	getApduMor() bool
-	setApduSA(bool)
-	getApduSA() bool
-	setApduSrv(bool)
-	getApduSrv() bool
-	setApduNak(bool)
-	getApduNak() bool
-	setApduSeq(*uint8)
-	getApduSeq() *uint8
-	setApduWin(*uint8)
-	getApduWin() *uint8
-	setApduMaxSegs(*uint8)
-	getApduMaxSegs() *uint8
-	setApduMaxResp(*uint8)
-	getApduMaxResp() *uint8
-	setApduService(*uint8)
-	getApduService() *uint8
-	SetApduInvokeID(*uint8)
-	GetApduInvokeID() *uint8
-	setApduAbortRejectReason(*uint8)
-	getApduAbortRejectReason() *uint8
-
-	getAPCI() APCI
-}
-
-type _APCI struct {
-	PCI
-	*DebugContents
-
-	apduType              *readWriteModel.ApduType
-	apduSeg               bool   // segmented
-	apduMor               bool   // more follows
-	apduSA                bool   // segmented response accepted
-	apduSrv               bool   // sent by server
-	apduNak               bool   // negative acknowledgement
-	apduSeq               *uint8 // sequence number
-	apduWin               *uint8 // actual/proposed window size
-	apduMaxSegs           *uint8 // maximum segments accepted (decoded)
-	apduMaxResp           *uint8 // max response accepted (decoded)
-	apduService           *uint8
-	apduInvokeID          *uint8
-	apduAbortRejectReason *uint8
-
-	// Deprecated: hacky workaround
-	bytesToDiscard int
-
-	_leafName string
-}
-
-var _ APCI = (*_APCI)(nil)
-
-func NewAPCI(args Args, kwArgs KWArgs, options ...Option) (APCI, error) {
-	return newAPCI(args, kwArgs, options...)
-}
-
-func newAPCI(args Args, kwArgs KWArgs, options ...Option) (*_APCI, error) {
-	if _debug != nil {
-		_debug("__init__ %r %r", args, kwArgs)
-	}
-	a := &_APCI{
-		_leafName: ExtractLeafName(options, StructName()),
-	}
-	options = AddLeafTypeIfAbundant(options, a)
-	a.DebugContents = NewDebugContents(a, "apduType", "apduSeg", "apduMor", "apduSA", "apduSrv",
-		"apduNak", "apduSeq", "apduWin", "apduMaxSegs", "apduMaxResp",
-		"apduService", "apduInvokeID", "apduAbortRejectReason")
-	a.PCI = NewPCI(args, kwArgs, options...)
-	a.AddExtraPrinters(a.PCI.(DebugContentPrinter))
-	return a, nil
-}
-
-func (a *_APCI) GetDebugAttr(attr string) any {
-	switch attr {
-	case "apduType":
-		if a.apduType != nil {
-			return *a.apduType
-		}
-	case "apduSeg":
-		if a.apduSeg {
-			return a.apduSeq
-		}
-	case "apduMor":
-		if a.apduMor {
-			return a.apduMor
-		}
-	case "apduSA":
-		if a.apduSA {
-			return a.apduSA
-		}
-	case "apduSrv":
-		if a.apduSrv {
-			return a.apduSrv
-		}
-	case "apduNak":
-		if a.apduNak {
-			return a.apduNak
-		}
-	case "apduSeq":
-		if a.apduSeq != nil {
-			return *a.apduSeq
-		}
-	case "apduWin":
-		if a.apduWin != nil {
-			return *a.apduWin
-		}
-	case "apduMaxSegs":
-		if a.apduMaxSegs != nil {
-			return *a.apduMaxSegs
-		}
-	case "apduMaxResp":
-		if a.apduMaxResp != nil {
-			return *a.apduMaxResp
-		}
-	case "apduService":
-		if a.apduService != nil {
-			return *a.apduService
-		}
-	case "apduInvokeID":
-		if a.apduInvokeID != nil {
-			return *a.apduInvokeID
-		}
-	case "apduAbortRejectReason":
-		if a.apduAbortRejectReason != nil {
-			return *a.apduAbortRejectReason
-		}
-	default:
-		return nil
-	}
-	return nil
-}
-
-func (a *_APCI) setApduType(apduType *readWriteModel.ApduType) {
-	a.apduType = apduType
-}
-func (a *_APCI) getApduType() *readWriteModel.ApduType {
-	return a.apduType
-}
-func (a *_APCI) setApduSeg(apduSeg bool) {
-	a.apduSeg = apduSeg
-}
-func (a *_APCI) getApduSeg() bool {
-	return a.apduSeg
-}
-func (a *_APCI) setApduMor(apduMor bool) {
-	a.apduMor = apduMor
-}
-func (a *_APCI) getApduMor() bool {
-	return a.apduMor
-}
-func (a *_APCI) setApduSA(apduSA bool) {
-	a.apduSA = apduSA
-}
-func (a *_APCI) getApduSA() bool {
-	return a.apduSA
-}
-func (a *_APCI) setApduSrv(apduSrv bool) {
-	a.apduSrv = apduSrv
-}
-func (a *_APCI) getApduSrv() bool {
-	return a.apduSrv
-}
-func (a *_APCI) setApduNak(apduNak bool) {
-	a.apduNak = apduNak
-}
-func (a *_APCI) getApduNak() bool {
-	return a.apduNak
-}
-func (a *_APCI) setApduSeq(apduSeq *uint8) {
-	a.apduSeq = apduSeq
-}
-func (a *_APCI) getApduSeq() *uint8 {
-	return a.apduSeq
-}
-func (a *_APCI) setApduWin(apduWin *uint8) {
-	a.apduWin = apduWin
-}
-func (a *_APCI) getApduWin() *uint8 {
-	return a.apduWin
-}
-func (a *_APCI) setApduMaxSegs(apduMaxSegs *uint8) {
-	a.apduMaxSegs = apduMaxSegs
-}
-func (a *_APCI) getApduMaxSegs() *uint8 {
-	return a.apduMaxSegs
-}
-func (a *_APCI) setApduMaxResp(apduMaxResp *uint8) {
-	a.apduMaxResp = apduMaxResp
-}
-func (a *_APCI) getApduMaxResp() *uint8 {
-	return a.apduMaxResp
-}
-func (a *_APCI) setApduService(apduService *uint8) {
-	a.apduService = apduService
-}
-func (a *_APCI) getApduService() *uint8 {
-	return a.apduService
-}
-func (a *_APCI) SetApduInvokeID(apduInvokeID *uint8) {
-	a.apduInvokeID = apduInvokeID
-}
-func (a *_APCI) GetApduInvokeID() *uint8 {
-	return a.apduInvokeID
-}
-func (a *_APCI) setApduAbortRejectReason(apduAbortRejectReason *uint8) {
-	a.apduAbortRejectReason = apduAbortRejectReason
-}
-func (a *_APCI) getApduAbortRejectReason() *uint8 {
-	return a.apduAbortRejectReason
-}
-
-func (a *_APCI) getAPCI() APCI {
-	return a
-}
-
-func (a *_APCI) Update(apci Arg) error {
-	if err := a.PCI.Update(apci); err != nil {
-		return errors.Wrap(err, "error updating _PCI")
-	}
-	switch apci := apci.(type) {
-	case APCI:
-		a.apduType = apci.getApduType()
-		a.apduSeg = apci.getApduSeg()
-		a.apduMor = apci.getApduMor()
-		a.apduSA = apci.getApduSA()
-		a.apduSrv = apci.getApduSrv()
-		a.apduNak = apci.getApduNak()
-		a.apduSeq = apci.getApduSeq()
-		a.apduWin = apci.getApduWin()
-		a.apduMaxSegs = apci.getApduMaxSegs()
-		a.apduMaxResp = apci.getApduMaxResp()
-		a.apduService = apci.getApduService()
-		a.apduInvokeID = apci.GetApduInvokeID()
-		a.apduAbortRejectReason = apci.getApduAbortRejectReason()
-		return nil
-	default:
-		return errors.Errorf("invalid APCI type %T", apci)
-	}
-}
-
-func (a *_APCI) Encode(pdu Arg) error {
-	if _debug != nil {
-		_debug("encode %r", pdu)
-	}
-	switch pdu := pdu.(type) {
-	case PCI:
-		if err := pdu.GetPCI().Update(a); err != nil {
-			return errors.Wrap(err, "error updating pdu")
-		}
-	}
-	switch pdu := pdu.(type) {
-	case PDUData:
-		if a.apduType == nil {
-			return errors.New("APCI does not have APDU type")
-		}
-		switch *a.apduType {
-		case readWriteModel.ApduType_CONFIRMED_REQUEST_PDU:
-			// PDU type
-			buff := byte(*a.apduType << 4)
-			if a.apduSeg {
-				buff += 0x08
-			}
-			if a.apduMor {
-				buff += 0x04
-			}
-			if a.apduSA {
-				buff += 0x02
-			}
-			pdu.Put(buff)
-			pdu.Put((*a.apduMaxSegs << 4) + *a.apduMaxResp)
-			pdu.Put(*a.apduInvokeID)
-			if a.apduSeg {
-				pdu.Put(*a.apduSeq)
-				pdu.Put(*a.apduWin)
-			}
-			pdu.Put(byte(*a.apduService))
-
-		case readWriteModel.ApduType_UNCONFIRMED_REQUEST_PDU:
-			pdu.Put(uint8(*a.apduType) << 4)
-			pdu.Put(uint8(*a.apduService))
-
-		case readWriteModel.ApduType_SIMPLE_ACK_PDU:
-			pdu.Put(uint8(*a.apduType) << 4)
-			pdu.Put(*a.apduInvokeID)
-			pdu.Put(uint8(*a.apduService))
-
-		case readWriteModel.ApduType_COMPLEX_ACK_PDU:
-			// PDU type
-			buff := uint8(*a.apduType << 4)
-			if a.apduSeg {
-				buff += 0x08
-			}
-			if a.apduMor {
-				buff += 0x04
-			}
-			pdu.Put(buff)
-			pdu.Put(*a.apduInvokeID)
-			if a.apduSeg {
-				pdu.Put(*a.apduSeq)
-				pdu.Put(*a.apduWin)
-			}
-			pdu.Put(uint8(*a.apduService))
-
-		case readWriteModel.ApduType_SEGMENT_ACK_PDU:
-			// PDU type
-			buff := uint8(*a.apduType << 4)
-			if a.apduNak {
-				buff += 0x02
-			}
-			if a.apduSrv {
-				buff += 0x01
-			}
-			pdu.Put(buff)
-			pdu.Put(*a.apduInvokeID)
-			pdu.Put(*a.apduSeq)
-			pdu.Put(*a.apduWin)
-
-		case readWriteModel.ApduType_ERROR_PDU:
-			pdu.Put(uint8(*a.apduType << 4))
-			pdu.Put(*a.apduInvokeID)
-			pdu.Put(uint8(*a.apduService))
-
-		case readWriteModel.ApduType_REJECT_PDU:
-			pdu.Put(uint8(*a.apduType << 4))
-			pdu.Put(*a.apduInvokeID)
-			pdu.Put(*a.apduAbortRejectReason)
-
-		case readWriteModel.ApduType_ABORT_PDU:
-			// PDU type
-			buff := uint8(*a.apduType << 4)
-			if a.apduSrv {
-				buff += 0x01
-			}
-			pdu.Put(buff)
-			pdu.Put(*a.apduInvokeID)
-			pdu.Put(*a.apduAbortRejectReason)
-		}
-	}
-	return nil
-}
-
-func (a *_APCI) Decode(pdu Arg) error {
-	if _debug != nil {
-		_debug("decode %r", pdu)
-	}
-	if err := a.PCI.Update(pdu); err != nil {
-		return errors.Wrap(err, "error updating pdu")
-	}
-	// TODO: check if we want to stay with parsing or ditch that for now
-	data := pdu.(PDUData).GetPduData()
-	parse, err := readWriteModel.APDUParse[readWriteModel.APDU](context.Background(), data, uint16(len(data)))
-	if err != nil {
-		return errors.Wrap(err, "error parsing apdu")
-	}
-	a.SetRootMessage(parse)
-	readBytes := 0
-
-	// simulate the APCI type decode
-	readBytes++
-	switch rm := a.GetRootMessage().(type) {
-	case readWriteModel.APDU:
-		apduType := rm.GetApduType()
-		a.apduType = &apduType
-	}
-	switch rm := a.GetRootMessage().(type) {
-	case readWriteModel.APDUConfirmedRequest:
-		a.apduSeg = rm.GetSegmentedMessage()
-		a.apduMor = rm.GetMoreFollows()
-		a.apduSA = rm.GetSegmentedResponseAccepted()
-		readBytes++
-		maxSegmentsAccepted := uint8(rm.GetMaxSegmentsAccepted())
-		a.apduMaxSegs = &maxSegmentsAccepted
-		maxApduLengthAccepted := uint8(rm.GetMaxApduLengthAccepted())
-		a.apduMaxResp = &maxApduLengthAccepted
-		readBytes++
-		invokeId := rm.GetInvokeId()
-		a.apduInvokeID = &invokeId
-		if a.apduSeg {
-			readBytes++
-			a.apduSeq = rm.GetSequenceNumber()
-			readBytes++
-			a.apduWin = rm.GetProposedWindowSize()
-		}
-		readBytes++
-		if sr := rm.GetServiceRequest(); sr != nil {
-			serviceChoice := uint8(sr.GetServiceChoice())
-			a.apduService = &serviceChoice
-		}
-	case readWriteModel.APDUUnconfirmedRequest:
-		readBytes++
-		var choice *uint8
-		if sr := rm.GetServiceRequest(); sr != nil {
-			serviceChoice := uint8(sr.GetServiceChoice())
-			choice = &serviceChoice
-		}
-		a.apduService = choice
-	case readWriteModel.APDUSimpleAck:
-		readBytes++
-		invokeId := rm.GetOriginalInvokeId()
-		a.apduInvokeID = &invokeId
-	case readWriteModel.APDUComplexAck:
-		a.apduSeg = rm.GetSegmentedMessage()
-		a.apduMor = rm.GetMoreFollows()
-		readBytes++
-		invokeId := rm.GetOriginalInvokeId()
-		a.apduInvokeID = &invokeId
-		if a.apduSeg {
-			readBytes++
-			a.apduSeq = rm.GetSequenceNumber()
-			readBytes++
-			a.apduWin = rm.GetProposedWindowSize()
-		}
-		if sr := rm.GetServiceAck(); sr != nil {
-			serviceChoice := uint8(sr.GetServiceChoice())
-			a.apduService = &serviceChoice
-		}
-	case readWriteModel.APDUSegmentAck:
-		a.apduNak = rm.GetNegativeAck()
-		a.apduSrv = rm.GetServer()
-		readBytes++
-		invokeId := rm.GetOriginalInvokeId()
-		a.apduInvokeID = &invokeId
-		readBytes++
-		actualWindowSize := rm.GetActualWindowSize()
-		a.apduWin = &actualWindowSize
-	case readWriteModel.APDUError:
-		readBytes++
-		invokeId := rm.GetOriginalInvokeId()
-		a.apduInvokeID = &invokeId
-		serviceChoice := uint8(rm.GetErrorChoice())
-		a.apduService = &serviceChoice
-	case readWriteModel.APDUReject:
-		readBytes++
-		invokeId := rm.GetOriginalInvokeId()
-		a.apduInvokeID = &invokeId
-		apduAbortRejectReason := uint8(rm.GetRejectReason().GetValue())
-		a.apduAbortRejectReason = &apduAbortRejectReason
-	case readWriteModel.APDUAbort:
-		readBytes++
-		invokeId := rm.GetOriginalInvokeId()
-		a.apduInvokeID = &invokeId
-		apduAbortRejectReason := uint8(rm.GetAbortReason().GetValue())
-		a.apduAbortRejectReason = &apduAbortRejectReason
-	}
-	a.bytesToDiscard = readBytes
-	return nil
-}
-
-func (a *_APCI) deepCopy() *_APCI {
-	newA := &_APCI{
-		a.PCI.DeepCopy().(PCI),
-		nil,
-		CopyPtr(a.apduType),
-		a.apduSeg,
-		a.apduMor,
-		a.apduSA,
-		a.apduSrv,
-		a.apduNak,
-		CopyPtr(a.apduSeq),
-		CopyPtr(a.apduWin),
-		CopyPtr(a.apduMaxSegs),
-		CopyPtr(a.apduMaxResp),
-		CopyPtr(a.apduService),
-		CopyPtr(a.apduInvokeID),
-		CopyPtr(a.apduAbortRejectReason),
-		a.bytesToDiscard,
-		a._leafName,
-	}
-	newA.DebugContents = NewDebugContents(newA, "apduType", "apduSeg", "apduMor", "apduSA", "apduSrv",
-		"apduNak", "apduSeq", "apduWin", "apduMaxSegs", "apduMaxResp",
-		"apduService", "apduInvokeID", "apduAbortRejectReason") // TODO: bit ugly to repeat that here again but what are the options...
-	newA.AddExtraPrinters(newA.PCI.(DebugContentPrinter))
-	return newA
-}
-
-func (a *_APCI) String() string {
-	sname := a._leafName
-
-	// expand the type if possible
-	stype := ""
-	if a.apduType != nil {
-		if v, ok := APDUTypes[*a.apduType]; ok {
-			stype = fmt.Sprintf("%s(%d)", QualifiedTypeName(v()), *a.apduType)
-		} else {
-			stype = "?"
-		}
-	}
-
-	// add the invoke ID if it has one
-	if a.apduInvokeID != nil {
-		stype += ", " + strconv.Itoa(int(*a.apduInvokeID))
-	}
-	// put it together
-	return fmt.Sprintf("<%s(%s instance at %p)>", sname, stype, a)
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_APCISequence.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_APCISequence.go
deleted file mode 100644
index f88d575603..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_APCISequence.go
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * 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 apdu
-
-import (
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/constructeddata"
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/pdu"
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/primitivedata"
-	"github.com/apache/plc4x/plc4go/spi/errors"
-)
-
-// APCISequenceContract provides a set of functions which can be overwritten by a sub struct
-type APCISequenceContract interface {
-	SequenceContractRequirement
-}
-
-// APCISequenceContractRequirement is needed when one want to extend using SequenceContract
-type APCISequenceContractRequirement interface {
-	APCISequenceContract
-	// SetAPCISequence callback is needed as we work in the constructor already with the finished object // TODO: maybe we need to return as init again as it might not be finished constructing....
-	SetAPCISequence(a *APCISequence)
-}
-
-type APCISequence struct {
-	*_APCI
-	*Sequence
-
-	_contract APCISequenceContract
-
-	tagList *TagList
-}
-
-func NewAPCISequence(args Args, kwArgs KWArgs, options ...Option) (*APCISequence, error) {
-	a := &APCISequence{}
-	ApplyAppliers(options, a)
-	if _debug != nil {
-		_debug("__init__ %r %r", args, kwArgs)
-	}
-	if a._contract == nil {
-		a._contract = a
-	} else {
-		a._contract.(APCISequenceContractRequirement).SetAPCISequence(a)
-	}
-	options = AddLeafTypeIfAbundant(options, a)
-	var err error
-	a._APCI, err = CreateSharedSuperIfAbundant[_APCI](options, newAPCI, args, kwArgs, options...)
-	if err != nil {
-		return nil, errors.Wrap(err, "error creating APCI")
-	}
-	a.Sequence, err = NewSequence(args, kwArgs, Combine(options, WithSequenceExtension(a._contract))...)
-	if err != nil {
-		return nil, errors.Wrap(err, "error creating sequence")
-	}
-	a.AddExtraPrinters(a.Sequence)
-
-	// start with an empty tag list
-	a.tagList = NewTagList(nil)
-	return a, nil
-}
-
-func WithAPCISequenceExtension(contract APCISequenceContractRequirement) GenericApplier[*APCISequence] {
-	return WrapGenericApplier(func(a *APCISequence) { a._contract = contract })
-}
-
-func (a *APCISequence) SetSequence(sequence *Sequence) {
-	a.Sequence = sequence
-}
-
-func (a *APCISequence) Encode(apdu Arg) error {
-	if _debug != nil {
-		_debug("encode %r", apdu)
-	}
-	switch apdu := apdu.(type) {
-	case Updater:
-		if err := apdu.Update(a); err != nil {
-			return errors.Wrap(err, "error updating APDU")
-		}
-	}
-
-	// create a tag list
-	a.tagList = NewTagList(nil)
-
-	if err := a.Sequence.Encode(a.tagList); err != nil {
-		return errors.Wrap(err, "error encoding TagList")
-	}
-
-	switch apdu := apdu.(type) {
-	case PDUData:
-		// encode the tag list
-		a.tagList.Encode(apdu)
-	default:
-		return errors.Errorf("invalid APDU type %T", apdu)
-	}
-	return nil
-}
-
-func (a *APCISequence) Decode(apdu Arg) error {
-	if _debug != nil {
-		_debug("decode %r", apdu)
-	}
-	// copy the header fields
-	if err := a.Update(apdu); err != nil {
-		return errors.Wrap(err, "error updating APDU")
-	}
-
-	// create a tag list and decode the rest of the data
-	a.tagList = NewTagList(nil)
-	switch apdu := apdu.(type) {
-	case PDUData:
-		if err := a.tagList.Decode(apdu); err != nil {
-			return errors.Wrap(err, "error decoding TagList")
-		}
-	default:
-		return errors.Errorf("invalid APDU type %T", apdu)
-	}
-	// pass the taglist to the Sequence for additional decoding
-	if err := a.Sequence.Decode(a.tagList); err != nil {
-		return errors.Wrap(err, "error encoding TagList")
-	}
-	if _debug != nil {
-		_debug("    - tag list: %r", a.tagList)
-	}
-
-	if len(a.tagList.GetTagList()) > 0 {
-		if _debug != nil {
-			_debug("    - trailing unmatched tags")
-		}
-		return errors.New("trailing unmatched tags")
-	}
-	return nil
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_APDU.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_APDU.go
deleted file mode 100644
index 224fe56f18..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_APDU.go
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * 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 apdu
-
-import (
-	"context"
-	"fmt"
-
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/debugging"
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/pdu"
-	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
-	"github.com/apache/plc4x/plc4go/spi"
-	"github.com/apache/plc4x/plc4go/spi/errors"
-)
-
-type APDU interface {
-	Copyable
-	readWriteModel.APDU
-	APCI
-	PDUData
-}
-
-type __APDU struct {
-	*_APCI
-	PDUData
-}
-
-var _ APDU = (*__APDU)(nil)
-
-func NewAPDU(args Args, kwArgs KWArgs, options ...Option) (APDU, error) {
-	if _debug != nil {
-		_debug("__init__ %r %r", args, kwArgs)
-	}
-	a := &__APDU{}
-	options = AddLeafTypeIfAbundant(options, a)
-	var err error
-	a._APCI, err = CreateSharedSuperIfAbundant[_APCI](options, newAPCI, args, kwArgs, options...)
-	if err != nil {
-		return nil, errors.Wrap(err, "error creating APCI")
-	}
-	a.PDUData = NewPDUData(args, kwArgs, options...)
-	a.AddExtraPrinters(a.PDUData.(DebugContentPrinter))
-	return a, nil
-}
-
-func (a *__APDU) Encode(pdu Arg) error {
-	if _debug != nil {
-		_debug("encode %s", pdu.(fmt.Stringer).String())
-	}
-	if err := a._APCI.Encode(pdu); err != nil {
-		return errors.Wrap(err, "error encoding APCI")
-	}
-	switch pdu := pdu.(type) {
-	case PDUData:
-		pdu.PutData(a.GetPduData()...)
-	}
-	return nil
-}
-
-func (a *__APDU) Decode(pdu Arg) error {
-	if _debug != nil {
-		_debug("decode %s", pdu.(fmt.Stringer).String())
-	}
-	var rootMessage spi.Message
-	switch pdu := pdu.(type) { // Save a root message as long as we have enough data
-	case PDUData:
-		data := pdu.GetPduData()
-		rootMessage, _ = Try1(func() (readWriteModel.APDU, error) {
-			return readWriteModel.APDUParse[readWriteModel.APDU](context.Background(), data, uint16(len(data)))
-		})
-	}
-	switch pdu := pdu.(type) {
-	case IPCI:
-		if rootMessage != nil { // in this case we are good and want to parse from that
-			pdu.SetRootMessage(rootMessage)
-		}
-	}
-	if err := a._APCI.Decode(pdu); err != nil {
-		return errors.Wrap(err, "error decoding APCI")
-	}
-	switch pdu := pdu.(type) {
-	case PDUData:
-		a.PutData(pdu.GetPduData()[a.bytesToDiscard:]...)
-	}
-	if rootMessage != nil {
-		// Overwrite the root message again so we can use it for matching
-		a.SetRootMessage(rootMessage)
-	}
-	return nil
-}
-
-func (a *__APDU) CreateAPDUBuilder() readWriteModel.APDUBuilder {
-	switch rm := a.GetRootMessage().(type) {
-	case readWriteModel.APDU:
-		return rm.CreateAPDUBuilder()
-	default:
-		return readWriteModel.NewAPDUBuilder()
-	}
-}
-
-func (a *__APDU) GetApduType() readWriteModel.ApduType {
-	switch rm := a.GetRootMessage().(type) {
-	case readWriteModel.APDU:
-		return rm.GetApduType()
-	default:
-		return *a.apduType
-	}
-}
-
-func (a *__APDU) IsAPDU() {
-}
-
-func (a *__APDU) deepCopy() *__APDU {
-	return &__APDU{_APCI: a._APCI.deepCopy(), PDUData: a.PDUData.DeepCopy().(PDUData)}
-}
-
-func (a *__APDU) DeepCopy() any {
-	return a.deepCopy()
-}
-
-func (a *__APDU) String() string {
-	return a._APCI.String()
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AbortPDU.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AbortPDU.go
deleted file mode 100644
index bffa3f078c..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AbortPDU.go
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type AbortPDU struct {
-	*___APDU
-
-	apduSrv any
-}
-
-func (a *AbortPDU) GetAPDUSrv() any {
-	panic("implement me")
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AbortReason.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AbortReason.go
deleted file mode 100644
index ed5dfb150d..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AbortReason.go
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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 apdu
-
-import . "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/primitivedata"
-
-// TODO: implement it...
-type AbortReason struct {
-	*Enumerated
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AcknowledgeAlarmRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AcknowledgeAlarmRequest.go
deleted file mode 100644
index 27b410d049..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AcknowledgeAlarmRequest.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type AcknowledgeAlarmRequest struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AddListElementRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AddListElementRequest.go
deleted file mode 100644
index ff49166242..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AddListElementRequest.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type AddListElementRequest struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicReadFileACKAccessMethodChoice.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicReadFileACKAccessMethodChoice.go
deleted file mode 100644
index 41982234d5..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicReadFileACKAccessMethodChoice.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type AtomicReadFileACKAccessMethodChoice struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicReadFileACKAccessMethodRecordAccess.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicReadFileACKAccessMethodRecordAccess.go
deleted file mode 100644
index e4a5f49b32..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicReadFileACKAccessMethodRecordAccess.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type AtomicReadFileACKAccessMethodRecordAccess struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicReadFileACKAccessMethodStreamAccess.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicReadFileACKAccessMethodStreamAccess.go
deleted file mode 100644
index c01d1b9e4c..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicReadFileACKAccessMethodStreamAccess.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type AtomicReadFileACKAccessMethodStreamAccess struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicReadFileRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicReadFileRequest.go
deleted file mode 100644
index 33a0875340..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicReadFileRequest.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type AtomicReadFileRequest struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicReadFileRequestAccessMethodChoice.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicReadFileRequestAccessMethodChoice.go
deleted file mode 100644
index 744923dfc4..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicReadFileRequestAccessMethodChoice.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type AtomicReadFileRequestAccessMethodChoice struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicReadFileRequestAccessMethodChoiceRecordAccess.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicReadFileRequestAccessMethodChoiceRecordAccess.go
deleted file mode 100644
index 37e4ed2c3e..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicReadFileRequestAccessMethodChoiceRecordAccess.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type AtomicReadFileRequestAccessMethodChoiceRecordAccess struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicReadFileRequestAccessMethodChoiceStreamAccess.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicReadFileRequestAccessMethodChoiceStreamAccess.go
deleted file mode 100644
index 33095a3428..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicReadFileRequestAccessMethodChoiceStreamAccess.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type AtomicReadFileRequestAccessMethodChoiceStreamAccess struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicWriteFileACK.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicWriteFileACK.go
deleted file mode 100644
index c2782b86a0..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicWriteFileACK.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type AtomicWriteFileACK struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicWriteFileRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicWriteFileRequest.go
deleted file mode 100644
index e7f7b2ac84..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicWriteFileRequest.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type AtomicWriteFileRequest struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicWriteFileRequestAccessMethodChoice.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicWriteFileRequestAccessMethodChoice.go
deleted file mode 100644
index b0085c7954..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicWriteFileRequestAccessMethodChoice.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type AtomicWriteFileRequestAccessMethodChoice struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicWriteFileRequestAccessMethodChoiceRecordAccess.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicWriteFileRequestAccessMethodChoiceRecordAccess.go
deleted file mode 100644
index 289f42e0c9..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicWriteFileRequestAccessMethodChoiceRecordAccess.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type AtomicWriteFileRequestAccessMethodChoiceRecordAccess struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicWriteFileRequestAccessMethodChoiceStreamAccess.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicWriteFileRequestAccessMethodChoiceStreamAccess.go
deleted file mode 100644
index 5f804d2871..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AtomicWriteFileRequestAccessMethodChoiceStreamAccess.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type AtomicWriteFileRequestAccessMethodChoiceStreamAccess struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AuthenticateACK.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AuthenticateACK.go
deleted file mode 100644
index d179f36991..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AuthenticateACK.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type AuthenticateACK struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AuthenticateRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AuthenticateRequest.go
deleted file mode 100644
index c9b4075592..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_AuthenticateRequest.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type AuthenticateRequest struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_COVNotificationParameters.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_COVNotificationParameters.go
deleted file mode 100644
index c0df9dfc85..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_COVNotificationParameters.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type COVNotificationParameters struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ChangeListError.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ChangeListError.go
deleted file mode 100644
index 47e3cd12db..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ChangeListError.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type ChangeListError struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ComplexAckPDU.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ComplexAckPDU.go
deleted file mode 100644
index ba1e97cb4e..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ComplexAckPDU.go
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * 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 apdu
-
-import readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
-
-// TODO: implement it...
-type ComplexAckPDU struct {
-	*___APDU
-}
-
-var _ readWriteModel.APDUComplexAck = (*ComplexAckPDU)(nil)
-
-func (c *ComplexAckPDU) CreateAPDUComplexAckBuilder() readWriteModel.APDUComplexAckBuilder {
-	panic("implement me")
-}
-
-func (c *ComplexAckPDU) GetSegmentedMessage() bool {
-	//TODO implement me
-	panic("implement me")
-}
-
-func (c *ComplexAckPDU) GetMoreFollows() bool {
-	//TODO implement me
-	panic("implement me")
-}
-
-func (c *ComplexAckPDU) GetOriginalInvokeId() uint8 {
-	//TODO implement me
-	panic("implement me")
-}
-
-func (c *ComplexAckPDU) GetSequenceNumber() *uint8 {
-	//TODO implement me
-	panic("implement me")
-}
-
-func (c *ComplexAckPDU) GetProposedWindowSize() *uint8 {
-	//TODO implement me
-	panic("implement me")
-}
-
-func (c *ComplexAckPDU) GetServiceAck() readWriteModel.BACnetServiceAck {
-	//TODO implement me
-	panic("implement me")
-}
-
-func (c *ComplexAckPDU) GetSegmentServiceChoice() *readWriteModel.BACnetConfirmedServiceChoice {
-	//TODO implement me
-	panic("implement me")
-}
-
-func (c *ComplexAckPDU) GetSegment() []byte {
-	//TODO implement me
-	panic("implement me")
-}
-
-func (c *ComplexAckPDU) GetApduHeaderReduction() uint16 {
-	//TODO implement me
-	panic("implement me")
-}
-
-func (c *ComplexAckPDU) GetSegmentReduction() uint16 {
-	//TODO implement me
-	panic("implement me")
-}
-
-func (c *ComplexAckPDU) IsAPDUComplexAck() {
-	//TODO implement me
-	panic("implement me")
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ComplexAckSequence.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ComplexAckSequence.go
deleted file mode 100644
index a59a65180e..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ComplexAckSequence.go
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type ComplexAckSequence struct {
-	*APCISequence
-	*ComplexAckPDU
-}
-
-func (c *ComplexAckSequence) String() string {
-	return c.APCISequence.String()
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedCOVNotificationRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedCOVNotificationRequest.go
deleted file mode 100644
index f9227ba8b7..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedCOVNotificationRequest.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type ConfirmedCOVNotificationRequest struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedEventNotificationRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedEventNotificationRequest.go
deleted file mode 100644
index 76285dfaf2..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedEventNotificationRequest.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type ConfirmedEventNotificationRequest struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedPrivateTransferACK.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedPrivateTransferACK.go
deleted file mode 100644
index ebbeafb64a..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedPrivateTransferACK.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type ConfirmedPrivateTransferACK struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedPrivateTransferError.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedPrivateTransferError.go
deleted file mode 100644
index 72525c69a7..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedPrivateTransferError.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type ConfirmedPrivateTransferError struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedPrivateTransferRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedPrivateTransferRequest.go
deleted file mode 100644
index 9d31374c1e..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedPrivateTransferRequest.go
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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 apdu
-
-import (
-	"fmt"
-
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/constructeddata"
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/primitivedata"
-	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
-	"github.com/apache/plc4x/plc4go/spi/errors"
-)
-
-type ConfirmedPrivateTransferRequest struct {
-	*ConfirmedRequestSequence
-
-	serviceChoice    readWriteModel.BACnetConfirmedServiceChoice
-	sequenceElements []Element
-}
-
-func NewConfirmedPrivateTransferRequest(args Args, kwArgs KWArgs, options ...Option) (*ConfirmedPrivateTransferRequest, error) {
-	c := &ConfirmedPrivateTransferRequest{
-		serviceChoice: readWriteModel.BACnetConfirmedServiceChoice_CONFIRMED_PRIVATE_TRANSFER,
-		sequenceElements: []Element{
-			NewElement("vendorID", V2E(NewUnsigned), WithElementContext(0)),
-			NewElement("serviceNumber", V2E(NewUnsigned), WithElementContext(1)),
-			NewElement("serviceParameters", Vs2E(NewAny), WithElementContext(2), WithElementOptional(true)),
-		},
-	}
-	options = AddRootMessageIfAbundant(options, readWriteModel.NewBACnetConfirmedServiceRequestConfirmedPrivateTransfer(
-		0,
-		readWriteModel.CreateBACnetVendorIdContextTagged(0, 0),     // TODO: get right values
-		readWriteModel.CreateBACnetContextTagUnsignedInteger(1, 0), // TODO: get right values
-		nil,
-	))
-	options = AddLeafTypeIfAbundant(options, c)
-	var err error
-	c.ConfirmedRequestSequence, err = NewConfirmedRequestSequence(args, kwArgs, Combine(options, WithConfirmedRequestSequenceExtension(c))...)
-	if err != nil {
-		return nil, errors.Wrap(err, "error building confirmed request")
-	}
-	return c, nil
-}
-
-func (c *ConfirmedPrivateTransferRequest) SetConfirmedRequestSequence(crs *ConfirmedRequestSequence) {
-	c.ConfirmedRequestSequence = crs
-}
-
-func (c *ConfirmedPrivateTransferRequest) String() string {
-	return fmt.Sprintf("ConfirmedPrivateTransferRequest{%s}", c.ConfirmedRequestSequence)
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedRequestPDU.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedRequestPDU.go
deleted file mode 100644
index 7d20346079..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedRequestPDU.go
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * 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 apdu
-
-import (
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
-	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
-	"github.com/apache/plc4x/plc4go/spi/errors"
-)
-
-type ConfirmedRequestPDU struct {
-	*___APDU
-
-	serviceRequest readWriteModel.BACnetConfirmedServiceRequest
-}
-
-var _ readWriteModel.APDUConfirmedRequest = (*ConfirmedRequestPDU)(nil)
-
-func NewConfirmedRequestPDU(args Args, kwArgs KWArgs, options ...Option) (*ConfirmedRequestPDU, error) {
-	c := &ConfirmedRequestPDU{}
-	choice, ok := KWO[*readWriteModel.BACnetConfirmedServiceChoice](kwArgs, KWConfirmedServiceChoice, nil)
-	if _debug != nil {
-		_debug("__init__ %r %r %r", choice, args, kwArgs)
-	}
-	apdu, err := New_APDU(args, kwArgs, options...)
-	if err != nil {
-		return nil, errors.Wrap(err, "error creating _APDU")
-	}
-	c.___APDU = apdu.(*___APDU)
-	c.apduType = new(readWriteModel.ApduType_CONFIRMED_REQUEST_PDU)
-	if ok {
-		serviceChoice := uint8(*choice)
-		c.apduService = &serviceChoice
-	}
-	c.SetExpectingReply(true)
-	switch rm := c.GetRootMessage().(type) {
-	case readWriteModel.BACnetConfirmedServiceRequest:
-		c.serviceRequest = rm
-		serviceChoice := rm.GetServiceChoice()
-		c.apduService = new(uint8(serviceChoice))
-	}
-	c.SetRootMessage(c.buildConfirmedRequest(c.serviceRequest))
-
-	return c, nil
-}
-
-func (c *ConfirmedRequestPDU) buildConfirmedRequest(serviceRequest readWriteModel.BACnetConfirmedServiceRequest) readWriteModel.APDUConfirmedRequest {
-	if serviceRequest == nil {
-		return nil
-	}
-	invokeID := uint8(0)
-	if c.apduInvokeID != nil {
-		invokeID = *c.apduInvokeID
-	}
-	return readWriteModel.NewAPDUConfirmedRequest(
-		c.apduSeg,
-		c.apduMor,
-		c.apduSA,
-		readWriteModel.MaxSegmentsAccepted_MORE_THAN_64_SEGMENTS,
-		readWriteModel.MaxApduLengthAccepted_NUM_OCTETS_1476,
-		invokeID,
-		c.apduSeq,
-		c.apduWin,
-		serviceRequest,
-		nil, // TODO: where to get from
-		nil, // TODO: where to get from
-	)
-}
-
-func (c *ConfirmedRequestPDU) CreateAPDUConfirmedRequestBuilder() readWriteModel.APDUConfirmedRequestBuilder {
-	//TODO implement me
-	panic("implement me")
-}
-
-func (c *ConfirmedRequestPDU) GetSegmentedMessage() bool {
-	return c.apduSeg
-}
-
-func (c *ConfirmedRequestPDU) GetMoreFollows() bool {
-	return c.apduMor
-}
-
-func (c *ConfirmedRequestPDU) GetSegmentedResponseAccepted() bool {
-	return c.apduSA
-}
-
-func (c *ConfirmedRequestPDU) GetMaxSegmentsAccepted() readWriteModel.MaxSegmentsAccepted {
-	if c.apduMaxSegs != nil {
-		return readWriteModel.MaxSegmentsAccepted(*c.apduMaxSegs)
-	}
-	return readWriteModel.MaxSegmentsAccepted_MORE_THAN_64_SEGMENTS
-}
-
-func (c *ConfirmedRequestPDU) GetMaxApduLengthAccepted() readWriteModel.MaxApduLengthAccepted {
-	if c.apduMaxResp != nil {
-		return readWriteModel.MaxApduLengthAccepted(*c.apduMaxResp)
-	}
-	return readWriteModel.MaxApduLengthAccepted_NUM_OCTETS_1476
-}
-
-func (c *ConfirmedRequestPDU) GetInvokeId() uint8 {
-	if c.apduInvokeID != nil {
-		return *c.apduInvokeID
-	}
-	return 0
-}
-
-func (c *ConfirmedRequestPDU) GetSequenceNumber() *uint8 {
-	return c.apduSeq
-}
-
-func (c *ConfirmedRequestPDU) GetProposedWindowSize() *uint8 {
-	return c.apduWin
-}
-
-func (c *ConfirmedRequestPDU) GetServiceRequest() readWriteModel.BACnetConfirmedServiceRequest {
-	return c.serviceRequest
-}
-
-func (c *ConfirmedRequestPDU) GetSegmentServiceChoice() *readWriteModel.BACnetConfirmedServiceChoice {
-	serviceChoice := c.serviceRequest.GetServiceChoice()
-	return &serviceChoice
-}
-
-func (c *ConfirmedRequestPDU) GetSegment() []byte {
-	return nil
-}
-
-func (c *ConfirmedRequestPDU) GetApduHeaderReduction() uint16 {
-	return 0
-}
-
-func (c *ConfirmedRequestPDU) GetSegmentReduction() uint16 {
-	return 0
-}
-
-func (c *ConfirmedRequestPDU) IsAPDUConfirmedRequest() {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedRequestSequence.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedRequestSequence.go
deleted file mode 100644
index c1c75d2380..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedRequestSequence.go
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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 apdu
-
-import (
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
-	"github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
-	"github.com/apache/plc4x/plc4go/spi/errors"
-)
-
-// ConfirmedRequestSequenceContract provides a set of functions which can be overwritten by a sub struct
-type ConfirmedRequestSequenceContract interface {
-	APCISequenceContractRequirement
-	GetServiceChoice() *model.BACnetConfirmedServiceChoice
-}
-
-// ConfirmedRequestSequenceContractRequirement is needed when one want to extend using SequenceContract
-type ConfirmedRequestSequenceContractRequirement interface {
-	ConfirmedRequestSequenceContract
-	// SetConfirmedRequestSequence callback is needed as we work in the constructor already with the finished object // TODO: maybe we need to return as init again as it might not be finished constructing....
-	SetConfirmedRequestSequence(crs *ConfirmedRequestSequence)
-}
-
-type ConfirmedRequestSequence struct {
-	*APCISequence
-	*ConfirmedRequestPDU
-
-	_contract ConfirmedRequestSequenceContract
-}
-
-func NewConfirmedRequestSequence(args Args, kwArgs KWArgs, options ...Option) (*ConfirmedRequestSequence, error) {
-	u := &ConfirmedRequestSequence{}
-	ApplyAppliers(options, u)
-	if u._contract == nil {
-		u._contract = u
-	} else {
-		u._contract.(ConfirmedRequestSequenceContractRequirement).SetConfirmedRequestSequence(u)
-	}
-	options = AddSharedSuperIfAbundant[_APCI](options)
-	options = AddLeafTypeIfAbundant(options, u)
-	kwArgs[KWConfirmedServiceChoice] = u._contract.GetServiceChoice()
-	var err error
-	u.ConfirmedRequestPDU, err = NewConfirmedRequestPDU(args, kwArgs, options...)
-	if err != nil {
-		return nil, errors.Wrap(err, "error creating ConfirmedRequestPDU")
-	}
-	//TODO: the sequence is usually init first but seems upstream does a init on the same level first before going deeper
-	u.APCISequence, err = NewAPCISequence(args, kwArgs, Combine(options, WithAPCISequenceExtension(u._contract))...)
-	if err != nil {
-		return nil, errors.Wrap(err, "error creating _APCISequence")
-	}
-	if u.GetRootMessage() == nil {
-		panic("this should be set by NewConfirmedRequestPDU")
-		serviceRequest, _ := GAO[model.BACnetConfirmedServiceRequest](args, 0, nil)
-		if serviceRequest != nil {
-			apduConfirmedRequest := model.NewAPDUConfirmedRequest(false, false, false, model.MaxSegmentsAccepted_MORE_THAN_64_SEGMENTS, model.MaxApduLengthAccepted_NUM_OCTETS_1476, 0, nil, nil, serviceRequest, nil, nil)
-			u.SetRootMessage(apduConfirmedRequest)
-		}
-	}
-	return u, nil
-}
-
-func WithConfirmedRequestSequenceExtension(contract ConfirmedRequestSequenceContractRequirement) GenericApplier[*ConfirmedRequestSequence] {
-	return WrapGenericApplier(func(a *ConfirmedRequestSequence) { a._contract = contract })
-}
-
-func (u *ConfirmedRequestSequence) SetAPCISequence(a *APCISequence) {
-	u.APCISequence = a
-}
-
-func (*ConfirmedRequestSequence) GetServiceChoice() *model.BACnetConfirmedServiceChoice {
-	return nil
-}
-
-func (u *ConfirmedRequestSequence) DeepCopy() any {
-	panic("implement me")
-}
-
-func (u *ConfirmedRequestSequence) String() string {
-	return u.APCISequence.String()
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedServiceChoice.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedServiceChoice.go
deleted file mode 100644
index 39a10fd0d8..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedServiceChoice.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type ConfirmedServiceChoice struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedTextMessageRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedTextMessageRequest.go
deleted file mode 100644
index 4ced9e1003..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedTextMessageRequest.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type ConfirmedTextMessageRequest struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedTextMessageRequestMessageClass.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedTextMessageRequestMessageClass.go
deleted file mode 100644
index abeba5fb4f..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedTextMessageRequestMessageClass.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type ConfirmedTextMessageRequestMessageClass struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedTextMessageRequestMessagePriority.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedTextMessageRequestMessagePriority.go
deleted file mode 100644
index 9604f82b50..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ConfirmedTextMessageRequestMessagePriority.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type ConfirmedTextMessageRequestMessagePriority struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_CreateObjectACK.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_CreateObjectACK.go
deleted file mode 100644
index 81735cf780..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_CreateObjectACK.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type CreateObjectACK struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_CreateObjectError.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_CreateObjectError.go
deleted file mode 100644
index 99a6028e05..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_CreateObjectError.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type CreateObjectError struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_CreateObjectRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_CreateObjectRequest.go
deleted file mode 100644
index 1ffabc74aa..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_CreateObjectRequest.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type CreateObjectRequest struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_CreateObjectRequestObjectSpecifier.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_CreateObjectRequestObjectSpecifier.go
deleted file mode 100644
index e19c0fa28c..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_CreateObjectRequestObjectSpecifier.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type CreateObjectRequestObjectSpecifier struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_DeleteObjectRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_DeleteObjectRequest.go
deleted file mode 100644
index 1090a197a3..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_DeleteObjectRequest.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type DeleteObjectRequest struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_DeviceCommunicationControlRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_DeviceCommunicationControlRequest.go
deleted file mode 100644
index 1c4e884bea..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_DeviceCommunicationControlRequest.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type DeviceCommunicationControlRequest struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_DeviceCommunicationControlRequestEnableDisable.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_DeviceCommunicationControlRequestEnableDisable.go
deleted file mode 100644
index 5a340ab0a2..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_DeviceCommunicationControlRequestEnableDisable.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type DeviceCommunicationControlRequestEnableDisable struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_Error.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_Error.go
deleted file mode 100644
index 3ccf2a0208..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_Error.go
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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 apdu
-
-import (
-	"fmt"
-
-	"github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/basetypes"
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/constructeddata"
-	"github.com/apache/plc4x/plc4go/spi/errors"
-)
-
-type Error struct {
-	*ErrorSequence
-}
-
-func NewError(args Args, kwArgs KWArgs) (*Error, error) {
-	e := &Error{}
-	var err error
-	e.ErrorSequence, err = NewErrorSequence(args, kwArgs, WithErrorSequenceExtension(e))
-	if err != nil {
-		return e, errors.Wrap(err, "Error creating new ErrorSequence")
-	}
-	return e, nil
-}
-
-func (e *Error) SetErrorSequence(es *ErrorSequence) {
-	e.ErrorSequence = es
-}
-
-func (e *Error) GetSequenceElements() []Element {
-	errorType, _ := basetypes.NewErrorType(nil) // TODO: check if is meant to be like that
-	return errorType.GetSequenceElements()
-}
-
-func (e *Error) String() string {
-	errorClass, _ := e.GetAttr("errorClass")
-	errorCode, _ := e.GetAttr("errorCode")
-	return fmt.Sprintf("%s:%s", errorClass, errorCode)
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ErrorPDU.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ErrorPDU.go
deleted file mode 100644
index b9a7ca0710..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ErrorPDU.go
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * 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 apdu
-
-import (
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
-	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
-	"github.com/apache/plc4x/plc4go/spi/errors"
-)
-
-type ErrorPDU struct {
-	*___APDU
-
-	bacnetError readWriteModel.BACnetError
-}
-
-var _ readWriteModel.APDUError = (*ErrorPDU)(nil)
-
-func NewErrorPDU(args Args, kwArgs KWArgs, options ...Option) (*ErrorPDU, error) {
-	e := &ErrorPDU{}
-	choice, ok := KWO[*readWriteModel.BACnetConfirmedServiceChoice](kwArgs, KWConfirmedServiceChoice, nil)
-	invokeID, ok := KWO[*uint8](kwArgs, KWInvokedID, nil)
-	context, ok := KWO[APDU](kwArgs, KWContext, nil)
-	if _debug != nil {
-		_debug("__init__ %r %r %r %r %r", choice, invokeID, context, args, kwArgs)
-	}
-	options = AddLeafTypeIfAbundant(options, e)
-	apdu, err := New_APDU(args, kwArgs, options...)
-	if err != nil {
-		return nil, errors.Wrap(err, "error creating _APDU")
-	}
-	e.___APDU = apdu.(*___APDU)
-	e.apduType = new(readWriteModel.ApduType_ERROR_PDU)
-	if ok {
-		serviceChoice := uint8(*choice)
-		e.apduService = &serviceChoice
-	}
-	e.apduInvokeID = invokeID
-
-	// use the context to fill in most of the fields
-	if context != nil {
-		e.apduService = context.getApduService()
-		e.SetContext(context)
-	}
-
-	switch rm := e.GetRootMessage().(type) {
-	case readWriteModel.BACnetError:
-		e.bacnetError = rm
-		serviceChoice := rm.GetErrorChoice()
-		e.apduService = new(uint8(serviceChoice))
-	}
-	e.SetRootMessage(e.buildConfirmedRequest(e.bacnetError))
-
-	return e, nil
-}
-
-func (e *ErrorPDU) buildConfirmedRequest(bacnetError readWriteModel.BACnetError) readWriteModel.APDUError {
-	if bacnetError == nil {
-		return nil
-	}
-	invokeID := uint8(0)
-	if e.apduInvokeID != nil {
-		invokeID = *e.apduInvokeID
-	}
-	return readWriteModel.NewAPDUError(
-		invokeID,
-		e.GetErrorChoice(),
-		e.bacnetError,
-	)
-}
-
-func (e *ErrorPDU) CreateAPDUErrorBuilder() readWriteModel.APDUErrorBuilder {
-	//TODO implement me
-	panic("implement me")
-}
-
-func (e *ErrorPDU) GetSegmentedMessage() bool {
-	return e.apduSeg
-}
-
-func (e *ErrorPDU) GetMoreFollows() bool {
-	return e.apduMor
-}
-
-func (e *ErrorPDU) GetSegmentedResponseAccepted() bool {
-	return e.apduSA
-}
-
-func (e *ErrorPDU) GetMaxSegmentsAccepted() readWriteModel.MaxSegmentsAccepted {
-	if e.apduMaxSegs != nil {
-		return readWriteModel.MaxSegmentsAccepted(*e.apduMaxSegs)
-	}
-	return readWriteModel.MaxSegmentsAccepted_MORE_THAN_64_SEGMENTS
-}
-
-func (e *ErrorPDU) GetMaxApduLengthAccepted() readWriteModel.MaxApduLengthAccepted {
-	if e.apduMaxResp != nil {
-		return readWriteModel.MaxApduLengthAccepted(*e.apduMaxResp)
-	}
-	return readWriteModel.MaxApduLengthAccepted_NUM_OCTETS_1476
-}
-
-func (e *ErrorPDU) GetInvokeId() uint8 {
-	if e.apduInvokeID != nil {
-		return *e.apduInvokeID
-	}
-	return 0
-}
-
-func (e *ErrorPDU) GetSequenceNumber() *uint8 {
-	return e.apduSeq
-}
-
-func (e *ErrorPDU) GetProposedWindowSize() *uint8 {
-	return e.apduWin
-}
-
-func (e *ErrorPDU) GetSegment() []byte {
-	return nil
-}
-
-func (e *ErrorPDU) GetApduHeaderReduction() uint16 {
-	return 0
-}
-
-func (e *ErrorPDU) GetSegmentReduction() uint16 {
-	return 0
-}
-
-func (e *ErrorPDU) GetOriginalInvokeId() uint8 {
-	invokeID := e.apduInvokeID
-	if invokeID != nil {
-		return *invokeID
-	}
-	return 0
-}
-
-func (e *ErrorPDU) GetErrorChoice() readWriteModel.BACnetConfirmedServiceChoice {
-	service := e.apduService
-	if service != nil {
-		return readWriteModel.BACnetConfirmedServiceChoice(*service)
-	}
-	return 0
-}
-
-func (e *ErrorPDU) GetError() readWriteModel.BACnetError {
-	return e.bacnetError
-}
-
-func (e *ErrorPDU) IsAPDUError() {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ErrorSequence.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ErrorSequence.go
deleted file mode 100644
index 15b3d53816..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ErrorSequence.go
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * 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 apdu
-
-import (
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
-	"github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
-	"github.com/apache/plc4x/plc4go/spi/errors"
-)
-
-// ErrorSequenceContract provides a set of functions which can be overwritten by a sub struct
-type ErrorSequenceContract interface {
-	APCISequenceContractRequirement
-	GetErrorChoice() *model.BACnetConfirmedServiceChoice
-}
-
-// ErrorSequenceContractRequirement is needed when one want to extend using SequenceContract
-type ErrorSequenceContractRequirement interface {
-	ErrorSequenceContract
-	// SetErrorSequence callback is needed as we work in the constructor already with the finished object // TODO: maybe we need to return as init again as it might not be finished constructing....
-	SetErrorSequence(es *ErrorSequence)
-}
-
-type ErrorSequence struct {
-	*APCISequence
-	*ErrorPDU
-
-	_contract ErrorSequenceContract
-}
-
-func NewErrorSequence(args Args, kwArgs KWArgs, options ...Option) (*ErrorSequence, error) {
-	e := &ErrorSequence{}
-	ApplyAppliers(options, e)
-	if e._contract == nil {
-		e._contract = e
-	} else {
-		e._contract.(ErrorSequenceContractRequirement).SetErrorSequence(e)
-	}
-	options = AddLeafTypeIfAbundant(options, e)
-	var err error
-	kwArgs[KWConfirmedServiceChoice] = e._contract.GetErrorChoice()
-	e.ErrorPDU, err = NewErrorPDU(args, kwArgs, options...)
-	if err != nil {
-		return nil, errors.Wrap(err, "error creating ErrorPDU")
-	}
-	e.APCISequence, err = NewAPCISequence(args, kwArgs, Combine(options, WithAPCISequenceExtension(e._contract))...)
-	if err != nil {
-		return nil, errors.Wrap(err, "error creating _APCISequence")
-	}
-	// We need to set the APCI to the same objects...
-	e.APCISequence._APCI = e.ErrorPDU._APCI
-	return e, nil
-}
-
-func WithErrorSequenceExtension(contract ErrorSequenceContractRequirement) GenericApplier[*ErrorSequence] {
-	return WrapGenericApplier(func(a *ErrorSequence) { a._contract = contract })
-}
-
-func (u *ErrorSequence) SetAPCISequence(a *APCISequence) {
-	u.APCISequence = a
-}
-
-func (*ErrorSequence) GetErrorChoice() *model.BACnetConfirmedServiceChoice {
-	return nil
-}
-
-func (u *ErrorSequence) DeepCopy() any {
-	panic("implement me")
-}
-
-func (u *ErrorSequence) String() string {
-	return u.APCISequence.String()
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_EventNotificationParameters.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_EventNotificationParameters.go
deleted file mode 100644
index 2273f24fe7..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_EventNotificationParameters.go
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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 apdu
-
-import "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
-
-// TODO: implement it...
-type EventNotificationParameters struct {
-}
-
-func NewEventNotificationParameters(arg comp.Arg) (*EventNotificationParameters, error) {
-	panic("Not implemented")
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetAlarmSummaryACK.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetAlarmSummaryACK.go
deleted file mode 100644
index facd060e9d..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetAlarmSummaryACK.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type GetAlarmSummaryACK struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetAlarmSummaryAlarmSummary.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetAlarmSummaryAlarmSummary.go
deleted file mode 100644
index 842ab2504f..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetAlarmSummaryAlarmSummary.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type GetAlarmSummaryAlarmSummary struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetAlarmSummaryRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetAlarmSummaryRequest.go
deleted file mode 100644
index db17b95250..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetAlarmSummaryRequest.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type GetAlarmSummaryRequest struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetEnrollmentSummaryACK.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetEnrollmentSummaryACK.go
deleted file mode 100644
index b389774566..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetEnrollmentSummaryACK.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type GetEnrollmentSummaryACK struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetEnrollmentSummaryEnrollmentSummary.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetEnrollmentSummaryEnrollmentSummary.go
deleted file mode 100644
index 80f4bf278e..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetEnrollmentSummaryEnrollmentSummary.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type GetEnrollmentSummaryEnrollmentSummary struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetEnrollmentSummaryRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetEnrollmentSummaryRequest.go
deleted file mode 100644
index 98e33a60e7..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetEnrollmentSummaryRequest.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type GetEnrollmentSummaryRequest struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetEnrollmentSummaryRequestAcknowledgmentFilterType.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetEnrollmentSummaryRequestAcknowledgmentFilterType.go
deleted file mode 100644
index 85455094f2..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetEnrollmentSummaryRequestAcknowledgmentFilterType.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type GetEnrollmentSummaryRequestAcknowledgmentFilterType struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetEnrollmentSummaryRequestEventStateFilterType.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetEnrollmentSummaryRequestEventStateFilterType.go
deleted file mode 100644
index 1e962550db..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetEnrollmentSummaryRequestEventStateFilterType.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type GetEnrollmentSummaryRequestEventStateFilterType struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetEnrollmentSummaryRequestPriorityFilterType.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetEnrollmentSummaryRequestPriorityFilterType.go
deleted file mode 100644
index d9ef02de38..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetEnrollmentSummaryRequestPriorityFilterType.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type GetEnrollmentSummaryRequestPriorityFilterType struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetEventInformationACK.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetEventInformationACK.go
deleted file mode 100644
index ef45c1c117..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetEventInformationACK.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type GetEventInformationACK struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetEventInformationEventSummary.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetEventInformationEventSummary.go
deleted file mode 100644
index 84cbef2f44..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetEventInformationEventSummary.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type GetEventInformationEventSummary struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetEventInformationRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetEventInformationRequest.go
deleted file mode 100644
index 88ad86c0fc..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GetEventInformationRequest.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type GetEventInformationRequest struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GroupChannelValue.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GroupChannelValue.go
deleted file mode 100644
index e5b2d7fb1f..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_GroupChannelValue.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type GroupChannelValue struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_IAmRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_IAmRequest.go
deleted file mode 100644
index ecc0e017b6..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_IAmRequest.go
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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 apdu
-
-import (
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/basetypes"
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/constructeddata"
-	. "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/primitivedata"
-	readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
-	"github.com/apache/plc4x/plc4go/spi/errors"
-)
-
-type IAmRequest struct {
-	*UnconfirmedRequestSequence
-
-	serviceChoice    readWriteModel.BACnetUnconfirmedServiceChoice
-	sequenceElements []Element
-}
-
-func NewIAmRequest(args Args, kwArgs KWArgs, options ...Option) (*IAmRequest, error) {
-	w := &IAmRequest{
-		serviceChoice: readWriteModel.BACnetUnconfirmedServiceChoice_WHO_IS,
-		sequenceElements: []Element{
-			NewElement("iAmDeviceIdentifier", Vs2E(NewObjectIdentifier)),
-			NewElement("maxAPDULengthAccepted", V2E(NewUnsigned)),
-			NewElement("segmentationSupported", V2E(NewSegmentation)),
-			NewElement("vendorID", V2E(NewUnsigned)),
-		},
-	}
-	options = AddRootMessageIfAbundant(options, readWriteModel.NewBACnetUnconfirmedServiceRequestIAm(
-		readWriteModel.CreateBACnetApplicationTagObjectIdentifier(0, 0),                                          // TODO: get right values
-		readWriteModel.CreateBACnetApplicationTagUnsignedInteger(0),                                              // TODO: get right values
-		readWriteModel.NewBACnetSegmentationTagged(readWriteModel.CreateBACnetTagHeaderBalanced(false, 0, 0), 0), // TODO: get right values
-		readWriteModel.CreateBACnetVendorIdApplicationTagged(0),                                                  // TODO: get right values
-	))
-	options = AddLeafTypeIfAbundant(options, w)
-	var err error
-	w.UnconfirmedRequestSequence, err = NewUnconfirmedRequestSequence(args, kwArgs, Combine(options, WithUnconfirmedRequestSequenceExtension(w))...)
-	if err != nil {
-		return nil, errors.Wrap(err, "error creating UnconfirmedRequestSequence")
-	}
-
-	return w, nil
-}
-
-func (w *IAmRequest) GetServiceChoice() *readWriteModel.BACnetUnconfirmedServiceChoice {
-	return &w.serviceChoice
-}
-
-func (w *IAmRequest) GetSequenceElements() []Element {
-	return w.sequenceElements
-}
-
-func (w *IAmRequest) SetUnconfirmedRequestSequence(u *UnconfirmedRequestSequence) {
-	w.UnconfirmedRequestSequence = u
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_IHaveRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_IHaveRequest.go
deleted file mode 100644
index f41774a7c9..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_IHaveRequest.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type IHaveRequest struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_LifeSafetyOperationRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_LifeSafetyOperationRequest.go
deleted file mode 100644
index 6d6e32ad25..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_LifeSafetyOperationRequest.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type LifeSafetyOperationRequest struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_Range.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_Range.go
deleted file mode 100644
index 3dcaa0340c..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_Range.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type Range struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_RangeByPosition.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_RangeByPosition.go
deleted file mode 100644
index c786fb7378..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_RangeByPosition.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type RangeByPosition struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_RangeBySequenceNumber.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_RangeBySequenceNumber.go
deleted file mode 100644
index e3e9868375..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_RangeBySequenceNumber.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type RangeBySequenceNumber struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_RangeByTime.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_RangeByTime.go
deleted file mode 100644
index 7e6b9a07a3..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_RangeByTime.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type RangeByTime struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReadAccessResult.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReadAccessResult.go
deleted file mode 100644
index 606c59e4c1..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReadAccessResult.go
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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 apdu
-
-import "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
-
-// TODO: implement it...
-type ReadAccessResult struct {
-}
-
-func NewReadAccessResult(arg comp.Arg) (*ReadAccessResult, error) {
-	panic("implement me")
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReadAccessResultElement.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReadAccessResultElement.go
deleted file mode 100644
index c264861abb..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReadAccessResultElement.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type ReadAccessResultElement struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReadAccessResultElementChoice.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReadAccessResultElementChoice.go
deleted file mode 100644
index 3a7ad1e30e..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReadAccessResultElementChoice.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type ReadAccessResultElementChoice struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReadAccessSpecification.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReadAccessSpecification.go
deleted file mode 100644
index 38078790bc..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReadAccessSpecification.go
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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 apdu
-
-import "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/comp"
-
-// TODO: implement it...
-type ReadAccessSpecification struct {
-}
-
-func NewReadAccessSpecification(arg comp.Arg) (*ReadAccessSpecification, error) {
-	panic("implement me")
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReadPropertyACK.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReadPropertyACK.go
deleted file mode 100644
index 293108b2cf..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReadPropertyACK.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type ReadPropertyACK struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReadPropertyMultipleACK.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReadPropertyMultipleACK.go
deleted file mode 100644
index f68c8f91ef..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReadPropertyMultipleACK.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type ReadPropertyMultipleACK struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReadPropertyMultipleRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReadPropertyMultipleRequest.go
deleted file mode 100644
index c4045a1cbb..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReadPropertyMultipleRequest.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type ReadPropertyMultipleRequest struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReadPropertyRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReadPropertyRequest.go
deleted file mode 100644
index d659f943ab..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReadPropertyRequest.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type ReadPropertyRequest struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReadRangeACK.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReadRangeACK.go
deleted file mode 100644
index 28c17ee89b..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReadRangeACK.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type ReadRangeACK struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReadRangeRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReadRangeRequest.go
deleted file mode 100644
index 6482fe4dd6..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReadRangeRequest.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type ReadRangeRequest struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReinitializeDeviceRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReinitializeDeviceRequest.go
deleted file mode 100644
index 0dd0ef4245..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReinitializeDeviceRequest.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type ReinitializeDeviceRequest struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReinitializeDeviceRequestReinitializedStateOfDevice.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReinitializeDeviceRequestReinitializedStateOfDevice.go
deleted file mode 100644
index a12f3d8032..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_ReinitializeDeviceRequestReinitializedStateOfDevice.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type ReinitializeDeviceRequestReinitializedStateOfDevice struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_RejectPDU.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_RejectPDU.go
deleted file mode 100644
index d826b8aa9c..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_RejectPDU.go
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type RejectPDU struct {
-	*___APDU
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_RejectReason.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_RejectReason.go
deleted file mode 100644
index c65d43c54c..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_RejectReason.go
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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 apdu
-
-import . "github.com/apache/plc4x/plc4go/internal/bacnetip/bacgopes/primitivedata"
-
-// TODO: implement it...
-type RejectReason struct {
-	*Enumerated
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_RemoveListElementRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_RemoveListElementRequest.go
deleted file mode 100644
index 50815a531e..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_RemoveListElementRequest.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type RemoveListElementRequest struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_RequestKeyRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_RequestKeyRequest.go
deleted file mode 100644
index 3a96c2f423..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_RequestKeyRequest.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type RequestKeyRequest struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_SegmentAckPDU.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_SegmentAckPDU.go
deleted file mode 100644
index eb913c61ff..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_SegmentAckPDU.go
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type SegmentAckPDU struct {
-	*___APDU
-}
-
-func (s *SegmentAckPDU) GetServer() any {
-	panic("implement me")
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_SimpleAckPDU.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_SimpleAckPDU.go
deleted file mode 100644
index 6d2e8e87ad..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_SimpleAckPDU.go
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * 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 apdu
-
-import readWriteModel "github.com/apache/plc4x/plc4go/protocols/bacnetip/readwrite/model"
-
-// TODO: implement it...
-type SimpleAckPDU struct {
-	*___APDU
-}
-
-var _ readWriteModel.APDUComplexAck = (*SimpleAckPDU)(nil)
-
-func (s *SimpleAckPDU) CreateAPDUComplexAckBuilder() readWriteModel.APDUComplexAckBuilder {
-	panic("implement me")
-}
-
-func (s *SimpleAckPDU) GetSegmentedMessage() bool {
-	//TODO implement me
-	panic("implement me")
-}
-
-func (s *SimpleAckPDU) GetMoreFollows() bool {
-	//TODO implement me
-	panic("implement me")
-}
-
-func (s *SimpleAckPDU) GetOriginalInvokeId() uint8 {
-	//TODO implement me
-	panic("implement me")
-}
-
-func (s *SimpleAckPDU) GetSequenceNumber() *uint8 {
-	//TODO implement me
-	panic("implement me")
-}
-
-func (s *SimpleAckPDU) GetProposedWindowSize() *uint8 {
-	//TODO implement me
-	panic("implement me")
-}
-
-func (s *SimpleAckPDU) GetServiceAck() readWriteModel.BACnetServiceAck {
-	//TODO implement me
-	panic("implement me")
-}
-
-func (s *SimpleAckPDU) GetSegmentServiceChoice() *readWriteModel.BACnetConfirmedServiceChoice {
-	//TODO implement me
-	panic("implement me")
-}
-
-func (s *SimpleAckPDU) GetSegment() []byte {
-	//TODO implement me
-	panic("implement me")
-}
-
-func (s *SimpleAckPDU) GetApduHeaderReduction() uint16 {
-	//TODO implement me
-	panic("implement me")
-}
-
-func (s *SimpleAckPDU) GetSegmentReduction() uint16 {
-	//TODO implement me
-	panic("implement me")
-}
-
-func (s *SimpleAckPDU) IsAPDUComplexAck() {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_SubscribeCOVPropertyRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_SubscribeCOVPropertyRequest.go
deleted file mode 100644
index 50c1877490..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_SubscribeCOVPropertyRequest.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type SubscribeCOVPropertyRequest struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_SubscribeCOVRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_SubscribeCOVRequest.go
deleted file mode 100644
index de8e12e947..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_SubscribeCOVRequest.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type SubscribeCOVRequest struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_TimeSynchronizationRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_TimeSynchronizationRequest.go
deleted file mode 100644
index 741f500cb9..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_TimeSynchronizationRequest.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type TimeSynchronizationRequest struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_UTCTimeSynchronizationRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_UTCTimeSynchronizationRequest.go
deleted file mode 100644
index 68f60c476f..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_UTCTimeSynchronizationRequest.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type UTCTimeSynchronizationRequest struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_UnconfirmedCOVNotificationRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_UnconfirmedCOVNotificationRequest.go
deleted file mode 100644
index a26c3eee52..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_UnconfirmedCOVNotificationRequest.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type UnconfirmedCOVNotificationRequest struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_UnconfirmedEventNotificationRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_UnconfirmedEventNotificationRequest.go
deleted file mode 100644
index f2893188b3..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_UnconfirmedEventNotificationRequest.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 apdu
-
-// TODO: implement it...
-type UnconfirmedEventNotificationRequest struct {
-}
diff --git a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_UnconfirmedPrivateTransferRequest.go b/plc4go/internal/bacnetip/bacgopes/apdu/apdu_UnconfirmedPrivateTransferRequest.go
deleted file mode 100644
index ab6bc48f25..0000000000
--- a/plc4go/internal/bacnetip/bacgopes/apdu/apdu_UnconfirmedPrivateTransferRequest.go
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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
- *
... 121652 lines suppressed ...