This commit is contained in:
lsiepel 2025-01-09 11:06:02 +01:00 committed by GitHub
commit 1955677cdb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 64 additions and 30 deletions

View File

@ -19,6 +19,7 @@ import java.time.Duration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ExecutionException;
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.DiscoveryResultBuilder;
import org.openhab.core.config.discovery.DiscoveryService;
import org.openhab.core.net.CidrAddress;
import org.openhab.core.thing.ThingUID;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
@ -133,37 +135,43 @@ public class NetworkDiscoveryService extends AbstractDiscoveryService implements
return;
}
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);
scannedIPcount.set(0);
for (String networkInterface : discoveryList.keySet()) {
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) {
final PresenceDetection pd = new PresenceDetection(this, scheduler, Duration.ofSeconds(2));
pd.setHostname(ip);
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);
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();
}
});
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 on interface {} successful", scannedIPcount, networkInterface);
stopScan();
}
});
}
}
logger.debug("Finished Network Device Discovery");
}
@Override

View File

@ -32,9 +32,11 @@ import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
@ -139,7 +141,7 @@ public class NetworkUtils {
try {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface networkInterface = en.nextElement();
if (!networkInterface.isLoopback()) {
if (networkInterface.isUp() && !networkInterface.isLoopback()) {
result.add(networkInterface.getName());
}
}
@ -160,6 +162,30 @@ public class NetworkUtils {
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
*
@ -167,7 +193,7 @@ public class NetworkUtils {
* @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
*/
private Set<String> getNetworkIPs(Set<CidrAddress> interfaceIPs, int maximumPerInterface) {
public Set<String> getNetworkIPs(Set<CidrAddress> interfaceIPs, int maximumPerInterface) {
Set<String> networkIPs = new LinkedHashSet<>();
short minCidrPrefixLength = 8; // historic Class A network, addresses = 16777214