Improvements

Signed-off-by: Leo Siepel <leosiepel@gmail.com>
This commit is contained in:
Leo Siepel 2025-01-01 23:26:22 +01:00
parent 6b42d75378
commit f6c6a3cf82
No known key found for this signature in database
GPG Key ID: E3035441D9FCD768
2 changed files with 63 additions and 29 deletions

View File

@ -19,6 +19,7 @@ import java.time.Duration;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
@ -37,6 +38,7 @@ import org.openhab.core.config.core.Configuration;
import org.openhab.core.config.discovery.AbstractDiscoveryService; import org.openhab.core.config.discovery.AbstractDiscoveryService;
import org.openhab.core.config.discovery.DiscoveryResultBuilder; import org.openhab.core.config.discovery.DiscoveryResultBuilder;
import org.openhab.core.config.discovery.DiscoveryService; import org.openhab.core.config.discovery.DiscoveryService;
import org.openhab.core.net.CidrAddress;
import org.openhab.core.thing.ThingUID; import org.openhab.core.thing.ThingUID;
import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Component;
@ -133,37 +135,43 @@ public class NetworkDiscoveryService extends AbstractDiscoveryService implements
return; return;
} }
removeOlderResults(getTimestampOfLastScan(), null); removeOlderResults(getTimestampOfLastScan(), null);
logger.trace("Starting Network Device Discovery"); logger.debug("Starting Network Device Discovery");
Map<String, Set<CidrAddress>> discoveryList = networkUtils.getNetworkIPsPerInterface();
final Set<String> networkIPs = networkUtils.getNetworkIPs(MAXIMUM_IPS_PER_INTERFACE); for (String networkInterface : discoveryList.keySet()) {
scannedIPcount.set(0); final Set<String> networkIPs = networkUtils.getNetworkIPs(
Objects.requireNonNull(discoveryList.get(networkInterface)), MAXIMUM_IPS_PER_INTERFACE);
logger.debug("Scanning {} IPs on interface {} ", networkIPs.size(), networkInterface);
scannedIPcount.set(0);
for (String ip : networkIPs) {
final PresenceDetection pd = new PresenceDetection(this, scheduler, Duration.ofSeconds(2));
pd.setHostname(ip);
pd.setNetworkInterfaceNames(Set.of(networkInterface));
pd.setIOSDevice(true);
pd.setUseDhcpSniffing(false);
pd.setTimeout(PING_TIMEOUT);
// Ping devices
pd.setUseIcmpPing(true);
pd.setUseArpPing(true, configuration.arpPingToolPath, configuration.arpPingUtilMethod);
// TCP devices
pd.setServicePorts(tcpServicePorts);
for (String ip : networkIPs) { service.execute(() -> {
final PresenceDetection pd = new PresenceDetection(this, scheduler, Duration.ofSeconds(2)); Thread.currentThread().setName("Discovery thread " + ip);
pd.setHostname(ip); try {
pd.setIOSDevice(true); pd.getValue();
pd.setUseDhcpSniffing(false); } catch (ExecutionException | InterruptedException e) {
pd.setTimeout(PING_TIMEOUT); stopScan();
// Ping devices }
pd.setUseIcmpPing(true); int count = scannedIPcount.incrementAndGet();
pd.setUseArpPing(true, configuration.arpPingToolPath, configuration.arpPingUtilMethod); if (count == networkIPs.size()) {
// TCP devices logger.trace("Scan of {} IPs on interface {} successful", scannedIPcount, networkInterface);
pd.setServicePorts(tcpServicePorts); stopScan();
}
service.execute(() -> { });
Thread.currentThread().setName("Discovery thread " + ip); }
try {
pd.getValue();
} catch (ExecutionException | InterruptedException e) {
stopScan();
}
int count = scannedIPcount.incrementAndGet();
if (count == networkIPs.size()) {
logger.trace("Scan of {} IPs successful", scannedIPcount);
stopScan();
}
});
} }
logger.debug("Finished Network Device Discovery");
} }
@Override @Override

View File

@ -32,9 +32,11 @@ import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -160,6 +162,30 @@ public class NetworkUtils {
return getNetworkIPs(getInterfaceIPs(), maximumPerInterface); return getNetworkIPs(getInterfaceIPs(), maximumPerInterface);
} }
/**
* Retrieves a map of network interface names to their associated IP addresses.
*
* @return A map where the key is the name of the network interface and the value is a set of CidrAddress objects
* representing the IP addresses and network prefix lengths for that interface.
*/
public Map<String, Set<CidrAddress>> getNetworkIPsPerInterface() {
Map<String, Set<CidrAddress>> outputMap = new HashMap<>();
try {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface networkInterface = en.nextElement();
if (networkInterface.isUp() && !networkInterface.isLoopback()) {
outputMap.put(networkInterface.getName(),
networkInterface.getInterfaceAddresses().stream()
.map(m -> new CidrAddress(m.getAddress(), m.getNetworkPrefixLength()))
.collect(Collectors.toSet()));
}
}
} catch (SocketException e) {
logger.trace("Could not get network interfaces", e);
}
return outputMap;
}
/** /**
* Takes the interfaceIPs and fetches every IP which can be assigned on their network * Takes the interfaceIPs and fetches every IP which can be assigned on their network
* *
@ -167,7 +193,7 @@ public class NetworkUtils {
* @param maximumPerInterface The maximum of IP addresses per interface or 0 to get all. * @param maximumPerInterface The maximum of IP addresses per interface or 0 to get all.
* @return Every single IP which can be assigned on the Networks the computer is connected to * @return Every single IP which can be assigned on the Networks the computer is connected to
*/ */
private Set<String> getNetworkIPs(Set<CidrAddress> interfaceIPs, int maximumPerInterface) { public Set<String> getNetworkIPs(Set<CidrAddress> interfaceIPs, int maximumPerInterface) {
Set<String> networkIPs = new LinkedHashSet<>(); Set<String> networkIPs = new LinkedHashSet<>();
short minCidrPrefixLength = 8; // historic Class A network, addresses = 16777214 short minCidrPrefixLength = 8; // historic Class A network, addresses = 16777214