Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 5 commits into from
Jul 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion bundles/org.openhab.binding.ipcamera/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,11 @@ Thing ipcamera:hikvision:West "West Camera"

## Discovery

The discovery feature of openHAB can be used to find and setup any ONVIF cameras.
The discovery feature of openHAB can be used to find and setup ONVIF cameras.
This method should be preferred as it will discover the cameras IP, ports and URLs for you, making the setup much easier.
The binding needs to use UDP port 3702 to discover the cameras with, so this port needs to be unblocked by your firewall or add the camera manually if the camera is not auto found.
To use the discovery, just press the `+` icon located in the Inbox, then select the IpCamera binding from the list of installed bindings.
The binding will only search using openHAB's currently selected primary network address, see <https://www.openhab.org/docs/settings/>.
If your camera is not found after a few searches, it may not be ONVIF and in this case you will need to manually add the camera via the UI.
Cameras that are not ONVIF should be added as a `generic` thing type and you will need to provide the URLs manually.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,12 @@
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;

Expand All @@ -39,9 +42,12 @@
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
Expand All @@ -65,7 +71,7 @@ public void newCameraFound(String brand, String hostname, int onvifPort) {
@Override
protected void startScan() {
removeOlderResults(getTimestampOfLastScan());
OnvifDiscovery onvifDiscovery = new OnvifDiscovery(this);
OnvifDiscovery onvifDiscovery = new OnvifDiscovery(networkAddressService, this);
try {
onvifDiscovery.discoverCameras();
} catch (UnknownHostException | InterruptedException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
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;

Expand Down Expand Up @@ -62,16 +63,21 @@
*/

@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
Expand All @@ -82,7 +88,15 @@ public OnvifDiscovery(IpCameraDiscoveryService ipCameraDiscoveryService) {
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());
}
}
}
Expand Down Expand Up @@ -130,8 +144,18 @@ void processCameraReplys() {
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);
}
}
}
}
Expand All @@ -141,20 +165,20 @@ String checkForBrand(String response) {
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";
}
Expand Down Expand Up @@ -197,6 +221,8 @@ private DatagramPacket wsDiscovery() throws UnknownHostException {
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);
Expand Down