├── assets ├── readme_architecture.odg └── readme_architecture.png ├── src ├── test │ ├── resources │ │ ├── plugin │ │ │ └── my-test-plugin.jar │ │ ├── knxproj │ │ │ ├── Project (2-Level, v20).knxproj │ │ │ ├── Project (3-Level, v14).knxproj │ │ │ ├── Project (3-Level, v20).knxproj │ │ │ ├── Project Scheme14 v01.00.00.pdf │ │ │ ├── Project Scheme20 v01.00.00.pdf │ │ │ ├── Project (Free-Level, v14).knxproj │ │ │ ├── Project (Free-Level, v20).knxproj │ │ │ ├── Corrupted Project (Incomplete).knxproj │ │ │ ├── Corrupted Project (No Project Id).knxproj │ │ │ ├── Empty Project (No Group Addresses).knxproj │ │ │ ├── Corrupted Project (No GroupAddress Id).knxproj │ │ │ ├── Corrupted Project (No GroupRange Id).knxproj │ │ │ ├── Corrupted Project (No GroupRange Name).knxproj │ │ │ ├── Corrupted Project (No GroupAddress Name).knxproj │ │ │ ├── Corrupted Project (No GroupAddress Address).knxproj │ │ │ ├── Corrupted Project (No GroupRange RangeEnd).knxproj │ │ │ ├── Corrupted Project (No GroupRange RangeStart).knxproj │ │ │ ├── Corrupted Project (No ProjectInformation Name).knxproj │ │ │ └── Corrupted Project (No ProjectInformation GroupAddressStyle).knxproj │ │ ├── junit-platform.properties │ │ ├── logback-off.xml │ │ └── logback.xml │ └── java │ │ └── li │ │ └── pitschmann │ │ └── knx │ │ └── core │ │ ├── test │ │ ├── data │ │ │ ├── TestPlugin.java │ │ │ ├── TestConstructorExceptionPlugin.java │ │ │ ├── TestExtensionPlugin.java │ │ │ ├── TestMethodExceptionPlugin.java │ │ │ └── TestObserverPlugin.java │ │ ├── action │ │ │ ├── MockAction.java │ │ │ ├── WaitDelayMockAction.java │ │ │ ├── RequestMockAction.java │ │ │ └── WaitServiceTypeMockAction.java │ │ ├── strategy │ │ │ ├── ConnectStrategy.java │ │ │ ├── ConnectionStateStrategy.java │ │ │ ├── DiscoveryStrategy.java │ │ │ ├── DescriptionStrategy.java │ │ │ ├── impl │ │ │ │ ├── ConnectNoMoreConnectionsStrategy.java │ │ │ │ ├── TunnelingWrongChannelIdStrategy.java │ │ │ │ ├── ConnectBadDataStrategy.java │ │ │ │ ├── DescriptionInvalidServiceStrategy.java │ │ │ │ ├── DescriptionBadDataStrategy.java │ │ │ │ ├── DescriptionNoTunnelingStrategy.java │ │ │ │ └── DefaultConnectionStateStrategy.java │ │ │ ├── ResponseStrategy.java │ │ │ ├── RequestStrategy.java │ │ │ ├── IgnoreStrategy.java │ │ │ ├── DisconnectStrategy.java │ │ │ └── TunnelingStrategy.java │ │ ├── body │ │ │ ├── MockResponseControlChannelBody.java │ │ │ └── MockResponseBody.java │ │ ├── MockServerHeartbeatMonitor.java │ │ └── MockServerChannel.java │ │ ├── config │ │ └── CoreConfigsTest.java │ │ ├── datapoint │ │ ├── DPT23Test.java │ │ └── value │ │ │ ├── DataPointValueTest.java │ │ │ └── DPTRawValueTest.java │ │ ├── knxproj │ │ ├── parser │ │ │ └── AbstractParserTest.java │ │ └── XmlGroupAddressTest.java │ │ ├── body │ │ └── BodyTest.java │ │ ├── address │ │ └── AddressTypeTest.java │ │ ├── dib │ │ └── ServiceTypeFamilyVersionTest.java │ │ ├── plugin │ │ ├── EnumConfigValueTest.java │ │ ├── PluginConfigValueTest.java │ │ └── BooleanConfigValueTest.java │ │ ├── cemi │ │ ├── BroadcastTypeTest.java │ │ └── AdditionalInfoTest.java │ │ ├── net │ │ ├── HostProtocolTest.java │ │ └── tunnel │ │ │ └── LayerTypeTest.java │ │ └── AbstractKnxByteEnumTest.java └── main │ └── java │ └── li │ └── pitschmann │ └── knx │ └── core │ ├── datapoint │ ├── value │ │ ├── PayloadOptimizable.java │ │ ├── DataPointEnumValue.java │ │ └── DataPointValue.java │ ├── DataPoint.java │ ├── BaseRangeDataPointType.java │ └── DPT25.java │ ├── plugin │ ├── BooleanConfigValue.java │ ├── LongConfigValue.java │ ├── DoubleConfigValue.java │ ├── StringConfigValue.java │ ├── IntegerConfigValue.java │ ├── PathConfigValue.java │ ├── EnumConfigValue.java │ ├── Plugin.java │ ├── ExtensionPlugin.java │ ├── ObserverPlugin.java │ └── PluginConfigValue.java │ ├── knxproj │ └── parser │ │ └── ParserStrategy.java │ ├── annotations │ └── Nullable.java │ ├── body │ ├── RequestBody.java │ ├── ResponseBody.java │ ├── DataChannelRelated.java │ ├── ControlChannelRelated.java │ ├── MulticastChannelRelated.java │ ├── DescriptionChannelRelated.java │ └── Body.java │ ├── KnxBytesEnum.java │ ├── SingleRawDataAware.java │ ├── KnxByteEnum.java │ ├── config │ └── InternalConfigValue.java │ ├── exceptions │ ├── KnxDataPointTypeNotFoundException.java │ ├── KnxProjectParserException.java │ ├── KnxPluginException.java │ ├── KnxNoTunnelingException.java │ ├── KnxException.java │ ├── KnxConfigurationException.java │ ├── KnxEnumNotFoundException.java │ ├── KnxCommunicationException.java │ ├── KnxNullPointerException.java │ ├── KnxDescriptionNotReceivedException.java │ ├── KnxUnknownBodyException.java │ ├── KnxBodyNotReceivedException.java │ ├── DataPointTypeIncompatibleBytesException.java │ ├── KnxServiceTypeHasNoResponseIdentifier.java │ ├── DataPointTypeIncompatibleSyntaxException.java │ ├── KnxIllegalArgumentException.java │ ├── KnxWrongChannelIdException.java │ ├── KnxDiscoveryNotReceivedException.java │ ├── KnxChannelIdNotReceivedException.java │ └── KnxUnsupportedAPCICodeException.java │ ├── MultiRawDataAware.java │ ├── KnxEnum.java │ ├── CEMIAware.java │ ├── address │ └── KnxAddress.java │ ├── ChannelIdAware.java │ ├── communication │ ├── communicator │ │ ├── DataChannelCommunicator.java │ │ ├── ControlChannelCommunicator.java │ │ ├── DescriptionChannelCommunicator.java │ │ └── ControlAndDataChannelCommunicator.java │ ├── queue │ │ ├── DefaultInboxQueue.java │ │ ├── DefaultOutboxQueue.java │ │ ├── MulticastInboxQueue.java │ │ └── MulticastOutboxQueue.java │ ├── event │ │ ├── RequestEvent.java │ │ ├── ResponseEvent.java │ │ └── KnxEvent.java │ └── task │ │ ├── SearchResponseTask.java │ │ ├── ConnectionStateResponseTask.java │ │ ├── DisconnectResponseTask.java │ │ └── DescriptionResponseTask.java │ ├── utils │ ├── Maps.java │ └── Strings.java │ ├── dib │ └── ServiceTypeFamilyVersion.java │ └── cemi │ └── BroadcastType.java ├── .gitignore ├── scripts └── clean-up-log-files.sh └── .github └── workflows └── build.yml /assets/readme_architecture.odg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pitschr/knx-core/HEAD/assets/readme_architecture.odg -------------------------------------------------------------------------------- /assets/readme_architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pitschr/knx-core/HEAD/assets/readme_architecture.png -------------------------------------------------------------------------------- /src/test/resources/plugin/my-test-plugin.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pitschr/knx-core/HEAD/src/test/resources/plugin/my-test-plugin.jar -------------------------------------------------------------------------------- /src/test/resources/knxproj/Project (2-Level, v20).knxproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pitschr/knx-core/HEAD/src/test/resources/knxproj/Project (2-Level, v20).knxproj -------------------------------------------------------------------------------- /src/test/resources/knxproj/Project (3-Level, v14).knxproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pitschr/knx-core/HEAD/src/test/resources/knxproj/Project (3-Level, v14).knxproj -------------------------------------------------------------------------------- /src/test/resources/knxproj/Project (3-Level, v20).knxproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pitschr/knx-core/HEAD/src/test/resources/knxproj/Project (3-Level, v20).knxproj -------------------------------------------------------------------------------- /src/test/resources/knxproj/Project Scheme14 v01.00.00.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pitschr/knx-core/HEAD/src/test/resources/knxproj/Project Scheme14 v01.00.00.pdf -------------------------------------------------------------------------------- /src/test/resources/knxproj/Project Scheme20 v01.00.00.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pitschr/knx-core/HEAD/src/test/resources/knxproj/Project Scheme20 v01.00.00.pdf -------------------------------------------------------------------------------- /src/test/resources/knxproj/Project (Free-Level, v14).knxproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pitschr/knx-core/HEAD/src/test/resources/knxproj/Project (Free-Level, v14).knxproj -------------------------------------------------------------------------------- /src/test/resources/knxproj/Project (Free-Level, v20).knxproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pitschr/knx-core/HEAD/src/test/resources/knxproj/Project (Free-Level, v20).knxproj -------------------------------------------------------------------------------- /src/test/resources/knxproj/Corrupted Project (Incomplete).knxproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pitschr/knx-core/HEAD/src/test/resources/knxproj/Corrupted Project (Incomplete).knxproj -------------------------------------------------------------------------------- /src/test/resources/knxproj/Corrupted Project (No Project Id).knxproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pitschr/knx-core/HEAD/src/test/resources/knxproj/Corrupted Project (No Project Id).knxproj -------------------------------------------------------------------------------- /src/test/resources/knxproj/Empty Project (No Group Addresses).knxproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pitschr/knx-core/HEAD/src/test/resources/knxproj/Empty Project (No Group Addresses).knxproj -------------------------------------------------------------------------------- /src/test/resources/knxproj/Corrupted Project (No GroupAddress Id).knxproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pitschr/knx-core/HEAD/src/test/resources/knxproj/Corrupted Project (No GroupAddress Id).knxproj -------------------------------------------------------------------------------- /src/test/resources/knxproj/Corrupted Project (No GroupRange Id).knxproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pitschr/knx-core/HEAD/src/test/resources/knxproj/Corrupted Project (No GroupRange Id).knxproj -------------------------------------------------------------------------------- /src/test/resources/knxproj/Corrupted Project (No GroupRange Name).knxproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pitschr/knx-core/HEAD/src/test/resources/knxproj/Corrupted Project (No GroupRange Name).knxproj -------------------------------------------------------------------------------- /src/test/resources/knxproj/Corrupted Project (No GroupAddress Name).knxproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pitschr/knx-core/HEAD/src/test/resources/knxproj/Corrupted Project (No GroupAddress Name).knxproj -------------------------------------------------------------------------------- /src/test/resources/knxproj/Corrupted Project (No GroupAddress Address).knxproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pitschr/knx-core/HEAD/src/test/resources/knxproj/Corrupted Project (No GroupAddress Address).knxproj -------------------------------------------------------------------------------- /src/test/resources/knxproj/Corrupted Project (No GroupRange RangeEnd).knxproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pitschr/knx-core/HEAD/src/test/resources/knxproj/Corrupted Project (No GroupRange RangeEnd).knxproj -------------------------------------------------------------------------------- /src/test/resources/knxproj/Corrupted Project (No GroupRange RangeStart).knxproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pitschr/knx-core/HEAD/src/test/resources/knxproj/Corrupted Project (No GroupRange RangeStart).knxproj -------------------------------------------------------------------------------- /src/test/resources/knxproj/Corrupted Project (No ProjectInformation Name).knxproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pitschr/knx-core/HEAD/src/test/resources/knxproj/Corrupted Project (No ProjectInformation Name).knxproj -------------------------------------------------------------------------------- /src/test/resources/knxproj/Corrupted Project (No ProjectInformation GroupAddressStyle).knxproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pitschr/knx-core/HEAD/src/test/resources/knxproj/Corrupted Project (No ProjectInformation GroupAddressStyle).knxproj -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore 'IntelliJ' folder/files 2 | .idea 3 | *.iml 4 | 5 | # Ignore 'eclipse' folder/files 6 | .settings 7 | .classpath 8 | .project 9 | 10 | # Ignore 'target' folder generated by maven 11 | target 12 | 13 | # Ignore 'log' files 14 | *.log 15 | *.log.*.gz 16 | -------------------------------------------------------------------------------- /src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.execution.parallel.enabled=true 2 | junit.jupiter.execution.parallel.mode.default=concurrent 3 | junit.jupiter.execution.parallel.mode.classes.default=concurrent 4 | junit.jupiter.execution.parallel.config.dynamic.factor=0.5 5 | -------------------------------------------------------------------------------- /scripts/clean-up-log-files.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # switch to knx-link folder (regardless where the script is executed) 4 | SCRIPTS_DIR="$( cd "$( dirname "${BASH_SOURCE}" )" >/dev/null 2>&1 && pwd )" 5 | cd $SCRIPTS_DIR/.. 6 | 7 | # delete 'knx.log' 8 | rm -f knx.log 9 | 10 | # delete all with: 11 | # knx-*.log 12 | # knx-*.log.0000-00-00.gz 13 | find knx-* -type f -regex '.*\.log\(\.[0-9-]+\.gz\)?$' -delete 14 | -------------------------------------------------------------------------------- /src/test/resources/logback-off.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/test/data/TestPlugin.java: -------------------------------------------------------------------------------- 1 | package li.pitschmann.knx.core.test.data; 2 | 3 | import li.pitschmann.knx.core.communication.KnxClient; 4 | import li.pitschmann.knx.core.plugin.Plugin; 5 | 6 | /** 7 | * Test {@link Plugin} implementation 8 | */ 9 | public final class TestPlugin implements Plugin { 10 | @Override 11 | public void onInitialization(final KnxClient client) { 12 | // NO-OP 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/datapoint/value/PayloadOptimizable.java: -------------------------------------------------------------------------------- 1 | package li.pitschmann.knx.core.datapoint.value; 2 | 3 | /** 4 | * A marker interface if the payload can be optimized and indicates that the 5 | * payload of {@link DataPointValue} can be optimized for the APCI data frame 6 | *

