mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-26 15:21:41 +01:00
[knx] Add discovery service (#16033)
* [knx] Add discovery service Signed-off-by: Holger Friedrich <mail@holger-friedrich.de>
This commit is contained in:
parent
157d3d0141
commit
e6982e71bb
@ -31,6 +31,20 @@ There is an _ip_ bridge to connect to KNX IP Gateways, and a _serial_ bridge for
|
|||||||
The following two bridge types are supported.
|
The following two bridge types are supported.
|
||||||
Bridges don't have channels on their own.
|
Bridges don't have channels on their own.
|
||||||
|
|
||||||
|
### Discovery
|
||||||
|
|
||||||
|
KNX IP bridges, i.e. IP interfaces, routers, and knxd instances, are discovered through mulitcast communication in the local network.
|
||||||
|
As a KNX setup is typically static, this in only done during startup of the binding.
|
||||||
|
Corresponding bridges are added to the inbox.
|
||||||
|
Additional configuration might be necessary after adding a bridge.
|
||||||
|
|
||||||
|
Note that several items per device might be created, as routers typically support routing and tunneling.
|
||||||
|
Make sure you import only one item per device.
|
||||||
|
|
||||||
|
Discovery is not available for serial bridges and device Things described below.
|
||||||
|
Discovery of IP bridges will not work without further measures if openHAB and the interface run on different network segments,
|
||||||
|
as multicast traffic is typically not forwarded.
|
||||||
|
|
||||||
### IP Gateway
|
### IP Gateway
|
||||||
|
|
||||||
The IP Gateway is the most commonly used way to connect to the KNX bus. At its base, the _ip_ bridge accepts the following configuration parameters:
|
The IP Gateway is the most commonly used way to connect to the KNX bus. At its base, the _ip_ bridge accepts the following configuration parameters:
|
||||||
|
@ -0,0 +1,143 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2023 Contributors to the openHAB project
|
||||||
|
*
|
||||||
|
* See the NOTICE file(s) distributed with this work for additional
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.openhab.binding.knx.internal.discovery;
|
||||||
|
|
||||||
|
import static org.openhab.binding.knx.internal.KNXBindingConstants.THING_TYPE_IP_BRIDGE;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.core.config.discovery.AbstractDiscoveryService;
|
||||||
|
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
|
||||||
|
import org.openhab.core.config.discovery.DiscoveryService;
|
||||||
|
import org.openhab.core.thing.ThingUID;
|
||||||
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import tuwien.auto.calimero.knxnetip.Discoverer;
|
||||||
|
import tuwien.auto.calimero.knxnetip.Discoverer.Result;
|
||||||
|
import tuwien.auto.calimero.knxnetip.servicetype.SearchResponse;
|
||||||
|
import tuwien.auto.calimero.knxnetip.util.ServiceFamiliesDIB;
|
||||||
|
import tuwien.auto.calimero.knxnetip.util.ServiceFamiliesDIB.ServiceFamily;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Discovers KNXnet/IP interfaces or routers and adds the results to the inbox.
|
||||||
|
* Several items per device might be created, as routers typically support routing and tunneling.
|
||||||
|
* Discovery uses multicast traffic to IP 224.0.23.12, port 3671.
|
||||||
|
*
|
||||||
|
* @implNote Discovery is based on the functionality provided by Calimero library.
|
||||||
|
* @author Holger Friedrich - Initial contribution
|
||||||
|
*/
|
||||||
|
@Component(service = DiscoveryService.class, configurationPid = "discovery.knx")
|
||||||
|
@NonNullByDefault
|
||||||
|
public class KNXnetDiscoveryService extends AbstractDiscoveryService {
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(KNXnetDiscoveryService.class);
|
||||||
|
|
||||||
|
private @Nullable Future<?> scanFuture = null;
|
||||||
|
|
||||||
|
public KNXnetDiscoveryService() {
|
||||||
|
super(Set.of(THING_TYPE_IP_BRIDGE), 3, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void startBackgroundDiscovery() {
|
||||||
|
// only start once at startup
|
||||||
|
startScan();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void stopBackgroundDiscovery() {
|
||||||
|
stopScan();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void startScan() {
|
||||||
|
if (scanFuture == null) {
|
||||||
|
scanFuture = scheduler.submit(this::startDiscovery);
|
||||||
|
} else {
|
||||||
|
logger.debug("KNXnet/IP background discovery scan in progress");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void stopScan() {
|
||||||
|
Future<?> tmpScanFuture = scanFuture;
|
||||||
|
if (tmpScanFuture != null) {
|
||||||
|
tmpScanFuture.cancel(false);
|
||||||
|
scanFuture = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void startDiscovery() {
|
||||||
|
try {
|
||||||
|
logger.debug("Starting KNXnet/IP discovery scan");
|
||||||
|
Discoverer discovererUdp = new Discoverer(0, false);
|
||||||
|
discovererUdp.startSearch(3, true);
|
||||||
|
|
||||||
|
List<Result<SearchResponse>> responses = discovererUdp.getSearchResponses();
|
||||||
|
|
||||||
|
for (Result<SearchResponse> r : responses) {
|
||||||
|
@Nullable
|
||||||
|
SearchResponse response = r.getResponse();
|
||||||
|
if (response == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Map<ServiceFamily, Integer> services = response.getServiceFamilies().families();
|
||||||
|
|
||||||
|
if (services.containsKey(ServiceFamiliesDIB.ServiceFamily.Tunneling)
|
||||||
|
|| services.containsKey(ServiceFamiliesDIB.ServiceFamily.Routing)) {
|
||||||
|
String serial = Objects.toString(response.getDevice().serialNumber()).replace(':', '-');
|
||||||
|
|
||||||
|
if (logger.isTraceEnabled()) {
|
||||||
|
logger.trace("Discovered device {}", response);
|
||||||
|
} else {
|
||||||
|
logger.debug("Discovered device {}, {}, {}", response.getDevice().getName(), serial,
|
||||||
|
response.getDevice().getMACAddressString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (services.containsKey(ServiceFamiliesDIB.ServiceFamily.Tunneling)) {
|
||||||
|
thingDiscovered(DiscoveryResultBuilder.create(new ThingUID(THING_TYPE_IP_BRIDGE, serial))
|
||||||
|
.withLabel(response.getDevice().getName()).withProperty("serialNumber", serial)
|
||||||
|
.withProperty("type", "TUNNEL")
|
||||||
|
.withProperty("ipAddress",
|
||||||
|
"" + response.getControlEndpoint().getAddress().getHostAddress())
|
||||||
|
.withProperty("port", "" + response.getControlEndpoint().getPort())
|
||||||
|
.withRepresentationProperty("serialNumber").build());
|
||||||
|
}
|
||||||
|
if (services.containsKey(ServiceFamiliesDIB.ServiceFamily.Routing)) {
|
||||||
|
thingDiscovered(DiscoveryResultBuilder.create(new ThingUID(THING_TYPE_IP_BRIDGE, serial))
|
||||||
|
.withLabel(response.getDevice().getName() + " (router mode)")
|
||||||
|
.withProperty("serialNumber", serial + "-r").withProperty("type", "ROUTER")
|
||||||
|
.withProperty("ipAddress", "224.0.23.12")
|
||||||
|
.withProperty("port", "" + response.getControlEndpoint().getPort())
|
||||||
|
.withRepresentationProperty("serialNumber").build());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.trace("Ignoring device {}", response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.debug("Completed KNXnet/IP discovery scan");
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logger.warn("An error occurred during KNXnet/IP discovery {}", ex.getMessage(), ex);
|
||||||
|
} finally {
|
||||||
|
scanFuture = null;
|
||||||
|
removeOlderResults(getTimestampOfLastScan());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -8,6 +8,8 @@
|
|||||||
<label>KNX/IP Gateway</label>
|
<label>KNX/IP Gateway</label>
|
||||||
<description>This is a KNX IP interface or router</description>
|
<description>This is a KNX IP interface or router</description>
|
||||||
|
|
||||||
|
<representation-property>serialNumber</representation-property>
|
||||||
|
|
||||||
<config-description>
|
<config-description>
|
||||||
<parameter-group name="knxsecure">
|
<parameter-group name="knxsecure">
|
||||||
<label>KNX secure</label>
|
<label>KNX secure</label>
|
||||||
|
Loading…
Reference in New Issue
Block a user