diff --git a/bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/HikvisionHandler.java b/bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/HikvisionHandler.java
index 69cf11f70a85..fc48f9395886 100644
--- a/bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/HikvisionHandler.java
+++ b/bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/HikvisionHandler.java
@@ -15,6 +15,8 @@
import static org.openhab.binding.ipcamera.internal.IpCameraBindingConstants.*;
import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
@@ -53,6 +55,7 @@ public class HikvisionHandler extends ChannelDuplexHandler {
private IpCameraHandler ipCameraHandler;
private int nvrChannel;
private int lineCount, vmdCount, leftCount, takenCount, faceCount, pirCount, fieldCount;
+ private String requestUrl = "";
public HikvisionHandler(ThingHandler handler, int nvrChannel) {
ipCameraHandler = (IpCameraHandler) handler;
@@ -110,6 +113,10 @@ private void processEvent(String content) {
countDown();
}
+ public void setURL(String url) {
+ requestUrl = url;
+ }
+
// This handles the incoming http replies back from the camera.
@Override
public void channelRead(@Nullable ChannelHandlerContext ctx, @Nullable Object msg) throws Exception {
@@ -118,90 +125,145 @@ public void channelRead(@Nullable ChannelHandlerContext ctx, @Nullable Object ms
}
try {
String content = msg.toString();
- logger.trace("HTTP Result back from camera is \t:{}:", content);
- if (content.startsWith("--boundary")) {// Alarm checking goes in here//
- int startIndex = content.indexOf("<");// skip to start of XML content
- if (startIndex != -1) {
- String eventData = content.substring(startIndex, content.length());
- processEvent(eventData);
- }
- } else {
- String replyElement = Helper.fetchXML(content, "", "<");
- switch (replyElement) {
- case "MotionDetection version=":
- ipCameraHandler.storeHttpReply(
- "/ISAPI/System/Video/inputs/channels/" + nvrChannel + "01/motionDetection", content);
- if (content.contains("true")) {
- ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.ON);
- } else if (content.contains("false")) {
- ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.OFF);
+ logger.trace("HTTP Result from {} contains \t:{}:", requestUrl, content);
+ switch (requestUrl) {
+ case "/ISAPI/Event/notification/alertStream":
+ int startIndex = content.indexOf("<");// skip to start of XML content
+ if (startIndex != -1) {
+ String eventData = content.substring(startIndex, content.length());
+ processEvent(eventData);
+ }
+ return;
+ case "/ISAPI/System/IO/capabilities": // Used to check if the camera supports IO
+ List removeChannels = new ArrayList<>();
+ org.openhab.core.thing.Channel channel;
+ if (content.contains("0<") || !content.contains("")) {
+ logger.debug("Camera does not support IO outputs.");
+ channel = ipCameraHandler.getThing().getChannel(CHANNEL_ACTIVATE_ALARM_OUTPUT);
+ if (channel != null) {
+ removeChannels.add(channel);
}
- break;
- case "IOInputPort version=":
- ipCameraHandler.storeHttpReply("/ISAPI/System/IO/inputs/" + nvrChannel, content);
- if (content.contains("true")) {
- ipCameraHandler.setChannelState(CHANNEL_ENABLE_EXTERNAL_ALARM_INPUT, OnOffType.ON);
- } else if (content.contains("false")) {
- ipCameraHandler.setChannelState(CHANNEL_ENABLE_EXTERNAL_ALARM_INPUT, OnOffType.OFF);
+ channel = ipCameraHandler.getThing().getChannel(CHANNEL_ACTIVATE_ALARM_OUTPUT2);
+ if (channel != null) {
+ removeChannels.add(channel);
}
- if (content.contains("low")) {
- ipCameraHandler.setChannelState(CHANNEL_TRIGGER_EXTERNAL_ALARM_INPUT, OnOffType.OFF);
- } else if (content.contains("high")) {
- ipCameraHandler.setChannelState(CHANNEL_TRIGGER_EXTERNAL_ALARM_INPUT, OnOffType.ON);
+ } else if (content.contains("1<")) {
+ channel = ipCameraHandler.getThing().getChannel(CHANNEL_ACTIVATE_ALARM_OUTPUT2);
+ if (channel != null) {
+ removeChannels.add(channel);
}
- break;
- case "LineDetection":
- ipCameraHandler.storeHttpReply("/ISAPI/Smart/LineDetection/" + nvrChannel + "01", content);
- if (content.contains("true")) {
- ipCameraHandler.setChannelState(CHANNEL_ENABLE_LINE_CROSSING_ALARM, OnOffType.ON);
- } else if (content.contains("false")) {
- ipCameraHandler.setChannelState(CHANNEL_ENABLE_LINE_CROSSING_ALARM, OnOffType.OFF);
+ }
+ ipCameraHandler.lowPriorityRequests.clear(); // no longer need to check if the IO is supported.
+ if (content.contains("0<") || !content.contains("")) {
+ logger.debug("Camera does not support IO inputs.");
+ channel = ipCameraHandler.getThing().getChannel(CHANNEL_ENABLE_EXTERNAL_ALARM_INPUT);
+ if (channel != null) {
+ removeChannels.add(channel);
}
- break;
- case "TextOverlay version=":
- ipCameraHandler.storeHttpReply(
- "/ISAPI/System/Video/inputs/channels/" + nvrChannel + "/overlays/text/1", content);
- String text = Helper.fetchXML(content, "true", "");
- ipCameraHandler.setChannelState(CHANNEL_TEXT_OVERLAY, StringType.valueOf(text));
- break;
- case "AudioDetection version=":
- ipCameraHandler.storeHttpReply("/ISAPI/Smart/AudioDetection/channels/" + nvrChannel + "01",
- content);
- if (content.contains("true")) {
- ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.ON);
- } else if (content.contains("false")) {
- ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.OFF);
+ channel = ipCameraHandler.getThing().getChannel(CHANNEL_TRIGGER_EXTERNAL_ALARM_INPUT);
+ if (channel != null) {
+ removeChannels.add(channel);
}
- break;
- case "IOPortStatus version=":
- if (content.contains("active")) {
- ipCameraHandler.setChannelState(CHANNEL_EXTERNAL_ALARM_INPUT, OnOffType.ON);
- } else if (content.contains("inactive")) {
- ipCameraHandler.setChannelState(CHANNEL_EXTERNAL_ALARM_INPUT, OnOffType.OFF);
+ channel = ipCameraHandler.getThing().getChannel(CHANNEL_EXTERNAL_ALARM_INPUT);
+ if (channel != null) {
+ removeChannels.add(channel);
}
- break;
- case "FieldDetection version=":
- ipCameraHandler.storeHttpReply("/ISAPI/Smart/FieldDetection/" + nvrChannel + "01", content);
- if (content.contains("true")) {
- ipCameraHandler.setChannelState(CHANNEL_ENABLE_FIELD_DETECTION_ALARM, OnOffType.ON);
- } else if (content.contains("false")) {
- ipCameraHandler.setChannelState(CHANNEL_ENABLE_FIELD_DETECTION_ALARM, OnOffType.OFF);
+ channel = ipCameraHandler.getThing().getChannel(CHANNEL_EXTERNAL_ALARM_INPUT2);
+ if (channel != null) {
+ removeChannels.add(channel);
}
- break;
- case "ResponseStatus version=":
- ////////////////// External Alarm Input ///////////////
- if (content.contains(
- "/ISAPI/System/IO/inputs/" + nvrChannel + "/status")) {
- // Stops checking the external alarm if camera does not have feature.
- if (content.contains("Invalid Operation")) {
- ipCameraHandler.lowPriorityRequests.remove(0);
- ipCameraHandler.logger.debug(
- "Stopping checks for alarm inputs as camera appears to be missing this feature.");
- }
+ } else if (content.contains("1<")) {
+ channel = ipCameraHandler.getThing().getChannel(CHANNEL_EXTERNAL_ALARM_INPUT2);
+ if (channel != null) {
+ removeChannels.add(channel);
}
- break;
- }
+ // start checking the input IO status
+ ipCameraHandler.lowPriorityRequests.set(0,
+ "/ISAPI/System/IO/inputs/" + ipCameraHandler.cameraConfig.getNvrChannel() + "/status");
+ } else {
+ // start checking the input IO status
+ ipCameraHandler.lowPriorityRequests.set(0,
+ "/ISAPI/System/IO/inputs/" + ipCameraHandler.cameraConfig.getNvrChannel() + "/status");
+ }
+ ipCameraHandler.removeChannels(removeChannels);
+ return;
+ }
+ String replyElement = Helper.fetchXML(content, "", "<");
+ switch (replyElement) {
+ case "MotionDetection version=":
+ ipCameraHandler.storeHttpReply(
+ "/ISAPI/System/Video/inputs/channels/" + nvrChannel + "01/motionDetection", content);
+ if (content.contains("true")) {
+ ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.ON);
+ } else if (content.contains("false")) {
+ ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.OFF);
+ }
+ break;
+ case "IOInputPort version=":
+ ipCameraHandler.storeHttpReply("/ISAPI/System/IO/inputs/" + nvrChannel, content);
+ if (content.contains("true")) {
+ ipCameraHandler.setChannelState(CHANNEL_ENABLE_EXTERNAL_ALARM_INPUT, OnOffType.ON);
+ } else if (content.contains("false")) {
+ ipCameraHandler.setChannelState(CHANNEL_ENABLE_EXTERNAL_ALARM_INPUT, OnOffType.OFF);
+ }
+ if (content.contains("low")) {
+ ipCameraHandler.setChannelState(CHANNEL_TRIGGER_EXTERNAL_ALARM_INPUT, OnOffType.OFF);
+ } else if (content.contains("high")) {
+ ipCameraHandler.setChannelState(CHANNEL_TRIGGER_EXTERNAL_ALARM_INPUT, OnOffType.ON);
+ }
+ break;
+ case "LineDetection":
+ ipCameraHandler.storeHttpReply("/ISAPI/Smart/LineDetection/" + nvrChannel + "01", content);
+ if (content.contains("true")) {
+ ipCameraHandler.setChannelState(CHANNEL_ENABLE_LINE_CROSSING_ALARM, OnOffType.ON);
+ } else if (content.contains("false")) {
+ ipCameraHandler.setChannelState(CHANNEL_ENABLE_LINE_CROSSING_ALARM, OnOffType.OFF);
+ }
+ break;
+ case "TextOverlay version=":
+ ipCameraHandler.storeHttpReply(
+ "/ISAPI/System/Video/inputs/channels/" + nvrChannel + "/overlays/text/1", content);
+ String text = Helper.fetchXML(content, "true", "");
+ ipCameraHandler.setChannelState(CHANNEL_TEXT_OVERLAY, StringType.valueOf(text));
+ break;
+ case "AudioDetection version=":
+ ipCameraHandler.storeHttpReply("/ISAPI/Smart/AudioDetection/channels/" + nvrChannel + "01",
+ content);
+ if (content.contains("true")) {
+ ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.ON);
+ } else if (content.contains("false")) {
+ ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.OFF);
+ }
+ break;
+ case "IOPortStatus version=":
+ if (content.contains("active")) {
+ ipCameraHandler.setChannelState(CHANNEL_EXTERNAL_ALARM_INPUT, OnOffType.ON);
+ } else if (content.contains("inactive")) {
+ ipCameraHandler.setChannelState(CHANNEL_EXTERNAL_ALARM_INPUT, OnOffType.OFF);
+ }
+ break;
+ case "FieldDetection version=":
+ ipCameraHandler.storeHttpReply("/ISAPI/Smart/FieldDetection/" + nvrChannel + "01", content);
+ if (content.contains("true")) {
+ ipCameraHandler.setChannelState(CHANNEL_ENABLE_FIELD_DETECTION_ALARM, OnOffType.ON);
+ } else if (content.contains("false")) {
+ ipCameraHandler.setChannelState(CHANNEL_ENABLE_FIELD_DETECTION_ALARM, OnOffType.OFF);
+ }
+ break;
+ case "ResponseStatus version=":
+ ////////////////// External Alarm Input ///////////////
+ if (content
+ .contains("/ISAPI/System/IO/inputs/" + nvrChannel + "/status")) {
+ // Stops checking the external alarm if camera does not have feature.
+ if (content.contains("Invalid Operation")) {
+ ipCameraHandler.lowPriorityRequests.remove(0);
+ ipCameraHandler.logger.debug(
+ "Stopping checks for alarm inputs as camera appears to be missing this feature.");
+ }
+ }
+ break;
}
+
} finally {
ReferenceCountUtil.release(msg);
}
diff --git a/bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/IpCameraBindingConstants.java b/bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/IpCameraBindingConstants.java
index 4d9d96fd21aa..0c3f5f2ab705 100644
--- a/bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/IpCameraBindingConstants.java
+++ b/bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/IpCameraBindingConstants.java
@@ -34,6 +34,7 @@ public class IpCameraBindingConstants {
public static final String COMMON_HANDLER = "commonHandler";
public static final String INSTAR_HANDLER = "instarHandler";
public static final String REOLINK_HANDLER = "reolinkHandler";
+ public static final String HIKVISION_HANDLER = "hikvisionHandler";
public enum FFmpegFormat {
HLS,
diff --git a/bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/handler/IpCameraHandler.java b/bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/handler/IpCameraHandler.java
index e43c05f09aac..a973dfd651c3 100644
--- a/bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/handler/IpCameraHandler.java
+++ b/bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/handler/IpCameraHandler.java
@@ -583,8 +583,8 @@ public void initChannel(SocketChannel socketChannel) throws Exception {
new FoscamHandler(getHandle(), cameraConfig.getUser(), cameraConfig.getPassword()));
break;
case HIKVISION_THING:
- socketChannel.pipeline()
- .addLast(new HikvisionHandler(getHandle(), cameraConfig.getNvrChannel()));
+ socketChannel.pipeline().addLast(HIKVISION_HANDLER,
+ new HikvisionHandler(getHandle(), cameraConfig.getNvrChannel()));
break;
case INSTAR_THING:
socketChannel.pipeline().addLast(INSTAR_HANDLER, new InstarHandler(getHandle()));
@@ -654,6 +654,11 @@ public void operationComplete(@Nullable ChannelFuture future) {
AmcrestHandler amcrestHandler = (AmcrestHandler) ch.pipeline().get(AMCREST_HANDLER);
amcrestHandler.setURL(httpRequestURL);
break;
+ case HIKVISION_THING:
+ HikvisionHandler hikvisionHandler = (HikvisionHandler) ch.pipeline()
+ .get(HIKVISION_HANDLER);
+ hikvisionHandler.setURL(httpRequestURL);
+ break;
case INSTAR_THING:
InstarHandler instarHandler = (InstarHandler) ch.pipeline().get(INSTAR_HANDLER);
instarHandler.setURL(httpRequestURL);
@@ -1701,7 +1706,7 @@ public void initialize() {
snapshotUri = "/ISAPI/Streaming/channels/" + cameraConfig.getNvrChannel() + "01/picture";
}
if (lowPriorityRequests.isEmpty()) {
- lowPriorityRequests.add("/ISAPI/System/IO/inputs/" + cameraConfig.getNvrChannel() + "/status");
+ lowPriorityRequests.add("/ISAPI/System/IO/capabilities");
}
break;
case INSTAR_THING: