[ipcamera] Fix discovery crashes when networks have access rights issues in docker (#15059)

* Fix discovery crashes if network use is blocked by docker.
* Change log levels to be more useful.
* add better reolink discovery check

Signed-off-by: Matthew Skinner <matt@pcmus.com>
This commit is contained in:
Matthew Skinner
2023-07-02 17:11:06 +10:00
committed by GitHub
parent bd4a8385e0
commit 1f78f9ac7b
3 changed files with 44 additions and 11 deletions

View File

@@ -22,9 +22,12 @@ import org.openhab.core.config.discovery.AbstractDiscoveryService;
import org.openhab.core.config.discovery.DiscoveryResult;
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
import org.openhab.core.config.discovery.DiscoveryService;
import org.openhab.core.net.NetworkAddressService;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.ThingUID;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -39,9 +42,12 @@ import org.slf4j.LoggerFactory;
public class IpCameraDiscoveryService extends AbstractDiscoveryService {
private final Logger logger = LoggerFactory.getLogger(IpCameraDiscoveryService.class);
private final NetworkAddressService networkAddressService;
public IpCameraDiscoveryService() {
@Activate
public IpCameraDiscoveryService(@Reference NetworkAddressService networkAddressService) {
super(SUPPORTED_THING_TYPES, 0, false);
this.networkAddressService = networkAddressService;
}
@Override
@@ -65,7 +71,7 @@ public class IpCameraDiscoveryService extends AbstractDiscoveryService {
@Override
protected void startScan() {
removeOlderResults(getTimestampOfLastScan());
OnvifDiscovery onvifDiscovery = new OnvifDiscovery(this);
OnvifDiscovery onvifDiscovery = new OnvifDiscovery(networkAddressService, this);
try {
onvifDiscovery.discoverCameras();
} catch (UnknownHostException | InterruptedException e) {

View File

@@ -35,6 +35,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.ipcamera.internal.Helper;
import org.openhab.binding.ipcamera.internal.IpCameraDiscoveryService;
import org.openhab.core.net.NetworkAddressService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -62,16 +63,21 @@ import io.netty.util.concurrent.GlobalEventExecutor;
*/
@NonNullByDefault
@io.netty.channel.ChannelHandler.Sharable
public class OnvifDiscovery {
private IpCameraDiscoveryService ipCameraDiscoveryService;
private final Logger logger = LoggerFactory.getLogger(OnvifDiscovery.class);
private final NetworkAddressService networkAddressService;
public ArrayList<DatagramPacket> listOfReplys = new ArrayList<DatagramPacket>(10);
public OnvifDiscovery(IpCameraDiscoveryService ipCameraDiscoveryService) {
public OnvifDiscovery(NetworkAddressService networkAddressService,
IpCameraDiscoveryService ipCameraDiscoveryService) {
this.ipCameraDiscoveryService = ipCameraDiscoveryService;
this.networkAddressService = networkAddressService;
}
public @Nullable List<NetworkInterface> getLocalNICs() {
String primaryHostAddress = networkAddressService.getPrimaryIpv4HostAddress();
List<NetworkInterface> results = new ArrayList<>(2);
try {
for (Enumeration<NetworkInterface> enumNetworks = NetworkInterface.getNetworkInterfaces(); enumNetworks
@@ -82,7 +88,15 @@ public class OnvifDiscovery {
InetAddress inetAddress = enumIpAddr.nextElement();
if (!inetAddress.isLoopbackAddress() && inetAddress.getHostAddress().toString().length() < 18
&& inetAddress.isSiteLocalAddress()) {
results.add(networkInterface);
if (inetAddress.getHostAddress().equals(primaryHostAddress)) {
results.add(networkInterface);
logger.debug("Scanning network {} for any ONVIF cameras", primaryHostAddress);
} else {
logger.debug("Skipping network {} as it was not selected as openHAB's 'Primary Address'",
inetAddress.getHostAddress());
}
} else {
logger.debug("Skipping network {} as it was not site local", inetAddress.getHostAddress());
}
}
}
@@ -130,8 +144,18 @@ public class OnvifDiscovery {
if (!xAddr.isEmpty()) {
searchReply(xAddr, xml);
} else if (xml.contains("onvif")) {
logger.info("Possible ONVIF camera found at:{}", packet.sender().getHostString());
ipCameraDiscoveryService.newCameraFound("onvif", packet.sender().getHostString(), 80);
String brand;
try {
brand = getBrandFromLoginPage(packet.sender().getHostString());
} catch (IOException e) {
brand = "onvif";
}
logger.info("Possible {} camera found at:{}", brand, packet.sender().getHostString());
if ("reolink".equals(brand)) {
ipCameraDiscoveryService.newCameraFound(brand, packet.sender().getHostString(), 8000);
} else {
ipCameraDiscoveryService.newCameraFound(brand, packet.sender().getHostString(), 80);
}
}
}
}
@@ -141,20 +165,20 @@ public class OnvifDiscovery {
return "dahua";
} else if (response.toLowerCase().contains("dahua")) {
return "dahua";
} else if (response.toLowerCase().contains("doorbird")) {
return "doorbird";
} else if (response.toLowerCase().contains("foscam")) {
return "foscam";
} else if (response.toLowerCase().contains("hikvision")) {
return "hikvision";
} else if (response.toLowerCase().contains("instar")) {
return "instar";
} else if (response.toLowerCase().contains("doorbird")) {
return "doorbird";
} else if (response.toLowerCase().contains("reolink")) {
return "reolink";
} else if (response.toLowerCase().contains("ipc-")) {
return "dahua";
} else if (response.toLowerCase().contains("dh-sd")) {
return "dahua";
} else if (response.toLowerCase().contains("reolink")) {
return "reolink";
}
return "onvif";
}
@@ -197,6 +221,8 @@ public class OnvifDiscovery {
public void discoverCameras() throws UnknownHostException, InterruptedException {
List<NetworkInterface> nics = getLocalNICs();
if (nics == null || nics.isEmpty()) {
logger.warn(
"No 'Primary Address' selected to use for camera discovery. Check openHAB's Network Settings page to select a valid Primary Address.");
return;
}
NetworkInterface networkInterface = nics.get(0);