You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cd...@apache.org on 2019/11/09 17:47:44 UTC
[plc4x] branch feature/knxnet-ip updated: - Started implementing an
active KNXNet/IP driver
This is an automated email from the ASF dual-hosted git repository.
cdutz pushed a commit to branch feature/knxnet-ip
in repository https://gitbox.apache.org/repos/asf/plc4x.git
The following commit(s) were added to refs/heads/feature/knxnet-ip by this push:
new 1edd59f - Started implementing an active KNXNet/IP driver
1edd59f is described below
commit 1edd59fb64cf58eb84a4cd61d1124738b246fd1b
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Sat Nov 9 18:47:33 2019 +0100
- Started implementing an active KNXNet/IP driver
---
plc4j/protocols/driver-bases/udp/pom.xml | 10 +-
.../protocol/DatagramUnpackingHandler.java | 39 ++
.../resources/protocols/knxnetip/knxnetip.mspec | 77 +--
sandbox/pom.xml | 1 +
.../java/streampipes/bacnetip/BacNetIpAdapter.java | 61 ++-
sandbox/test-java-knxnetip-driver/pom.xml | 5 +
...siveKnxNetIpDriver.java => KnxNetIpDriver.java} | 27 +-
...pPlcConnection.java => KnxNetIpConnection.java} | 31 +-
.../java/knxnetip/events/KnxGatewayFoundEvent.java | 22 +
.../knxnetip/protocol/KnxNetIpProtocolLogic.java | 120 +++++
...pProtocol.java => KnxNetIpProtocolPackets.java} | 4 +-
.../services/org.apache.plc4x.java.spi.PlcDriver | 2 +-
.../apache/plc4x/java/knxnetip/ManualKnxNetIp.java | 46 +-
.../pom.xml | 17 +-
.../passive}/knxnetip/PassiveKnxNetIpDriver.java | 6 +-
.../knxnetip/connection/KnxNetIpFieldHandler.java | 36 ++
.../connection/PassiveKnxNetIpPlcConnection.java | 6 +-
.../java/passive/knxnetip/model/KnxNetIpField.java | 47 ++
.../knxnetip/protocol/HelloWorldProtocol.java | 4 +-
.../knxnetip/protocol/KnxNetIpProtocol.java | 8 +-
.../services/org.apache.plc4x.java.spi.PlcDriver | 2 +-
.../org/apache/plc4x/java/knxnetip/IOTest.java | 79 +++
.../apache/plc4x/java/knxnetip/KNXNetIpTest.java | 30 ++
.../apache/plc4x/java/knxnetip/ManualKnxNetIp.java | 27 +
.../test/resources/testsuite/KNXNetIPTestsuite.xml | 544 +++++++++++++++++++++
25 files changed, 1107 insertions(+), 144 deletions(-)
diff --git a/plc4j/protocols/driver-bases/udp/pom.xml b/plc4j/protocols/driver-bases/udp/pom.xml
index c7aa485..0a9c43a 100644
--- a/plc4j/protocols/driver-bases/udp/pom.xml
+++ b/plc4j/protocols/driver-bases/udp/pom.xml
@@ -45,12 +45,20 @@
<dependency>
<groupId>io.netty</groupId>
- <artifactId>netty-transport</artifactId>
+ <artifactId>netty-buffer</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.netty</groupId>
+ <artifactId>netty-codec</artifactId>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-common</artifactId>
</dependency>
+ <dependency>
+ <groupId>io.netty</groupId>
+ <artifactId>netty-transport</artifactId>
+ </dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
diff --git a/plc4j/protocols/driver-bases/udp/src/main/java/org/apache/plc4x/java/base/connection/protocol/DatagramUnpackingHandler.java b/plc4j/protocols/driver-bases/udp/src/main/java/org/apache/plc4x/java/base/connection/protocol/DatagramUnpackingHandler.java
new file mode 100644
index 0000000..5e45723
--- /dev/null
+++ b/plc4j/protocols/driver-bases/udp/src/main/java/org/apache/plc4x/java/base/connection/protocol/DatagramUnpackingHandler.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.base.connection.protocol;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.socket.DatagramPacket;
+import io.netty.handler.codec.MessageToMessageDecoder;
+
+import java.util.List;
+
+/**
+ * Handler to unpack and pass along the ByteBuf objects contained in the DatagramPackets.
+ */
+public class DatagramUnpackingHandler extends MessageToMessageDecoder<DatagramPacket> {
+
+ @Override
+ protected void decode(ChannelHandlerContext ctx, DatagramPacket msg, List<Object> out) {
+ final ByteBuf content = msg.content();
+ out.add(content.retain());
+ }
+
+}
diff --git a/protocols/knxnetip/src/main/resources/protocols/knxnetip/knxnetip.mspec b/protocols/knxnetip/src/main/resources/protocols/knxnetip/knxnetip.mspec
index 3e2d429..b1fa2e8 100644
--- a/protocols/knxnetip/src/main/resources/protocols/knxnetip/knxnetip.mspec
+++ b/protocols/knxnetip/src/main/resources/protocols/knxnetip/knxnetip.mspec
@@ -45,7 +45,7 @@
]
['0x0206' ConnectionResponse
[simple uint 8 'communicationChannelId']
- [simple uint 8 'status']
+ [enum Status 'status']
[simple HPAIDataEndpoint 'hpaiDataEndpoint']
[simple ConnectionResponseDataBlock 'connectionResponseDataBlock']
]
@@ -56,7 +56,7 @@
]
['0x0208' ConnectionStateResponse
[simple uint 8 'communicationChannelId']
- [simple uint 8 'status']
+ [enum Status 'status']
]
['0x0209' DisconnectRequest
[simple uint 8 'communicationChannelId']
@@ -65,7 +65,7 @@
]
['0x020A' DisconnectResponse
[simple uint 8 'communicationChannelId']
- [simple uint 8 'status']
+ [enum Status 'status']
]
['0x020B' UnknownMessage [uint 16 'totalLength']
[array int 8 'unknownData' count 'totalLength - 6']
@@ -90,17 +90,17 @@
]
[type 'HPAIDiscoveryEndpoint'
- [implicit uint 8 'structureLength' 'lengthInBytes']
- [simple uint 8 'hostProtocolCode']
- [simple IPAddress 'ipAddress']
- [simple uint 16 'ipPort']
+ [implicit uint 8 'structureLength' 'lengthInBytes']
+ [enum HostProtocolCode 'hostProtocolCode']
+ [simple IPAddress 'ipAddress']
+ [simple uint 16 'ipPort']
]
[type 'HPAIControlEndpoint'
- [implicit uint 8 'structureLength' 'lengthInBytes']
- [simple uint 8 'hostProtocolCode']
- [simple IPAddress 'ipAddress']
- [simple uint 16 'ipPort']
+ [implicit uint 8 'structureLength' 'lengthInBytes']
+ [enum HostProtocolCode 'hostProtocolCode']
+ [simple IPAddress 'ipAddress']
+ [simple uint 16 'ipPort']
]
[type 'DIBDeviceInfo'
@@ -110,10 +110,10 @@
[simple DeviceStatus 'deviceStatus']
[simple KNXAddress 'knxAddress']
[simple ProjectInstallationIdentifier 'projectInstallationIdentifier']
- [array uint 8 'knxNetIpDeviceSerialNumber' count '6']
+ [array int 8 'knxNetIpDeviceSerialNumber' count '6']
[simple IPAddress 'knxNetIpDeviceMulticastAddress']
[simple MACAddress 'knxNetIpDeviceMacAddress']
- [array uint 8 'deviceFriendlyName' count '30']
+ [array int 8 'deviceFriendlyName' count '30']
]
[type 'DIBSuppSvcFamilies'
@@ -123,10 +123,10 @@
]
[type 'HPAIDataEndpoint'
- [implicit uint 8 'structureLength' 'lengthInBytes']
- [simple uint 8 'hostProtocolCode']
- [simple IPAddress 'ipAddress']
- [simple uint 16 'ipPort']
+ [implicit uint 8 'structureLength' 'lengthInBytes']
+ [enum HostProtocolCode 'hostProtocolCode']
+ [simple IPAddress 'ipAddress']
+ [simple uint 16 'ipPort']
]
[discriminatedType 'ConnectionRequestInformation'
@@ -136,7 +136,7 @@
['0x03' ConnectionRequestInformationDeviceManagement
]
['0x04' ConnectionRequestInformationTunnelConnection
- [simple uint 8 'knxLayer']
+ [enum KnxLayer 'knxLayer']
[reserved uint 8 '0x00']
]
]
@@ -165,7 +165,7 @@
[implicit uint 8 'structureLength' 'lengthInBytes']
[simple uint 8 'communicationChannelId']
[simple uint 8 'sequenceCounter']
- [simple uint 8 'status']
+ [enum Status 'status']
]
[type 'TunnelingRequestDataBlock'
@@ -179,15 +179,15 @@
[implicit uint 8 'structureLength' 'lengthInBytes']
[simple uint 8 'communicationChannelId']
[simple uint 8 'sequenceCounter']
- [simple uint 8 'status']
+ [enum Status 'status']
]
[type 'IPAddress'
- [array uint 8 'addr' count '4']
+ [array int 8 'addr' count '4']
]
[type 'MACAddress'
- [array uint 8 'addr' count '6']
+ [array int 8 'addr' count '6']
]
[type 'KNXAddress'
@@ -233,29 +233,28 @@
[discriminatedType 'CEMI' [uint 8 'size']
[discriminator uint 8 'messageCode']
[typeSwitch 'messageCode'
- ['0x10' CEMILRawReq
+ ['0x10' CEMIRawReq
]
- ['0x11' CEMILDataReq
+ ['0x11' CEMIDataReq
]
- ['0x13' CEMILPollDataReq
+ ['0x13' CEMIPollDataReq
]
- ['0x25' CEMILPollDataCon
+ ['0x25' CEMIPollDataCon
]
- ['0x29' CEMILDataInd
+ ['0x29' CEMIDataInd
]
- ['0x2B' CEMILBusmonInd
+ ['0x2B' CEMIBusmonInd
[simple uint 8 'additionalInformationLength']
[array CEMIAdditionalInformation 'additionalInformation' length 'additionalInformationLength']
[simple CEMIFrame 'cemiFrame']
]
- ['0x2D' CEMILRawInd
+ ['0x2D' CEMIRawInd
]
- ['0x2E' CEMILDataCon
+ ['0x2E' CEMIDataCon
]
- ['0x2F' CEMILRawCon
+ ['0x2F' CEMIRawCon
]
-
['0xFC' CEMIMPropReadReq
[simple uint 16 'interfaceObjectType']
[simple uint 8 'objectInstance']
@@ -348,3 +347,17 @@
['0x3' LOW]
]
+[enum uint 8 'Status'
+ ['0x00' NO_ERROR]
+ ['0x24' NO_MORE_CONNECTIONS]
+]
+
+[enum uint 8 'HostProtocolCode'
+ ['0x01' IPV4_UDP]
+ ['0x02' IPV4_TCP]
+]
+
+[enum uint 8 'KnxLayer'
+ ['0x80' TUNNEL_BUSMONITOR]
+]
+
diff --git a/sandbox/pom.xml b/sandbox/pom.xml
index 600d99c..916d160 100644
--- a/sandbox/pom.xml
+++ b/sandbox/pom.xml
@@ -41,6 +41,7 @@
<module>test-java-bacnetip-driver</module>
<module>test-java-knxnetip-driver</module>
+ <module>test-java-passive-knxnetip-driver</module>
<module>test-java-s7-driver</module>
<module>test-java-passive-s7-driver</module>
<module>test-java-df1-driver</module>
diff --git a/sandbox/streampipes-connectors/src/main/java/org/apache/plc4x/java/streampipes/bacnetip/BacNetIpAdapter.java b/sandbox/streampipes-connectors/src/main/java/org/apache/plc4x/java/streampipes/bacnetip/BacNetIpAdapter.java
index c2c6cbd..c053d77 100644
--- a/sandbox/streampipes-connectors/src/main/java/org/apache/plc4x/java/streampipes/bacnetip/BacNetIpAdapter.java
+++ b/sandbox/streampipes-connectors/src/main/java/org/apache/plc4x/java/streampipes/bacnetip/BacNetIpAdapter.java
@@ -24,13 +24,14 @@ import org.apache.plc4x.java.bacnetip.PassiveBacNetIpDriver;
import org.apache.plc4x.java.bacnetip.connection.PassiveBacNetIpPlcConnection;
import org.apache.plc4x.java.bacnetip.readwrite.*;
import org.apache.plc4x.java.base.PlcMessageToMessageCodec;
+import org.apache.plc4x.java.base.connection.ChannelFactory;
import org.apache.plc4x.java.base.connection.NettyPlcConnection;
import org.apache.plc4x.java.base.connection.PcapChannelFactory;
+import org.apache.plc4x.java.base.connection.RawSocketChannelFactory;
import org.apache.plc4x.java.base.messages.PlcRequestContainer;
import org.apache.plc4x.java.streampipes.bacnetip.config.ConnectWorkerConfig;
import org.apache.plc4x.java.utils.pcapsockets.netty.PcapSocketAddress;
import org.apache.plc4x.java.utils.pcapsockets.netty.PcapSocketChannelConfig;
-import org.apache.plc4x.java.utils.pcapsockets.netty.UdpIpPacketHandler;
import org.pcap4j.core.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -38,6 +39,7 @@ import org.streampipes.connect.adapter.Adapter;
import org.streampipes.connect.adapter.exception.AdapterException;
import org.streampipes.connect.adapter.exception.ParseException;
import org.streampipes.connect.adapter.model.specific.SpecificDataStreamAdapter;
+import org.streampipes.connect.adapter.sdk.ParameterExtractor;
import org.streampipes.connect.container.worker.init.AdapterWorkerContainer;
import org.streampipes.connect.init.AdapterDeclarerSingleton;
import org.streampipes.model.AdapterType;
@@ -45,7 +47,7 @@ import org.streampipes.model.connect.adapter.SpecificAdapterStreamDescription;
import org.streampipes.model.connect.guess.GuessSchema;
import org.streampipes.model.schema.EventProperty;
import org.streampipes.model.schema.EventSchema;
-import org.streampipes.model.staticproperty.FileStaticProperty;
+import org.streampipes.model.staticproperty.*;
import org.streampipes.sdk.StaticProperties;
import org.streampipes.sdk.builder.PrimitivePropertyBuilder;
import org.streampipes.sdk.builder.adapter.SpecificDataStreamAdapterBuilder;
@@ -62,14 +64,18 @@ public class BacNetIpAdapter extends SpecificDataStreamAdapter {
private static final Logger logger = LoggerFactory.getLogger(BacNetIpAdapter.class);
+ private String deviceName;
+ private String pcapFile;
private NettyPlcConnection connection;
public BacNetIpAdapter() {
super();
}
- public BacNetIpAdapter(SpecificAdapterStreamDescription adapterDescription) {
+ public BacNetIpAdapter(SpecificAdapterStreamDescription adapterDescription, String deviceName, String pcapFile) {
super(adapterDescription);
+ this.deviceName = deviceName;
+ this.pcapFile = pcapFile;
}
@Override
@@ -102,12 +108,10 @@ public class BacNetIpAdapter extends SpecificDataStreamAdapter {
.category(AdapterType.Manufacturing)
.requiredAlternatives(Labels.from("source", "Source", "Select the source, where the data is read from"),
Alternatives.from(Labels.from("device", "Network", "Capture data via network device"),
- StaticProperties.group(Labels.withId("device-group"),
- StaticProperties.singleValueSelection(Labels.from("network-device", "Network Device", "Network device used for capturing"),
- Options.from(deviceList)))),
+ StaticProperties.singleValueSelection(Labels.from("network-device", "Network Device", "Network device used for capturing"),
+ Options.from(deviceList))),
Alternatives.from(Labels.from("file", "File", "Capture data from a PCAP network recording"),
- StaticProperties.group(Labels.withId("file-group"),
- new FileStaticProperty(fileLabel.getInternalId(), fileLabel.getLabel(), fileLabel.getDescription()))))
+ new FileStaticProperty(fileLabel.getInternalId(), fileLabel.getLabel(), fileLabel.getDescription())))
.build();
description.setAppId(ID);
return description;
@@ -186,11 +190,21 @@ public class BacNetIpAdapter extends SpecificDataStreamAdapter {
@Override
public void startAdapter() throws AdapterException {
try {
- 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/Projects/Apache/PLC4X-Documents/BacNET/Captures/Merck/BACnet.pcapng"), null,
- PassiveBacNetIpDriver.BACNET_IP_PORT, PcapSocketAddress.ALL_PROTOCOLS,
- PcapSocketChannelConfig.SPEED_REALTIME, new UdpIpPacketHandler()), "",
+ ChannelFactory channelFactory;
+ if(deviceName != null) {
+ channelFactory = new RawSocketChannelFactory(deviceName, null,
+ PassiveBacNetIpDriver.BACNET_IP_PORT, PcapSocketAddress.ALL_PROTOCOLS,
+ new org.apache.plc4x.java.utils.rawsockets.netty.UdpIpPacketHandler());
+ } else if(pcapFile != null) {
+ channelFactory = new PcapChannelFactory(new File(pcapFile), null,
+ PassiveBacNetIpDriver.BACNET_IP_PORT, PcapSocketAddress.ALL_PROTOCOLS,
+ PcapSocketChannelConfig.SPEED_REALTIME,
+ new org.apache.plc4x.java.utils.pcapsockets.netty.UdpIpPacketHandler());
+ } else {
+ throw new AdapterException("Configuration Exception. Either device or file have to be selected.");
+ }
+
+ connection = new PassiveBacNetIpPlcConnection(channelFactory, "",
new PlcMessageToMessageCodec<BVLC, PlcRequestContainer>() {
@Override
@@ -346,8 +360,27 @@ public class BacNetIpAdapter extends SpecificDataStreamAdapter {
}
@Override
+ @SuppressWarnings("unchecked")
public Adapter getInstance(SpecificAdapterStreamDescription specificAdapterStreamDescription) {
- return new BacNetIpAdapter(specificAdapterStreamDescription);
+ ParameterExtractor extractor = new ParameterExtractor(specificAdapterStreamDescription.getConfig());
+ String deviceName = null;
+ String pcapFile = null;
+
+ StaticPropertyAlternatives sources = (StaticPropertyAlternatives) extractor.getStaticPropertyByName("source");
+ final Optional<StaticPropertyAlternative> selectedAlternative = sources.getAlternatives().stream().filter(
+ staticPropertyAlternative -> staticPropertyAlternative.getSelected()).findFirst();
+ if(selectedAlternative.isPresent()) {
+ final StaticPropertyAlternative staticPropertyAlternative = selectedAlternative.get();
+ if("device".equals(staticPropertyAlternative.getInternalName())) {
+ final Optional<Option> first =
+ ((OneOfStaticProperty) staticPropertyAlternative.getStaticProperty()).getOptions().stream().filter(
+ option -> option.isSelected()).findFirst();
+ deviceName = first.get().getName();
+ } else {
+ pcapFile = ((FileStaticProperty) staticPropertyAlternative.getStaticProperty()).getLocationPath();
+ }
+ }
+ return new BacNetIpAdapter(specificAdapterStreamDescription, deviceName, pcapFile);
}
@Override
diff --git a/sandbox/test-java-knxnetip-driver/pom.xml b/sandbox/test-java-knxnetip-driver/pom.xml
index 3b3bec4..735b440 100644
--- a/sandbox/test-java-knxnetip-driver/pom.xml
+++ b/sandbox/test-java-knxnetip-driver/pom.xml
@@ -71,6 +71,11 @@
</dependency>
<dependency>
<groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4j-protocol-driver-base-udp</artifactId>
+ <version>0.6.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.plc4x</groupId>
<artifactId>plc4j-protocol-driver-base-raw-socket</artifactId>
<version>0.6.0-SNAPSHOT</version>
</dependency>
diff --git a/sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/PassiveKnxNetIpDriver.java b/sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/KnxNetIpDriver.java
similarity index 69%
copy from sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/PassiveKnxNetIpDriver.java
copy to sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/KnxNetIpDriver.java
index 1f17192..d5d5d88 100644
--- a/sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/PassiveKnxNetIpDriver.java
+++ b/sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/KnxNetIpDriver.java
@@ -21,31 +21,27 @@ package org.apache.plc4x.java.knxnetip;
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.knxnetip.connection.PassiveKnxNetIpPlcConnection;
-import org.apache.plc4x.java.knxnetip.protocol.HelloWorldProtocol;
+import org.apache.plc4x.java.knxnetip.connection.KnxNetIpConnection;
+import org.apache.plc4x.java.knxnetip.protocol.KnxNetIpProtocolLogic;
import org.apache.plc4x.java.spi.PlcDriver;
-import org.apache.plc4x.java.utils.rawsockets.netty.RawSocketIpAddress;
+import java.net.InetAddress;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import static org.apache.plc4x.java.utils.rawsockets.netty.RawSocketAddress.ALL_PROTOCOLS;
-
-public class PassiveKnxNetIpDriver implements PlcDriver {
-
- public static final int KNXNET_IP_PORT = 3671;
+public class KnxNetIpDriver implements PlcDriver {
private static final Pattern PASSIVE_KNXNET_IP_URI_PATTERN =
- Pattern.compile("^knxnet-ip-passive://(?<networkDevice>.*)(?<params>\\?.*)?");
+ Pattern.compile("^knxnet-ip://(?<host>.*)(?<params>\\?.*)?");
@Override
public String getProtocolCode() {
- return "knxnet-ip-passive";
+ return "knxnet-ip";
}
@Override
public String getProtocolName() {
- return "KNXNet/IP (Passive)";
+ return "KNXNet/IP";
}
@Override
@@ -53,16 +49,15 @@ public class PassiveKnxNetIpDriver implements PlcDriver {
Matcher matcher = PASSIVE_KNXNET_IP_URI_PATTERN.matcher(url);
if (!matcher.matches()) {
throw new PlcConnectionException(
- "Connection url doesn't match the format 'knxnet-ip-passive://{host|ip}'");
+ "Connection url doesn't match the format 'knxnet-ip://{host|ip}'");
}
- String networkDevice = matcher.group("networkDevice");
+ String host = matcher.group("host");
String params = matcher.group("params") != null ? matcher.group("params").substring(1) : null;
try {
- RawSocketIpAddress rawSocketAddress = new RawSocketIpAddress(
- networkDevice, ALL_PROTOCOLS, null, KNXNET_IP_PORT);
- return new PassiveKnxNetIpPlcConnection(rawSocketAddress, params, new HelloWorldProtocol());
+ InetAddress serverInetAddress = InetAddress.getByName(host);
+ return new KnxNetIpConnection(serverInetAddress, params, new KnxNetIpProtocolLogic());
} catch (Exception e) {
throw new PlcConnectionException("Error connecting to host", e);
}
diff --git a/sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/connection/PassiveKnxNetIpPlcConnection.java b/sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/connection/KnxNetIpConnection.java
similarity index 77%
copy from sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/connection/PassiveKnxNetIpPlcConnection.java
copy to sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/connection/KnxNetIpConnection.java
index e82c7df..91eca9e 100644
--- a/sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/connection/PassiveKnxNetIpPlcConnection.java
+++ b/sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/connection/KnxNetIpConnection.java
@@ -25,39 +25,40 @@ import org.apache.plc4x.java.api.messages.PlcReadResponse;
import org.apache.plc4x.java.api.model.PlcField;
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.connection.UdpSocketChannelFactory;
+import org.apache.plc4x.java.base.connection.protocol.DatagramUnpackingHandler;
+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.knxnetip.model.KnxNetIpField;
-import org.apache.plc4x.java.knxnetip.protocol.KnxNetIpProtocol;
-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.apache.plc4x.java.knxnetip.protocol.KnxNetIpProtocolPackets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.net.InetAddress;
import java.util.concurrent.CompletableFuture;
-public class PassiveKnxNetIpPlcConnection extends NettyPlcConnection implements PlcReader {
+public class KnxNetIpConnection extends NettyPlcConnection implements PlcReader {
- private static final Logger logger = LoggerFactory.getLogger(PassiveKnxNetIpPlcConnection.class);
+ public static final int KNXNET_IP_PORT = 3671;
+
+ private static final Logger logger = LoggerFactory.getLogger(KnxNetIpConnection.class);
private final ChannelHandler handler;
- public PassiveKnxNetIpPlcConnection(RawSocketIpAddress address, String params, ChannelHandler handler) {
- this(new RawSocketChannelFactory(address.getDeviceName(), null,
- address.getPort(), RawSocketAddress.ALL_PROTOCOLS, new UdpIpPacketHandler()), params, handler);
+ public KnxNetIpConnection(InetAddress address, String params, ChannelHandler handler) {
+ this(new UdpSocketChannelFactory(address, KNXNET_IP_PORT), params, handler);
}
- public PassiveKnxNetIpPlcConnection(ChannelFactory channelFactory, String params, ChannelHandler handler) {
+ public KnxNetIpConnection(ChannelFactory channelFactory, String params, ChannelHandler handler) {
super(channelFactory, true);
this.handler = handler;
}
@Override
protected void sendChannelCreatedEvent() {
- // As this type of protocol doesn't require any form of connection, we just send the connected event.
- channel.pipeline().fireUserEventTriggered(new ConnectedEvent());
+ // Send an event to the pipeline telling the Protocol filters what's going on.
+ channel.pipeline().fireUserEventTriggered(new ConnectEvent());
}
@Override
@@ -82,7 +83,9 @@ public class PassiveKnxNetIpPlcConnection extends NettyPlcConnection implements
}
}
});
- pipeline.addLast(new KnxNetIpProtocol());
+ // Unpack the ByteBuf included in the DatagramPackage.
+ pipeline.addLast(new DatagramUnpackingHandler());
+ pipeline.addLast(new KnxNetIpProtocolPackets());
pipeline.addLast(handler);
}
};
diff --git a/sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/events/KnxGatewayFoundEvent.java b/sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/events/KnxGatewayFoundEvent.java
new file mode 100644
index 0000000..3b73148
--- /dev/null
+++ b/sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/events/KnxGatewayFoundEvent.java
@@ -0,0 +1,22 @@
+/*
+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.knxnetip.events;
+
+public class KnxGatewayFoundEvent {
+}
diff --git a/sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/protocol/KnxNetIpProtocolLogic.java b/sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/protocol/KnxNetIpProtocolLogic.java
new file mode 100644
index 0000000..bfee8d1
--- /dev/null
+++ b/sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/protocol/KnxNetIpProtocolLogic.java
@@ -0,0 +1,120 @@
+/*
+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.knxnetip.protocol;
+
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.socket.DatagramChannel;
+import org.apache.commons.codec.binary.Hex;
+import org.apache.plc4x.java.base.PlcMessageToMessageCodec;
+import org.apache.plc4x.java.base.events.ConnectEvent;
+import org.apache.plc4x.java.base.events.ConnectedEvent;
+import org.apache.plc4x.java.base.messages.PlcRequestContainer;
+import org.apache.plc4x.java.knxnetip.events.KnxGatewayFoundEvent;
+import org.apache.plc4x.java.knxnetip.readwrite.*;
+import org.apache.plc4x.java.knxnetip.readwrite.types.HostProtocolCode;
+import org.apache.plc4x.java.knxnetip.readwrite.types.KnxLayer;
+import org.apache.plc4x.java.knxnetip.readwrite.types.Status;
+
+import java.net.InetSocketAddress;
+import java.util.Arrays;
+import java.util.List;
+
+public class KnxNetIpProtocolLogic extends PlcMessageToMessageCodec<KNXNetIPMessage, PlcRequestContainer> {
+
+ private KNXAddress gatewayAddress;
+ private String gatewayName;
+
+ @Override
+ public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
+ if (evt instanceof ConnectEvent) {
+ DatagramChannel channel = (DatagramChannel) ctx.pipeline().channel();
+ final InetSocketAddress localSocketAddress = channel.localAddress();
+ final IPAddress localAddress = new IPAddress(localSocketAddress.getAddress().getAddress());
+ final int localPort = localSocketAddress.getPort();
+ SearchRequest searchRequest = new SearchRequest(new HPAIDiscoveryEndpoint(HostProtocolCode.IPV4_UDP, localAddress, localPort));
+ ctx.channel().writeAndFlush(searchRequest);
+ } else if(evt instanceof KnxGatewayFoundEvent) {
+ DatagramChannel channel = (DatagramChannel) ctx.pipeline().channel();
+ final InetSocketAddress localSocketAddress = channel.localAddress();
+ final IPAddress localAddress = new IPAddress(localSocketAddress.getAddress().getAddress());
+ final int localPort = localSocketAddress.getPort();
+ ConnectionRequest connectionRequest = new ConnectionRequest(
+ new HPAIDiscoveryEndpoint(HostProtocolCode.IPV4_UDP, localAddress, localPort),
+ new HPAIDataEndpoint(HostProtocolCode.IPV4_UDP, localAddress, localPort),
+ new ConnectionRequestInformationTunnelConnection(KnxLayer.TUNNEL_BUSMONITOR));
+ ctx.channel().writeAndFlush(connectionRequest);
+ }
+ }
+
+ @Override
+ protected void encode(ChannelHandlerContext ctx, PlcRequestContainer msg, List<Object> out) {
+ // Ignore ...
+ }
+
+ @Override
+ protected void decode(ChannelHandlerContext ctx, KNXNetIPMessage msg, List<Object> out) {
+ if(msg instanceof SearchResponse) {
+ SearchResponse searchResponse = (SearchResponse) msg;
+ final ServiceId tunnelingService = Arrays.stream(searchResponse.getDibSuppSvcFamilies().getServiceIds()).filter(serviceId -> serviceId instanceof KnxNetIpTunneling).findFirst().orElse(null);
+ // If this service has the
+ if(tunnelingService != null) {
+ gatewayAddress = searchResponse.getDibDeviceInfo().getKnxAddress();
+ gatewayName = new String(searchResponse.getDibDeviceInfo().getDeviceFriendlyName());
+ ctx.channel().pipeline().fireUserEventTriggered(new KnxGatewayFoundEvent());
+ }
+ } else if(msg instanceof ConnectionResponse) {
+ ConnectionResponse connectionResponse = (ConnectionResponse) msg;
+ Status status = connectionResponse.getStatus();
+ if(status == Status.NO_ERROR) {
+ ctx.channel().pipeline().fireUserEventTriggered(new ConnectedEvent());
+ }
+ } else if(msg instanceof TunnelingRequest) {
+ TunnelingRequest tunnelingRequest = (TunnelingRequest) msg;
+ final short communicationChannelId = tunnelingRequest.getTunnelingRequestDataBlock().getCommunicationChannelId();
+ final short sequenceCounter = tunnelingRequest.getTunnelingRequestDataBlock().getSequenceCounter();
+ TunnelingResponse tunnelingResponse = new TunnelingResponse(
+ new TunnelingResponseDataBlock(communicationChannelId, sequenceCounter, Status.NO_ERROR));
+ ctx.channel().writeAndFlush(tunnelingResponse);
+ CEMIBusmonInd busmonInd = (CEMIBusmonInd) tunnelingRequest.getCemi();
+ if(busmonInd.getCemiFrame() instanceof CEMIFrameData) {
+ outputStringRepresentation((CEMIFrameData) busmonInd.getCemiFrame());
+ }
+ }
+ }
+
+ private void outputStringRepresentation(CEMIFrameData data) {
+ final CEMIAddress sourceAddress = data.getSourceAddress();
+ final CEMIAddress destinationAddress = data.getDestinationAddress();
+ final boolean groupAddress = data.getGroupAddress();
+ final byte[] payload = data.getData();
+ String payloadString = Hex.encodeHexString(payload);
+ if(groupAddress) {
+ System.out.println(String.format("Telegram from %d.%d.%d to %d/%d/%d with payload %s",
+ sourceAddress.getArea(), sourceAddress.getLine(), sourceAddress.getDevice(),
+ destinationAddress.getArea(), destinationAddress.getLine(), destinationAddress.getDevice(),
+ payloadString));
+ } else {
+ System.out.println(String.format("Telegram from %d.%d.%d to %d.%d.%d with payload %s",
+ sourceAddress.getArea(), sourceAddress.getLine(), sourceAddress.getDevice(),
+ destinationAddress.getArea(), destinationAddress.getLine(), destinationAddress.getDevice(),
+ payloadString));
+ }
+ }
+
+}
diff --git a/sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/protocol/KnxNetIpProtocol.java b/sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/protocol/KnxNetIpProtocolPackets.java
similarity index 93%
copy from sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/protocol/KnxNetIpProtocol.java
copy to sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/protocol/KnxNetIpProtocolPackets.java
index d8e5cc9..4b60b4b 100644
--- a/sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/protocol/KnxNetIpProtocol.java
+++ b/sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/protocol/KnxNetIpProtocolPackets.java
@@ -27,9 +27,9 @@ import org.apache.plc4x.java.utils.ParseException;
import org.apache.plc4x.java.utils.ReadBuffer;
import org.apache.plc4x.java.utils.WriteBuffer;
-public class KnxNetIpProtocol extends GeneratedDriverByteToMessageCodec<KNXNetIPMessage> {
+public class KnxNetIpProtocolPackets extends GeneratedDriverByteToMessageCodec<KNXNetIPMessage> {
- public KnxNetIpProtocol() {
+ public KnxNetIpProtocolPackets() {
super(new MessageIO<KNXNetIPMessage, KNXNetIPMessage>() {
@Override
public KNXNetIPMessage parse(ReadBuffer io) throws ParseException {
diff --git a/sandbox/test-java-knxnetip-driver/src/main/resources/META-INF/services/org.apache.plc4x.java.spi.PlcDriver b/sandbox/test-java-knxnetip-driver/src/main/resources/META-INF/services/org.apache.plc4x.java.spi.PlcDriver
index afe85bf..50a5f8d 100644
--- a/sandbox/test-java-knxnetip-driver/src/main/resources/META-INF/services/org.apache.plc4x.java.spi.PlcDriver
+++ b/sandbox/test-java-knxnetip-driver/src/main/resources/META-INF/services/org.apache.plc4x.java.spi.PlcDriver
@@ -16,4 +16,4 @@
# specific language governing permissions and limitations
# under the License.
#
-org.apache.plc4x.java.knxnetip.PassiveKnxNetIpDriver
+org.apache.plc4x.java.knxnetip.KnxNetIpDriver
diff --git a/sandbox/test-java-knxnetip-driver/src/test/java/org/apache/plc4x/java/knxnetip/ManualKnxNetIp.java b/sandbox/test-java-knxnetip-driver/src/test/java/org/apache/plc4x/java/knxnetip/ManualKnxNetIp.java
index a1ac874..76d89db 100644
--- a/sandbox/test-java-knxnetip-driver/src/test/java/org/apache/plc4x/java/knxnetip/ManualKnxNetIp.java
+++ b/sandbox/test-java-knxnetip-driver/src/test/java/org/apache/plc4x/java/knxnetip/ManualKnxNetIp.java
@@ -18,52 +18,14 @@ under the License.
*/
package org.apache.plc4x.java.knxnetip;
-import io.netty.channel.ChannelHandlerContext;
-import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
-import org.apache.plc4x.java.base.PlcMessageToMessageCodec;
-import org.apache.plc4x.java.base.connection.NettyPlcConnection;
-import org.apache.plc4x.java.base.connection.PcapChannelFactory;
-import org.apache.plc4x.java.base.messages.PlcRequestContainer;
-import org.apache.plc4x.java.knxnetip.connection.PassiveKnxNetIpPlcConnection;
-import org.apache.plc4x.java.knxnetip.readwrite.KNXNetIPMessage;
-import org.apache.plc4x.java.utils.pcapsockets.netty.PcapSocketAddress;
-import org.apache.plc4x.java.utils.pcapsockets.netty.PcapSocketChannelConfig;
-import org.apache.plc4x.java.utils.pcapsockets.netty.UdpIpPacketHandler;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.File;
-import java.util.List;
+import org.apache.plc4x.java.PlcDriverManager;
+import org.apache.plc4x.java.api.PlcConnection;
public class ManualKnxNetIp {
- private static final Logger logger = LoggerFactory.getLogger(ManualKnxNetIp.class);
-
- private static NettyPlcConnection connection;
-
public static void main(String[] args) throws Exception {
- try {
- connection = new PassiveKnxNetIpPlcConnection(new PcapChannelFactory(
- new File(args[0]), null,
- PassiveKnxNetIpDriver.KNXNET_IP_PORT, PcapSocketAddress.ALL_PROTOCOLS,
- PcapSocketChannelConfig.SPEED_REALTIME, new UdpIpPacketHandler()), "",
- new PlcMessageToMessageCodec<KNXNetIPMessage, PlcRequestContainer>() {
-
- @Override
- protected void decode(ChannelHandlerContext channelHandlerContext, KNXNetIPMessage packet, List<Object> list) throws Exception {
- System.out.println(packet);
- }
-
- @Override
- protected void encode(ChannelHandlerContext ctx, PlcRequestContainer msg, List<Object> out) throws Exception {
- // Ignore this as we don't send anything.
- }
- });
- connection.connect();
- } catch (PlcConnectionException e) {
- logger.error("An error occurred starting the BACnet/IP driver", e);
- throw new Exception(e);
- }
+ final PlcConnection connection = new PlcDriverManager().getConnection("knxnet-ip://192.168.42.11");
+ System.out.println(connection);
}
}
diff --git a/sandbox/test-java-knxnetip-driver/pom.xml b/sandbox/test-java-passive-knxnetip-driver/pom.xml
similarity index 93%
copy from sandbox/test-java-knxnetip-driver/pom.xml
copy to sandbox/test-java-passive-knxnetip-driver/pom.xml
index 3b3bec4..ca9ac14 100644
--- a/sandbox/test-java-knxnetip-driver/pom.xml
+++ b/sandbox/test-java-passive-knxnetip-driver/pom.xml
@@ -26,9 +26,9 @@
<version>0.6.0-SNAPSHOT</version>
</parent>
- <artifactId>test-java-knxnetip-driver</artifactId>
+ <artifactId>test-java-passive-knxnetip-driver</artifactId>
- <name>Sandbox: Test Generated KNXNet/IP Driver</name>
+ <name>Sandbox: Test Generated KNXNet/IP Driver (Passive)</name>
<build>
<plugins>
@@ -45,7 +45,7 @@
<configuration>
<protocolName>knxnetip</protocolName>
<languageName>java</languageName>
- <outputFlavor>read-write</outputFlavor>
+ <outputFlavor>passive</outputFlavor>
</configuration>
</execution>
</executions>
@@ -74,6 +74,11 @@
<artifactId>plc4j-protocol-driver-base-raw-socket</artifactId>
<version>0.6.0-SNAPSHOT</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.plc4x</groupId>
+ <artifactId>plc4j-utils-raw-sockets</artifactId>
+ <version>0.6.0-SNAPSHOT</version>
+ </dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
@@ -87,12 +92,6 @@
<scope>test</scope>
</dependency>
<dependency>
- <groupId>org.apache.plc4x</groupId>
- <artifactId>plc4j-protocol-driver-base-pcap-socket</artifactId>
- <version>0.6.0-SNAPSHOT</version>
- <!--scope>test</scope-->
- </dependency>
- <dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>test</scope>
diff --git a/sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/PassiveKnxNetIpDriver.java b/sandbox/test-java-passive-knxnetip-driver/src/main/java/org/apache/plc4x/java/passive/knxnetip/PassiveKnxNetIpDriver.java
similarity index 93%
rename from sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/PassiveKnxNetIpDriver.java
rename to sandbox/test-java-passive-knxnetip-driver/src/main/java/org/apache/plc4x/java/passive/knxnetip/PassiveKnxNetIpDriver.java
index 1f17192..28225f9 100644
--- a/sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/PassiveKnxNetIpDriver.java
+++ b/sandbox/test-java-passive-knxnetip-driver/src/main/java/org/apache/plc4x/java/passive/knxnetip/PassiveKnxNetIpDriver.java
@@ -16,13 +16,13 @@ KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
-package org.apache.plc4x.java.knxnetip;
+package org.apache.plc4x.java.passive.knxnetip;
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.knxnetip.connection.PassiveKnxNetIpPlcConnection;
-import org.apache.plc4x.java.knxnetip.protocol.HelloWorldProtocol;
+import org.apache.plc4x.java.passive.knxnetip.connection.PassiveKnxNetIpPlcConnection;
+import org.apache.plc4x.java.passive.knxnetip.protocol.HelloWorldProtocol;
import org.apache.plc4x.java.spi.PlcDriver;
import org.apache.plc4x.java.utils.rawsockets.netty.RawSocketIpAddress;
diff --git a/sandbox/test-java-passive-knxnetip-driver/src/main/java/org/apache/plc4x/java/passive/knxnetip/connection/KnxNetIpFieldHandler.java b/sandbox/test-java-passive-knxnetip-driver/src/main/java/org/apache/plc4x/java/passive/knxnetip/connection/KnxNetIpFieldHandler.java
new file mode 100644
index 0000000..5787d10
--- /dev/null
+++ b/sandbox/test-java-passive-knxnetip-driver/src/main/java/org/apache/plc4x/java/passive/knxnetip/connection/KnxNetIpFieldHandler.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.passive.knxnetip.connection;
+
+import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+import org.apache.plc4x.java.api.model.PlcField;
+import org.apache.plc4x.java.base.connection.DefaultPlcFieldHandler;
+import org.apache.plc4x.java.passive.knxnetip.model.KnxNetIpField;
+
+public class KnxNetIpFieldHandler extends DefaultPlcFieldHandler {
+
+ @Override
+ public PlcField createField(String fieldQuery) throws PlcInvalidFieldException {
+ if (KnxNetIpField.matches(fieldQuery)) {
+ return KnxNetIpField.of(fieldQuery);
+ }
+ throw new PlcInvalidFieldException(fieldQuery);
+ }
+
+}
diff --git a/sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/connection/PassiveKnxNetIpPlcConnection.java b/sandbox/test-java-passive-knxnetip-driver/src/main/java/org/apache/plc4x/java/passive/knxnetip/connection/PassiveKnxNetIpPlcConnection.java
similarity index 95%
rename from sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/connection/PassiveKnxNetIpPlcConnection.java
rename to sandbox/test-java-passive-knxnetip-driver/src/main/java/org/apache/plc4x/java/passive/knxnetip/connection/PassiveKnxNetIpPlcConnection.java
index e82c7df..cca1a3c 100644
--- a/sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/connection/PassiveKnxNetIpPlcConnection.java
+++ b/sandbox/test-java-passive-knxnetip-driver/src/main/java/org/apache/plc4x/java/passive/knxnetip/connection/PassiveKnxNetIpPlcConnection.java
@@ -16,7 +16,7 @@ KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
-package org.apache.plc4x.java.knxnetip.connection;
+package org.apache.plc4x.java.passive.knxnetip.connection;
import io.netty.channel.*;
import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
@@ -28,8 +28,8 @@ import org.apache.plc4x.java.base.connection.NettyPlcConnection;
import org.apache.plc4x.java.base.connection.RawSocketChannelFactory;
import org.apache.plc4x.java.base.events.ConnectedEvent;
import org.apache.plc4x.java.base.messages.*;
-import org.apache.plc4x.java.knxnetip.model.KnxNetIpField;
-import org.apache.plc4x.java.knxnetip.protocol.KnxNetIpProtocol;
+import org.apache.plc4x.java.passive.knxnetip.model.KnxNetIpField;
+import org.apache.plc4x.java.passive.knxnetip.protocol.KnxNetIpProtocol;
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;
diff --git a/sandbox/test-java-passive-knxnetip-driver/src/main/java/org/apache/plc4x/java/passive/knxnetip/model/KnxNetIpField.java b/sandbox/test-java-passive-knxnetip-driver/src/main/java/org/apache/plc4x/java/passive/knxnetip/model/KnxNetIpField.java
new file mode 100644
index 0000000..b7e45a5
--- /dev/null
+++ b/sandbox/test-java-passive-knxnetip-driver/src/main/java/org/apache/plc4x/java/passive/knxnetip/model/KnxNetIpField.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.passive.knxnetip.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 KnxNetIpField 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 KnxNetIpField() {
+ }
+
+ public static boolean matches(String fieldString) {
+ return ADDRESS_PATTERN.matcher(fieldString).matches();
+ }
+
+ public static KnxNetIpField of(String fieldString) {
+ Matcher matcher = ADDRESS_PATTERN.matcher(fieldString);
+ if(matcher.matches()) {
+ return new KnxNetIpField();
+ }
+ throw new PlcInvalidFieldException("Unable to parse address: " + fieldString);
+ }
+
+}
diff --git a/sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/protocol/HelloWorldProtocol.java b/sandbox/test-java-passive-knxnetip-driver/src/main/java/org/apache/plc4x/java/passive/knxnetip/protocol/HelloWorldProtocol.java
similarity index 96%
rename from sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/protocol/HelloWorldProtocol.java
rename to sandbox/test-java-passive-knxnetip-driver/src/main/java/org/apache/plc4x/java/passive/knxnetip/protocol/HelloWorldProtocol.java
index 6bd481a..5c0fb6d 100644
--- a/sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/protocol/HelloWorldProtocol.java
+++ b/sandbox/test-java-passive-knxnetip-driver/src/main/java/org/apache/plc4x/java/passive/knxnetip/protocol/HelloWorldProtocol.java
@@ -16,12 +16,12 @@ KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
-package org.apache.plc4x.java.knxnetip.protocol;
+package org.apache.plc4x.java.passive.knxnetip.protocol;
import io.netty.channel.ChannelHandlerContext;
import org.apache.plc4x.java.base.PlcMessageToMessageCodec;
import org.apache.plc4x.java.base.messages.PlcRequestContainer;
-import org.apache.plc4x.java.knxnetip.readwrite.KNXNetIPMessage;
+import org.apache.plc4x.java.knxnetip.passive.KNXNetIPMessage;
import java.util.List;
diff --git a/sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/protocol/KnxNetIpProtocol.java b/sandbox/test-java-passive-knxnetip-driver/src/main/java/org/apache/plc4x/java/passive/knxnetip/protocol/KnxNetIpProtocol.java
similarity index 88%
rename from sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/protocol/KnxNetIpProtocol.java
rename to sandbox/test-java-passive-knxnetip-driver/src/main/java/org/apache/plc4x/java/passive/knxnetip/protocol/KnxNetIpProtocol.java
index d8e5cc9..9d97bfd 100644
--- a/sandbox/test-java-knxnetip-driver/src/main/java/org/apache/plc4x/java/knxnetip/protocol/KnxNetIpProtocol.java
+++ b/sandbox/test-java-passive-knxnetip-driver/src/main/java/org/apache/plc4x/java/passive/knxnetip/protocol/KnxNetIpProtocol.java
@@ -16,12 +16,12 @@ KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
-package org.apache.plc4x.java.knxnetip.protocol;
+package org.apache.plc4x.java.passive.knxnetip.protocol;
import io.netty.buffer.ByteBuf;
import org.apache.plc4x.java.base.GeneratedDriverByteToMessageCodec;
-import org.apache.plc4x.java.knxnetip.readwrite.KNXNetIPMessage;
-import org.apache.plc4x.java.knxnetip.readwrite.io.KNXNetIPMessageIO;
+import org.apache.plc4x.java.knxnetip.passive.KNXNetIPMessage;
+import org.apache.plc4x.java.knxnetip.passive.io.KNXNetIPMessageIO;
import org.apache.plc4x.java.utils.MessageIO;
import org.apache.plc4x.java.utils.ParseException;
import org.apache.plc4x.java.utils.ReadBuffer;
@@ -38,7 +38,7 @@ public class KnxNetIpProtocol extends GeneratedDriverByteToMessageCodec<KNXNetIP
@Override
public void serialize(WriteBuffer io, KNXNetIPMessage value) throws ParseException {
- KNXNetIPMessageIO.serialize(io, value);
+ // Ignore.
}
});
}
diff --git a/sandbox/test-java-knxnetip-driver/src/main/resources/META-INF/services/org.apache.plc4x.java.spi.PlcDriver b/sandbox/test-java-passive-knxnetip-driver/src/main/resources/META-INF/services/org.apache.plc4x.java.spi.PlcDriver
similarity index 92%
copy from sandbox/test-java-knxnetip-driver/src/main/resources/META-INF/services/org.apache.plc4x.java.spi.PlcDriver
copy to sandbox/test-java-passive-knxnetip-driver/src/main/resources/META-INF/services/org.apache.plc4x.java.spi.PlcDriver
index afe85bf..087e7e6 100644
--- a/sandbox/test-java-knxnetip-driver/src/main/resources/META-INF/services/org.apache.plc4x.java.spi.PlcDriver
+++ b/sandbox/test-java-passive-knxnetip-driver/src/main/resources/META-INF/services/org.apache.plc4x.java.spi.PlcDriver
@@ -16,4 +16,4 @@
# specific language governing permissions and limitations
# under the License.
#
-org.apache.plc4x.java.knxnetip.PassiveKnxNetIpDriver
+org.apache.plc4x.java.passive.knxnetip.PassiveKnxNetIpDriver
diff --git a/sandbox/test-java-passive-knxnetip-driver/src/test/java/org/apache/plc4x/java/knxnetip/IOTest.java b/sandbox/test-java-passive-knxnetip-driver/src/test/java/org/apache/plc4x/java/knxnetip/IOTest.java
new file mode 100644
index 0000000..952ff89
--- /dev/null
+++ b/sandbox/test-java-passive-knxnetip-driver/src/test/java/org/apache/plc4x/java/knxnetip/IOTest.java
@@ -0,0 +1,79 @@
+/*
+ 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.knxnetip;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.xml.XmlMapper;
+import org.apache.commons.codec.binary.Hex;
+import org.apache.plc4x.java.knxnetip.passive.KNXNetIPMessage;
+import org.apache.plc4x.java.knxnetip.passive.io.KNXNetIPMessageIO;
+import org.apache.plc4x.java.utils.ReadBuffer;
+import org.apache.plc4x.java.utils.WriteBuffer;
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+
+public class IOTest {
+
+ @Test
+ public void testXml() throws Exception {
+ byte[] rData = Hex.decodeHex("06100420001c046b00002b0703010504024502bc360a1e0ce100810d");
+ ObjectMapper mapper = new XmlMapper().enableDefaultTyping();
+ ReadBuffer rBuf = new ReadBuffer(rData);
+ KNXNetIPMessage packet = new KNXNetIPMessageIO().parse(rBuf);
+ String xml = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(packet);
+ System.out.println(xml);
+ KNXNetIPMessage pack2 = mapper.readValue(xml, KNXNetIPMessage.class);
+ System.out.println(pack2);
+ }
+
+ @Test
+ public void testJson() throws Exception {
+ byte[] rData = Hex.decodeHex("0610020500180801c0a82a46c4090801c0a82a46c40a0203");
+ ObjectMapper mapper = new ObjectMapper().enableDefaultTyping();
+ ReadBuffer rBuf = new ReadBuffer(rData);
+ KNXNetIPMessage packet = new KNXNetIPMessageIO().parse(rBuf);
+ String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(packet);
+ System.out.println(json);
+ KNXNetIPMessage pack2 = mapper.readValue(json, KNXNetIPMessage.class);
+ System.out.println(pack2);
+ }
+
+ @Test
+ public void testParser() throws Exception {
+ byte[] rData = Hex.decodeHex("0610020500180801c0a82a46c4090801c0a82a46c40a0203");
+ long start = System.currentTimeMillis();
+ int numRunsParse = 20000;
+
+ KNXNetIPMessageIO knxNetIPMessageIO = new KNXNetIPMessageIO();
+
+ // Benchmark the parsing code
+ KNXNetIPMessage packet = null;
+ for(int i = 0; i < numRunsParse; i++) {
+ ReadBuffer rBuf = new ReadBuffer(rData);
+ packet = knxNetIPMessageIO.parse(rBuf);
+ }
+ long endParsing = System.currentTimeMillis();
+
+ System.out.println("Parsed " + numRunsParse + " packets in " + (endParsing - start) + "ms");
+ System.out.println("That's " + ((float) (endParsing - start) / numRunsParse) + "ms per packet");
+ }
+
+}
diff --git a/sandbox/test-java-passive-knxnetip-driver/src/test/java/org/apache/plc4x/java/knxnetip/KNXNetIpTest.java b/sandbox/test-java-passive-knxnetip-driver/src/test/java/org/apache/plc4x/java/knxnetip/KNXNetIpTest.java
new file mode 100644
index 0000000..b968eeb
--- /dev/null
+++ b/sandbox/test-java-passive-knxnetip-driver/src/test/java/org/apache/plc4x/java/knxnetip/KNXNetIpTest.java
@@ -0,0 +1,30 @@
+/*
+ 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.knxnetip;
+
+import org.apache.plc4x.protocol.test.ProtocolTestsuiteRunner;
+
+public class KNXNetIpTest extends ProtocolTestsuiteRunner {
+
+ public KNXNetIpTest() {
+ super("/testsuite/KNXNetIPTestsuite.xml");
+ }
+
+}
diff --git a/sandbox/test-java-passive-knxnetip-driver/src/test/java/org/apache/plc4x/java/knxnetip/ManualKnxNetIp.java b/sandbox/test-java-passive-knxnetip-driver/src/test/java/org/apache/plc4x/java/knxnetip/ManualKnxNetIp.java
new file mode 100644
index 0000000..bc8253b
--- /dev/null
+++ b/sandbox/test-java-passive-knxnetip-driver/src/test/java/org/apache/plc4x/java/knxnetip/ManualKnxNetIp.java
@@ -0,0 +1,27 @@
+/*
+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.knxnetip;
+
+public class ManualKnxNetIp {
+
+ public static void main(String[] args) {
+
+ }
+
+}
diff --git a/sandbox/test-java-passive-knxnetip-driver/src/test/resources/testsuite/KNXNetIPTestsuite.xml b/sandbox/test-java-passive-knxnetip-driver/src/test/resources/testsuite/KNXNetIPTestsuite.xml
new file mode 100644
index 0000000..10fb85c
--- /dev/null
+++ b/sandbox/test-java-passive-knxnetip-driver/src/test/resources/testsuite/KNXNetIPTestsuite.xml
@@ -0,0 +1,544 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+<test:testsuite xmlns:test="https://plc4x.apache.org/schemas/testsuite.xsd">
+
+ <name>KNXNet/IP</name>
+
+ <testcase>
+ <name>Search Request</name>
+ <raw>06100201000e0801c0a82a46ef8e</raw>
+ <root-type>KNXNetIPMessage</root-type>
+ <xml>
+ <SearchRequest className="org.apache.plc4x.java.knxnetip.readwrite.SearchRequest">
+ <hpaiIDiscoveryEndpoint>
+ <hostProtocolCode>1</hostProtocolCode>
+ <ipAddress>
+ <addr>
+ <addr>192</addr>
+ <addr>168</addr>
+ <addr>42</addr>
+ <addr>70</addr>
+ </addr>
+ </ipAddress>
+ <ipPort>61326</ipPort>
+ </hpaiIDiscoveryEndpoint>
+ </SearchRequest>
+ </xml>
+ </testcase>
+
+ <testcase>
+ <name>Search Response</name>
+ <raw>06100202004c0801c0a82a0b0e5736010200ffff000000082d409852e000170c000ab327553647697261204b4e582f49502d5363686e6974747374656c6c6500000000000802020103010401</raw>
+ <root-type>KNXNetIPMessage</root-type>
+ <xml>
+ <SearchResponse className="org.apache.plc4x.java.knxnetip.readwrite.SearchResponse">
+ <hpaiControlEndpoint>
+ <hostProtocolCode>1</hostProtocolCode>
+ <ipAddress>
+ <addr>
+ <addr>192</addr>
+ <addr>168</addr>
+ <addr>42</addr>
+ <addr>11</addr>
+ </addr>
+ </ipAddress>
+ <ipPort>3671</ipPort>
+ </hpaiControlEndpoint>
+ <dibDeviceInfo>
+ <descriptionType>1</descriptionType>
+ <knxMedium>2</knxMedium>
+ <deviceStatus>
+ <programMode>false</programMode>
+ </deviceStatus>
+ <knxAddress>
+ <mainGroup>15</mainGroup>
+ <middleGroup>15</middleGroup>
+ <subGroup>255</subGroup>
+ </knxAddress>
+ <projectInstallationIdentifier>
+ <projectNumber>0</projectNumber>
+ <installationNumber>0</installationNumber>
+ </projectInstallationIdentifier>
+ <knxNetIpDeviceSerialNumber>
+ <knxNetIpDeviceSerialNumber>0</knxNetIpDeviceSerialNumber>
+ <knxNetIpDeviceSerialNumber>8</knxNetIpDeviceSerialNumber>
+ <knxNetIpDeviceSerialNumber>45</knxNetIpDeviceSerialNumber>
+ <knxNetIpDeviceSerialNumber>64</knxNetIpDeviceSerialNumber>
+ <knxNetIpDeviceSerialNumber>152</knxNetIpDeviceSerialNumber>
+ <knxNetIpDeviceSerialNumber>82</knxNetIpDeviceSerialNumber>
+ </knxNetIpDeviceSerialNumber>
+ <knxNetIpDeviceMulticastAddress>
+ <addr>
+ <addr>224</addr>
+ <addr>0</addr>
+ <addr>23</addr>
+ <addr>12</addr>
+ </addr>
+ </knxNetIpDeviceMulticastAddress>
+ <knxNetIpDeviceMacAddress>
+ <addr>
+ <addr>0</addr>
+ <addr>10</addr>
+ <addr>179</addr>
+ <addr>39</addr>
+ <addr>85</addr>
+ <addr>54</addr>
+ </addr>
+ </knxNetIpDeviceMacAddress>
+ <deviceFriendlyName>
+ <deviceFriendlyName>71</deviceFriendlyName>
+ <deviceFriendlyName>105</deviceFriendlyName>
+ <deviceFriendlyName>114</deviceFriendlyName>
+ <deviceFriendlyName>97</deviceFriendlyName>
+ <deviceFriendlyName>32</deviceFriendlyName>
+ <deviceFriendlyName>75</deviceFriendlyName>
+ <deviceFriendlyName>78</deviceFriendlyName>
+ <deviceFriendlyName>88</deviceFriendlyName>
+ <deviceFriendlyName>47</deviceFriendlyName>
+ <deviceFriendlyName>73</deviceFriendlyName>
+ <deviceFriendlyName>80</deviceFriendlyName>
+ <deviceFriendlyName>45</deviceFriendlyName>
+ <deviceFriendlyName>83</deviceFriendlyName>
+ <deviceFriendlyName>99</deviceFriendlyName>
+ <deviceFriendlyName>104</deviceFriendlyName>
+ <deviceFriendlyName>110</deviceFriendlyName>
+ <deviceFriendlyName>105</deviceFriendlyName>
+ <deviceFriendlyName>116</deviceFriendlyName>
+ <deviceFriendlyName>116</deviceFriendlyName>
+ <deviceFriendlyName>115</deviceFriendlyName>
+ <deviceFriendlyName>116</deviceFriendlyName>
+ <deviceFriendlyName>101</deviceFriendlyName>
+ <deviceFriendlyName>108</deviceFriendlyName>
+ <deviceFriendlyName>108</deviceFriendlyName>
+ <deviceFriendlyName>101</deviceFriendlyName>
+ <deviceFriendlyName>0</deviceFriendlyName>
+ <deviceFriendlyName>0</deviceFriendlyName>
+ <deviceFriendlyName>0</deviceFriendlyName>
+ <deviceFriendlyName>0</deviceFriendlyName>
+ <deviceFriendlyName>0</deviceFriendlyName>
+ </deviceFriendlyName>
+ </dibDeviceInfo>
+ <dibSuppSvcFamilies>
+ <descriptionType>2</descriptionType>
+ <serviceIds>
+ <serviceIds className="org.apache.plc4x.java.knxnetip.readwrite.KnxNetIpCore">
+ <version>1</version>
+ </serviceIds>
+ <serviceIds className="org.apache.plc4x.java.knxnetip.readwrite.KnxNetIpDeviceManagement">
+ <version>1</version>
+ </serviceIds>
+ <serviceIds className="org.apache.plc4x.java.knxnetip.readwrite.KnxNetIpTunneling">
+ <version>1</version>
+ </serviceIds>
+ </serviceIds>
+ </dibSuppSvcFamilies>
+ </SearchResponse>
+ </xml>
+ </testcase>
+
+ <testcase>
+ <name>Description Request</name>
+ <raw>06100203000e0801000000000000</raw>
+ <root-type>KNXNetIPMessage</root-type>
+ <xml>
+ <DescriptionRequest className="org.apache.plc4x.java.knxnetip.readwrite.DescriptionRequest">
+ <hpaiControlEndpoint>
+ <hostProtocolCode>1</hostProtocolCode>
+ <ipAddress>
+ <addr>
+ <addr>0</addr>
+ <addr>0</addr>
+ <addr>0</addr>
+ <addr>0</addr>
+ </addr>
+ </ipAddress>
+ <ipPort>0</ipPort>
+ </hpaiControlEndpoint>
+ </DescriptionRequest>
+ </xml>
+ </testcase>
+
+ <testcase>
+ <name>Description Response</name>
+ <raw>06100204004436010200ffff000000082d409852e000170c000ab327553647697261204b4e582f49502d5363686e6974747374656c6c6500000000000802020103010401</raw>
+ <root-type>KNXNetIPMessage</root-type>
+ <xml>
+ <DescriptionResponse className="org.apache.plc4x.java.knxnetip.readwrite.DescriptionResponse">
+ <dibDeviceInfo>
+ <descriptionType>1</descriptionType>
+ <knxMedium>2</knxMedium>
+ <deviceStatus>
+ <programMode>false</programMode>
+ </deviceStatus>
+ <knxAddress>
+ <mainGroup>15</mainGroup>
+ <middleGroup>15</middleGroup>
+ <subGroup>255</subGroup>
+ </knxAddress>
+ <projectInstallationIdentifier>
+ <projectNumber>0</projectNumber>
+ <installationNumber>0</installationNumber>
+ </projectInstallationIdentifier>
+ <knxNetIpDeviceSerialNumber>
+ <knxNetIpDeviceSerialNumber>0</knxNetIpDeviceSerialNumber>
+ <knxNetIpDeviceSerialNumber>8</knxNetIpDeviceSerialNumber>
+ <knxNetIpDeviceSerialNumber>45</knxNetIpDeviceSerialNumber>
+ <knxNetIpDeviceSerialNumber>64</knxNetIpDeviceSerialNumber>
+ <knxNetIpDeviceSerialNumber>152</knxNetIpDeviceSerialNumber>
+ <knxNetIpDeviceSerialNumber>82</knxNetIpDeviceSerialNumber>
+ </knxNetIpDeviceSerialNumber>
+ <knxNetIpDeviceMulticastAddress>
+ <addr>
+ <addr>224</addr>
+ <addr>0</addr>
+ <addr>23</addr>
+ <addr>12</addr>
+ </addr>
+ </knxNetIpDeviceMulticastAddress>
+ <knxNetIpDeviceMacAddress>
+ <addr>
+ <addr>0</addr>
+ <addr>10</addr>
+ <addr>179</addr>
+ <addr>39</addr>
+ <addr>85</addr>
+ <addr>54</addr>
+ </addr>
+ </knxNetIpDeviceMacAddress>
+ <deviceFriendlyName>
+ <deviceFriendlyName>71</deviceFriendlyName>
+ <deviceFriendlyName>105</deviceFriendlyName>
+ <deviceFriendlyName>114</deviceFriendlyName>
+ <deviceFriendlyName>97</deviceFriendlyName>
+ <deviceFriendlyName>32</deviceFriendlyName>
+ <deviceFriendlyName>75</deviceFriendlyName>
+ <deviceFriendlyName>78</deviceFriendlyName>
+ <deviceFriendlyName>88</deviceFriendlyName>
+ <deviceFriendlyName>47</deviceFriendlyName>
+ <deviceFriendlyName>73</deviceFriendlyName>
+ <deviceFriendlyName>80</deviceFriendlyName>
+ <deviceFriendlyName>45</deviceFriendlyName>
+ <deviceFriendlyName>83</deviceFriendlyName>
+ <deviceFriendlyName>99</deviceFriendlyName>
+ <deviceFriendlyName>104</deviceFriendlyName>
+ <deviceFriendlyName>110</deviceFriendlyName>
+ <deviceFriendlyName>105</deviceFriendlyName>
+ <deviceFriendlyName>116</deviceFriendlyName>
+ <deviceFriendlyName>116</deviceFriendlyName>
+ <deviceFriendlyName>115</deviceFriendlyName>
+ <deviceFriendlyName>116</deviceFriendlyName>
+ <deviceFriendlyName>101</deviceFriendlyName>
+ <deviceFriendlyName>108</deviceFriendlyName>
+ <deviceFriendlyName>108</deviceFriendlyName>
+ <deviceFriendlyName>101</deviceFriendlyName>
+ <deviceFriendlyName>0</deviceFriendlyName>
+ <deviceFriendlyName>0</deviceFriendlyName>
+ <deviceFriendlyName>0</deviceFriendlyName>
+ <deviceFriendlyName>0</deviceFriendlyName>
+ <deviceFriendlyName>0</deviceFriendlyName>
+ </deviceFriendlyName>
+ </dibDeviceInfo>
+ <dibSuppSvcFamilies>
+ <descriptionType>2</descriptionType>
+ <serviceIds>
+ <serviceIds className="org.apache.plc4x.java.knxnetip.readwrite.KnxNetIpCore">
+ <version>1</version>
+ </serviceIds>
+ <serviceIds className="org.apache.plc4x.java.knxnetip.readwrite.KnxNetIpDeviceManagement">
+ <version>1</version>
+ </serviceIds>
+ <serviceIds className="org.apache.plc4x.java.knxnetip.readwrite.KnxNetIpTunneling">
+ <version>1</version>
+ </serviceIds>
+ </serviceIds>
+ </dibSuppSvcFamilies>
+ </DescriptionResponse>
+ </xml>
+ </testcase>
+
+ <testcase>
+ <name>Connect Request</name>
+ <raw>06100205001a0801c0a82a46f4310801c0a82a46f43204040200</raw>
+ <root-type>KNXNetIPMessage</root-type>
+ <xml>
+ <ConnectionRequest className="org.apache.plc4x.java.knxnetip.readwrite.ConnectionRequest">
+ <hpaiDiscoveryEndpoint>
+ <hostProtocolCode>1</hostProtocolCode>
+ <ipAddress>
+ <addr>
+ <addr>192</addr>
+ <addr>168</addr>
+ <addr>42</addr>
+ <addr>70</addr>
+ </addr>
+ </ipAddress>
+ <ipPort>62513</ipPort>
+ </hpaiDiscoveryEndpoint>
+ <hpaiDataEndpoint>
+ <hostProtocolCode>1</hostProtocolCode>
+ <ipAddress>
+ <addr>
+ <addr>192</addr>
+ <addr>168</addr>
+ <addr>42</addr>
+ <addr>70</addr>
+ </addr>
+ </ipAddress>
+ <ipPort>62514</ipPort>
+ </hpaiDataEndpoint>
+ <connectionRequestInformation className="org.apache.plc4x.java.knxnetip.readwrite.ConnectionRequestInformationTunnelConnection">
+ <knxLayer>2</knxLayer>
+ </connectionRequestInformation>
+ </ConnectionRequest>
+ </xml>
+ </testcase>
+
+ <testcase>
+ <name>Connect Response</name>
+ <raw>06100206001466000801c0a82a0b0e5704041101</raw>
+ <root-type>KNXNetIPMessage</root-type>
+ <xml>
+ <ConnectionResponse className="org.apache.plc4x.java.knxnetip.readwrite.ConnectionResponse">
+ <communicationChannelId>102</communicationChannelId>
+ <status>0</status>
+ <hpaiDataEndpoint>
+ <hostProtocolCode>1</hostProtocolCode>
+ <ipAddress>
+ <addr>
+ <addr>192</addr>
+ <addr>168</addr>
+ <addr>42</addr>
+ <addr>11</addr>
+ </addr>
+ </ipAddress>
+ <ipPort>3671</ipPort>
+ </hpaiDataEndpoint>
+ <connectionResponseDataBlock className="org.apache.plc4x.java.knxnetip.readwrite.ConnectionResponseDataBlockTunnelConnection">
+ <knxAddress>
+ <mainGroup>1</mainGroup>
+ <middleGroup>1</middleGroup>
+ <subGroup>1</subGroup>
+ </knxAddress>
+ </connectionResponseDataBlock>
+ </ConnectionResponse>
+ </xml>
+ </testcase>
+
+ <testcase>
+ <name>Connection State Request</name>
+ <raw>06100207001066000801c0a82a46f431</raw>
+ <root-type>KNXNetIPMessage</root-type>
+ <xml>
+ <ConnectionStateRequest className="org.apache.plc4x.java.knxnetip.readwrite.ConnectionStateRequest">
+ <communicationChannelId>102</communicationChannelId>
+ <hpaiControlEndpoint>
+ <hostProtocolCode>1</hostProtocolCode>
+ <ipAddress>
+ <addr>
+ <addr>192</addr>
+ <addr>168</addr>
+ <addr>42</addr>
+ <addr>70</addr>
+ </addr>
+ </ipAddress>
+ <ipPort>62513</ipPort>
+ </hpaiControlEndpoint>
+ </ConnectionStateRequest>
+ </xml>
+ </testcase>
+
+ <testcase>
+ <name>Connection State Response</name>
+ <raw>0610020800086600</raw>
+ <root-type>KNXNetIPMessage</root-type>
+ <xml>
+ <ConnectionStateResponse className="org.apache.plc4x.java.knxnetip.readwrite.ConnectionStateResponse">
+ <communicationChannelId>102</communicationChannelId>
+ <status>0</status>
+ </ConnectionStateResponse>
+ </xml>
+ </testcase>
+
+ <testcase>
+ <name>Device Configuration Request</name>
+ <raw>06100310001104670000fc000001531001</raw>
+ <root-type>KNXNetIPMessage</root-type>
+ <xml>
+ <DeviceConfigurationRequest className="org.apache.plc4x.java.knxnetip.readwrite.DeviceConfigurationRequest">
+ <deviceConfigurationRequestDataBlock>
+ <communicationChannelId>103</communicationChannelId>
+ <sequenceCounter>0</sequenceCounter>
+ </deviceConfigurationRequestDataBlock>
+ <cemi className="org.apache.plc4x.java.knxnetip.readwrite.CEMIMPropReadReq">
+ <interfaceObjectType>0</interfaceObjectType>
+ <objectInstance>1</objectInstance>
+ <propertyId>83</propertyId>
+ <numberOfElements>1</numberOfElements>
+ <startIndex>1</startIndex>
+ </cemi>
+ </DeviceConfigurationRequest>
+ </xml>
+ </testcase>
+
+ <testcase>
+ <name>Device Configuration Ack</name>
+ <raw>06100311000a04670000</raw>
+ <root-type>KNXNetIPMessage</root-type>
+ <xml>
+ <DeviceConfigurationAck className="org.apache.plc4x.java.knxnetip.readwrite.DeviceConfigurationAck">
+ <deviceConfigurationAckDataBlock>
+ <communicationChannelId>103</communicationChannelId>
+ <sequenceCounter>0</sequenceCounter>
+ <status>0</status>
+ </deviceConfigurationAckDataBlock>
+ </DeviceConfigurationAck>
+ </xml>
+ </testcase>
+
+ <testcase>
+ <name>Disconnect Request</name>
+ <raw>06100209001067000801c0a82a46f431</raw>
+ <root-type>KNXNetIPMessage</root-type>
+ <xml>
+ <DisconnectRequest className="org.apache.plc4x.java.knxnetip.readwrite.DisconnectRequest">
+ <communicationChannelId>103</communicationChannelId>
+ <hpaiControlEndpoint>
+ <hostProtocolCode>1</hostProtocolCode>
+ <ipAddress>
+ <addr>
+ <addr>192</addr>
+ <addr>168</addr>
+ <addr>42</addr>
+ <addr>70</addr>
+ </addr>
+ </ipAddress>
+ <ipPort>62513</ipPort>
+ </hpaiControlEndpoint>
+ </DisconnectRequest>
+ </xml>
+ </testcase>
+
+ <testcase>
+ <name>Disconnect Response</name>
+ <raw>0610020a00086600</raw>
+ <root-type>KNXNetIPMessage</root-type>
+ <xml>
+ <DisconnectResponse className="org.apache.plc4x.java.knxnetip.readwrite.DisconnectResponse">
+ <communicationChannelId>102</communicationChannelId>
+ <status>0</status>
+ </DisconnectResponse>
+ </xml>
+ </testcase>
+
+ <testcase>
+ <name>Tunneling Request</name>
+ <raw>06100420001c046b00002b0703010504024502bc360a1e0ce100810d</raw>
+ <root-type>KNXNetIPMessage</root-type>
+ <xml>
+ <TunnelingRequest className="org.apache.plc4x.java.knxnetip.readwrite.TunnelingRequest">
+ <tunnelingRequestDataBlock>
+ <communicationChannelId>107</communicationChannelId>
+ <sequenceCounter>0</sequenceCounter>
+ </tunnelingRequestDataBlock>
+ <cemi className="org.apache.plc4x.java.knxnetip.readwrite.CEMILBusmonInd">
+ <additionalInformationLength>7</additionalInformationLength>
+ <additionalInformation>
+ <additionalInformation className="org.apache.plc4x.java.knxnetip.readwrite.CEMIAdditionalInformationBusmonitorInfo">
+ <frameErrorFlag>false</frameErrorFlag>
+ <bitErrorFlag>false</bitErrorFlag>
+ <parityErrorFlag>false</parityErrorFlag>
+ <unknownFlag>false</unknownFlag>
+ <lostFlag>false</lostFlag>
+ <sequenceNumber>5</sequenceNumber>
+ </additionalInformation>
+ <additionalInformation className="org.apache.plc4x.java.knxnetip.readwrite.CEMIAdditionalInformationRelativeTimestamp">
+ <relativeTimestamp>
+ <timestamp>17666</timestamp>
+ </relativeTimestamp>
+ </additionalInformation>
+ </additionalInformation>
+ <rawFrame>
+ <rawFrame>188</rawFrame>
+ <rawFrame>54</rawFrame>
+ <rawFrame>10</rawFrame>
+ <rawFrame>30</rawFrame>
+ <rawFrame>12</rawFrame>
+ <rawFrame>225</rawFrame>
+ <rawFrame>0</rawFrame>
+ <rawFrame>129</rawFrame>
+ <rawFrame>13</rawFrame>
+ </rawFrame>
+ </cemi>
+ </TunnelingRequest>
+
+ </xml>
+ </testcase>
+
+ <testcase>
+ <name>Tunneling Response</name>
+ <raw>06100421000a046b0000</raw>
+ <root-type>KNXNetIPMessage</root-type>
+ <xml>
+ <TunnelingResponse className="org.apache.plc4x.java.knxnetip.readwrite.TunnelingResponse">
+ <tunnelingResponseDataBlock>
+ <communicationChannelId>107</communicationChannelId>
+ <sequenceCounter>0</sequenceCounter>
+ <status>0</status>
+ </tunnelingResponseDataBlock>
+ </TunnelingResponse>
+ </xml>
+ </testcase>
+
+ <testcase>
+ <name>Default</name>
+ <raw>0610020500180801c0a82a46c4090801c0a82a46c40a0203</raw>
+ <root-type>KNXNetIPMessage</root-type>
+ <xml>
+ <ConnectionRequest className="org.apache.plc4x.java.knxnetip.readwrite.ConnectionRequest">
+ <hpaiDiscoveryEndpoint>
+ <hostProtocolCode>1</hostProtocolCode>
+ <ipAddress>
+ <addr>
+ <addr>192</addr>
+ <addr>168</addr>
+ <addr>42</addr>
+ <addr>70</addr>
+ </addr>
+ </ipAddress>
+ <ipPort>50185</ipPort>
+ </hpaiDiscoveryEndpoint>
+ <hpaiDataEndpoint>
+ <hostProtocolCode>1</hostProtocolCode>
+ <ipAddress>
+ <addr>
+ <addr>192</addr>
+ <addr>168</addr>
+ <addr>42</addr>
+ <addr>70</addr>
+ </addr>
+ </ipAddress>
+ <ipPort>50186</ipPort>
+ </hpaiDataEndpoint>
+ <connectionRequestInformation className="org.apache.plc4x.java.knxnetip.readwrite.ConnectionRequestInformationDeviceManagement"/>
+ </ConnectionRequest>
+ </xml>
+ </testcase>
+
+</test:testsuite>
\ No newline at end of file