mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-25 14:55:55 +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.
|
||||
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
|
||||
|
||||
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>
|
||||
<description>This is a KNX IP interface or router</description>
|
||||
|
||||
<representation-property>serialNumber</representation-property>
|
||||
|
||||
<config-description>
|
||||
<parameter-group name="knxsecure">
|
||||
<label>KNX secure</label>
|
||||
|
Loading…
Reference in New Issue
Block a user