This is an automated email from the ASF dual-hosted git repository. cdutz pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/plc4x.git
commit 86d833b1b5e016ce8640c7da3dec8e82517c3979 Author: Christofer Dutz <[email protected]> AuthorDate: Tue Sep 24 10:02:26 2019 +0200 - Continued working on the BACnet driver --- .../resources/protocols/bacnetip/bacnetip.mspec | 397 ++++++++++++++++++--- sandbox/test-java-bacnetip-driver/pom.xml | 13 +- .../plc4x/java/bacnetip/PassiveBacNetIpDriver.java | 75 ++++ .../bacnetip/connection/BacNetIpFieldHandler.java | 36 ++ .../connection/PassiveBacNetIpPlcConnection.java | 115 ++++++ .../plc4x/java/bacnetip/model/BacNetIpField.java | 47 +++ .../java/bacnetip/protocol/BacNetIpProtocol.java | 62 ++++ .../java/bacnetip/protocol/HelloWorldProtocol.java | 61 ++++ .../services/org.apache.plc4x.java.spi.PlcDriver | 19 + .../plc4x/java/bacnetip/ManualBacNetDecoder.java | 35 ++ .../java/bacnetip/PassiveBacNetIpDriverManual.java | 39 ++ 11 files changed, 856 insertions(+), 43 deletions(-) diff --git a/protocols/bacnetip/src/main/resources/protocols/bacnetip/bacnetip.mspec b/protocols/bacnetip/src/main/resources/protocols/bacnetip/bacnetip.mspec index 8f517af..6e99211 100644 --- a/protocols/bacnetip/src/main/resources/protocols/bacnetip/bacnetip.mspec +++ b/protocols/bacnetip/src/main/resources/protocols/bacnetip/bacnetip.mspec @@ -30,7 +30,10 @@ ] ['0x03' BVLCReadBroadcastDistributionTableAck ] - ['0x04' BVLCForwardedNPDU + ['0x04' BVLCForwardedNPDU [uint 16 'bvlcLength'] + [array uint 8 'ip' count '4'] + [simple uint 16 'port'] + [simple NPDU 'npdu' ['bvlcLength - 10']] ] ['0x05' BVLCRegisterForeignDevice ] @@ -42,38 +45,51 @@ ] ['0x09' BVLCDistributeBroadcastToNetwork ] - ['0x0A' BVLCOriginalUnicastNPDU + ['0x0A' BVLCOriginalUnicastNPDU [uint 16 'bvlcLength'] + [simple NPDU 'npdu' ['bvlcLength - 4']] ] - ['0x0B' BVLCOriginalBroadcastNPDU + ['0x0B' BVLCOriginalBroadcastNPDU [uint 16 'bvlcLength'] + [simple NPDU 'npdu' ['bvlcLength - 4']] ] ['0x0C' BVLCSecureBVLL ] ] ] -[type 'NPDU' - [simple uint 8 'protocolVersionNumber'] - [simple bit 'messageTypeFieldPresent'] - [reserved uint 1 '0'] - [simple bit 'destinationSpecified'] - [reserved uint 1 '0'] - [simple bit 'sourceSpecified'] - [reserved uint 1 '0'] - [simple bit 'expectingReply'] - [simple uint 2 'networkPriority'] - [optional uint 16 'destinationNetworkAddress' 'destinationSpecified'] - [optional uint 8 'destinationLength' 'destinationSpecified'] - [optional Address 'destinationAddress' 'destinationSpecified && (destinationLength > 0)'] - [optional uint 16 'sourceNetworkAddress' 'sourceSpecified'] - [optional uint 8 'sourceLength' 'sourceSpecified'] - [optional Address 'sourceAddress' 'sourceSpecified && (sourceLength > 0)'] - [optional uint 8 'hopCount' 'destinationSpecified || sourceSpecified'] - [optional uint 8 'messageType' 'messageTypeFieldPresent'] - [optional uint 16 'vendorId' 'messageTypeFieldPresent'] - [simple APDU 'apdu'] +[type 'NPDU' [uint 16 'npduLength'] + [simple uint 8 'protocolVersionNumber'] + [simple bit 'messageTypeFieldPresent'] + [reserved uint 1 '0'] + [simple bit 'destinationSpecified'] + [reserved uint 1 '0'] + [simple bit 'sourceSpecified'] + [simple bit 'expectingReply'] + [simple uint 2 'networkPriority'] + [optional uint 16 'destinationNetworkAddress' 'destinationSpecified'] + [optional uint 8 'destinationLength' 'destinationSpecified'] + [array uint 8 'destinationAddress' count 'destinationSpecified ? destinationLength : 0'] + [optional uint 16 'sourceNetworkAddress' 'sourceSpecified'] + [optional uint 8 'sourceLength' 'sourceSpecified'] + [array uint 8 'sourceAddress' count 'sourceSpecified ? sourceLength : 0'] + [optional uint 8 'hopCount' 'destinationSpecified'] + [optional NLM 'nlm' 'messageTypeFieldPresent' ['npduLength - (2 + (sourceSpecified ? 3 + sourceLength : 0) + (destinationSpecified ? 3 + destinationLength: 0) + ((destinationSpecified || sourceSpecified) ? 1 : 0))']] + [optional APDU 'apdu' '!messageTypeFieldPresent' ['npduLength - (2 + (sourceSpecified ? 3 + sourceLength : 0) + (destinationSpecified ? 3 + destinationLength: 0) + ((destinationSpecified || sourceSpecified) ? 1 : 0))']] ] -[discriminatedType 'APDU' +[discriminatedType 'NLM' [uint 16 'apduLength'] + [discriminator uint 8 'messageType'] + [optional uint 16 'vendorId' '(messageType >= 128) && (messageType <= 255)'] + [typeSwitch 'messageType' + ['0x0' NLMWhoIsRouterToNetwork [uint 8 'messageType'] + [array uint 16 'destinationNetworkAddress' length 'apduLength - (((messageType >= 128) && (messageType <= 255)) ? 3 : 1)'] + ] + ['0x1' NLMIAmRouterToNetwork [uint 8 'messageType'] + [array uint 16 'destinationNetworkAddress' length 'apduLength - (((messageType >= 128) && (messageType <= 255)) ? 3 : 1)'] + ] + ] +] + +[discriminatedType 'APDU' [uint 16 'apduLength'] [discriminator uint 4 'apduType'] [typeSwitch 'apduType' ['0x0' APDUConfirmedRequest @@ -83,15 +99,14 @@ [reserved uint 2 '0'] [simple uint 3 'maxSegmentsAccepted'] [simple uint 4 'maxApduLengthAccepted'] - [simple uint 6 'invokeId'] + [simple uint 8 'invokeId'] [optional uint 8 'sequenceNumber' 'segmentedMessage'] [optional uint 8 'proposedWindowSize' 'segmentedMessage'] - [simple BACnetConfirmedServiceRequest 'serviceRequest'] + [simple BACnetConfirmedServiceRequest 'serviceRequest' ['apduLength - (3 + (segmentedMessage ? 2 : 0))']] ] ['0x1' APDUUnconfirmedRequest [reserved uint 4 '0'] - [simple uint 8 'serviceChoice'] - [simple BACnetUnconfirmedServiceRequest 'serviceRequest'] + [simple BACnetUnconfirmedServiceRequest 'serviceRequest' ['apduLength - 1']] ] ['0x2' APDUSimpleAck [reserved uint 4 '0'] @@ -105,7 +120,6 @@ [simple uint 8 'originalInvokeId'] [optional uint 8 'sequenceNumber' 'segmentedMessage'] [optional uint 8 'proposedWindowSize' 'segmentedMessage'] - [simple uint 8 'serviceChoice'] [simple BACnetServiceAck 'serviceAck'] ] ['0x4' APDUSegmentAck @@ -119,7 +133,6 @@ ['0x5' APDUError [reserved uint 4 '0x00'] [simple uint 8 'originalInvokeId'] - [simple uint 8 'errorChoice'] [simple BACnetError 'error'] ] ['0x6' APDUReject @@ -136,17 +149,26 @@ ] ] -[discriminatedType 'BACnetConfirmedServiceRequest' +[discriminatedType 'BACnetConfirmedServiceRequest' [uint 16 'len'] [discriminator uint 8 'serviceChoice'] [typeSwitch 'serviceChoice' ['0x00' BACnetConfirmedServiceRequestAcknowledgeAlarm ] ['0x01' BACnetConfirmedServiceRequestConfirmedCOVNotification - subscriber-process-identifier (Unsigned32) - initiating-device-identifier (BACnetObjectIdentifier) - monitored-object-identifier (BACnetObjectIdentifier) - time-remaining (Unsigned) - list-of-values (SEQUENCE OF BACnetPropertyValue) + [const uint 8 'subscriberProcessIdentifierHeader' '0x09'] + [simple uint 8 'subscriberProcessIdentifier'] + [const uint 8 'monitoredObjectIdentifierHeader' '0x1C'] + [simple uint 10 'monitoredObjectType'] + [simple uint 22 'monitoredObjectInstanceNumber'] + [const uint 8 'issueConfirmedNotificationsHeader' '0x2C'] + [simple uint 10 'issueConfirmedNotificationsType'] + [simple uint 22 'issueConfirmedNotificationsInstanceNumber'] + [const uint 5 'lifetimeHeader' '0x07'] + [simple uint 3 'lifetimeLength'] + [array int 8 'lifetimeSeconds' count 'lifetimeLength'] + [const uint 8 'listOfValuesOpeningTag' '0x4E'] + [array BACnetTagWithContent 'notifications' length 'len - 18'] + [const uint 8 'listOfValuesClosingTag' '0x4F'] ] ['0x1F' BACnetConfirmedServiceRequestConfirmedCOVNotificationMultiple ] @@ -160,10 +182,21 @@ ['0x1B' BACnetConfirmedServiceRequestLifeSafetyOperation ] ['0x05' BACnetConfirmedServiceRequestSubscribeCOV + [const uint 8 'subscriberProcessIdentifierHeader' '0x09'] + [simple uint 8 'subscriberProcessIdentifier'] + [const uint 8 'monitoredObjectIdentifierHeader' '0x1C'] + [simple uint 10 'monitoredObjectType'] + [simple uint 22 'monitoredObjectInstanceNumber'] + [const uint 8 'issueConfirmedNotificationsHeader' '0x29'] + [const uint 7 'issueConfirmedNotificationsSkipBits' '0x00'] + [simple bit 'issueConfirmedNotifications'] + [const uint 5 'lifetimeHeader' '0x07'] + [simple uint 3 'lifetimeLength'] + [array int 8 'lifetimeSeconds' count 'lifetimeLength'] ] - ['0x0C' BACnetConfirmedServiceRequestSubscribeCOVProperty + ['0x1C' BACnetConfirmedServiceRequestSubscribeCOVProperty ] - ['0x0E' BACnetConfirmedServiceRequestSubscribeCOVPropertyMultiple + ['0x1E' BACnetConfirmedServiceRequestSubscribeCOVPropertyMultiple ] ['0x06' BACnetConfirmedServiceRequestAtomicReadFile @@ -180,12 +213,28 @@ ['0x0B' BACnetConfirmedServiceRequestDeleteObject ] ['0x0C' BACnetConfirmedServiceRequestReadProperty + [const uint 8 'objectIdentifierHeader' '0x0C'] + [simple uint 10 'objectType'] + [simple uint 22 'objectInstanceNumber'] + [const uint 5 'propertyIdentifierHeader' '0x03'] + [simple uint 3 'propertyIdentifierLength'] + [array int 8 'propertyIdentifier' count 'propertyIdentifierLength'] ] ['0x0E' BACnetConfirmedServiceRequestReadPropertyMultiple ] ['0x1A' BACnetConfirmedServiceRequestReadRange ] ['0x0F' BACnetConfirmedServiceRequestWriteProperty + [const uint 8 'objectIdentifierHeader' '0x0C'] + [simple uint 10 'objectType'] + [simple uint 22 'objectInstanceNumber'] + [const uint 5 'propertyIdentifierHeader' '0x03'] + [simple uint 3 'propertyIdentifierLength'] + [array int 8 'propertyIdentifier' count 'propertyIdentifierLength'] + [const uint 8 'openingTag' '0x3E'] + [simple BACnetTag 'val'] + [const uint 8 'closingTag' '0x3F'] + [optional BACnetTag 'priority' 'curPos < (len - 1)'] ] ['0x10' BACnetConfirmedServiceRequestWritePropertyMultiple ] @@ -218,6 +267,7 @@ ['0x1B' BACnetConfirmedServiceRequestLifeSafetyOperation ] ['0x1C' BACnetConfirmedServiceRequestSubscribeCOVProperty + ] ['0x1D' BACnetConfirmedServiceRequestGetEventInformation ] @@ -229,10 +279,20 @@ ] ] -[discriminatedType 'BACnetUnconfirmedServiceRequest' +[discriminatedType 'BACnetUnconfirmedServiceRequest' [uint 16 'len'] [discriminator uint 8 'serviceChoice'] [typeSwitch 'serviceChoice' ['0x00' BACnetUnconfirmedServiceRequestIAm + [const uint 8 'objectIdentifierHeader' '0xC4'] + [simple uint 10 'objectType'] + [simple uint 22 'objectInstanceNumber'] + [const uint 5 'maximumApduLengthAcceptedHeader' '0x04'] + [simple uint 3 'maximumApduLengthAcceptedLength'] + [array int 8 'maximumApduLengthAccepted' count 'maximumApduLengthAcceptedLength'] + [const uint 8 'segmentationSupportedHeader' '0x91'] + [simple uint 8 'segmentationSupported'] + [const uint 8 'vendorIdHeader' '0x21'] + [simple uint 8 'vendorId'] ] ['0x01' BACnetUnconfirmedServiceRequestIHave ] @@ -241,14 +301,35 @@ ['0x03' BACnetUnconfirmedServiceRequestUnconfirmedEventNotification ] ['0x04' BACnetUnconfirmedServiceRequestUnconfirmedPrivateTransfer + [const uint 8 'vendorIdHeader' '0x09'] + [simple uint 8 'vendorId'] + [const uint 8 'serviceNumberHeader' '0x1A'] + [simple uint 16 'serviceNumber'] + [const uint 8 'listOfValuesOpeningTag' '0x2E'] + [array int 8 'values' length 'len - 8'] + [const uint 8 'listOfValuesClosingTag' '0x2F'] ] ['0x05' BACnetUnconfirmedServiceRequestUnconfirmedTextMessage ] ['0x06' BACnetUnconfirmedServiceRequestTimeSynchronization ] ['0x07' BACnetUnconfirmedServiceRequestWhoHas + [const uint 8 'deviceInstanceLowLimitHeader' '0x0B'] + [simple uint 24 'deviceInstanceLowLimit'] + [const uint 8 'deviceInstanceHighLimitHeader' '0x1B'] + [simple uint 24 'deviceInstanceHighLimit'] + [const uint 8 'objectNameHeader' '0x3D'] + [implicit uint 8 'objectNameLength' 'COUNT(objectName) + 1'] + [simple uint 8 'objectNameCharacterSet'] + [array int 8 'objectName' length 'objectNameLength - 1'] ] ['0x08' BACnetUnconfirmedServiceRequestWhoIs + [const uint 5 'deviceInstanceRangeLowLimitHeader' '0x01'] + [simple uint 3 'deviceInstanceRangeLowLimitLength'] + [array int 8 'deviceInstanceRangeLowLimit' count 'deviceInstanceRangeLowLimitLength'] + [const uint 5 'deviceInstanceRangeHighLimitHeader' '0x03'] + [simple uint 3 'deviceInstanceRangeHighLimitLength'] + [array int 8 'deviceInstanceRangeHighLimit' count 'deviceInstanceRangeHighLimitLength'] ] ['0x09' BACnetUnconfirmedServiceRequestUTCTimeSynchronization ] @@ -259,7 +340,65 @@ ] ] -[type 'BACnetServiceAck' +[discriminatedType 'BACnetServiceAck' + [discriminator uint 8 'serviceChoice'] + [typeSwitch 'serviceChoice' + ['0x03' BACnetServiceAckGetAlarmSummary + + ] + ['0x04' BACnetServiceAckGetEnrollmentSummary + + ] + ['0x1D' BACnetServiceAckGetEventInformation + + ] + + ['0x06' BACnetServiceAckAtomicReadFile + + ] + ['0x07' BACnetServiceAckAtomicWriteFile + + ] + + ['0x0A' BACnetServiceAckCreateObject + + ] + ['0x0C' BACnetServiceAckReadProperty + [const uint 8 'objectIdentifierHeader' '0x0C'] + [simple uint 10 'objectType'] + [simple uint 22 'objectInstanceNumber'] + [const uint 5 'propertyIdentifierHeader' '0x03'] + [simple uint 3 'propertyIdentifierLength'] + [array int 8 'propertyIdentifier' count 'propertyIdentifierLength'] + [const uint 8 'openingTag' '0x3E'] + [simple BACnetTag 'val'] + [const uint 8 'closingTag' '0x3F'] + ] + ['0x0E' BACnetServiceAckReadPropertyMultiple + + ] + ['0x1A' BACnetServiceAckReadRange + + ] + + ['0x12' BACnetServiceAckConfirmedPrivateTransfer + + ] + + ['0x15' BACnetServiceAckVTOpen + + ] + ['0x17' BACnetServiceAckVTData + + ] + + ['0x18' BACnetServiceAckRemovedAuthenticate + + ] + ['0x0D' BACnetServiceAckRemovedReadPropertyConditional + + ] + ] ] [discriminatedType 'BACnetConfirmedServiceACK' @@ -319,6 +458,12 @@ ['0x0A' BACnetErrorCreateObject ] ['0x0C' BACnetErrorReadProperty + [const uint 5 'errorClassHeader' '0x12'] + [simple uint 3 'errorClassLength'] + [array int 8 'errorClass' count 'errorClassLength'] + [const uint 5 'errorCodeHeader' '0x12'] + [simple uint 3 'errorCodeLength'] + [array int 8 'errorCode' count 'errorCodeLength'] ] ['0x0E' BACnetErrorReadPropertyMultiple ] @@ -340,11 +485,67 @@ ] ] -[type 'Address' - [array uint 8 'address' count '4'] +[type 'BACnetAddress' + [array uint 8 'address' count '4'] [simple uint 16 'port'] ] +[type 'BACnetTagWithContent' + [simple uint 4 'typeOrTagNumber'] + [simple uint 1 'contextSpecificTag'] + [simple uint 3 'lengthValueType'] + [optional uint 8 'extTagNumber' 'typeOrTagNumber == 15'] + [optional uint 8 'extLength' 'lengthValueType == 5'] + [array uint 8 'propertyIdentifier' length '(lengthValueType == 5) ? extLength : lengthValueType'] + [const uint 8 'openTag' '0x2e'] + [simple BACnetTag 'val'] + [const uint 8 'closingTag' '0x2f'] +] + +[discriminatedType 'BACnetTag' + [simple uint 4 'typeOrTagNumber'] + [discriminator uint 1 'contextSpecificTag'] + [simple uint 3 'lengthValueType'] + [optional uint 8 'extTagNumber' 'typeOrTagNumber == 15'] + [optional uint 8 'extLength' 'lengthValueType == 5'] + [typeSwitch 'contextSpecificTag','typeOrTagNumber' + ['0','0x0' BACnetTagApplicationNull + ] + ['0','0x1' BACnetTagApplicationBoolean + ] + ['0','0x2' BACnetTagApplicationUnsignedInteger [uint 3 'lengthValueType', uint 8 'extLength'] + [array uint 8 'data' length '(lengthValueType == 5) ? extLength : lengthValueType'] + ] + ['0','0x3' BACnetTagApplicationSignedInteger [uint 3 'lengthValueType', uint 8 'extLength'] + [array uint 8 'data' length '(lengthValueType == 5) ? extLength : lengthValueType'] + ] + ['0','0x4' BACnetTagApplicationReal [uint 3 'lengthValueType', uint 8 'extLength'] + [array uint 8 'data' length '(lengthValueType == 5) ? extLength : lengthValueType'] + ] + ['0','0x5' BACnetTagApplicationDouble + ] + ['0','0x6' BACnetTagApplicationOctetString + ] + ['0','0x7' BACnetTagApplicationCharacterString + ] + ['0','0x8' BACnetTagApplicationBitString [uint 3 'lengthValueType', uint 8 'extLength'] + [array uint 8 'data' length '(lengthValueType == 5) ? extLength : lengthValueType'] + ] + ['0','0x9' BACnetTagApplicationEnumerated [uint 3 'lengthValueType', uint 8 'extLength'] + [array uint 8 'data' length '(lengthValueType == 5) ? extLength : lengthValueType'] + ] + ['0','0xA' BACnetTagApplicationDate + ] + ['0','0xB' BACnetTagApplicationTime + ] + ['0','0xC' BACnetTagApplicationObjectIdentifier + ] + ['1' BACnetTagContext [uint 4 'typeOrTagNumber', uint 8 'extTagNumber', uint 3 'lengthValueType', uint 8 'extLength'] + [array uint 8 'data' length '(lengthValueType == 5) ? extLength : lengthValueType'] + ] + ] +] + [enum uint 4 'ApplicationTags' ['0x0' NULL] ['0x1' BOOLEAN] @@ -360,3 +561,115 @@ ['0xB' TIME] ['0xC' BACNET_OBJECT_IDENTIFIER] ] + +[enum uint 4 'BACnetNetworkType' + ['0x0' ETHERNET] + ['0x1' ARCNET] + ['0x2' MSTP] + ['0x3' PTP] + ['0x4' LONTALK] + ['0x5' IPV4] + ['0x6' ZIGBEE] + ['0x7' VIRTUAL] + ['0x8' REMOVED_NON_BACNET] + ['0x9' IPV6] + ['0xA' SERIAL] +] + +[enum uint 8 'BACnetNodeType' + ['0x00' UNKNOWN] + ['0x01' SYSTEM] + ['0x02' NETWORK] + ['0x03' DEVICE] + ['0x04' ORGANIZATIONAL] + ['0x05' AREA] + ['0x06' EQUIPMENT] + ['0x07' POINT] + ['0x08' COLLECTION] + ['0x09' PROPERTY] + ['0x0A' FUNCTIONAL] + ['0x0B' OTHER] + ['0x0C' SUBSYSTEM] + ['0x0D' BUILDING] + ['0x0E' FLOOR] + ['0x0F' SECTION] + ['0x10' MODULE] + ['0x11' TREE] + ['0x12' MEMBER] + ['0x13' PROTOCOL] + ['0x14' ROOM] + ['0x15' ZONE] +] + +[enum uint 4 'BACnetNotifyType' + ['0x0' ALARM] + ['0x1' EVENT] + ['0x2' ACK_NOTIFICATION] +] + +[enum uint 10 'BACnetObjectType' + ['0x000' ANALOG_INPUT] + ['0x001' ANALOG_OUTPUT] + ['0x002' ANALOG_VALUE] + + ['0x003' BINARY_INPUT] + ['0x004' BINARY_OUTPUT] + ['0x005' BINARY_VALUE] + + ['0x00D' MULTISTATE_INPUT] + ['0x00E' MULTISTATE_OUTPUT] + ['0x013' MULTISTATE_VALUE] + + ['0x011' SCHEDULE] + + ['0x008' DEVICE] + + ['0x006' CALENDAR] + ['0x007' COMMAND] + ['0x009' EVENT_ENROLLMENT] + ['0x00A' FILE] + ['0x00B' GROUP] + ['0x00C' LOOP] + ['0x00F' NOTIFICATION_CLASS] + ['0x010' PROGRAM] + ['0x012' AVERAGING] + ['0x014' TREND_LOG] + ['0x015' LIFE_SAFETY_POINT] + ['0x016' LIFE_SAFETY_ZONE] + ['0x017' ACCUMULATOR] + ['0x018' PULSE_CONVERTER] + ['0x019' EVENT_LOG] + ['0x01A' GLOBAL_GROUP] + ['0x01B' TREND_LOG_MULTIPLE] + ['0x01C' LOAD_CONTROL] + ['0x01D' STRUCTURED_VIEW] + ['0x01E' ACCESS_DOOR] + ['0x01F' TIMER] + ['0x020' ACCESS_CREDENTIAL] + ['0x021' ACCESS_POINT] + ['0x022' ACCESS_RIGHTS] + ['0x023' ACCESS_USER] + ['0x024' ACCESS_ZONE] + ['0x025' CREDENTIAL_DATA_INPUT] + ['0x026' NETWORK_SECURITY] + ['0x027' BITSTRING_VALUE] + ['0x028' CHARACTERSTRING_VALUE] + ['0x029' DATEPATTERN_VALUE] + ['0x02A' DATE_VALUE] + ['0x02B' DATETIMEPATTERN_VALUE] + ['0x02C' DATETIME_VALUE] + ['0x02D' INTEGER_VALUE] + ['0x02E' LARGE_ANALOG_VALUE] + ['0x02F' OCTETSTRING_VALUE] + ['0x030' POSITIVE_INTEGER_VALUE] + ['0x031' TIMEPATTERN_VALUE] + ['0x032' TIME_VALUE] + ['0x033' NOTIFICATION_FORWARDER] + ['0x034' ALERT_ENROLLMENT] + ['0x035' CHANNEL] + ['0x036' LIGHTING_OUTPUT] + ['0x037' BINARY_LIGHTING_OUTPUT] + ['0x038' NETWORK_PORT] + ['0x039' ELEVATOR_GROUP] + ['0x03A' ESCALATOR] +] diff --git a/sandbox/test-java-bacnetip-driver/pom.xml b/sandbox/test-java-bacnetip-driver/pom.xml index 0b8a904..793ac24 100644 --- a/sandbox/test-java-bacnetip-driver/pom.xml +++ b/sandbox/test-java-bacnetip-driver/pom.xml @@ -74,7 +74,7 @@ </dependency> <dependency> <groupId>org.apache.plc4x</groupId> - <artifactId>plc4j-protocol-driver-base-tcp</artifactId> + <artifactId>plc4j-protocol-driver-base-raw-socket</artifactId> <version>0.5.0-SNAPSHOT</version> </dependency> <dependency> @@ -88,6 +88,17 @@ <version>0.5.0-SNAPSHOT</version> <scope>test</scope> </dependency> + <dependency> + <groupId>org.apache.plc4x</groupId> + <artifactId>plc4j-protocol-driver-base-pcap-socket</artifactId> + <version>0.5.0-SNAPSHOT</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-classic</artifactId> + <scope>test</scope> + </dependency> <dependency> <groupId>org.apache.plc4x</groupId> diff --git a/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/PassiveBacNetIpDriver.java b/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/PassiveBacNetIpDriver.java new file mode 100644 index 0000000..48916f8 --- /dev/null +++ b/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/PassiveBacNetIpDriver.java @@ -0,0 +1,75 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ +package org.apache.plc4x.java.bacnetip; + +import org.apache.plc4x.java.api.PlcConnection; +import org.apache.plc4x.java.api.authentication.PlcAuthentication; +import org.apache.plc4x.java.api.exceptions.PlcConnectionException; +import org.apache.plc4x.java.bacnetip.connection.PassiveBacNetIpPlcConnection; +import org.apache.plc4x.java.spi.PlcDriver; +import org.apache.plc4x.java.utils.rawsockets.netty.RawSocketIpAddress; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static org.apache.plc4x.java.utils.rawsockets.netty.RawSocketAddress.ALL_PROTOCOLS; + +public class PassiveBacNetIpDriver implements PlcDriver { + + public static final int BACNET_IP_PORT = 47808; + + private static final Pattern PASSIVE_BACNET_IP_URI_PATTERN = + Pattern.compile("^bachnet-ip-passive://(?<networkDevice>.*)(?<params>\\?.*)?"); + + @Override + public String getProtocolCode() { + return "bacnet-ip"; + } + + @Override + public String getProtocolName() { + return "BACnet/IP"; + } + + @Override + public PlcConnection connect(String url) throws PlcConnectionException { + Matcher matcher = PASSIVE_BACNET_IP_URI_PATTERN.matcher(url); + if (!matcher.matches()) { + throw new PlcConnectionException( + "Connection url doesn't match the format 'bacnet-ip://{host|ip}'"); + } + String networkDevice = matcher.group("networkDevice"); + + String params = matcher.group("params") != null ? matcher.group("params").substring(1) : null; + + try { + RawSocketIpAddress rawSocketAddress = new RawSocketIpAddress( + networkDevice, ALL_PROTOCOLS, null, BACNET_IP_PORT); + return new PassiveBacNetIpPlcConnection(rawSocketAddress, params); + } catch (Exception e) { + throw new PlcConnectionException("Error connecting to host", e); + } + } + + @Override + public PlcConnection connect(String url, PlcAuthentication authentication) throws PlcConnectionException { + throw new PlcConnectionException("BACnet/IP connections don't support authentication."); + } + +} diff --git a/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/connection/BacNetIpFieldHandler.java b/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/connection/BacNetIpFieldHandler.java new file mode 100644 index 0000000..d7f354d --- /dev/null +++ b/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/connection/BacNetIpFieldHandler.java @@ -0,0 +1,36 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ +package org.apache.plc4x.java.bacnetip.connection; + +import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException; +import org.apache.plc4x.java.api.model.PlcField; +import org.apache.plc4x.java.bacnetip.model.BacNetIpField; +import org.apache.plc4x.java.base.connection.DefaultPlcFieldHandler; + +public class BacNetIpFieldHandler extends DefaultPlcFieldHandler { + + @Override + public PlcField createField(String fieldQuery) throws PlcInvalidFieldException { + if (BacNetIpField.matches(fieldQuery)) { + return BacNetIpField.of(fieldQuery); + } + throw new PlcInvalidFieldException(fieldQuery); + } + +} diff --git a/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/connection/PassiveBacNetIpPlcConnection.java b/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/connection/PassiveBacNetIpPlcConnection.java new file mode 100644 index 0000000..c15bac4 --- /dev/null +++ b/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/connection/PassiveBacNetIpPlcConnection.java @@ -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 + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ +package org.apache.plc4x.java.bacnetip.connection; + +import io.netty.channel.*; +import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException; +import org.apache.plc4x.java.api.messages.PlcReadRequest; +import org.apache.plc4x.java.api.messages.PlcReadResponse; +import org.apache.plc4x.java.api.model.PlcField; +import org.apache.plc4x.java.bacnetip.model.BacNetIpField; +import org.apache.plc4x.java.bacnetip.protocol.BacNetIpProtocol; +import org.apache.plc4x.java.bacnetip.protocol.HelloWorldProtocol; +import org.apache.plc4x.java.base.connection.ChannelFactory; +import org.apache.plc4x.java.base.connection.NettyPlcConnection; +import org.apache.plc4x.java.base.connection.RawSocketChannelFactory; +import org.apache.plc4x.java.base.events.ConnectEvent; +import org.apache.plc4x.java.base.events.ConnectedEvent; +import org.apache.plc4x.java.base.messages.*; +import org.apache.plc4x.java.utils.rawsockets.netty.RawSocketAddress; +import org.apache.plc4x.java.utils.rawsockets.netty.RawSocketIpAddress; +import org.apache.plc4x.java.utils.rawsockets.netty.UdpIpPacketHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.CompletableFuture; + +public class PassiveBacNetIpPlcConnection extends NettyPlcConnection implements PlcReader { + + private static final Logger logger = LoggerFactory.getLogger(PassiveBacNetIpPlcConnection.class); + + public PassiveBacNetIpPlcConnection(RawSocketIpAddress address, String params) { + this(new RawSocketChannelFactory(address.getDeviceName(), null, + address.getPort(), RawSocketAddress.ALL_PROTOCOLS, new UdpIpPacketHandler()), params); + } + + public PassiveBacNetIpPlcConnection(ChannelFactory channelFactory, String params) { + super(channelFactory, true); + } + + @Override + protected void sendChannelCreatedEvent() { + // Send an event to the pipeline telling the Protocol filters what's going on. + channel.pipeline().fireUserEventTriggered(new ConnectEvent()); + } + + @Override + public PlcField prepareField(String fieldQuery) throws PlcInvalidFieldException { + return BacNetIpField.of(fieldQuery); + } + + @Override + protected ChannelHandler getChannelHandler(CompletableFuture<Void> sessionSetupCompleteFuture) { + return new ChannelInitializer() { + @Override + protected void initChannel(Channel channel) { + // Build the protocol stack for communicating with the s7 protocol. + ChannelPipeline pipeline = channel.pipeline(); + pipeline.addLast(new ChannelInboundHandlerAdapter() { + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { + if (evt instanceof ConnectedEvent) { + sessionSetupCompleteFuture.complete(null); + } else { + super.userEventTriggered(ctx, evt); + } + } + }); + pipeline.addLast(new BacNetIpProtocol()); + pipeline.addLast(new HelloWorldProtocol()); + } + }; + } + + @Override + public boolean canRead() { + return true; + } + + @Override + public PlcReadRequest.Builder readRequestBuilder() { + return new DefaultPlcReadRequest.Builder(this, new BacNetIpFieldHandler()); + } + + @Override + public CompletableFuture<PlcReadResponse> read(PlcReadRequest readRequest) { + InternalPlcReadRequest internalReadRequest = checkInternal(readRequest, InternalPlcReadRequest.class); + CompletableFuture<InternalPlcReadResponse> future = new CompletableFuture<>(); + PlcRequestContainer<InternalPlcReadRequest, InternalPlcReadResponse> container = + new PlcRequestContainer<>(internalReadRequest, future); + channel.writeAndFlush(container).addListener(f -> { + if (!f.isSuccess()) { + future.completeExceptionally(f.cause()); + } + }); + return future + .thenApply(PlcReadResponse.class::cast); + } + +} diff --git a/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/model/BacNetIpField.java b/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/model/BacNetIpField.java new file mode 100644 index 0000000..49f51ea --- /dev/null +++ b/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/model/BacNetIpField.java @@ -0,0 +1,47 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ +package org.apache.plc4x.java.bacnetip.model; + +import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException; +import org.apache.plc4x.java.api.model.PlcField; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class BacNetIpField implements PlcField { + + private static final Pattern ADDRESS_PATTERN = + Pattern.compile("^N(?<fileNumber>\\d{1,7}):(?<elementNumber>\\d{1,7})(/(?<bitNumber>\\d{1,7}))?:(?<dataType>[a-zA-Z_]+)(\\[(?<size>\\d+)])?"); + + public BacNetIpField() { + } + + public static boolean matches(String fieldString) { + return ADDRESS_PATTERN.matcher(fieldString).matches(); + } + + public static BacNetIpField of(String fieldString) { + Matcher matcher = ADDRESS_PATTERN.matcher(fieldString); + if(matcher.matches()) { + return new BacNetIpField(); + } + throw new PlcInvalidFieldException("Unable to parse address: " + fieldString); + } + +} diff --git a/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/protocol/BacNetIpProtocol.java b/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/protocol/BacNetIpProtocol.java new file mode 100644 index 0000000..34489bc --- /dev/null +++ b/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/protocol/BacNetIpProtocol.java @@ -0,0 +1,62 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ +package org.apache.plc4x.java.bacnetip.protocol; + +import io.netty.buffer.ByteBuf; +import org.apache.plc4x.java.bacnetip.readwrite.BVLC; +import org.apache.plc4x.java.bacnetip.readwrite.io.BVLCIO; +import org.apache.plc4x.java.base.GeneratedDriverByteToMessageCodec; +import org.apache.plc4x.java.utils.MessageIO; +import org.apache.plc4x.java.utils.ParseException; +import org.apache.plc4x.java.utils.ReadBuffer; +import org.apache.plc4x.java.utils.WriteBuffer; + +public class BacNetIpProtocol extends GeneratedDriverByteToMessageCodec<BVLC> { + + public BacNetIpProtocol() { + super(new MessageIO<BVLC, BVLC>() { + @Override + public BVLC parse(ReadBuffer io) throws ParseException { + return BVLCIO.parse(io); + } + + @Override + public void serialize(WriteBuffer io, BVLC value) throws ParseException { + BVLCIO.serialize(io, value); + } + }); + } + + @Override + protected int getPacketSize(ByteBuf byteBuf) { + if(byteBuf.readableBytes() >= 4) { + return byteBuf.getUnsignedShort(byteBuf.readerIndex() + 2); + } + return -1; + } + + @Override + protected void removeRestOfCorruptPackage(ByteBuf byteBuf) { + while (byteBuf.getUnsignedByte(0) != BVLC.BACNETTYPE) { + // Just consume the bytes till the next possible start position. + byteBuf.readByte(); + } + } + +} diff --git a/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/protocol/HelloWorldProtocol.java b/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/protocol/HelloWorldProtocol.java new file mode 100644 index 0000000..c8b8e8f --- /dev/null +++ b/sandbox/test-java-bacnetip-driver/src/main/java/org/apache/plc4x/java/bacnetip/protocol/HelloWorldProtocol.java @@ -0,0 +1,61 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ +package org.apache.plc4x.java.bacnetip.protocol; + +import io.netty.channel.ChannelHandlerContext; +import org.apache.plc4x.java.bacnetip.readwrite.*; +import org.apache.plc4x.java.base.PlcMessageToMessageCodec; +import org.apache.plc4x.java.base.messages.PlcRequestContainer; + +import java.util.List; + +public class HelloWorldProtocol extends PlcMessageToMessageCodec<BVLC, PlcRequestContainer> { + + @Override + protected void encode(ChannelHandlerContext channelHandlerContext, PlcRequestContainer plcRequestContainer, List<Object> list) throws Exception { + System.out.println(plcRequestContainer); + } + + @Override + protected void decode(ChannelHandlerContext channelHandlerContext, BVLC packet, List<Object> list) throws Exception { + if(packet instanceof BVLCOriginalUnicastNPDU) { + final NPDU npdu = ((BVLCOriginalUnicastNPDU) packet).getNpdu(); + final APDU apdu = npdu.getApdu(); + if(apdu instanceof APDUSimpleAck) { + APDUSimpleAck ack = (APDUSimpleAck) apdu; + System.out.println("Simple-ACK(" + ack.getOriginalInvokeId() + ")"); + } else if(apdu instanceof APDUConfirmedRequest) { + APDUConfirmedRequest request = (APDUConfirmedRequest) apdu; + final BACnetConfirmedServiceRequest serviceRequest = request.getServiceRequest(); + if(serviceRequest instanceof BACnetConfirmedServiceRequestConfirmedCOVNotification) { + BACnetConfirmedServiceRequestConfirmedCOVNotification covNotification = (BACnetConfirmedServiceRequestConfirmedCOVNotification) serviceRequest; + final BACnetTagWithContent[] notifications = covNotification.getNotifications(); + System.out.println("Simple-ACK(" + request.getInvokeId() + "): Confirmed COV Notification [" + notifications.length + "]"); + } else { + System.out.println("Simple-ACK(" + request.getInvokeId() + "): Other"); + } + } else { + System.out.println("Other"); + } + } else { + System.out.println("Other"); + } + } + +} diff --git a/sandbox/test-java-bacnetip-driver/src/main/resources/META-INF/services/org.apache.plc4x.java.spi.PlcDriver b/sandbox/test-java-bacnetip-driver/src/main/resources/META-INF/services/org.apache.plc4x.java.spi.PlcDriver new file mode 100644 index 0000000..9c311c9 --- /dev/null +++ b/sandbox/test-java-bacnetip-driver/src/main/resources/META-INF/services/org.apache.plc4x.java.spi.PlcDriver @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +org.apache.plc4x.java.bacnetip.PassiveBacNetIpDriver diff --git a/sandbox/test-java-bacnetip-driver/src/test/java/org/apache/plc4x/java/bacnetip/ManualBacNetDecoder.java b/sandbox/test-java-bacnetip-driver/src/test/java/org/apache/plc4x/java/bacnetip/ManualBacNetDecoder.java new file mode 100644 index 0000000..d7ca1c3 --- /dev/null +++ b/sandbox/test-java-bacnetip-driver/src/test/java/org/apache/plc4x/java/bacnetip/ManualBacNetDecoder.java @@ -0,0 +1,35 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ +package org.apache.plc4x.java.bacnetip; + +import org.apache.commons.codec.binary.Hex; +import org.apache.plc4x.java.bacnetip.readwrite.BVLC; +import org.apache.plc4x.java.bacnetip.readwrite.io.BVLCIO; +import org.apache.plc4x.java.utils.ReadBuffer; + +public class ManualBacNetDecoder { + + public static void main(String[] args) throws Exception { + final byte[] bytes = Hex.decodeHex("810a002b01040205790109011c020000142c000002f93a06b24e09552e44434a00002f096f2e8204002f4f"); + ReadBuffer readBuffer = new ReadBuffer(bytes); + final BVLC packet = BVLCIO.parse(readBuffer); + System.out.println(packet); + } + +} diff --git a/sandbox/test-java-bacnetip-driver/src/test/java/org/apache/plc4x/java/bacnetip/PassiveBacNetIpDriverManual.java b/sandbox/test-java-bacnetip-driver/src/test/java/org/apache/plc4x/java/bacnetip/PassiveBacNetIpDriverManual.java new file mode 100644 index 0000000..5903221 --- /dev/null +++ b/sandbox/test-java-bacnetip-driver/src/test/java/org/apache/plc4x/java/bacnetip/PassiveBacNetIpDriverManual.java @@ -0,0 +1,39 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ +package org.apache.plc4x.java.bacnetip; + +import org.apache.plc4x.java.bacnetip.connection.PassiveBacNetIpPlcConnection; +import org.apache.plc4x.java.base.connection.NettyPlcConnection; +import org.apache.plc4x.java.base.connection.PcapChannelFactory; +import org.apache.plc4x.java.utils.pcapsockets.netty.PcapSocketAddress; +import org.apache.plc4x.java.utils.pcapsockets.netty.UdpIpPacketHandler; + +import java.io.File; + +public class PassiveBacNetIpDriverManual { + + public static void main(String[] args) throws Exception { + NettyPlcConnection connection = new PassiveBacNetIpPlcConnection(new PcapChannelFactory( + //new File("/Users/christofer.dutz/Projects/Apache/PLC4X-Documents/BacNET/Captures/Merck/BACnetWhoIsRouterToNetwork.pcapng"), null, + new File("/Users/christofer.dutz/Downloads/20190906_udp.pcapng"), null, + PassiveBacNetIpDriver.BACNET_IP_PORT, PcapSocketAddress.ALL_PROTOCOLS, 1.5f, new UdpIpPacketHandler()), ""); + connection.connect(); + } + +}
