Compare commits

...

3 Commits

Author SHA1 Message Date
lsiepel
d99a0f272e
Merge f6c6a3cf82 into e611b5d368 2025-01-05 00:21:18 +01:00
Leo Siepel
f6c6a3cf82
Improvements
Signed-off-by: Leo Siepel <leosiepel@gmail.com>
2025-01-01 23:26:22 +01:00
Leo Siepel
6b42d75378
Fix performance
Signed-off-by: Leo Siepel <leosiepel@gmail.com>
2024-12-24 13:42:24 +01:00
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.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;
@ -139,7 +141,7 @@ public class NetworkUtils {
try { try {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) { for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface networkInterface = en.nextElement(); NetworkInterface networkInterface = en.nextElement();
if (!networkInterface.isLoopback()) { if (networkInterface.isUp() && !networkInterface.isLoopback()) {
result.add(networkInterface.getName()); result.add(networkInterface.getName());
} }
} }
@ -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