7 | * If the size {@link DataPointValue} is up to 6-bits only, then payload 8 | * is subject to be optimized according to the KNX specification. 9 | */ 10 | public interface PayloadOptimizable { 11 | // nothing... 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/plugin/BooleanConfigValue.java: -------------------------------------------------------------------------------- 1 | package li.pitschmann.knx.core.plugin; 2 | 3 | import java.util.function.Supplier; 4 | 5 | /** 6 | * Plugin Config Value for {@link Boolean} 7 | * 8 | * @author PITSCHR 9 | */ 10 | public final class BooleanConfigValue extends PluginConfigValue { 11 | 12 | public BooleanConfigValue(final String configName, final Supplier defaultSupplier) { 13 | super(configName, Boolean.class, Boolean::valueOf, defaultSupplier, null); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/config/CoreConfigsTest.java: -------------------------------------------------------------------------------- 1 | package li.pitschmann.knx.core.config; 2 | 3 | import li.pitschmann.knx.core.test.TestHelpers; 4 | import org.junit.jupiter.api.DisplayName; 5 | import org.junit.jupiter.api.Test; 6 | 7 | /** 8 | * Testing for {@link CoreConfigs} instance 9 | */ 10 | public class CoreConfigsTest { 11 | @Test 12 | @DisplayName("Constructor not instantiable") 13 | public void testConstructorNonInstantiable() { 14 | TestHelpers.assertThatNotInstantiable(CoreConfigs.class); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | [TEST] [%X{junitClass}.%X{junitMethod}] %date [%-5level] [%logger{40}:%line] - %msg%n 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/plugin/LongConfigValue.java: -------------------------------------------------------------------------------- 1 | package li.pitschmann.knx.core.plugin; 2 | 3 | import li.pitschmann.knx.core.annotations.Nullable; 4 | 5 | import java.util.function.Predicate; 6 | import java.util.function.Supplier; 7 | 8 | /** 9 | * Plugin Config Value for {@link Long} 10 | * 11 | * @author PITSCHR 12 | */ 13 | public final class LongConfigValue extends PluginConfigValue { 14 | 15 | public LongConfigValue(final String configName, final Supplier defaultSupplier, final @Nullable Predicate predicate) { 16 | super(configName, Long.class, Long::valueOf, defaultSupplier, predicate); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/plugin/DoubleConfigValue.java: -------------------------------------------------------------------------------- 1 | package li.pitschmann.knx.core.plugin; 2 | 3 | import li.pitschmann.knx.core.annotations.Nullable; 4 | 5 | import java.util.function.Predicate; 6 | import java.util.function.Supplier; 7 | 8 | /** 9 | * Plugin Config Value for {@link Double} 10 | * 11 | * @author PITSCHR 12 | */ 13 | public final class DoubleConfigValue extends PluginConfigValue { 14 | 15 | public DoubleConfigValue(final String configName, final Supplier defaultSupplier, final @Nullable Predicate predicate) { 16 | super(configName, Double.class, Double::valueOf, defaultSupplier, predicate); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/plugin/StringConfigValue.java: -------------------------------------------------------------------------------- 1 | package li.pitschmann.knx.core.plugin; 2 | 3 | import li.pitschmann.knx.core.annotations.Nullable; 4 | 5 | import java.util.function.Predicate; 6 | import java.util.function.Supplier; 7 | 8 | /** 9 | * Plugin Config Value for {@link String} 10 | * 11 | * @author PITSCHR 12 | */ 13 | public final class StringConfigValue extends PluginConfigValue { 14 | 15 | public StringConfigValue(final String configName, final Supplier defaultSupplier, final @Nullable Predicate predicate) { 16 | super(configName, String.class, String::valueOf, defaultSupplier, predicate); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/test/data/TestConstructorExceptionPlugin.java: -------------------------------------------------------------------------------- 1 | package li.pitschmann.knx.core.test.data; 2 | 3 | import li.pitschmann.knx.core.communication.KnxClient; 4 | import li.pitschmann.knx.core.plugin.Plugin; 5 | 6 | /** 7 | * Test {@link Plugin} implementation that is throwing 8 | * an {@link RuntimeException} in constructor. 9 | */ 10 | public final class TestConstructorExceptionPlugin implements Plugin { 11 | public TestConstructorExceptionPlugin() { 12 | throw new RuntimeException("Exception in constructor"); 13 | } 14 | 15 | @Override 16 | public void onInitialization(final KnxClient client) { 17 | // NO-OP 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/plugin/IntegerConfigValue.java: -------------------------------------------------------------------------------- 1 | package li.pitschmann.knx.core.plugin; 2 | 3 | import li.pitschmann.knx.core.annotations.Nullable; 4 | 5 | import java.util.function.Predicate; 6 | import java.util.function.Supplier; 7 | 8 | /** 9 | * Plugin Config Value for {@link Integer} 10 | * 11 | * @author PITSCHR 12 | */ 13 | public final class IntegerConfigValue extends PluginConfigValue { 14 | 15 | public IntegerConfigValue(final String configName, final Supplier defaultSupplier, final @Nullable Predicate predicate) { 16 | super(configName, Integer.class, Integer::valueOf, defaultSupplier, predicate); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/plugin/PathConfigValue.java: -------------------------------------------------------------------------------- 1 | package li.pitschmann.knx.core.plugin; 2 | 3 | import li.pitschmann.knx.core.annotations.Nullable; 4 | 5 | import java.nio.file.Path; 6 | import java.nio.file.Paths; 7 | import java.util.function.Predicate; 8 | import java.util.function.Supplier; 9 | 10 | /** 11 | * Plugin Config Value for {@link Path} 12 | * 13 | * @author PITSCHR 14 | */ 15 | public final class PathConfigValue extends PluginConfigValue { 16 | 17 | public PathConfigValue(final String configName, final Supplier defaultSupplier, final @Nullable Predicate predicate) { 18 | super(configName, Path.class, Paths::get, defaultSupplier, predicate); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/knxproj/parser/ParserStrategy.java: -------------------------------------------------------------------------------- 1 | package li.pitschmann.knx.core.knxproj.parser; 2 | 3 | import li.pitschmann.knx.core.knxproj.XmlProject; 4 | 5 | import javax.xml.stream.XMLStreamException; 6 | import java.util.zip.ZipFile; 7 | 8 | /** 9 | * Strategy for Project Data Parsers 10 | * 11 | * @author PITSCHR 12 | */ 13 | public interface ParserStrategy { 14 | 15 | /** 16 | * Loads project specific for given {@link XmlProject} and from {@link ZipFile} 17 | * 18 | * @param xmlProject the XML project instance 19 | * @param zipFile zip file of KNX project file to be parsed 20 | * @throws XMLStreamException If there was a XML stream error 21 | */ 22 | void load(final XmlProject xmlProject, final ZipFile zipFile) throws XMLStreamException; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/annotations/Nullable.java: -------------------------------------------------------------------------------- 1 | package li.pitschmann.knx.core.annotations; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * Annotation to declare that the field, parameter, local variable 11 | * or method return type may be null. 12 | *

13 | * This class is copied over to this class from 'com.google.code.findbugs:jsr305' 14 | * and will avoid potential library dependency because of only one class. 15 | *

16 | * If you are still reading ... I am still waiting for an official @Nullable annotation! 17 | */ 18 | @Documented 19 | @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE}) 20 | @Retention(RetentionPolicy.CLASS) 21 | public @interface Nullable { 22 | // marker annotation interface 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/body/RequestBody.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.body; 19 | 20 | /** 21 | * Marker interface for Request Body 22 | * 23 | * @author PITSCHR 24 | */ 25 | public interface RequestBody extends Body { 26 | // empty 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/body/ResponseBody.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.body; 19 | 20 | /** 21 | * Marker interface for Response Body 22 | * 23 | * @author PITSCHR 24 | */ 25 | public interface ResponseBody extends Body { 26 | // empty 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/body/DataChannelRelated.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.body; 19 | 20 | /** 21 | * Marker interface that this body is subject to be sent over data channel only. 22 | * 23 | * @author PITSCHR 24 | */ 25 | public interface DataChannelRelated { 26 | // empty 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/body/ControlChannelRelated.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.body; 19 | 20 | /** 21 | * Marker interface that this body is subject to be sent over control channel only. 22 | * 23 | * @author PITSCHR 24 | */ 25 | public interface ControlChannelRelated { 26 | // empty 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/body/MulticastChannelRelated.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.body; 19 | 20 | /** 21 | * Marker interface that this body is subject to be sent over multicast channel 22 | * 23 | * @author PITSCHR 24 | */ 25 | public interface MulticastChannelRelated { 26 | // empty 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/body/DescriptionChannelRelated.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.body; 19 | 20 | /** 21 | * Marker interface that this body is subject to be sent over description channel only. 22 | * 23 | * @author PITSCHR 24 | */ 25 | public interface DescriptionChannelRelated { 26 | // empty 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/plugin/EnumConfigValue.java: -------------------------------------------------------------------------------- 1 | package li.pitschmann.knx.core.plugin; 2 | 3 | import java.util.Objects; 4 | import java.util.function.Function; 5 | import java.util.function.Supplier; 6 | 7 | /** 8 | * Plugin Config Value for {@link Enum} 9 | * 10 | * @author PITSCHR 11 | */ 12 | public final class EnumConfigValue> extends PluginConfigValue { 13 | 14 | public EnumConfigValue(final String configName, 15 | final Class enumClass, 16 | final Supplier defaultSupplier) { 17 | super(configName, enumClass, createConverter(enumClass), defaultSupplier, Objects::nonNull); 18 | } 19 | 20 | /** 21 | * Create default converter for {@link Enum} instances 22 | * 23 | * @param enumClass the enumeration class for look-up 24 | * @param type of enumeration value 25 | * @return the enumeration value 26 | */ 27 | private static > Function createConverter(final Class enumClass) { 28 | return s -> Enum.valueOf(enumClass, s); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/test/action/MockAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.test.action; 19 | 20 | /** 21 | * Interface for mock actions if given criteria was meet 22 | */ 23 | public interface MockAction { 24 | /** 25 | * Applies if the given criteria was meet 26 | * 27 | * @return {@code true} if success (criteria meet), otherwise {@code false} 28 | */ 29 | boolean apply(); 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/KnxBytesEnum.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core; 19 | 20 | /** 21 | * Interface for {@link KnxEnum} which have a code with a size of 22 | * two or more bytes. 23 | * 24 | * @author PITSCHR 25 | */ 26 | public interface KnxBytesEnum extends KnxEnum { 27 | /** 28 | * Returns the {@link #getCode()} as byte array 29 | * 30 | * @return code as byte array 31 | */ 32 | byte[] getCodeAsBytes(); 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/SingleRawDataAware.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core; 19 | 20 | /** 21 | * Single Byte Raw Data Aware interface. 22 | *

23 | * Classes which implements this interface are aware of the raw data in single byte format. 24 | * 25 | * @author PITSCHR 26 | */ 27 | public interface SingleRawDataAware { 28 | /** 29 | * Returns the raw data in byte 30 | * 31 | * @return byte 32 | */ 33 | byte toByte(); 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/KnxByteEnum.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core; 19 | 20 | /** 21 | * Interface for {@link KnxEnum} which have a code with a size of 22 | * one byte. 23 | * 24 | * @author PITSCHR 25 | */ 26 | public interface KnxByteEnum extends KnxEnum { 27 | /** 28 | * Returns the {@link #getCode()} as byte 29 | * 30 | * @return code as byte 31 | */ 32 | default byte getCodeAsByte() { 33 | return (byte) getCode(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/config/InternalConfigValue.java: -------------------------------------------------------------------------------- 1 | package li.pitschmann.knx.core.config; 2 | 3 | import li.pitschmann.knx.core.annotations.Nullable; 4 | 5 | import java.util.function.Function; 6 | import java.util.function.Predicate; 7 | import java.util.function.Supplier; 8 | 9 | /** 10 | * {@link ConfigValue} for internal purposes only! 11 | * Initialization of this class is package-protected. 12 | *

13 | * This allows us to read / parse the config from a file, but 14 | * does not allow user to set the configuration directly in code. 15 | *

16 | * Used for: 17 | *

21 | * 22 | * @param value type of internal config (e.g. Boolean) 23 | * @author PITSCHR 24 | */ 25 | public final class InternalConfigValue extends ConfigValue { 26 | InternalConfigValue( 27 | final String key, 28 | final Class classType, 29 | final Function converter, 30 | final Supplier defaultSupplier, 31 | final @Nullable Predicate predicate) { 32 | super(key, classType, converter, defaultSupplier, predicate); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/exceptions/KnxDataPointTypeNotFoundException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.exceptions; 19 | 20 | /** 21 | * Exception when KNX/IP specific data point type could not be found 22 | * 23 | * @author PITSCHR 24 | */ 25 | public final class KnxDataPointTypeNotFoundException extends KnxException { 26 | 27 | public KnxDataPointTypeNotFoundException(final String id) { 28 | super("Could not find data point type id: {}", id); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/exceptions/KnxProjectParserException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.exceptions; 19 | 20 | import li.pitschmann.knx.core.annotations.Nullable; 21 | 22 | /** 23 | * Exception about any issue during parsing of '*.knxproj' file 24 | */ 25 | public final class KnxProjectParserException extends KnxException { 26 | 27 | public KnxProjectParserException(final String message, final @Nullable Object... args) { 28 | super(message, args); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/MultiRawDataAware.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core; 19 | 20 | /** 21 | * Multi Byte Raw Data Aware interface. 22 | *

23 | * Classes which implements this interface are aware of the raw data in byte array format. 24 | * 25 | * @author PITSCHR 26 | */ 27 | public interface MultiRawDataAware { 28 | /** 29 | * Returns the body as raw data in byte array format 30 | * 31 | * @return byte array, defensively copied 32 | */ 33 | byte[] toByteArray(); 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/exceptions/KnxPluginException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.exceptions; 19 | 20 | import li.pitschmann.knx.core.annotations.Nullable; 21 | 22 | /** 23 | * Exception to be thrown in case something is wrong with the plugin. 24 | * 25 | * @author PITSCHR 26 | */ 27 | public final class KnxPluginException extends KnxException { 28 | 29 | public KnxPluginException(final String message, final @Nullable Object... args) { 30 | super(message, args); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/KnxEnum.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core; 19 | 20 | /** 21 | * Interface for KNX enumeration 22 | * 23 | * @author PITSCHR 24 | */ 25 | public interface KnxEnum { 26 | /** 27 | * Returns the identification code as an integer 28 | * 29 | * @return code 30 | */ 31 | int getCode(); 32 | 33 | /** 34 | * Returns the human-friendly name of KNX enumeration 35 | * 36 | * @return friendly name 37 | */ 38 | String getFriendlyName(); 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/CEMIAware.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core; 19 | 20 | import li.pitschmann.knx.core.cemi.CEMI; 21 | 22 | /** 23 | * Interface for KNX packet bodies which are aware of {@link CEMI}. 24 | * 25 | * @author PITSCHR 26 | */ 27 | public interface CEMIAware { 28 | /** 29 | * Returns the {@link CEMI} which represents the cEMI message format 30 | * in a generic structure for KNX Net/IP medium. 31 | * 32 | * @return cEMI message 33 | */ 34 | CEMI getCEMI(); 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/test/strategy/ConnectStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.test.strategy; 19 | 20 | /** 21 | * Marker interface for connect strategy to establish a connection between 22 | * KNX Net/IP client and the KNX mock server 23 | *

24 | * Possible workflow: 25 | *

26 |  * [ Client ] --- request --> [ Mock Server ]
27 |  * [ Client ] <-- response -- [ Mock Server ]
28 |  * 
29 | */ 30 | public interface ConnectStrategy extends ResponseStrategy { 31 | // empty 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/plugin/Plugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.plugin; 19 | 20 | import li.pitschmann.knx.core.communication.KnxClient; 21 | 22 | /** 23 | * Marker interface for plugin to extend the {@link KnxClient} with some features. 24 | * 25 | * @author PITSCHR 26 | */ 27 | public interface Plugin { 28 | /** 29 | * Notifies the plug-in on {@link KnxClient} initialization. 30 | * 31 | * @param client the KNX client 32 | */ 33 | void onInitialization(final KnxClient client); 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/exceptions/KnxNoTunnelingException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.exceptions; 19 | 20 | /** 21 | * KNX communication partner exception that is being thrown when KNX client cannot establish a communication to the 22 | * KNX Net/IP device because it doesn't support the tunneling. 23 | * 24 | * @author PITSCHR 25 | */ 26 | public class KnxNoTunnelingException extends KnxException { 27 | 28 | public KnxNoTunnelingException(final String message) { 29 | super(message); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/exceptions/KnxException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.exceptions; 19 | 20 | import li.pitschmann.knx.core.utils.Exceptions; 21 | 22 | /** 23 | * This is the "root" exception for all KNX specific exceptions. 24 | * 25 | * @author PITSCHR 26 | */ 27 | public class KnxException extends RuntimeException { 28 | 29 | public KnxException(final String message, final Object... args) { 30 | super(Exceptions.toErrorMessage(message, args), Exceptions.getThrowableIfPresent(args)); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/test/strategy/ConnectionStateStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.test.strategy; 19 | 20 | /** 21 | * Marker interface for connection state strategy to check the health of 22 | * connection between KNX Net/IP client and the KNX mock server 23 | *

24 | * Possible workflow: 25 | *

26 |  * [ Client ] --- request --> [ Mock Server ]
27 |  * [ Client ] <-- response -- [ Mock Server ]
28 |  * 
29 | */ 30 | public interface ConnectionStateStrategy extends ResponseStrategy { 31 | // empty 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/test/strategy/DiscoveryStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.test.strategy; 19 | 20 | /** 21 | * Marker interface for discovery strategy to provide available KNX Net/IP client and 22 | * device hardware and capabilities of the KNX mock server. 23 | *

24 | * Possible workflow: 25 | *

26 |  * [ Client ] --- request --> [ Mock Server ]
27 |  * [ Client ] <-- response -- [ Mock Server ]
28 |  * 
29 | */ 30 | public interface DiscoveryStrategy extends ResponseStrategy { 31 | // empty 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/test/body/MockResponseControlChannelBody.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.test.body; 19 | 20 | import li.pitschmann.knx.core.body.ControlChannelRelated; 21 | 22 | /** 23 | * A {@link MockResponseBody} that is going to be sent to Control channel. 24 | *

25 | * Using it we can simulate a false body routing. 26 | */ 27 | public final class MockResponseControlChannelBody extends MockResponseBody implements ControlChannelRelated { 28 | public MockResponseControlChannelBody(final byte[] bytes) { 29 | super(bytes); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/exceptions/KnxConfigurationException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.exceptions; 19 | 20 | import li.pitschmann.knx.core.annotations.Nullable; 21 | 22 | /** 23 | * Exception to be thrown in case something is wrong with the configuration 24 | * like providing a wrong IP address or an unsupported setting. 25 | * 26 | * @author PITSCHR 27 | */ 28 | public final class KnxConfigurationException extends KnxException { 29 | 30 | public KnxConfigurationException(final String message, final @Nullable Object... args) { 31 | super(message, args); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/test/action/WaitDelayMockAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.test.action; 19 | 20 | import li.pitschmann.knx.core.utils.Sleeper; 21 | 22 | /** 23 | * A request mock action defining that KNX Mock Server should wait for {@code N} milliseconds (delay) 24 | */ 25 | public class WaitDelayMockAction implements MockAction { 26 | private final int delay; 27 | 28 | public WaitDelayMockAction(final int delay) { 29 | this.delay = delay; 30 | } 31 | 32 | public boolean apply() { 33 | Sleeper.milliseconds(delay); 34 | return true; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/exceptions/KnxEnumNotFoundException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.exceptions; 19 | 20 | /** 21 | * Exception when KNX/IP specific enumeration could not be found 22 | * 23 | * @author PITSCHR 24 | */ 25 | public final class KnxEnumNotFoundException extends KnxException { 26 | public KnxEnumNotFoundException(final String message) { 27 | super(message); 28 | } 29 | 30 | public KnxEnumNotFoundException(final Class> clazz, final int code) { 31 | super("Could not find enum for class '{}' and code: {}", clazz.getName(), code); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/datapoint/DPT23Test.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.datapoint; 19 | 20 | import li.pitschmann.knx.core.test.TestHelpers; 21 | import org.junit.jupiter.api.DisplayName; 22 | import org.junit.jupiter.api.Test; 23 | 24 | /** 25 | * Test Class for {@link DPT23} 26 | * 27 | * @author PITSCHR 28 | */ 29 | class DPT23Test { 30 | /** 31 | * Test constructor of {@link DPT23} 32 | */ 33 | @Test 34 | @DisplayName("Constructor not instantiable") 35 | void testConstructorNonInstantiable() { 36 | TestHelpers.assertThatNotInstantiable(DPT23.class); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/test/strategy/DescriptionStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.test.strategy; 19 | 20 | /** 21 | * Marker interface for description strategy to provide description about the 22 | * KNX mock server. The KNX Net/IP client will check the predication if the 23 | * communication between the KNX mock server and client are meet. 24 | *

25 | * Possible workflow: 26 | *

27 |  * [ Client ] --- request --> [ Mock Server ]
28 |  * [ Client ] <-- response -- [ Mock Server ]
29 |  * 
30 | */ 31 | public interface DescriptionStrategy extends ResponseStrategy { 32 | // empty 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/test/strategy/impl/ConnectNoMoreConnectionsStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.test.strategy.impl; 19 | 20 | import li.pitschmann.knx.core.body.Status; 21 | import li.pitschmann.knx.core.test.strategy.ConnectStrategy; 22 | 23 | /** 24 | * No More Connections implementation for {@link ConnectStrategy} 25 | */ 26 | public class ConnectNoMoreConnectionsStrategy extends DefaultConnectStrategy { 27 | /** 28 | * Return no more connections status 29 | * 30 | * @return status 31 | */ 32 | protected Status getStatus() { 33 | return Status.NO_MORE_CONNECTIONS; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/exceptions/KnxCommunicationException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.exceptions; 19 | 20 | import li.pitschmann.knx.core.annotations.Nullable; 21 | 22 | /** 23 | * A general KNX/IP communication exception. This exception is used for general communication issues as well like 24 | * IOException, InterruptedException during sending and receiving procedures. 25 | * 26 | * @author PITSCHR 27 | */ 28 | public class KnxCommunicationException extends KnxException { 29 | 30 | public KnxCommunicationException(final String message, final @Nullable Object... args) { 31 | super(message, args); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/exceptions/KnxNullPointerException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.exceptions; 19 | 20 | import li.pitschmann.knx.core.annotations.Nullable; 21 | 22 | /** 23 | * {@link NullPointerException} for KNX 24 | * 25 | * @author PITSCHR 26 | */ 27 | public final class KnxNullPointerException extends KnxException { 28 | 29 | /** 30 | * {@link NullPointerException} for KNX specific array 31 | * 32 | * @param argumentName argument that is null 33 | */ 34 | public KnxNullPointerException(final @Nullable String argumentName) { 35 | super("Argument '{}' is null.", argumentName); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/test/body/MockResponseBody.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.test.body; 19 | 20 | import li.pitschmann.knx.core.body.ResponseBody; 21 | import li.pitschmann.knx.core.header.ServiceType; 22 | 23 | public class MockResponseBody implements ResponseBody { 24 | private final byte[] bytes; 25 | 26 | public MockResponseBody(final byte[] bytes) { 27 | this.bytes = bytes.clone(); 28 | } 29 | 30 | @Override 31 | public ServiceType getServiceType() { 32 | throw new UnsupportedOperationException(); 33 | } 34 | 35 | @Override 36 | public byte[] toByteArray() { 37 | return this.bytes.clone(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/exceptions/KnxDescriptionNotReceivedException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.exceptions; 19 | 20 | import li.pitschmann.knx.core.annotations.Nullable; 21 | import li.pitschmann.knx.core.body.Body; 22 | 23 | /** 24 | * Exception when description information could not be received by KNX Net/IP device. 25 | * This exception is a subclass of {@link KnxCommunicationException}. 26 | * 27 | * @author PITSCHR 28 | */ 29 | public final class KnxDescriptionNotReceivedException extends KnxCommunicationException { 30 | 31 | public KnxDescriptionNotReceivedException(final @Nullable Body body) { 32 | super("Could not get description from KNX Net/IP device: {}", body); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/test/strategy/impl/TunnelingWrongChannelIdStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.test.strategy.impl; 19 | 20 | import li.pitschmann.knx.core.test.MockServer; 21 | import li.pitschmann.knx.core.test.strategy.TunnelingStrategy; 22 | 23 | /** 24 | * Wrong Channel Id implementation for {@link TunnelingStrategy} 25 | */ 26 | public class TunnelingWrongChannelIdStrategy extends DefaultTunnelingStrategy { 27 | /** 28 | * Returns the wrong channel id. 29 | * 30 | * @param mockServer the mock server 31 | * @return wrong channel id 32 | */ 33 | protected int getChannelId(final MockServer mockServer) { 34 | return (mockServer.getChannelId() + 100) % (0xFF + 1); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/test/data/TestExtensionPlugin.java: -------------------------------------------------------------------------------- 1 | package li.pitschmann.knx.core.test.data; 2 | 3 | import li.pitschmann.knx.core.communication.KnxClient; 4 | import li.pitschmann.knx.core.plugin.ExtensionPlugin; 5 | 6 | import java.util.concurrent.atomic.AtomicInteger; 7 | 8 | /** 9 | * Test {@link ExtensionPlugin} implementation 10 | */ 11 | public final class TestExtensionPlugin implements ExtensionPlugin { 12 | private final AtomicInteger initInvocations = new AtomicInteger(); 13 | private final AtomicInteger startInvocations = new AtomicInteger(); 14 | private final AtomicInteger shutdownInvocations = new AtomicInteger(); 15 | private KnxClient knxClient; 16 | 17 | @Override 18 | public void onInitialization(final KnxClient client) { 19 | initInvocations.incrementAndGet(); 20 | knxClient = client; 21 | } 22 | 23 | @Override 24 | public void onStart() { 25 | startInvocations.incrementAndGet(); 26 | } 27 | 28 | @Override 29 | public void onShutdown() { 30 | shutdownInvocations.incrementAndGet(); 31 | } 32 | 33 | public int getInitInvocations() { 34 | return initInvocations.get(); 35 | } 36 | 37 | public int getStartInvocations() { 38 | return startInvocations.get(); 39 | } 40 | 41 | public int getShutdownInvocations() { 42 | return shutdownInvocations.get(); 43 | } 44 | 45 | public KnxClient getKnxClient() { 46 | return knxClient; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/test/action/RequestMockAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.test.action; 19 | 20 | import li.pitschmann.knx.core.body.Body; 21 | import li.pitschmann.knx.core.test.MockServer; 22 | 23 | /** 24 | * A request mock action defining body that should be sent by KNX Mock Server 25 | */ 26 | public class RequestMockAction implements MockAction { 27 | private final MockServer mockServer; 28 | private final Body body; 29 | 30 | public RequestMockAction(final MockServer mockServer, final Body body) { 31 | this.mockServer = mockServer; 32 | this.body = body; 33 | } 34 | 35 | @Override 36 | public boolean apply() { 37 | this.mockServer.addToOutbox(body); 38 | return true; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/address/KnxAddress.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.address; 19 | 20 | import li.pitschmann.knx.core.MultiRawDataAware; 21 | 22 | /** 23 | * KNX Address interface for {@link IndividualAddress} and 24 | * {@link GroupAddress} implementations. 25 | * 26 | * @author PITSCHR 27 | */ 28 | public interface KnxAddress extends MultiRawDataAware { 29 | int STRUCTURE_LENGTH = 2; 30 | 31 | /** 32 | * Returns the {@link AddressType} of current implementation 33 | * 34 | * @return {@link AddressType} 35 | */ 36 | AddressType getAddressType(); 37 | 38 | /** 39 | * Returns the address as String 40 | * 41 | * @return address in human-friendly format. 42 | */ 43 | String getAddress(); 44 | } 45 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/test/strategy/ResponseStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.test.strategy; 19 | 20 | import li.pitschmann.knx.core.body.RequestBody; 21 | import li.pitschmann.knx.core.body.ResponseBody; 22 | import li.pitschmann.knx.core.test.MockServer; 23 | 24 | /** 25 | * Response Strategy defining what should be respond to KNX Net/IP client 26 | * when KNX mock server got a request 27 | */ 28 | public interface ResponseStrategy { 29 | /** 30 | * Returns an instance of {@link ResponseBody} to be sent to KNX Net/IP client 31 | * 32 | * @param mockServer the mock server 33 | * @param request the request body 34 | * @return a response body 35 | */ 36 | ResponseBody createResponse(MockServer mockServer, RequestBody request); 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/exceptions/KnxUnknownBodyException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.exceptions; 19 | 20 | import li.pitschmann.knx.core.annotations.Nullable; 21 | 22 | /** 23 | * Exception in case no Body could be parsed of raw data. 24 | * 25 | * @author PITSCHR 26 | */ 27 | public final class KnxUnknownBodyException extends KnxCommunicationException { 28 | 29 | /** 30 | * Constructor for {@link KnxUnknownBodyException} in case the body could not be parsed based on given 31 | * {@code rawData}. 32 | * 33 | * @param rawData raw byte array that could not be converted into a suitable KNX packet 34 | */ 35 | public KnxUnknownBodyException(final @Nullable byte[] rawData) { 36 | super("Unknown body received for raw data: {}", rawData); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/knxproj/parser/AbstractParserTest.java: -------------------------------------------------------------------------------- 1 | package li.pitschmann.knx.core.knxproj.parser; 2 | 3 | import li.pitschmann.knx.core.exceptions.KnxProjectParserException; 4 | import org.assertj.core.api.Assertions; 5 | import org.junit.jupiter.api.DisplayName; 6 | import org.junit.jupiter.api.Test; 7 | 8 | import java.io.IOException; 9 | import java.util.stream.Stream; 10 | import java.util.zip.ZipEntry; 11 | import java.util.zip.ZipFile; 12 | 13 | import static org.mockito.ArgumentMatchers.any; 14 | import static org.mockito.Mockito.doReturn; 15 | import static org.mockito.Mockito.mock; 16 | import static org.mockito.Mockito.when; 17 | 18 | /** 19 | * Test for {@link AbstractParser} 20 | */ 21 | class AbstractParserTest { 22 | @Test 23 | @DisplayName("Test #extractBytes(ZipFile, String) with IOException") 24 | void testExtractBytes() throws IOException { 25 | final var abstractParser = new AbstractParser() { 26 | }; 27 | 28 | final var zipEntryMock = mock(ZipEntry.class); 29 | when(zipEntryMock.getName()).thenReturn("foobar"); 30 | final var zipFileMock = mock(ZipFile.class); 31 | doReturn(Stream.of(zipEntryMock)).when(zipFileMock).stream(); 32 | when(zipFileMock.getInputStream(any(ZipEntry.class))).thenThrow(IOException.class); 33 | 34 | Assertions.assertThatThrownBy(() -> abstractParser.extractBytes(zipFileMock, "foobar")) 35 | .isInstanceOf(KnxProjectParserException.class) 36 | .hasMessage("Could not read the file: foobar"); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/exceptions/KnxBodyNotReceivedException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.exceptions; 19 | 20 | import li.pitschmann.knx.core.body.Body; 21 | 22 | /** 23 | * Exception when an expected body could not be received (during a given time frame). This exception is a subclass of 24 | * {@link KnxCommunicationException}. 25 | * 26 | * @author PITSCHR 27 | */ 28 | public final class KnxBodyNotReceivedException extends KnxCommunicationException { 29 | 30 | /** 31 | * Exception when an expected KNX Body ways not received 32 | * 33 | * @param bodyClass body class that could not be received 34 | */ 35 | public KnxBodyNotReceivedException(final Class bodyClass) { 36 | super("Body not received with class: " + bodyClass.getName()); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/test/data/TestMethodExceptionPlugin.java: -------------------------------------------------------------------------------- 1 | package li.pitschmann.knx.core.test.data; 2 | 3 | import li.pitschmann.knx.core.body.Body; 4 | import li.pitschmann.knx.core.communication.KnxClient; 5 | import li.pitschmann.knx.core.plugin.ExtensionPlugin; 6 | import li.pitschmann.knx.core.plugin.ObserverPlugin; 7 | import li.pitschmann.knx.core.plugin.Plugin; 8 | 9 | /** 10 | * Test {@link Plugin} implementation that is throwing 11 | * an {@link RuntimeException} in all methods. 12 | */ 13 | public final class TestMethodExceptionPlugin implements ObserverPlugin, ExtensionPlugin { 14 | @Override 15 | public void onInitialization(final KnxClient client) { 16 | throw new RuntimeException("Exception in onInitialization(..) method"); 17 | } 18 | 19 | @Override 20 | public void onStart() { 21 | throw new RuntimeException("Exception in onStart() method"); 22 | } 23 | 24 | @Override 25 | public void onIncomingBody(final Body item) { 26 | throw new RuntimeException("Exception in onIncomingBody(..) method"); 27 | } 28 | 29 | @Override 30 | public void onOutgoingBody(final Body item) { 31 | throw new RuntimeException("Exception in onOutgoingBody(..) method"); 32 | } 33 | 34 | @Override 35 | public void onError(final Throwable throwable) { 36 | throw new RuntimeException("Exception in onError(..) method"); 37 | } 38 | 39 | @Override 40 | public void onShutdown() { 41 | throw new RuntimeException("Exception in onShutdown() method"); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/test/strategy/RequestStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.test.strategy; 19 | 20 | import li.pitschmann.knx.core.body.RequestBody; 21 | import li.pitschmann.knx.core.test.MockServer; 22 | 23 | /** 24 | * Request Strategy defining what should be done when creating 25 | * a request when KNX mock server got a request from KNX NET/IP client 26 | * 27 | * @param type of a context instance 28 | */ 29 | public interface RequestStrategy { 30 | /** 31 | * Returns an instance of {@link RequestBody} that was sent to KNX mock server 32 | * 33 | * @param mockServer the mock server 34 | * @param context the context of request strategy 35 | * @return a request body 36 | */ 37 | RequestBody createRequest(MockServer mockServer, T context); 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/test/strategy/impl/ConnectBadDataStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.test.strategy.impl; 19 | 20 | import li.pitschmann.knx.core.body.RequestBody; 21 | import li.pitschmann.knx.core.body.ResponseBody; 22 | import li.pitschmann.knx.core.test.body.MockResponseBody; 23 | import li.pitschmann.knx.core.test.MockServer; 24 | import li.pitschmann.knx.core.test.strategy.ConnectStrategy; 25 | import li.pitschmann.knx.core.utils.Bytes; 26 | 27 | /** 28 | * Bad Data provided for {@link ConnectStrategy} 29 | */ 30 | public final class ConnectBadDataStrategy implements ConnectStrategy { 31 | 32 | @Override 33 | public ResponseBody createResponse(MockServer mockServer, RequestBody unused) { 34 | return new MockResponseBody(Bytes.toByteArray("0610020600140000000100000000000004000000")); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | # Controls when the action will run. 4 | on: 5 | # Triggers the workflow on push or pull request events but only for following branches 6 | push: 7 | branches: 8 | - main 9 | - main-* 10 | pull_request: 11 | branches: 12 | - main-* 13 | 14 | # Allows you to run this workflow manually from the Actions tab 15 | workflow_dispatch: 16 | 17 | jobs: 18 | build: 19 | # The type of runner that the job will run on 20 | runs-on: ubuntu-latest 21 | 22 | # Steps represent a sequence of tasks that will be executed as part of the job 23 | steps: 24 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 25 | - name: Check out 26 | uses: actions/checkout@v2 27 | 28 | # Uses the Cache for Maven 29 | - name: Cache 30 | uses: actions/cache@v1 31 | with: 32 | path: ~/.m2 33 | key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} 34 | restore-keys: ${{ runner.os }}-m2 35 | 36 | # Uses JDK 11 for compilation 37 | - name: Set up JDK 11 38 | uses: actions/setup-java@v1 39 | with: 40 | java-version: '11' 41 | 42 | # Compile & Test & Calculate Coverage 43 | - name: Compile & Test 44 | run: mvn clean test jacoco:report -B -P github-actions 45 | 46 | # Submit the code coverage to coveralls.io 47 | - name: Submit Code Coverage 48 | if: github.event_name != 'pull_request' 49 | run: mvn coveralls:report -B -P github-actions -D repoToken=${{ secrets.COVERALLS_TOKEN }} 50 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/test/action/WaitServiceTypeMockAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.test.action; 19 | 20 | import java.util.concurrent.atomic.AtomicInteger; 21 | 22 | /** 23 | * A mock action defining that KNX Mock Server should wait until the occurrence of service type 24 | * (by given {@link AtomicInteger} which is atomically updated outside of this class) is meet 25 | */ 26 | public final class WaitServiceTypeMockAction implements MockAction { 27 | private final AtomicInteger atomicInteger; 28 | private final int occurrence; 29 | 30 | public WaitServiceTypeMockAction(final AtomicInteger atomicInteger, final int occurrence) { 31 | this.atomicInteger = atomicInteger; 32 | this.occurrence = occurrence; 33 | } 34 | 35 | public boolean apply() { 36 | return atomicInteger.get() >= occurrence; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/datapoint/value/DataPointEnumValue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.datapoint.value; 19 | 20 | import java.lang.annotation.ElementType; 21 | import java.lang.annotation.Retention; 22 | import java.lang.annotation.RetentionPolicy; 23 | import java.lang.annotation.Target; 24 | 25 | /** 26 | * Data Point Value to define the value and description 27 | * for enumerated KNX data point field 28 | * 29 | * @author PITSCHR 30 | */ 31 | @Target(ElementType.FIELD) 32 | @Retention(RetentionPolicy.RUNTIME) 33 | public @interface DataPointEnumValue { 34 | /** 35 | * Value of enumerated KNX data point field (0..255) 36 | * 37 | * @return value 38 | */ 39 | int value(); 40 | 41 | /** 42 | * Description of enumerated KNX data point field 43 | * 44 | * @return description 45 | */ 46 | String description(); 47 | } 48 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/datapoint/value/DataPointValueTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.datapoint.value; 19 | 20 | import org.junit.jupiter.api.DisplayName; 21 | import org.junit.jupiter.api.Test; 22 | 23 | import static org.assertj.core.api.Assertions.assertThat; 24 | import static org.mockito.Mockito.mock; 25 | import static org.mockito.Mockito.when; 26 | 27 | /** 28 | * Test {@link DataPointValue} 29 | * 30 | * @author PITSCHR 31 | */ 32 | public class DataPointValueTest { 33 | 34 | @Test 35 | @DisplayName("Test #toText() that is not being overridden") 36 | public void testToText() { 37 | final var dptValue = mock(DataPointValue.class); 38 | when(dptValue.toByteArray()).thenReturn(new byte[]{0x44, 0x56, 0x78}); 39 | when(dptValue.toText()).thenCallRealMethod(); 40 | 41 | assertThat(dptValue.toText()).isEqualTo("0x44 56 78"); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/datapoint/value/DataPointValue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.datapoint.value; 19 | 20 | import li.pitschmann.knx.core.datapoint.DataPointType; 21 | import li.pitschmann.knx.core.utils.ByteFormatter; 22 | 23 | /** 24 | * Interface for Data Point Value implementations 25 | * 26 | * @author PITSCHR 27 | */ 28 | public interface DataPointValue { 29 | /** 30 | * Returns the current Data Point Value as a byte array. 31 | * 32 | * @return byte array 33 | */ 34 | byte[] toByteArray(); 35 | 36 | /** 37 | * Returns the human-friendly text representation of Data Point Value 38 | *

39 | * This text is not STABLE and should only be used for display purposes only! 40 | * 41 | * @return text 42 | */ 43 | default String toText() { 44 | return ByteFormatter.formatHexAsString(toByteArray()); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/test/strategy/impl/DescriptionInvalidServiceStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.test.strategy.impl; 19 | 20 | import li.pitschmann.knx.core.body.RequestBody; 21 | import li.pitschmann.knx.core.body.ResponseBody; 22 | import li.pitschmann.knx.core.test.body.MockResponseBody; 23 | import li.pitschmann.knx.core.test.MockServer; 24 | import li.pitschmann.knx.core.test.strategy.DescriptionStrategy; 25 | import li.pitschmann.knx.core.utils.Bytes; 26 | 27 | /** 28 | * Unsupported Device Families (0xFF) for {@link DescriptionStrategy} 29 | */ 30 | public final class DescriptionInvalidServiceStrategy implements DescriptionStrategy { 31 | 32 | @Override 33 | public ResponseBody createResponse(MockServer mockServer, RequestBody request) { 34 | return new MockResponseBody(Bytes.toByteArray("061002FF002036010200100000000083497f01ece000170ccc1be08008da4d44")); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/ChannelIdAware.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core; 19 | 20 | /** 21 | * Interface for KNX packet bodies which are aware of channel id. 22 | *

23 | * The KNX Net/IP Server shall assign a Communication Channel ID 24 | * to each established communication channel and is initially 25 | * set in the CONNECT_REQUEST for unique identification. 26 | *

27 | * KNX Specification, Core 28 | * 29 | * @author PITSCHR 30 | */ 31 | public interface ChannelIdAware { 32 | /** 33 | * Returns the Channel ID that is set by the KNX/IP Net device. 34 | * It is in byte format and channel id is between {@code 0 (0x00)} 35 | * and {@code 255 (0xFF)} 36 | *

37 | * The channel id is required for tunneling communication only to 38 | * distinguish the KNX traffic between several clients/endpoints. 39 | * 40 | * @return channel id 41 | */ 42 | int getChannelId(); 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/plugin/ExtensionPlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.plugin; 19 | 20 | import li.pitschmann.knx.core.communication.KnxClient; 21 | 22 | /** 23 | * Plug-in to be invoked when {@link KnxClient} starts up / shuts down. 24 | * 25 | * @author PITSCHR 26 | */ 27 | public interface ExtensionPlugin extends Plugin { 28 | /** 29 | * Notifies the plug-in when KNX communication is established. 30 | *

31 | * The start of KNX communication is done when description & connect frames 32 | * have been exchanged between the KNX client and the KNX Net/IP device. 33 | */ 34 | void onStart(); 35 | 36 | /** 37 | * Notifies the plug-in after KNX communication stop. 38 | *

39 | * The stop of KNX communication is done when disconnect frames have been 40 | * exchanged between the KNX client and the KNX Net/IP device. 41 | */ 42 | void onShutdown(); 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/test/strategy/impl/DescriptionBadDataStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.test.strategy.impl; 19 | 20 | import li.pitschmann.knx.core.body.RequestBody; 21 | import li.pitschmann.knx.core.body.ResponseBody; 22 | import li.pitschmann.knx.core.test.body.MockResponseBody; 23 | import li.pitschmann.knx.core.test.MockServer; 24 | import li.pitschmann.knx.core.test.strategy.DescriptionStrategy; 25 | import li.pitschmann.knx.core.utils.Bytes; 26 | 27 | /** 28 | * Bad Data provided for {@link DescriptionStrategy} 29 | */ 30 | public final class DescriptionBadDataStrategy implements DescriptionStrategy { 31 | 32 | @Override 33 | public ResponseBody createResponse(MockServer mockServer, RequestBody unused) { 34 | return new MockResponseBody(Bytes.toByteArray("06100204004634010200100000000083497f01ece000170ccc1be08008da4d4454204b4e5820495020526f7574657200000000000000000000000000")); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/test/strategy/IgnoreStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.test.strategy; 19 | 20 | import li.pitschmann.knx.core.body.RequestBody; 21 | import li.pitschmann.knx.core.body.ResponseBody; 22 | import li.pitschmann.knx.core.test.MockServer; 23 | 24 | /** 25 | * A special {@link ResponseStrategy} to ignore the requests from KNX mock client 26 | *

27 | * This is useful if you want to simulate/test a no reaction on e.g. description request frame. 28 | * In this case the KNX client should resend the description request frame again which will be 29 | * responded by a different strategy class. 30 | */ 31 | public final class IgnoreStrategy implements ResponseStrategy { 32 | public static final IgnoreStrategy DEFAULT = new IgnoreStrategy(); 33 | 34 | @Override 35 | public ResponseBody createResponse(final MockServer mockServer, final RequestBody request) { 36 | // do nothing ... 37 | return null; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/exceptions/DataPointTypeIncompatibleBytesException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.exceptions; 19 | 20 | import li.pitschmann.knx.core.datapoint.DataPointType; 21 | 22 | /** 23 | * Exception when an incompatible byte array were provided. 24 | * 25 | * @author PITSCHR 26 | */ 27 | public final class DataPointTypeIncompatibleBytesException extends KnxException { 28 | 29 | /** 30 | * Creates an exception in case incompatible {@code bytes} array have 31 | * been provided for the {@code dpt}. 32 | * 33 | * @param dpt data point type 34 | * @param bytes incompatible byte array 35 | */ 36 | public DataPointTypeIncompatibleBytesException(final DataPointType dpt, 37 | final byte[] bytes) { 38 | super("Looks like you chose a wrong DPT. Given bytes is not compatible for '{}': {}", 39 | dpt.getClass().getSimpleName(), bytes); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/exceptions/KnxServiceTypeHasNoResponseIdentifier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.exceptions; 19 | 20 | import li.pitschmann.knx.core.header.ServiceType; 21 | 22 | /** 23 | * Exception in case no response identifier could be found for given {@link ServiceType}. 24 | * 25 | * @author PITSCHR 26 | * @see ServiceType#getResponseIdentifier() 27 | */ 28 | public final class KnxServiceTypeHasNoResponseIdentifier extends KnxCommunicationException { 29 | 30 | /** 31 | * Constructor for {@link KnxServiceTypeHasNoResponseIdentifier} in case when you are trying to get a response 32 | * identifier for given {@link ServiceType} which has no response identifier. 33 | * 34 | * @param serviceType service type that has no response identifier 35 | */ 36 | public KnxServiceTypeHasNoResponseIdentifier(final ServiceType serviceType) { 37 | super("No response identifier available for service type: {}", serviceType.name()); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/exceptions/DataPointTypeIncompatibleSyntaxException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.exceptions; 19 | 20 | import li.pitschmann.knx.core.datapoint.DataPointType; 21 | 22 | /** 23 | * Exception when an incompatible syntax was provided. 24 | * 25 | * @author PITSCHR 26 | */ 27 | public final class DataPointTypeIncompatibleSyntaxException extends KnxException { 28 | 29 | /** 30 | * Creates an exception in case incompatible {@code commands} array have been provided for the {@code dpt}. 31 | * 32 | * @param dpt data point type 33 | * @param commands incompatible commands / syntax 34 | */ 35 | public DataPointTypeIncompatibleSyntaxException(final DataPointType dpt, 36 | final String[] commands) { 37 | super("Looks like you chose a wrong DPT. Given syntax is not compatible or not sufficient for '{}': {}", 38 | dpt.getClass().getSimpleName(), commands); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/datapoint/DataPoint.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.datapoint; 19 | 20 | import java.lang.annotation.ElementType; 21 | import java.lang.annotation.Retention; 22 | import java.lang.annotation.RetentionPolicy; 23 | import java.lang.annotation.Target; 24 | 25 | /** 26 | * Data Point Annotation to define the id and description of KNX data point 27 | * 28 | * @author PITSCHR 29 | */ 30 | @Target({ElementType.FIELD, ElementType.TYPE}) 31 | @Retention(RetentionPolicy.RUNTIME) 32 | public @interface DataPoint { 33 | /** 34 | * Identifiers for KNX data point 35 | *

36 | * First is the main data point type identifier, and rest are alternative identifiers (e.g. for XML) 37 | * 38 | * @return string array of possible DPT identifiers, at least one DPT identifier must be defined 39 | */ 40 | String[] value(); 41 | 42 | /** 43 | * Description for KNX data point 44 | * 45 | * @return description 46 | */ 47 | String description() default ""; 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/exceptions/KnxIllegalArgumentException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.exceptions; 19 | 20 | import li.pitschmann.knx.core.annotations.Nullable; 21 | 22 | /** 23 | * Exception for KNX/IP specific illegal argument 24 | * 25 | * @author PITSCHR 26 | */ 27 | public final class KnxIllegalArgumentException extends KnxException { 28 | 29 | /** 30 | * Creates an exception for KNX/IP illegal argument with message only 31 | * 32 | * @param message error message 33 | */ 34 | public KnxIllegalArgumentException(final String message) { 35 | super(message); 36 | } 37 | 38 | /** 39 | * Creates an exception for KNX/IP illegal argument with message and 40 | * objects for more diagnostic data 41 | * 42 | * @param message error message 43 | * @param args arguments for error message 44 | */ 45 | public KnxIllegalArgumentException(final String message, final @Nullable Object... args) { 46 | super(message, args); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/communication/communicator/DataChannelCommunicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.communication.communicator; 19 | 20 | import li.pitschmann.knx.core.annotations.Nullable; 21 | import li.pitschmann.knx.core.body.Body; 22 | import li.pitschmann.knx.core.body.DataChannelRelated; 23 | import li.pitschmann.knx.core.communication.InternalKnxClient; 24 | 25 | import java.nio.channels.SelectableChannel; 26 | 27 | /** 28 | * Communicator for data channel related packets 29 | * 30 | * @author PITSCHR 31 | */ 32 | public final class DataChannelCommunicator extends AbstractChannelCommunicator { 33 | DataChannelCommunicator(final InternalKnxClient client) { 34 | super(client); 35 | } 36 | 37 | @Override 38 | protected SelectableChannel newChannel(final InternalKnxClient client) { 39 | return ChannelFactory.newDataChannel(client); 40 | } 41 | 42 | @Override 43 | public boolean isCompatible(final @Nullable Body body) { 44 | return body instanceof DataChannelRelated; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/communication/communicator/ControlChannelCommunicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.communication.communicator; 19 | 20 | import li.pitschmann.knx.core.annotations.Nullable; 21 | import li.pitschmann.knx.core.body.Body; 22 | import li.pitschmann.knx.core.body.ControlChannelRelated; 23 | import li.pitschmann.knx.core.communication.InternalKnxClient; 24 | 25 | import java.nio.channels.SelectableChannel; 26 | 27 | /** 28 | * Communicator for control channel related packets 29 | * 30 | * @author PITSCHR 31 | */ 32 | public final class ControlChannelCommunicator extends AbstractChannelCommunicator { 33 | ControlChannelCommunicator(final InternalKnxClient client) { 34 | super(client); 35 | } 36 | 37 | @Override 38 | 39 | protected SelectableChannel newChannel(final InternalKnxClient client) { 40 | return ChannelFactory.newControlChannel(client); 41 | } 42 | 43 | @Override 44 | public boolean isCompatible(final @Nullable Body body) { 45 | return body instanceof ControlChannelRelated; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/test/data/TestObserverPlugin.java: -------------------------------------------------------------------------------- 1 | package li.pitschmann.knx.core.test.data; 2 | 3 | import li.pitschmann.knx.core.body.Body; 4 | import li.pitschmann.knx.core.communication.KnxClient; 5 | import li.pitschmann.knx.core.plugin.ObserverPlugin; 6 | 7 | import java.util.Collections; 8 | import java.util.LinkedList; 9 | import java.util.List; 10 | import java.util.concurrent.atomic.AtomicInteger; 11 | 12 | /** 13 | * Test {@link ObserverPlugin} implementation 14 | */ 15 | public final class TestObserverPlugin implements ObserverPlugin { 16 | private final AtomicInteger initInvocations = new AtomicInteger(); 17 | private final List incomingBodies = new LinkedList<>(); 18 | private final List outgoingBodies = new LinkedList<>(); 19 | private final List errors = new LinkedList<>(); 20 | 21 | @Override 22 | public void onInitialization(final KnxClient client) { 23 | initInvocations.incrementAndGet(); 24 | } 25 | 26 | @Override 27 | public void onIncomingBody(final Body item) { 28 | incomingBodies.add(item); 29 | } 30 | 31 | @Override 32 | public void onOutgoingBody(final Body item) { 33 | outgoingBodies.add(item); 34 | } 35 | 36 | @Override 37 | public void onError(final Throwable throwable) { 38 | errors.add(throwable); 39 | } 40 | 41 | public int getInitInvocations() { 42 | return initInvocations.get(); 43 | } 44 | 45 | public List getIncomingBodies() { 46 | return Collections.unmodifiableList(incomingBodies); 47 | } 48 | 49 | public List getOutgoingBodies() { 50 | return Collections.unmodifiableList(outgoingBodies); 51 | } 52 | 53 | public List getErrors() { 54 | return Collections.unmodifiableList(errors); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/communication/communicator/DescriptionChannelCommunicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.communication.communicator; 19 | 20 | import li.pitschmann.knx.core.annotations.Nullable; 21 | import li.pitschmann.knx.core.body.Body; 22 | import li.pitschmann.knx.core.body.DescriptionResponseBody; 23 | import li.pitschmann.knx.core.communication.InternalKnxClient; 24 | 25 | import java.nio.channels.SelectableChannel; 26 | 27 | /** 28 | * Communicator for description channel related packets 29 | * 30 | * @author PITSCHR 31 | */ 32 | public final class DescriptionChannelCommunicator extends AbstractChannelCommunicator { 33 | DescriptionChannelCommunicator(final InternalKnxClient client) { 34 | super(client); 35 | } 36 | 37 | @Override 38 | protected SelectableChannel newChannel(final InternalKnxClient client) { 39 | return ChannelFactory.newDescriptionChannel(client); 40 | } 41 | 42 | @Override 43 | public boolean isCompatible(final @Nullable Body body) { 44 | return body instanceof DescriptionResponseBody; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/communication/queue/DefaultInboxQueue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.communication.queue; 19 | 20 | import li.pitschmann.knx.core.communication.InternalKnxClient; 21 | 22 | import java.io.IOException; 23 | import java.nio.ByteBuffer; 24 | import java.nio.channels.ByteChannel; 25 | import java.nio.channels.SelectableChannel; 26 | 27 | /** 28 | * Inbox Queue for KNX receiving packets from KNX Net/IP device 29 | * 30 | * @author PITSCHR 31 | */ 32 | public final class DefaultInboxQueue extends AbstractInboxQueue { 33 | /** 34 | * Constructor for Default KNX Inbox Queue 35 | * 36 | * @param client internal KNX client for internal actions like informing plug-ins 37 | * @param channel channel of communication 38 | */ 39 | public DefaultInboxQueue(final InternalKnxClient client, final SelectableChannel channel) { 40 | super(client, channel); 41 | } 42 | 43 | @Override 44 | protected void receive(final ByteChannel channel, final ByteBuffer bb) throws IOException { 45 | channel.read(bb); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/communication/queue/DefaultOutboxQueue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.communication.queue; 19 | 20 | import li.pitschmann.knx.core.communication.InternalKnxClient; 21 | 22 | import java.io.IOException; 23 | import java.nio.ByteBuffer; 24 | import java.nio.channels.ByteChannel; 25 | import java.nio.channels.SelectableChannel; 26 | 27 | /** 28 | * Default Outbox Queue for KNX packets to be sent to KNX Net/IP device 29 | * 30 | * @author PITSCHR 31 | */ 32 | public final class DefaultOutboxQueue extends AbstractOutboxQueue { 33 | /** 34 | * Constructor for Default KNX Outbox Queue 35 | * 36 | * @param client internal KNX client for internal actions like informing plug-ins 37 | * @param channel channel of communication 38 | */ 39 | public DefaultOutboxQueue(final InternalKnxClient client, final SelectableChannel channel) { 40 | super(client, channel); 41 | } 42 | 43 | @Override 44 | protected void send(final ByteChannel channel, final ByteBuffer bb) throws IOException { 45 | channel.write(bb); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/exceptions/KnxWrongChannelIdException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.exceptions; 19 | 20 | import li.pitschmann.knx.core.ChannelIdAware; 21 | 22 | /** 23 | * Exception in case we received a packet which doesn't belong to our channel id. This exception can be used for 24 | * ignoring such packets. This exception may apply to objects which contains the {@link ChannelIdAware} interface. 25 | * 26 | * @author PITSCHR 27 | */ 28 | public final class KnxWrongChannelIdException extends KnxCommunicationException { 29 | /** 30 | * Constructor for {@link KnxWrongChannelIdException} in case we received a packet with unexpected channel id. 31 | * 32 | * @param channelIdAware the body that is channel id aware (incl. actual channel id) 33 | * @param expectedChannelId the expected channel id 34 | */ 35 | public KnxWrongChannelIdException(final ChannelIdAware channelIdAware, final int expectedChannelId) { 36 | super("Wrong channel id '{}' received, expected channel id is '{}': {}", 37 | channelIdAware.getChannelId(), expectedChannelId, channelIdAware); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/test/strategy/DisconnectStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.test.strategy; 19 | 20 | /** 21 | * Marker interface for disconnect strategy to handle the disconnection. 22 | * The disconnect can be initiated by the KNX Net/IP client and by KNX mock server 23 | *

24 | * Possible workflows:
25 | * KNX client sends the disconnect request if it wants to close the connection and the 26 | * disconnect request will be received by the KNX mock server which will respond the 27 | * client with a disconnect response frame. 28 | *

29 |  * [ Client ] --- request --> [ Mock Server ]
30 |  * [ Client ] <-- response -- [ Mock Server ]
31 |  * 
32 | * KNX mock server will send the disconnect request to KNX client to close the connection. 33 | * Once disconnect frame was received by the KNX client the client should send a disconnect 34 | * response to KNX mock server. 35 | *
36 |  * [ Client ] <-- request --- [ Mock Server ]
37 |  * [ Client ] -- response --> [ Mock Server ]
38 |  * 
39 | */ 40 | public interface DisconnectStrategy extends RequestStrategy, ResponseStrategy { 41 | // empty 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/communication/queue/MulticastInboxQueue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.communication.queue; 19 | 20 | import li.pitschmann.knx.core.communication.InternalKnxClient; 21 | 22 | import java.io.IOException; 23 | import java.nio.ByteBuffer; 24 | import java.nio.channels.DatagramChannel; 25 | import java.nio.channels.SelectableChannel; 26 | 27 | /** 28 | * Inbox Queue for KNX receiving multicast packets from KNX Net/IP device. 29 | * This class is special because the multicast communication is based on broadcast. 30 | * 31 | * @author PITSCHR 32 | */ 33 | public final class MulticastInboxQueue extends AbstractInboxQueue { 34 | 35 | /** 36 | * Constructor for KNX Discovery Inbox Queue 37 | * 38 | * @param client internal KNX client for internal actions like informing plug-ins 39 | * @param channel channel of communication 40 | */ 41 | public MulticastInboxQueue(final InternalKnxClient client, final SelectableChannel channel) { 42 | super(client, channel); 43 | } 44 | 45 | @Override 46 | protected void receive(final DatagramChannel channel, final ByteBuffer bb) throws IOException { 47 | channel.receive(bb); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/test/strategy/TunnelingStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.test.strategy; 19 | 20 | import li.pitschmann.knx.core.cemi.CEMI; 21 | 22 | /** 23 | * Marker interface for tunneling strategy to handle tunneling request and 24 | * acknowledge packets. The tunneling packets are communicated bi-directional 25 | *

26 | * Possible workflows:
27 | * KNX client will send a read/write tunneling request to the KNX mock server and 28 | * the request will be acknowledged by the KNX mock server - in parallel the request 29 | * from client will be forwarded to KNX devices. 30 | *

31 |  * [ Client ] --- request --> [ Mock Server ]
32 |  * [ Client ] <-- response -- [ Mock Server ]
33 |  * 
34 | * If a status has been updated in a KNX device then they may inform all other KNX devices. 35 | * In our case the tunneling request will be simulated as a forward from KNX mock server 36 | * to the KNX client. As usually, the KNX client should respond with a tunneling acknowledge. 37 | *
38 |  * [ Client ] <-- request --- [ Mock Server ]
39 |  * [ Client ] -- response --> [ Mock Server ]
40 |  * 
41 | */ 42 | public interface TunnelingStrategy extends RequestStrategy, ResponseStrategy { 43 | // empty 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/body/Body.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.body; 19 | 20 | import li.pitschmann.knx.core.MultiRawDataAware; 21 | import li.pitschmann.knx.core.header.Header; 22 | import li.pitschmann.knx.core.header.ServiceType; 23 | import li.pitschmann.knx.core.utils.Bytes; 24 | 25 | /** 26 | * Marker interface for KNX packet body 27 | * 28 | * @author PITSCHR 29 | */ 30 | public interface Body extends MultiRawDataAware { 31 | 32 | /** 33 | * Returns the {@link ServiceType} to which the body belongs to 34 | * 35 | * @return {@link ServiceType} 36 | */ 37 | ServiceType getServiceType(); 38 | 39 | /** 40 | * Returns the byte array. 41 | *

42 | * If {@code includeHeader} is {@code true} then byte array also contains 43 | * {@link Header} byte array, otherwise it is equivalent to {@link #toByteArray()}. 44 | * 45 | * @param includeHeader if {@code true} then returned byte array will also contain the KNX header array 46 | * @return byte array 47 | */ 48 | default byte[] toByteArray(final boolean includeHeader) { 49 | if (includeHeader) { 50 | return Bytes.concat(Header.of(this).toByteArray(), toByteArray()); 51 | } else { 52 | return toByteArray(); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/body/BodyTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.body; 19 | 20 | import li.pitschmann.knx.core.header.Header; 21 | import li.pitschmann.knx.core.test.KnxBody; 22 | import li.pitschmann.knx.core.utils.Bytes; 23 | import org.junit.jupiter.api.DisplayName; 24 | import org.junit.jupiter.api.Test; 25 | 26 | import static org.assertj.core.api.Assertions.assertThat; 27 | 28 | /** 29 | * Tests for {@link Body} 30 | */ 31 | class BodyTest { 32 | 33 | @Test 34 | @DisplayName("Test #toByteArray(boolean)") 35 | void testToByteArray_with_boolean() { 36 | final var body = KnxBody.TUNNELING_ACK_BODY; 37 | 38 | // false -> should return the byte array of body only 39 | final var bodyBytes = body.toByteArray(); 40 | assertThat(body.toByteArray(false)).containsExactly(bodyBytes); 41 | 42 | // true -> should return the byte array of header and body 43 | final var headerBytes = Header.of(body).toByteArray(); 44 | assertThat(body.toByteArray(true)).startsWith(headerBytes); 45 | assertThat(body.toByteArray(true)).endsWith(body.toByteArray()); 46 | assertThat(body.toByteArray(true)).hasSize(headerBytes.length + bodyBytes.length); 47 | assertThat(body.toByteArray(true)).containsExactly(Bytes.concat(headerBytes, bodyBytes)); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/test/MockServerHeartbeatMonitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.test; 19 | 20 | import li.pitschmann.knx.core.utils.Sleeper; 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | 24 | import java.util.concurrent.atomic.AtomicLong; 25 | 26 | /** 27 | * Health check thread for KNX mock server (package-protected) 28 | */ 29 | class MockServerHeartbeatMonitor implements Runnable { 30 | private static final Logger log = LoggerFactory.getLogger(MockServerHeartbeatMonitor.class); 31 | private final MockServer mockServer; 32 | private final AtomicLong lastHeartbeat = new AtomicLong(System.currentTimeMillis()); 33 | 34 | MockServerHeartbeatMonitor(final MockServer mockServer) { 35 | this.mockServer = mockServer; 36 | } 37 | 38 | @Override 39 | public void run() { 40 | log.info("*** KNX Mock Server [heartbeat] START ***"); 41 | while (System.currentTimeMillis() - lastHeartbeat.get() < 10000 42 | && !this.mockServer.isCancelled()) { 43 | Sleeper.seconds(1); 44 | } 45 | log.info("*** KNX Mock Server [heartbeat] END *** ({})", System.currentTimeMillis() - lastHeartbeat.get()); 46 | this.mockServer.cancel(); 47 | } 48 | 49 | public void ping() { 50 | lastHeartbeat.set(System.currentTimeMillis()); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/communication/communicator/ControlAndDataChannelCommunicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.communication.communicator; 19 | 20 | import li.pitschmann.knx.core.annotations.Nullable; 21 | import li.pitschmann.knx.core.body.Body; 22 | import li.pitschmann.knx.core.body.ControlChannelRelated; 23 | import li.pitschmann.knx.core.body.DataChannelRelated; 24 | import li.pitschmann.knx.core.communication.InternalKnxClient; 25 | 26 | import java.nio.channels.SelectableChannel; 27 | 28 | /** 29 | * Communicator for control AND data channel related packets. 30 | *

31 | * When using NAT then control and data packets are going over the same channel. 32 | * 33 | * @author PITSCHR 34 | */ 35 | public final class ControlAndDataChannelCommunicator extends AbstractChannelCommunicator { 36 | ControlAndDataChannelCommunicator(final InternalKnxClient client) { 37 | super(client); 38 | } 39 | 40 | @Override 41 | 42 | protected SelectableChannel newChannel(final InternalKnxClient client) { 43 | // we will use the control channel for data as well 44 | return ChannelFactory.newControlChannel(client); 45 | } 46 | 47 | @Override 48 | public boolean isCompatible(final @Nullable Body body) { 49 | return body instanceof ControlChannelRelated 50 | || body instanceof DataChannelRelated; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/address/AddressTypeTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.address; 19 | 20 | import li.pitschmann.knx.core.AbstractKnxByteEnumTest; 21 | import org.junit.jupiter.api.Test; 22 | 23 | import static org.assertj.core.api.Assertions.assertThat; 24 | 25 | /** 26 | * Verifies {@link AddressType} enum class 27 | * 28 | * @author PITSCHR 29 | */ 30 | public final class AddressTypeTest extends AbstractKnxByteEnumTest { 31 | @Override 32 | protected int numberOfElements() { 33 | return 2; 34 | } 35 | 36 | @Test 37 | @Override 38 | public void validValueOf() { 39 | assertThat(AddressType.valueOf(0x00)).isEqualTo(AddressType.INDIVIDUAL); 40 | assertThat(AddressType.valueOf(0x01)).isEqualTo(AddressType.GROUP); 41 | } 42 | 43 | @Test 44 | @Override 45 | public void friendlyName() { 46 | assertThat(AddressType.INDIVIDUAL.getFriendlyName()).isEqualTo("Individual Address"); 47 | assertThat(AddressType.GROUP.getFriendlyName()).isEqualTo("Group Address"); 48 | } 49 | 50 | @Test 51 | @Override 52 | public void testToString() { 53 | assertThat(AddressType.INDIVIDUAL).hasToString("AddressType{name=INDIVIDUAL, friendlyName=Individual Address, code=0x00}"); 54 | assertThat(AddressType.GROUP).hasToString("AddressType{name=GROUP, friendlyName=Group Address, code=0x01}"); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/exceptions/KnxDiscoveryNotReceivedException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.exceptions; 19 | 20 | import li.pitschmann.knx.core.annotations.Nullable; 21 | import li.pitschmann.knx.core.body.SearchRequestBody; 22 | import li.pitschmann.knx.core.body.SearchResponseBody; 23 | 24 | /** 25 | * Exception when discovery information could not be received by KNX Net/IP device. 26 | * This exception is a subclass of {@link KnxCommunicationException}. 27 | * 28 | * @author PITSCHR 29 | */ 30 | public final class KnxDiscoveryNotReceivedException extends KnxCommunicationException { 31 | private final SearchRequestBody requestBody; 32 | private final SearchResponseBody responseBody; 33 | 34 | public KnxDiscoveryNotReceivedException(final SearchRequestBody requestBody, 35 | final @Nullable SearchResponseBody responseBody, 36 | final Throwable cause) { 37 | super("Could not get discovery from KNX Net/IP device: request={}, response={}", 38 | requestBody, responseBody, cause); 39 | this.requestBody = requestBody; 40 | this.responseBody = responseBody; 41 | } 42 | 43 | public SearchRequestBody getRequestBody() { 44 | return requestBody; 45 | } 46 | 47 | @Nullable 48 | public SearchResponseBody getResponseBody() { 49 | return responseBody; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/dib/ServiceTypeFamilyVersionTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.dib; 19 | 20 | import nl.jqno.equalsverifier.EqualsVerifier; 21 | import org.junit.jupiter.api.DisplayName; 22 | import org.junit.jupiter.api.Test; 23 | 24 | import static org.assertj.core.api.Assertions.assertThat; 25 | 26 | /** 27 | * Verifies {@link ServiceTypeFamily} enum class 28 | * 29 | * @author PITSCHR 30 | */ 31 | final class ServiceTypeFamilyVersionTest { 32 | 33 | @Test 34 | @DisplayName("Test #of(ServiceTypeFamily, int)") 35 | void testOf() { 36 | final var serviceTypeFamilyVersion = new ServiceTypeFamilyVersion(ServiceTypeFamily.ROUTING, 13); 37 | 38 | assertThat(serviceTypeFamilyVersion.getFamily()).isSameAs(ServiceTypeFamily.ROUTING); 39 | assertThat(serviceTypeFamilyVersion.getVersion()).isEqualTo(13); 40 | } 41 | 42 | @Test 43 | @DisplayName("Test #toString()") 44 | void testToString() { 45 | final var serviceTypeFamilyVersion = new ServiceTypeFamilyVersion(ServiceTypeFamily.TUNNELING, 17); 46 | 47 | assertThat(serviceTypeFamilyVersion).hasToString( 48 | "ServiceTypeFamilyVersion{family=TUNNELING, version=17}" 49 | ); 50 | } 51 | 52 | 53 | @Test 54 | @DisplayName("#equals() and #hashCode()") 55 | void testEqualsAndHashCode() { 56 | EqualsVerifier.forClass(ServiceTypeFamilyVersion.class).verify(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/test/MockServerChannel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.test; 19 | 20 | import li.pitschmann.knx.core.body.Body; 21 | 22 | import java.io.IOException; 23 | import java.nio.channels.SelectableChannel; 24 | import java.nio.channels.SelectionKey; 25 | 26 | /** 27 | * Interface for KNX Mock Server Channel (UDP, TCP) 28 | */ 29 | public interface MockServerChannel extends AutoCloseable { 30 | 31 | /** 32 | * Returns the current channel 33 | * 34 | * @return channel 35 | */ 36 | T getChannel(); 37 | 38 | /** 39 | * Returns the current port where KNX mock server is listening 40 | * 41 | * @return port 42 | */ 43 | int getPort(); 44 | 45 | /** 46 | * Reads {@link Body} from {@link SelectionKey} 47 | * 48 | * @param key contains channel for incoming traffic 49 | * @return An instance of {@link Body} 50 | * @throws IOException If an I/O error occurs 51 | */ 52 | Body read(SelectionKey key) throws IOException; 53 | 54 | /** 55 | * Sends {@link Body} to given {@link SelectionKey} 56 | * 57 | * @param key contains channel for outgoing traffic 58 | * @param body body to be sent 59 | * @throws IOException If an I/O error occurs 60 | */ 61 | void send(SelectionKey key, Body body) throws IOException; 62 | 63 | @Override 64 | void close() throws IOException; 65 | } 66 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/test/strategy/impl/DescriptionNoTunnelingStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.test.strategy.impl; 19 | 20 | import li.pitschmann.knx.core.dib.SupportedServiceFamiliesDIB; 21 | import li.pitschmann.knx.core.test.MockServer; 22 | import li.pitschmann.knx.core.test.strategy.DescriptionStrategy; 23 | 24 | /** 25 | * No Tunneling Service Family for {@link DescriptionStrategy} 26 | */ 27 | public class DescriptionNoTunnelingStrategy extends DefaultDescriptionStrategy { 28 | private static final SupportedServiceFamiliesDIB DEFAULT_SUPPORTED_DEVICE_FAMILIES; 29 | 30 | static { 31 | DEFAULT_SUPPORTED_DEVICE_FAMILIES = SupportedServiceFamiliesDIB.of(new byte[]{ // 32 | 0x08, // Structure Length 33 | 0x02, // Description Type Code 34 | 0x02, 0x01, // Service Family ID (Core) + Version #1 35 | 0x03, 0x02, // Service Family ID (Device Management)+ Version #2 36 | 0x05, 0x03 // Service Family ID (Routing) + Version #4 37 | }); 38 | } 39 | 40 | /** 41 | * Returns the supported service families without TUNNELING feature. 42 | * 43 | * @param mockServer the mock server 44 | * @return DIB supported service families 45 | */ 46 | protected SupportedServiceFamiliesDIB getSupportedDeviceFamilies(final MockServer mockServer) { 47 | return DEFAULT_SUPPORTED_DEVICE_FAMILIES; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/exceptions/KnxChannelIdNotReceivedException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.exceptions; 19 | 20 | import li.pitschmann.knx.core.annotations.Nullable; 21 | import li.pitschmann.knx.core.body.ConnectRequestBody; 22 | import li.pitschmann.knx.core.body.ConnectResponseBody; 23 | 24 | /** 25 | * Exception when an channel id could not be received by KNX Net/IP device. 26 | * This exception is a subclass of {@link KnxCommunicationException}. 27 | * 28 | * @author PITSCHR 29 | */ 30 | public final class KnxChannelIdNotReceivedException extends KnxCommunicationException { 31 | private final ConnectRequestBody requestBody; 32 | private final ConnectResponseBody responseBody; 33 | 34 | public KnxChannelIdNotReceivedException(final ConnectRequestBody requestBody, 35 | final @Nullable ConnectResponseBody responseBody, 36 | final Throwable cause) { 37 | super("Could not get channel id from KNX Net/IP device: request={}, response={}", 38 | requestBody, responseBody, cause); 39 | this.requestBody = requestBody; 40 | this.responseBody = responseBody; 41 | } 42 | 43 | @Nullable 44 | public ConnectRequestBody getRequestBody() { 45 | return requestBody; 46 | } 47 | 48 | @Nullable 49 | public ConnectResponseBody getResponseBody() { 50 | return responseBody; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/test/strategy/impl/DefaultConnectionStateStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.test.strategy.impl; 19 | 20 | import li.pitschmann.knx.core.body.ConnectionStateResponseBody; 21 | import li.pitschmann.knx.core.body.RequestBody; 22 | import li.pitschmann.knx.core.body.ResponseBody; 23 | import li.pitschmann.knx.core.body.Status; 24 | import li.pitschmann.knx.core.test.MockServer; 25 | import li.pitschmann.knx.core.test.strategy.ConnectionStateStrategy; 26 | 27 | /** 28 | * Default implementation for {@link ConnectionStateStrategy} 29 | *

30 | * {@inheritDoc} 31 | */ 32 | public class DefaultConnectionStateStrategy implements ConnectionStateStrategy { 33 | /** 34 | * Returns the channel id that is used by the mock server 35 | * 36 | * @param mockServer the mock server 37 | * @return channel id 38 | */ 39 | protected int getChannelId(final MockServer mockServer) { 40 | return mockServer.getChannelId(); 41 | } 42 | 43 | /** 44 | * Return status. This method can be overridden. 45 | * 46 | * @return status 47 | */ 48 | protected Status getStatus() { 49 | return Status.NO_ERROR; 50 | } 51 | 52 | @Override 53 | public ResponseBody createResponse(final MockServer mockServer, final RequestBody unused) { 54 | final var channelId = getChannelId(mockServer); 55 | final var status = getStatus(); 56 | 57 | return ConnectionStateResponseBody.of(channelId, status); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/datapoint/BaseRangeDataPointType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.datapoint; 19 | 20 | import li.pitschmann.knx.core.annotations.Nullable; 21 | import li.pitschmann.knx.core.datapoint.value.DataPointValue; 22 | 23 | /** 24 | * {@link BaseDataPointType} extended class with range capability 25 | * 26 | * @author PITSCHR 27 | */ 28 | public abstract class BaseRangeDataPointType> extends BaseDataPointType { 29 | private final R lowerValue; 30 | private final R upperValue; 31 | 32 | protected BaseRangeDataPointType(final String description, 33 | final R lowerValue, 34 | final R upperValue, 35 | final @Nullable String unit) { 36 | super(description, unit); 37 | this.lowerValue = lowerValue; 38 | this.upperValue = upperValue; 39 | } 40 | 41 | public R getLowerValue() { 42 | return this.lowerValue; 43 | } 44 | 45 | public R getUpperValue() { 46 | return this.upperValue; 47 | } 48 | 49 | public final boolean isRangeClosed(final R value) { 50 | final var isWithinRange = value.compareTo(this.lowerValue) >= 0 && value.compareTo(this.upperValue) <= 0; 51 | if (!isWithinRange) { 52 | log.warn("Value '{}' is not within [{}, {}] for DPT '{}'", value, this.lowerValue, this.upperValue, this.getClass().getSimpleName()); 53 | } 54 | return isWithinRange; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/plugin/ObserverPlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.plugin; 19 | 20 | import li.pitschmann.knx.core.body.Body; 21 | 22 | /** 23 | * Plug-in to be notified when incoming / outgoing {@link Body} or if there was a problem with communication of 24 | * {@link Body} 25 | * 26 | * @author PITSCHR 27 | */ 28 | public interface ObserverPlugin extends Plugin { 29 | /** 30 | * Notifies the plug-in about incoming successful {@link Body} message 31 | * 32 | * @param item the incoming body; is never null 33 | */ 34 | void onIncomingBody(Body item); 35 | 36 | /** 37 | * Notifies the plug-in about outgoing successful {@link Body} message 38 | * 39 | * @param item the outgoing body; is never null 40 | */ 41 | void onOutgoingBody(Body item); 42 | 43 | /** 44 | * Notifies the plug-in about a {@link Throwable}. This method is designed 45 | * to inform the plugin about an unexpected / malformed packet and is rather 46 | * designed for auditing or logging similar purposes. In most cases you 47 | * are not interested in implementing this method. 48 | *

49 | * You shall not close or control the KnxClient as the 50 | * communication by KnxClient shall continue without any further issues. 51 | * All unexpected / malformed packets are subject to be ignored by the KnxClient. 52 | * 53 | * @param throwable the cause; is never null 54 | */ 55 | default void onError(Throwable throwable) { 56 | // NO-OP 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/communication/event/RequestEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.communication.event; 19 | 20 | import li.pitschmann.knx.core.body.RequestBody; 21 | import li.pitschmann.knx.core.utils.Strings; 22 | 23 | import java.time.Instant; 24 | 25 | /** 26 | * Mutable KNX event data for {@link RequestBody} 27 | * 28 | * @param instance of {@link RequestBody} 29 | * @author PITSCHR 30 | */ 31 | public class RequestEvent { 32 | private final Instant requestTime; 33 | private final T request; 34 | 35 | /** 36 | * Creates a new request event (package-protected) 37 | * to be called by {@link KnxSingleEvent} or {@link KnxMultiEvent} 38 | * 39 | * @param request the request body 40 | */ 41 | RequestEvent(final T request) { 42 | this.requestTime = Instant.now(); 43 | this.request = request; 44 | } 45 | 46 | /** 47 | * Returns the time when last request was set. 48 | * 49 | * @return An {@link Instant} 50 | */ 51 | public Instant getRequestTime() { 52 | return this.requestTime; 53 | } 54 | 55 | /** 56 | * Returns the request 57 | * 58 | * @return The request body which was set last time 59 | */ 60 | public T getRequest() { 61 | return this.request; 62 | } 63 | 64 | @Override 65 | public String toString() { 66 | return Strings.toStringHelper(this) // 67 | .add("requestTime", this.requestTime) // 68 | .add("request", this.request) // 69 | .toString(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/plugin/EnumConfigValueTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.plugin; 19 | 20 | import li.pitschmann.knx.core.communication.KnxClient; 21 | import org.junit.jupiter.api.DisplayName; 22 | import org.junit.jupiter.api.Test; 23 | 24 | import static org.assertj.core.api.Assertions.assertThat; 25 | 26 | /** 27 | * Test class for {@link EnumConfigValue} 28 | */ 29 | public final class EnumConfigValueTest { 30 | 31 | @Test 32 | @DisplayName("OK: Test Enum Config Value") 33 | public void testConfigValue() { 34 | final var plugin = new DummyPlugin(); 35 | 36 | final var configValue = plugin.TEST; 37 | assertThat(configValue.getKey()).isEqualTo("plugin.config.dummyplugin.enum-key"); // lower-cased! 38 | assertThat(configValue.getClassType()).isSameAs(DummyEnum.class); 39 | assertThat(configValue.getDefaultValue()).isEqualTo(DummyEnum.ONE); 40 | assertThat(configValue.convert("ONE")).isEqualTo(DummyEnum.ONE); 41 | assertThat(configValue.isValid(null)).isFalse(); 42 | assertThat(configValue.isValid(DummyEnum.TWO)).isTrue(); 43 | assertThat(configValue.getPredicate()).isNotNull(); // built-in 44 | } 45 | 46 | private enum DummyEnum { 47 | ZERO, ONE, TWO, THREE 48 | } 49 | 50 | private static class DummyPlugin implements Plugin { 51 | final EnumConfigValue TEST = new EnumConfigValue<>("enum-key", DummyEnum.class, () -> DummyEnum.ONE); 52 | 53 | @Override 54 | public void onInitialization(final KnxClient client) { 55 | // NO-OP 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/communication/event/ResponseEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.communication.event; 19 | 20 | import li.pitschmann.knx.core.body.ResponseBody; 21 | import li.pitschmann.knx.core.utils.Strings; 22 | 23 | import java.time.Instant; 24 | 25 | /** 26 | * Mutable KNX event data for {@link ResponseBody} 27 | * 28 | * @param instance of {@link ResponseBody} 29 | * @author PITSCHR 30 | */ 31 | public class ResponseEvent { 32 | private final Instant responseTime; 33 | private final T response; 34 | 35 | /** 36 | * Creates a new response event (package-protected) 37 | * to be called by {@link KnxSingleEvent} or {@link KnxMultiEvent} 38 | * 39 | * @param response the response body 40 | */ 41 | ResponseEvent(final T response) { 42 | this.responseTime = Instant.now(); 43 | this.response = response; 44 | } 45 | 46 | /** 47 | * Returns the time when last response was set. 48 | * 49 | * @return An {@link Instant} 50 | */ 51 | public Instant getResponseTime() { 52 | return this.responseTime; 53 | } 54 | 55 | /** 56 | * Returns the response 57 | * 58 | * @return The response body which was set last time 59 | */ 60 | public T getResponse() { 61 | return this.response; 62 | } 63 | 64 | @Override 65 | public String toString() { 66 | return Strings.toStringHelper(this) // 67 | .add("responseTime", this.responseTime) // 68 | .add("response", this.response) // 69 | .toString(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/plugin/PluginConfigValueTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.plugin; 19 | 20 | import li.pitschmann.knx.core.communication.KnxClient; 21 | import org.junit.jupiter.api.DisplayName; 22 | import org.junit.jupiter.api.Test; 23 | 24 | import static org.assertj.core.api.Assertions.assertThat; 25 | import static org.assertj.core.api.Assertions.assertThatThrownBy; 26 | 27 | /** 28 | * Test class for {@link PluginConfigValue} 29 | */ 30 | public final class PluginConfigValueTest { 31 | 32 | @Test 33 | @DisplayName("Error: Test General Plugin Config Value in wrong class") 34 | public void testWrongClass() { 35 | assertThatThrownBy(() -> new PluginConfigValue<>("a-name", Object.class, x -> x, () -> "a-value", null)) 36 | .isInstanceOf(AssertionError.class) 37 | .hasMessage("PluginConfigValue may be used in Plugin class only!"); 38 | } 39 | 40 | @Test 41 | @DisplayName("OK: Test General Plugin Config Value in Plugin class") 42 | public void testInPluginClass() { 43 | final var configValue = DummyPlugin.configValueObject; 44 | assertThat(configValue.getKey()).isEqualTo("plugin.config.dummyplugin.b-name"); // lower-cased! 45 | } 46 | 47 | private static class DummyPlugin implements Plugin { 48 | private static final PluginConfigValue configValueObject = new PluginConfigValue<>("b-name", Object.class, x -> x, () -> "", null); 49 | final PluginConfigValue TEST = new PluginConfigValue<>("b-name", Object.class, x -> x, () -> "", null); 50 | 51 | @Override 52 | public void onInitialization(final KnxClient client) { 53 | // NO-OP 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/utils/Maps.java: -------------------------------------------------------------------------------- 1 | package li.pitschmann.knx.core.utils; 2 | 3 | import java.util.HashMap; 4 | import java.util.LinkedHashMap; 5 | 6 | /** 7 | * Utility class for Maps 8 | */ 9 | public final class Maps { 10 | private static final int INT_MAX_POWER_OF_TWO = 1 << (Integer.SIZE - 2); 11 | 12 | private Maps() { 13 | throw new AssertionError("Do not touch me!"); 14 | } 15 | 16 | /** 17 | * Creates a new {@link HashMap} with expected size. 18 | *

19 | * Similar to Guava's Maps#newHashMapWithExpectedSize(int) 20 | * 21 | * @param expectedSize the expected size of hash map 22 | * @param the type of keys maintained by this map 23 | * @param the type of mapped values 24 | * @return new {@link HashMap} initialized with expected size 25 | */ 26 | public static HashMap newHashMap(final int expectedSize) { 27 | return new HashMap<>(capacity(expectedSize)); 28 | } 29 | 30 | /** 31 | * Creates a new {@link LinkedHashMap} with expected size. 32 | *

33 | * Similar to Guava's Maps#newLinkedHashMapWithExpectedSize(int) 34 | * 35 | * @param expectedSize the expected size of linked hash map 36 | * @param the type of keys maintained by this map 37 | * @param the type of mapped values 38 | * @return new {@link LinkedHashMap} initialized with expected size 39 | */ 40 | public static LinkedHashMap newLinkedHashMap(final int expectedSize) { 41 | return new LinkedHashMap<>(capacity(expectedSize)); 42 | } 43 | 44 | /** 45 | * Returns a properly calculated capacity for maps that is large 46 | * enough to avoid map from resizing/reallocating its capacity. 47 | * 48 | * @param expectedSize the expected size of capacity 49 | * @return calculated capacity based on {@code expectedSize} 50 | */ 51 | private static int capacity(final int expectedSize) { 52 | if (expectedSize < 3) { 53 | return expectedSize + 1; 54 | } else if (expectedSize < INT_MAX_POWER_OF_TWO) { 55 | // This is the calculation used in JDK8 to resize when a putAll 56 | // happens; it seems to be the most conservative calculation we 57 | // can make. 0.75 is the default load factor. 58 | return (int) ((float) expectedSize / 0.75F + 1.0F); 59 | } 60 | return Integer.MAX_VALUE; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/exceptions/KnxUnsupportedAPCICodeException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.exceptions; 19 | 20 | /** 21 | * Exception when an unsupported code for {@link li.pitschmann.knx.core.cemi.APCI} 22 | * was received 23 | * 24 | * @author PITSCHR 25 | */ 26 | public final class KnxUnsupportedAPCICodeException extends KnxException { 27 | public KnxUnsupportedAPCICodeException(final int code) { 28 | super( 29 | String.format("Unsupported APCI code and is not suitable for KNX Net/IP communication: %s (%s)", 30 | code, asBinaryString(code) 31 | ) 32 | ); 33 | } 34 | 35 | /** 36 | * Converts the APCI code to a binary string format (xxxx | yyyyyy) 37 | * 38 | *

39 |      *             +-7-+-6-+-5-+-4-+-3-+-2-+-1-+-0-+-7-+-6-+-5-+-4-+-3-+-2-+-1-+-0--+
40 |      * Field Names |                     (APCI)        | (data or APCI)             |
41 |      * Encoding    |                     A   A   A   A | AD  AD  AD  AD  AD  AD  AD |
42 |      *             +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+----+
43 |      * 
44 | * 45 | * @param code the APCI code 46 | * @return string representation of APCI code 47 | */ 48 | private static String asBinaryString(final int code) { 49 | final var binaryString = "0000000000" + Integer.toBinaryString(code); 50 | final var binaryStringLength = binaryString.length(); 51 | final var apciMajor4 = binaryString.substring(binaryStringLength - 10, binaryStringLength - 6); 52 | final var apciMinor6 = binaryString.substring(binaryStringLength - 6, binaryStringLength); 53 | return apciMajor4 + " | " + apciMinor6; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/plugin/PluginConfigValue.java: -------------------------------------------------------------------------------- 1 | package li.pitschmann.knx.core.plugin; 2 | 3 | import li.pitschmann.knx.core.annotations.Nullable; 4 | import li.pitschmann.knx.core.config.ConfigValue; 5 | 6 | import java.util.function.Function; 7 | import java.util.function.Predicate; 8 | import java.util.function.Supplier; 9 | 10 | /** 11 | * Dedicated {@link ConfigValue} instance for Plugin 12 | * 13 | * @param value type of plugin config (e.g. Boolean) 14 | * @author PITSCHR 15 | */ 16 | public class PluginConfigValue extends ConfigValue { 17 | /** 18 | * Key is the name of {@code "plugin.config.."} 19 | * (in lower-case, to be done in parent class) 20 | */ 21 | private static final String KEY_PATTERN = "plugin.config.%s.%s"; 22 | private final String key; 23 | 24 | public PluginConfigValue( 25 | final String configName, 26 | final Class classType, 27 | final Function converter, 28 | final Supplier defaultSupplier, 29 | final @Nullable Predicate predicate) { 30 | super( 31 | // leave it empty -> we will overwrite the key anyway! 32 | "", 33 | // rest remain same like ConfigValue 34 | classType, converter, defaultSupplier, predicate); 35 | key = String.format(KEY_PATTERN, findPluginClass().getSimpleName(), configName).toLowerCase(); 36 | } 37 | 38 | /** 39 | * Returns the {@link Class} of Plugin where this 40 | * 41 | * @return the class that holds the {@link PluginConfigValue} 42 | */ 43 | private static Class findPluginClass() { 44 | try { 45 | for (final var stackTraceElement : Thread.currentThread().getStackTrace()) { 46 | final var clazz = Class.forName(stackTraceElement.getClassName()); 47 | if (Plugin.class.isAssignableFrom(clazz)) { 48 | return clazz; 49 | } 50 | } 51 | } catch (final ClassNotFoundException e) { 52 | // cannot happen! 53 | } 54 | throw new AssertionError("PluginConfigValue may be used in Plugin class only!"); 55 | } 56 | 57 | /** 58 | * Plugin Config specific key with following format: 59 | * {@code plugin.config..} 60 | * 61 | * @return the key (lower-cased) 62 | */ 63 | @Override 64 | public String getKey() { 65 | return key; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/datapoint/value/DPTRawValueTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.datapoint.value; 19 | 20 | import nl.jqno.equalsverifier.EqualsVerifier; 21 | import org.junit.jupiter.api.DisplayName; 22 | import org.junit.jupiter.api.Test; 23 | 24 | import static org.assertj.core.api.Assertions.assertThat; 25 | 26 | /** 27 | * Test {@link DPTRawValue} 28 | * 29 | * @author PITSCHR 30 | */ 31 | class DPTRawValueTest { 32 | 33 | @Test 34 | @DisplayName("#(byte[]) with: 0x11 22 33 44 55") 35 | void testByte_11_22_33_44_55() { 36 | final var value = new DPTRawValue(new byte[]{0x11, 0x22, 0x33, 0x44, 0x55}); 37 | assertThat(value.toByteArray()).containsExactly(0x11, 0x22, 0x33, 0x44, 0x55); 38 | 39 | assertThat(value.toText()).isEqualTo("0x11 22 33 44 55"); 40 | } 41 | 42 | @Test 43 | @DisplayName("#(byte[]) with: 0xAA BB CC DD EE FF") 44 | void testByte_AA_BB_CC_DD_EE_FF() { 45 | final var value = new DPTRawValue(new byte[]{(byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD, (byte) 0xEE, (byte) 0xFF}); 46 | assertThat(value.toByteArray()).containsExactly(0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF); 47 | 48 | assertThat(value.toText()).isEqualTo("0xAA BB CC DD EE FF"); 49 | } 50 | 51 | @Test 52 | @DisplayName("#toString()") 53 | void testToString() { 54 | final var value = new DPTRawValue(new byte[]{0x43, (byte) 0x83, (byte) 0xAD, 0x21}); 55 | assertThat(value).hasToString( 56 | "DPTRawValue{dpt=raw, byteArray=0x43 83 AD 21}" 57 | ); 58 | } 59 | 60 | @Test 61 | @DisplayName("#equals() and #hashCode()") 62 | void testEqualsAndHashCode() { 63 | EqualsVerifier.forClass(DPTRawValue.class).withIgnoredFields("dpt").verify(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/knxproj/XmlGroupAddressTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.knxproj; 19 | 20 | import org.junit.jupiter.api.DisplayName; 21 | import org.junit.jupiter.api.Test; 22 | 23 | import static org.assertj.core.api.Assertions.assertThat; 24 | 25 | /** 26 | * Tests {@link XmlGroupAddress} that contains data from '*.knxproj' file 27 | */ 28 | class XmlGroupAddressTest { 29 | 30 | @Test 31 | @DisplayName("Tests XmlGroupAddress#toString()") 32 | void testToString() { 33 | final var xmlGroupAddress = new XmlGroupAddress(); 34 | xmlGroupAddress.setId("ID"); 35 | xmlGroupAddress.setParentId("PARENT_ID"); 36 | xmlGroupAddress.setName("NAME"); 37 | xmlGroupAddress.setAddress("ADDRESS"); 38 | xmlGroupAddress.setDescription("DESCRIPTION"); 39 | xmlGroupAddress.setDataPointType("DPT"); 40 | 41 | // check if setter/getter are working 42 | assertThat(xmlGroupAddress.getId()).isEqualTo("ID"); 43 | assertThat(xmlGroupAddress.getParentId()).isEqualTo("PARENT_ID"); 44 | assertThat(xmlGroupAddress.getName()).isEqualTo("NAME"); 45 | assertThat(xmlGroupAddress.getAddress()).isEqualTo("ADDRESS"); 46 | assertThat(xmlGroupAddress.getDescription()).isEqualTo("DESCRIPTION"); 47 | assertThat(xmlGroupAddress.getDataPointType()).isEqualTo("DPT"); 48 | 49 | // @formatter:off 50 | assertThat(xmlGroupAddress).hasToString("XmlGroupAddress" + 51 | "{" + 52 | "id=ID, " + 53 | "parentId=PARENT_ID, " + 54 | "address=ADDRESS, " + 55 | "name=NAME, " + 56 | "description=DESCRIPTION, " + 57 | "dataPointType=DPT" + 58 | "}"); 59 | // @formatter:on 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/dib/ServiceTypeFamilyVersion.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.dib; 19 | 20 | import li.pitschmann.knx.core.annotations.Nullable; 21 | import li.pitschmann.knx.core.utils.Preconditions; 22 | import li.pitschmann.knx.core.utils.Strings; 23 | 24 | import java.util.Objects; 25 | 26 | /** 27 | * Service Type Family and Version. Designed to be used 28 | * for {@link SupportedServiceFamiliesDIB}. 29 | * 30 | * @author PITSCHR 31 | */ 32 | public final class ServiceTypeFamilyVersion { 33 | private final ServiceTypeFamily family; 34 | private final int version; 35 | 36 | public ServiceTypeFamilyVersion(final ServiceTypeFamily family, final int version) { 37 | Preconditions.checkNonNull(family, "Service Type Family is required."); 38 | 39 | this.family = family; 40 | this.version = version; 41 | } 42 | 43 | public ServiceTypeFamily getFamily() { 44 | return family; 45 | } 46 | 47 | public int getVersion() { 48 | return version; 49 | } 50 | 51 | @Override 52 | public String toString() { 53 | return Strings.toStringHelper(this) 54 | .add("family", family.name()) 55 | .add("version", version) 56 | .toString(); 57 | } 58 | 59 | @Override 60 | public boolean equals(final @Nullable Object obj) { 61 | if (this == obj) { 62 | return true; 63 | } else if (obj instanceof ServiceTypeFamilyVersion) { 64 | final var other = (ServiceTypeFamilyVersion) obj; 65 | return Objects.equals(this.family, other.family) 66 | && Objects.equals(this.version, other.version); 67 | } 68 | return false; 69 | } 70 | 71 | @Override 72 | public int hashCode() { 73 | return Objects.hash(family, version); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/cemi/BroadcastTypeTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.cemi; 19 | 20 | import li.pitschmann.knx.core.exceptions.KnxEnumNotFoundException; 21 | import org.junit.jupiter.api.DisplayName; 22 | import org.junit.jupiter.api.Test; 23 | 24 | import static org.assertj.core.api.Assertions.assertThat; 25 | import static org.assertj.core.api.Assertions.assertThatThrownBy; 26 | 27 | /** 28 | * Verifies {@link BroadcastType} enum class 29 | * 30 | * @author PITSCHR 31 | */ 32 | final class BroadcastTypeTest { 33 | 34 | @Test 35 | @DisplayName("Test number of enum elements") 36 | void numberOfElements() { 37 | assertThat(BroadcastType.values()).hasSize(2); 38 | } 39 | 40 | @Test 41 | @DisplayName("Valid cases for #valueOf()") 42 | void validValueOf() { 43 | assertThat(BroadcastType.valueOf(0x00)).isEqualTo(BroadcastType.SYSTEM); 44 | assertThat(BroadcastType.valueOf(0x01)).isEqualTo(BroadcastType.NORMAL); 45 | } 46 | 47 | @Test 48 | @DisplayName("Invalid cases for #valueOf()") 49 | void invalidValueOf() { 50 | assertThatThrownBy(() -> BroadcastType.valueOf(-1)).isInstanceOf(KnxEnumNotFoundException.class); 51 | } 52 | 53 | @Test 54 | @DisplayName("Test #getFriendlyName()") 55 | void testGetFriendlyName() { 56 | assertThat(BroadcastType.SYSTEM.getFriendlyName()).isEqualTo("System Broadcast"); 57 | assertThat(BroadcastType.NORMAL.getFriendlyName()).isEqualTo("Normal Broadcast"); 58 | } 59 | 60 | @Test 61 | @DisplayName("Test #toString()") 62 | void testToString() { 63 | assertThat(BroadcastType.SYSTEM).hasToString("BroadcastType{name=SYSTEM, friendlyName=System Broadcast, code=0}"); 64 | assertThat(BroadcastType.NORMAL).hasToString("BroadcastType{name=NORMAL, friendlyName=Normal Broadcast, code=1}"); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/net/HostProtocolTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.net; 19 | 20 | import li.pitschmann.knx.core.exceptions.KnxEnumNotFoundException; 21 | import org.junit.jupiter.api.DisplayName; 22 | import org.junit.jupiter.api.Test; 23 | 24 | import static org.assertj.core.api.Assertions.assertThat; 25 | import static org.assertj.core.api.Assertions.assertThatThrownBy; 26 | 27 | /** 28 | * Verifies {@link HostProtocol} enum class 29 | * 30 | * @author PITSCHR 31 | */ 32 | final class HostProtocolTest { 33 | 34 | @Test 35 | @DisplayName("Test number of enum elements") 36 | void numberOfElements() { 37 | assertThat(HostProtocol.values()).hasSize(2); 38 | } 39 | 40 | @Test 41 | @DisplayName("Valid cases for #valueOf()") 42 | void validValueOf() { 43 | assertThat(HostProtocol.valueOf(0x01)).isEqualTo(HostProtocol.IPV4_UDP); 44 | assertThat(HostProtocol.valueOf(0x02)).isEqualTo(HostProtocol.IPV4_TCP); 45 | } 46 | 47 | @Test 48 | @DisplayName("Invalid cases for #valueOf()") 49 | void invalidValueOf() { 50 | assertThatThrownBy(() -> HostProtocol.valueOf(0x00)).isInstanceOf(KnxEnumNotFoundException.class); 51 | assertThatThrownBy(() -> HostProtocol.valueOf(0xFF)).isInstanceOf(KnxEnumNotFoundException.class); 52 | } 53 | 54 | @Test 55 | @DisplayName("Test #getFriendlyName()") 56 | void testGetFriendlyName() { 57 | assertThat(HostProtocol.IPV4_UDP.getFriendlyName()).isEqualTo("IP v4 UDP communication"); 58 | assertThat(HostProtocol.IPV4_TCP.getFriendlyName()).isEqualTo("IP v4 TCP communication"); 59 | } 60 | 61 | @Test 62 | @DisplayName("Test #toString()") 63 | void testToString() { 64 | assertThat(HostProtocol.IPV4_UDP).hasToString( 65 | "HostProtocol{name=IPV4_UDP, friendlyName=IP v4 UDP communication, code=1}" 66 | ); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/cemi/BroadcastType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.cemi; 19 | 20 | import li.pitschmann.knx.core.KnxByteEnum; 21 | import li.pitschmann.knx.core.exceptions.KnxEnumNotFoundException; 22 | import li.pitschmann.knx.core.utils.Strings; 23 | 24 | import java.util.Arrays; 25 | 26 | public enum BroadcastType implements KnxByteEnum { 27 | /** 28 | * System Broadcast 29 | */ 30 | SYSTEM(0x00, "System Broadcast"), 31 | /** 32 | * Normal Broadcast 33 | */ 34 | NORMAL(0x01, "Normal Broadcast"); 35 | 36 | private final int code; 37 | private final String friendlyName; 38 | 39 | BroadcastType(final int code, final String friendlyName) { 40 | this.code = code; 41 | this.friendlyName = friendlyName; 42 | } 43 | 44 | /** 45 | * A matching {@link BroadcastType} for the given {@code code} 46 | * 47 | * @param code value to find the associated {@link BroadcastType} 48 | * @return existing {@link BroadcastType}, or {@link KnxEnumNotFoundException} if no {@link BroadcastType} 49 | * for given {@code code} exists 50 | */ 51 | public static BroadcastType valueOf(final int code) { 52 | return Arrays.stream(values()) 53 | .filter(x -> x.getCode() == code) 54 | .findFirst() 55 | .orElseThrow(() -> new KnxEnumNotFoundException(BroadcastType.class, code)); 56 | } 57 | 58 | @Override 59 | public int getCode() { 60 | return code; 61 | } 62 | 63 | @Override 64 | public String getFriendlyName() { 65 | return friendlyName; 66 | } 67 | 68 | @Override 69 | public String toString() { 70 | return Strings.toStringHelper(this) 71 | .add("name", name()) 72 | .add("friendlyName", friendlyName) 73 | .add("code", code) 74 | .toString(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/datapoint/DPT25.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.datapoint; 19 | 20 | import li.pitschmann.knx.core.datapoint.value.DPT25Value; 21 | 22 | /** 23 | * Data Point Type 25 for 'Double Nibble Set' (8 Bits) 24 | * 25 | *
26 |  *             +-7-+-6-+-5-+-4-+-3-+-2-+-1-+-0-+
27 |  * Field Names | (Busy)          (Nak)         |
28 |  * Encoding    | U   U   U   U   U   U   U   U |
29 |  *             +---+---+---+---+---+---+---+---+
30 |  * Format:     8 bit (U4U4)
31 |  * 
32 | * 33 | * @author PITSCHR 34 | */ 35 | public final class DPT25 extends BaseDataPointType { 36 | /** 37 | * 25.1000 Busy/Nak Repetitions 38 | * 39 | *
40 |      *             +-7-+-6-+-5-+-4-+-3-+-2-+-1-+-0-+
41 |      * Field Names | (Busy)          (Nak)         |
42 |      * Encoding    | U   U   U   U   U   U   U   U |
43 |      *             +---+---+---+---+---+---+---+---+
44 |      * Format:     8 bit (U4U4)
45 |      * Range:      Busy = [0 .. 15]
46 |      *             Nak  = [0 .. 15]
47 |      * 
48 | */ 49 | @DataPoint({"25.1000", "dpt-25", "dpst-25-1"}) 50 | public static final DPT25 BUSY_NAK_REPETITIONS = new DPT25("Busy/Nak Repetitions"); 51 | 52 | /** 53 | * Constructor for {@link DPT25} 54 | * 55 | * @param description description for {@link DPT25} 56 | */ 57 | private DPT25(final String description) { 58 | super(description); 59 | } 60 | 61 | @Override 62 | protected boolean isCompatible(final byte[] bytes) { 63 | return bytes.length == 1; 64 | } 65 | 66 | @Override 67 | protected DPT25Value parse(final byte[] bytes) { 68 | return new DPT25Value(bytes[0]); 69 | } 70 | 71 | public DPT25Value of(final int busy, final int nak) { 72 | return new DPT25Value(busy, nak); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/communication/queue/MulticastOutboxQueue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.communication.queue; 19 | 20 | import li.pitschmann.knx.core.communication.InternalKnxClient; 21 | import li.pitschmann.knx.core.config.CoreConfigs; 22 | 23 | import java.io.IOException; 24 | import java.net.InetSocketAddress; 25 | import java.nio.ByteBuffer; 26 | import java.nio.channels.DatagramChannel; 27 | import java.nio.channels.SelectableChannel; 28 | 29 | /** 30 | * Discovery Outbox Queue for KNX multicast packets to be sent to KNX Net/IP device 31 | * This class is special because the multicast communication is based on broadcast. 32 | * 33 | * @author PITSCHR 34 | */ 35 | public final class MulticastOutboxQueue extends AbstractOutboxQueue { 36 | private final InetSocketAddress multicastSocketAddress; 37 | 38 | /** 39 | * Constructor for KNX Discovery Inbox Queue 40 | * 41 | * @param client internal KNX client for internal actions like informing plug-ins 42 | * @param channel channel of communication 43 | */ 44 | public MulticastOutboxQueue(final InternalKnxClient client, final SelectableChannel channel) { 45 | super(client, channel); 46 | 47 | final var config = client.getConfig(); 48 | 49 | // use config setting, otherwise fall back to default setting 50 | final var remoteAddress = config.isRoutingEnabled() ? config.getRemoteControlAddress() : config.getValue(CoreConfigs.Multicast.ADDRESS); 51 | final var remotePort = config.getRemoteControlPort(); 52 | 53 | multicastSocketAddress = new InetSocketAddress(remoteAddress, remotePort); 54 | log.debug("Multicast Outbox Socket: {}", multicastSocketAddress); 55 | } 56 | 57 | @Override 58 | protected void send(final DatagramChannel channel, final ByteBuffer bb) throws IOException { 59 | channel.send(bb, multicastSocketAddress); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/utils/Strings.java: -------------------------------------------------------------------------------- 1 | package li.pitschmann.knx.core.utils; 2 | 3 | import li.pitschmann.knx.core.annotations.Nullable; 4 | 5 | /** 6 | * Utility class for strings 7 | */ 8 | public final class Strings { 9 | private Strings() { 10 | throw new AssertionError("Do not touch me!"); 11 | } 12 | 13 | /** 14 | * Returns {@code true} if the given {@link String} is null or empty. 15 | * 16 | * @param string the string representation to be checked 17 | * @return {@code true} if the string is null or is empty 18 | */ 19 | public static boolean isNullOrEmpty(final @Nullable String string) { 20 | return string == null || string.isEmpty(); 21 | } 22 | 23 | /** 24 | * Creates a {@link ToStringHelper} for creating string representations. 25 | * Similar to Guava's {@code ToStringHelper} but simpler. 26 | *

27 | * If the class of object is a member class the parent class will be also be a part of name. 28 | * Example: {@code my.package.MyClass$MyInnerClass} -> {@code MyClass$MyInnerClass} 29 | * 30 | * @param obj the instance of {@link Object} that should be used for creating a {@link ToStringHelper} 31 | * @return a new instance of {@link ToStringHelper} 32 | */ 33 | public static ToStringHelper toStringHelper(final Object obj) { 34 | final var clazz = obj.getClass(); 35 | if (clazz.isMemberClass()) { 36 | // E.g. my.package.MyClass$MyInnerClass -> MyClass$MyInnerClass 37 | final var name = clazz.getName(); 38 | return new ToStringHelper(name.substring(name.lastIndexOf('.') + 1)); 39 | } else { 40 | // E.g. my.package.MyClass -> MyClass 41 | return new ToStringHelper(clazz.getSimpleName()); 42 | } 43 | } 44 | 45 | /** 46 | * Helper for creating a string representation. This class 47 | * is much more simplified than from Guava. 48 | */ 49 | public static class ToStringHelper { 50 | private final StringBuilder sb = new StringBuilder(200); 51 | private final String className; 52 | 53 | private ToStringHelper(final String name) { 54 | this.className = Preconditions.checkNonNull(name); 55 | } 56 | 57 | public ToStringHelper add(final String name, @Nullable Object value) { 58 | Preconditions.checkNonNull(name); 59 | if (sb.length() != 0) { 60 | sb.append(", "); 61 | } 62 | sb.append(name).append('=').append(value); 63 | return this; 64 | } 65 | 66 | @Override 67 | public String toString() { 68 | return className + '{' + sb.toString() + '}'; 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/plugin/BooleanConfigValueTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.plugin; 19 | 20 | import li.pitschmann.knx.core.communication.KnxClient; 21 | import org.junit.jupiter.api.DisplayName; 22 | import org.junit.jupiter.api.Test; 23 | 24 | import static org.assertj.core.api.Assertions.assertThat; 25 | 26 | /** 27 | * Test class for {@link BooleanConfigValue} 28 | */ 29 | public final class BooleanConfigValueTest { 30 | 31 | @Test 32 | @DisplayName("OK: Test Boolean Config Value") 33 | public void testConfigValue() { 34 | final var plugin = new DummyPlugin(); 35 | 36 | final var configValue = plugin.TEST; 37 | assertThat(configValue.getKey()).isEqualTo("plugin.config.dummyplugin.bool-key"); // lower-cased! 38 | assertThat(configValue.getClassType()).isSameAs(Boolean.class); 39 | assertThat(configValue.getDefaultValue()).isEqualTo(Boolean.FALSE); 40 | 41 | assertThat(configValue.convert("true")).isTrue(); 42 | assertThat(configValue.convert("True")).isTrue(); 43 | assertThat(configValue.convert("TRUE")).isTrue(); 44 | assertThat(configValue.convert("false")).isFalse(); 45 | assertThat(configValue.convert("False")).isFalse(); 46 | assertThat(configValue.convert("FALSE")).isFalse(); 47 | 48 | assertThat(configValue.isValid(null)).isFalse(); 49 | assertThat(configValue.isValid(true)).isTrue(); 50 | assertThat(configValue.isValid(Boolean.TRUE)).isTrue(); 51 | assertThat(configValue.isValid(false)).isTrue(); 52 | assertThat(configValue.isValid(Boolean.FALSE)).isTrue(); 53 | 54 | assertThat(configValue.getPredicate()).isNull(); 55 | } 56 | 57 | private static class DummyPlugin implements Plugin { 58 | final BooleanConfigValue TEST = new BooleanConfigValue("bool-key", () -> Boolean.FALSE); 59 | 60 | @Override 61 | public void onInitialization(final KnxClient client) { 62 | // NO-OP 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/cemi/AdditionalInfoTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.cemi; 19 | 20 | import nl.jqno.equalsverifier.EqualsVerifier; 21 | import org.junit.jupiter.api.DisplayName; 22 | import org.junit.jupiter.api.Test; 23 | 24 | import static org.assertj.core.api.Assertions.assertThat; 25 | import static org.assertj.core.api.Assertions.assertThatThrownBy; 26 | 27 | /** 28 | * Test case for {@link AdditionalInfo} 29 | * 30 | * @author PITSCHR 31 | */ 32 | final class AdditionalInfoTest { 33 | 34 | @Test 35 | @DisplayName("Test #empty()") 36 | void testEmpty() { 37 | // create 38 | final var emptyInfo = AdditionalInfo.empty(); 39 | 40 | // byte array shall be empty 41 | assertThat(emptyInfo.toByteArray()).isEmpty(); 42 | 43 | // toString 44 | assertThat(emptyInfo).hasToString("AdditionalInfo{bytes=}"); 45 | } 46 | 47 | @Test 48 | @DisplayName("Test #of(byte[])") 49 | void testOf() { 50 | // create by bytes 51 | final var additionalInfo = AdditionalInfo.of(new byte[]{ 52 | 0x04, // Structure Length of Additional Info 53 | 0x01, 0x02, 0x03, 0x04 // data 54 | }); 55 | 56 | // compare the byte array of 'create by bytes' 57 | assertThat(additionalInfo.toByteArray()).containsExactly(0x04, 0x01, 0x02, 0x03, 0x04); 58 | 59 | // toString 60 | assertThat(additionalInfo).hasToString("AdditionalInfo{bytes=0x04 01 02 03 04}"); 61 | } 62 | 63 | @Test 64 | @DisplayName("Invalid cases for #of(byte[])") 65 | void invalidCases() { 66 | // null 67 | assertThatThrownBy(() -> AdditionalInfo.of(null)) 68 | .isInstanceOf(NullPointerException.class) 69 | .hasMessageStartingWith("Bytes is required."); 70 | } 71 | 72 | @Test 73 | @DisplayName("#equals() and #hashCode()") 74 | void testEqualsAndHashCode() { 75 | EqualsVerifier.forClass(AdditionalInfo.class).verify(); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/communication/event/KnxEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.communication.event; 19 | 20 | import li.pitschmann.knx.core.body.RequestBody; 21 | import li.pitschmann.knx.core.body.ResponseBody; 22 | 23 | import java.time.Instant; 24 | 25 | /** 26 | * Interface for mutable KNX event data container 27 | * 28 | * @param instance of {@link RequestBody} 29 | * @param instance of {@link ResponseBody} 30 | * @author PITSCHR 31 | */ 32 | public interface KnxEvent { 33 | /** 34 | * Returns the KNX request event 35 | * 36 | * @return request 37 | */ 38 | REQUEST getRequest(); 39 | 40 | /** 41 | * Sets the KNX request event 42 | * 43 | * @param request the request body 44 | */ 45 | void setRequest(REQUEST request); 46 | 47 | /** 48 | * Returns the {@link Instant} time of KNX request event 49 | * 50 | * @return instant time for request 51 | */ 52 | Instant getRequestTime(); 53 | 54 | /** 55 | * Returns the KNX response event 56 | * 57 | * @return response 58 | */ 59 | RESPONSE getResponse(); 60 | 61 | /** 62 | * Sets the KNX response event 63 | * 64 | * @param response the response body 65 | */ 66 | void setResponse(RESPONSE response); 67 | 68 | /** 69 | * Clears all responses 70 | */ 71 | void clearResponse(); 72 | 73 | /** 74 | * Returns the {@link Instant} time of KNX response event 75 | * 76 | * @return instant time for response 77 | */ 78 | Instant getResponseTime(); 79 | 80 | /** 81 | * Returns if KNX request event is present 82 | * 83 | * @return {@code true} if present, otherwise {@code false} 84 | */ 85 | boolean hasRequest(); 86 | 87 | /** 88 | * Returns if KNX response event is present 89 | * 90 | * @return {@code true} if present, otherwise {@code false} 91 | */ 92 | boolean hasResponse(); 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/communication/task/SearchResponseTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.communication.task; 19 | 20 | import li.pitschmann.knx.core.annotations.Nullable; 21 | import li.pitschmann.knx.core.body.Body; 22 | import li.pitschmann.knx.core.body.SearchRequestBody; 23 | import li.pitschmann.knx.core.body.SearchResponseBody; 24 | import li.pitschmann.knx.core.communication.InternalKnxClient; 25 | import org.slf4j.Logger; 26 | import org.slf4j.LoggerFactory; 27 | 28 | import java.util.Objects; 29 | import java.util.concurrent.Flow.Subscriber; 30 | import java.util.concurrent.Flow.Subscription; 31 | 32 | /** 33 | * Listens to {@link SearchResponseBody} frame that is sent by KNX Net/IP device to client when 34 | * {@link SearchRequestBody} was sent. 35 | * 36 | * @author PITSCHR 37 | */ 38 | public final class SearchResponseTask implements Subscriber { 39 | private static final Logger log = LoggerFactory.getLogger(SearchResponseTask.class); 40 | private final InternalKnxClient client; 41 | 42 | public SearchResponseTask(final InternalKnxClient client) { 43 | this.client = Objects.requireNonNull(client); 44 | } 45 | 46 | @Override 47 | public void onNext(final @Nullable Body body) { 48 | // we are interested in search response only 49 | if (body instanceof SearchResponseBody) { 50 | final var responseBody = (SearchResponseBody) body; 51 | log.debug("Search response received: {}", responseBody); 52 | this.client.getEventPool().searchEvent().addResponse(responseBody); 53 | log.trace("Search response saved."); 54 | } 55 | } 56 | 57 | @Override 58 | public void onError(final @Nullable Throwable throwable) { 59 | log.error("Error during Search Response Task class", throwable); 60 | } 61 | 62 | @Override 63 | public void onComplete() { 64 | // NO-OP 65 | } 66 | 67 | @Override 68 | public void onSubscribe(final Subscription subscription) { 69 | subscription.request(Long.MAX_VALUE); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/communication/task/ConnectionStateResponseTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.communication.task; 19 | 20 | import li.pitschmann.knx.core.annotations.Nullable; 21 | import li.pitschmann.knx.core.body.Body; 22 | import li.pitschmann.knx.core.body.ConnectionStateResponseBody; 23 | import li.pitschmann.knx.core.communication.InternalKnxClient; 24 | import org.slf4j.Logger; 25 | import org.slf4j.LoggerFactory; 26 | 27 | import java.util.Objects; 28 | import java.util.concurrent.Flow.Subscriber; 29 | import java.util.concurrent.Flow.Subscription; 30 | 31 | /** 32 | * Listens to {@link ConnectionStateResponseTask} received by KNX Net/IP device about the health. 33 | * 34 | * @author PITSCHR 35 | */ 36 | public final class ConnectionStateResponseTask implements Subscriber { 37 | private static final Logger log = LoggerFactory.getLogger(ConnectionStateResponseTask.class); 38 | private final InternalKnxClient client; 39 | 40 | public ConnectionStateResponseTask(final InternalKnxClient client) { 41 | this.client = Objects.requireNonNull(client); 42 | } 43 | 44 | @Override 45 | public void onNext(final @Nullable Body body) { 46 | // we are interested in connection state response only 47 | if (body instanceof ConnectionStateResponseBody) { 48 | final var responseBody = (ConnectionStateResponseBody) body; 49 | log.debug("Connection State Response received: {}", responseBody); 50 | this.client.getEventPool().connectionStateEvent().setResponse(responseBody); 51 | log.trace("Connection State Response saved."); 52 | } 53 | } 54 | 55 | @Override 56 | public void onError(final @Nullable Throwable throwable) { 57 | log.error("Error during Connection State Response Task class", throwable); 58 | } 59 | 60 | @Override 61 | public void onComplete() { 62 | // NO-OP 63 | } 64 | 65 | @Override 66 | public void onSubscribe(final Subscription subscription) { 67 | subscription.request(Long.MAX_VALUE); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/communication/task/DisconnectResponseTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.communication.task; 19 | 20 | import li.pitschmann.knx.core.annotations.Nullable; 21 | import li.pitschmann.knx.core.body.Body; 22 | import li.pitschmann.knx.core.body.DisconnectResponseBody; 23 | import li.pitschmann.knx.core.communication.InternalKnxClient; 24 | import org.slf4j.Logger; 25 | import org.slf4j.LoggerFactory; 26 | 27 | import java.util.Objects; 28 | import java.util.concurrent.Flow.Subscriber; 29 | import java.util.concurrent.Flow.Subscription; 30 | 31 | /** 32 | * Listens to {@link DisconnectResponseBody} frame when KNX connection was subject to be closed by the local machine and 33 | * replied by the KNX Net/IP device. 34 | * 35 | * @author PITSCHR 36 | */ 37 | public final class DisconnectResponseTask implements Subscriber { 38 | private static final Logger log = LoggerFactory.getLogger(DisconnectResponseTask.class); 39 | private final InternalKnxClient client; 40 | 41 | public DisconnectResponseTask(final InternalKnxClient client) { 42 | this.client = Objects.requireNonNull(client); 43 | } 44 | 45 | @Override 46 | public void onNext(final @Nullable Body body) { 47 | // we are interested in disconnect response only 48 | if (body instanceof DisconnectResponseBody) { 49 | final var responseBody = (DisconnectResponseBody) body; 50 | log.debug("Disconnect Response received: {}", responseBody); 51 | this.client.getEventPool().disconnectEvent().setResponse(responseBody); 52 | log.trace("Disconnect Response saved."); 53 | } 54 | } 55 | 56 | @Override 57 | public void onError(final @Nullable Throwable throwable) { 58 | log.error("Error during Disconnect Response Task class", throwable); 59 | } 60 | 61 | @Override 62 | public void onComplete() { 63 | // NO-OP 64 | } 65 | 66 | @Override 67 | public void onSubscribe(final Subscription subscription) { 68 | subscription.request(Long.MAX_VALUE); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/net/tunnel/LayerTypeTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.net.tunnel; 19 | 20 | import li.pitschmann.knx.core.exceptions.KnxEnumNotFoundException; 21 | import org.junit.jupiter.api.DisplayName; 22 | import org.junit.jupiter.api.Test; 23 | 24 | import static org.assertj.core.api.Assertions.assertThat; 25 | import static org.assertj.core.api.Assertions.assertThatThrownBy; 26 | 27 | /** 28 | * Verifies {@link LayerType} enum class 29 | * 30 | * @author PITSCHR 31 | */ 32 | final class LayerTypeTest { 33 | 34 | @Test 35 | @DisplayName("Test number of enum elements") 36 | void numberOfElements() { 37 | assertThat(LayerType.values()).hasSize(3); 38 | } 39 | 40 | @Test 41 | @DisplayName("Valid cases for #valueOf()") 42 | void validValueOf() { 43 | assertThat(LayerType.valueOf(0x02)).isEqualTo(LayerType.TUNNEL_LINK_LAYER); 44 | assertThat(LayerType.valueOf(0x04)).isEqualTo(LayerType.TUNNEL_RAW); 45 | assertThat(LayerType.valueOf(0x80)).isEqualTo(LayerType.TUNNEL_BUS_MONITOR); 46 | } 47 | 48 | @Test 49 | @DisplayName("Invalid cases for #valueOf()") 50 | void invalidValueOf() { 51 | assertThatThrownBy(() -> LayerType.valueOf(0x00)).isInstanceOf(KnxEnumNotFoundException.class); 52 | assertThatThrownBy(() -> LayerType.valueOf(0xFF)).isInstanceOf(KnxEnumNotFoundException.class); 53 | } 54 | 55 | @Test 56 | @DisplayName("Test #getFriendlyName()") 57 | void testGetFriendlyName() { 58 | assertThat(LayerType.TUNNEL_LINK_LAYER.getFriendlyName()).isEqualTo("Tunneling Link Layer"); 59 | assertThat(LayerType.TUNNEL_RAW.getFriendlyName()).isEqualTo("Tunneling Raw Layer"); 60 | assertThat(LayerType.TUNNEL_BUS_MONITOR.getFriendlyName()).isEqualTo("Tunneling Bus Monitor Layer"); 61 | } 62 | 63 | @Test 64 | @DisplayName("Test #toString()") 65 | void testToString() { 66 | assertThat(LayerType.TUNNEL_LINK_LAYER).hasToString( 67 | "LayerType{name=TUNNEL_LINK_LAYER, friendlyName=Tunneling Link Layer, code=2}" 68 | ); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/test/java/li/pitschmann/knx/core/AbstractKnxByteEnumTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core; 19 | 20 | import li.pitschmann.knx.core.exceptions.KnxEnumNotFoundException; 21 | import org.junit.jupiter.api.Test; 22 | 23 | import java.util.EnumSet; 24 | 25 | import static org.assertj.core.api.Assertions.assertThat; 26 | import static org.junit.jupiter.api.Assertions.assertThrows; 27 | 28 | /** 29 | * Abstract Test for {@link KnxByteEnum} classes 30 | * 31 | * @param 32 | * @author PITSCHR 33 | */ 34 | public abstract class AbstractKnxByteEnumTest & KnxByteEnum> extends AbstractKnxEnumTest { 35 | 36 | /** 37 | * Tests if the {@link KnxByteEnum#getCode()} and {@link KnxByteEnum#getCodeAsByte()} is same for single byte enum 38 | */ 39 | @Test 40 | public void verifyCodeIsSameAsCodeAsByte() { 41 | for (final var identifier : EnumSet.allOf(this.getCurrentClass())) { 42 | final var identifierCodeAsInt = identifier.getCode(); 43 | final var identifierCodeAsByte = identifier.getCodeAsByte(); 44 | assertThat(identifierCodeAsByte).inBinary().isSameAs((byte) (identifierCodeAsInt & 0xFF)); 45 | } 46 | } 47 | 48 | /** 49 | * Tests the {@code valueOf(int)} static method with valid samples 50 | */ 51 | @Override 52 | protected abstract void validValueOf(); 53 | 54 | /** 55 | * Tests the {@code valueOf(int)} static method with invalid samples 56 | */ 57 | @Override 58 | @Test 59 | public void invalidValueOf() { 60 | // bytes 61 | assertThrows(KnxEnumNotFoundException.class, () -> this.invokeValueOf((byte) -1)); 62 | 63 | // ints 64 | final var testInvalidInts = new int[]{-1, 0xFF}; 65 | for (final var testInvalidInt : testInvalidInts) { 66 | assertThrows(KnxEnumNotFoundException.class, () -> this.invokeValueOf(testInvalidInt)); 67 | } 68 | } 69 | 70 | /** 71 | * Tests the {@link KnxByteEnum#getFriendlyName()} 72 | */ 73 | @Override 74 | protected abstract void friendlyName(); 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/li/pitschmann/knx/core/communication/task/DescriptionResponseTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 Pitschmann Christoph 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | package li.pitschmann.knx.core.communication.task; 19 | 20 | import li.pitschmann.knx.core.annotations.Nullable; 21 | import li.pitschmann.knx.core.body.Body; 22 | import li.pitschmann.knx.core.body.DescriptionRequestBody; 23 | import li.pitschmann.knx.core.body.DescriptionResponseBody; 24 | import li.pitschmann.knx.core.communication.InternalKnxClient; 25 | import org.slf4j.Logger; 26 | import org.slf4j.LoggerFactory; 27 | 28 | import java.util.Objects; 29 | import java.util.concurrent.Flow.Subscriber; 30 | import java.util.concurrent.Flow.Subscription; 31 | 32 | /** 33 | * Listens to {@link DescriptionResponseBody} frame that is sent by KNX Net/IP device to client when 34 | * {@link DescriptionRequestBody} was sent. 35 | * 36 | * @author PITSCHR 37 | */ 38 | public final class DescriptionResponseTask implements Subscriber { 39 | private static final Logger log = LoggerFactory.getLogger(DescriptionResponseTask.class); 40 | private final InternalKnxClient client; 41 | 42 | public DescriptionResponseTask(final InternalKnxClient client) { 43 | this.client = Objects.requireNonNull(client); 44 | } 45 | 46 | @Override 47 | public void onNext(final @Nullable Body body) { 48 | // we are interested in description response only 49 | if (body instanceof DescriptionResponseBody) { 50 | final var responseBody = (DescriptionResponseBody) body; 51 | log.debug("Description response received: {}", responseBody); 52 | this.client.getEventPool().descriptionEvent().setResponse(responseBody); 53 | log.trace("Description response saved."); 54 | } 55 | } 56 | 57 | @Override 58 | public void onError(final @Nullable Throwable throwable) { 59 | log.error("Error during Description Response Task class", throwable); 60 | } 61 | 62 | @Override 63 | public void onComplete() { 64 | // NO-OP 65 | } 66 | 67 | @Override 68 | public void onSubscribe(final Subscription subscription) { 69 | subscription.request(Long.MAX_VALUE); 70 | } 71 | 72 | } 73 | --------------------------------------------------------------------------------