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 ©
+ }
+ 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 ...