]> git.basschouten.com Git - openhab-addons.git/commitdiff
Remove channels and checking IO status when camera does not support IO (#16081)
authorMatthew Skinner <matt@pcmus.com>
Sat, 23 Dec 2023 17:47:12 +0000 (04:47 +1100)
committerGitHub <noreply@github.com>
Sat, 23 Dec 2023 17:47:12 +0000 (18:47 +0100)
Signed-off-by: Matthew Skinner <matt@pcmus.com>
bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/HikvisionHandler.java
bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/IpCameraBindingConstants.java
bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/handler/IpCameraHandler.java

index 69cf11f70a857684a617fdf7fb910781a8419676..fc48f939588602bd305cf49c196157a0af0492b0 100644 (file)
@@ -15,6 +15,8 @@ package org.openhab.binding.ipcamera.internal;
 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 @@ public class HikvisionHandler extends ChannelDuplexHandler {
         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 class HikvisionHandler extends ChannelDuplexHandler {
         }
         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, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>", "<");
-                switch (replyElement) {
-                    case "MotionDetection version=":
-                        ipCameraHandler.storeHttpReply(
-                                "/ISAPI/System/Video/inputs/channels/" + nvrChannel + "01/motionDetection", content);
-                        if (content.contains("<enabled>true</enabled>")) {
-                            ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.ON);
-                        } else if (content.contains("<enabled>false</enabled>")) {
-                            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<org.openhab.core.thing.Channel> removeChannels = new ArrayList<>();
+                    org.openhab.core.thing.Channel channel;
+                    if (content.contains("<IOOutputPortNums>0<") || !content.contains("<IOOutputPortNums>")) {
+                        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("<enabled>true</enabled>")) {
-                            ipCameraHandler.setChannelState(CHANNEL_ENABLE_EXTERNAL_ALARM_INPUT, OnOffType.ON);
-                        } else if (content.contains("<enabled>false</enabled>")) {
-                            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("<triggering>low</triggering>")) {
-                            ipCameraHandler.setChannelState(CHANNEL_TRIGGER_EXTERNAL_ALARM_INPUT, OnOffType.OFF);
-                        } else if (content.contains("<triggering>high</triggering>")) {
-                            ipCameraHandler.setChannelState(CHANNEL_TRIGGER_EXTERNAL_ALARM_INPUT, OnOffType.ON);
+                    } else if (content.contains("<IOOutputPortNums>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("<enabled>true</enabled>")) {
-                            ipCameraHandler.setChannelState(CHANNEL_ENABLE_LINE_CROSSING_ALARM, OnOffType.ON);
-                        } else if (content.contains("<enabled>false</enabled>")) {
-                            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("<IOInputPortNums>0<") || !content.contains("<IOInputPortNums>")) {
+                        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, "<enabled>true</enabled>", "<displayText>");
-                        ipCameraHandler.setChannelState(CHANNEL_TEXT_OVERLAY, StringType.valueOf(text));
-                        break;
-                    case "AudioDetection version=":
-                        ipCameraHandler.storeHttpReply("/ISAPI/Smart/AudioDetection/channels/" + nvrChannel + "01",
-                                content);
-                        if (content.contains("<enabled>true</enabled>")) {
-                            ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.ON);
-                        } else if (content.contains("<enabled>false</enabled>")) {
-                            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("<ioState>active</ioState>")) {
-                            ipCameraHandler.setChannelState(CHANNEL_EXTERNAL_ALARM_INPUT, OnOffType.ON);
-                        } else if (content.contains("<ioState>inactive</ioState>")) {
-                            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("<enabled>true</enabled>")) {
-                            ipCameraHandler.setChannelState(CHANNEL_ENABLE_FIELD_DETECTION_ALARM, OnOffType.ON);
-                        } else if (content.contains("<enabled>false</enabled>")) {
-                            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(
-                                "<requestURL>/ISAPI/System/IO/inputs/" + nvrChannel + "/status</requestURL>")) {
-                            // Stops checking the external alarm if camera does not have feature.
-                            if (content.contains("<statusString>Invalid Operation</statusString>")) {
-                                ipCameraHandler.lowPriorityRequests.remove(0);
-                                ipCameraHandler.logger.debug(
-                                        "Stopping checks for alarm inputs as camera appears to be missing this feature.");
-                            }
+                    } else if (content.contains("<IOInputPortNums>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, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>", "<");
+            switch (replyElement) {
+                case "MotionDetection version=":
+                    ipCameraHandler.storeHttpReply(
+                            "/ISAPI/System/Video/inputs/channels/" + nvrChannel + "01/motionDetection", content);
+                    if (content.contains("<enabled>true</enabled>")) {
+                        ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.ON);
+                    } else if (content.contains("<enabled>false</enabled>")) {
+                        ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.OFF);
+                    }
+                    break;
+                case "IOInputPort version=":
+                    ipCameraHandler.storeHttpReply("/ISAPI/System/IO/inputs/" + nvrChannel, content);
+                    if (content.contains("<enabled>true</enabled>")) {
+                        ipCameraHandler.setChannelState(CHANNEL_ENABLE_EXTERNAL_ALARM_INPUT, OnOffType.ON);
+                    } else if (content.contains("<enabled>false</enabled>")) {
+                        ipCameraHandler.setChannelState(CHANNEL_ENABLE_EXTERNAL_ALARM_INPUT, OnOffType.OFF);
+                    }
+                    if (content.contains("<triggering>low</triggering>")) {
+                        ipCameraHandler.setChannelState(CHANNEL_TRIGGER_EXTERNAL_ALARM_INPUT, OnOffType.OFF);
+                    } else if (content.contains("<triggering>high</triggering>")) {
+                        ipCameraHandler.setChannelState(CHANNEL_TRIGGER_EXTERNAL_ALARM_INPUT, OnOffType.ON);
+                    }
+                    break;
+                case "LineDetection":
+                    ipCameraHandler.storeHttpReply("/ISAPI/Smart/LineDetection/" + nvrChannel + "01", content);
+                    if (content.contains("<enabled>true</enabled>")) {
+                        ipCameraHandler.setChannelState(CHANNEL_ENABLE_LINE_CROSSING_ALARM, OnOffType.ON);
+                    } else if (content.contains("<enabled>false</enabled>")) {
+                        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, "<enabled>true</enabled>", "<displayText>");
+                    ipCameraHandler.setChannelState(CHANNEL_TEXT_OVERLAY, StringType.valueOf(text));
+                    break;
+                case "AudioDetection version=":
+                    ipCameraHandler.storeHttpReply("/ISAPI/Smart/AudioDetection/channels/" + nvrChannel + "01",
+                            content);
+                    if (content.contains("<enabled>true</enabled>")) {
+                        ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.ON);
+                    } else if (content.contains("<enabled>false</enabled>")) {
+                        ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.OFF);
+                    }
+                    break;
+                case "IOPortStatus version=":
+                    if (content.contains("<ioState>active</ioState>")) {
+                        ipCameraHandler.setChannelState(CHANNEL_EXTERNAL_ALARM_INPUT, OnOffType.ON);
+                    } else if (content.contains("<ioState>inactive</ioState>")) {
+                        ipCameraHandler.setChannelState(CHANNEL_EXTERNAL_ALARM_INPUT, OnOffType.OFF);
+                    }
+                    break;
+                case "FieldDetection version=":
+                    ipCameraHandler.storeHttpReply("/ISAPI/Smart/FieldDetection/" + nvrChannel + "01", content);
+                    if (content.contains("<enabled>true</enabled>")) {
+                        ipCameraHandler.setChannelState(CHANNEL_ENABLE_FIELD_DETECTION_ALARM, OnOffType.ON);
+                    } else if (content.contains("<enabled>false</enabled>")) {
+                        ipCameraHandler.setChannelState(CHANNEL_ENABLE_FIELD_DETECTION_ALARM, OnOffType.OFF);
+                    }
+                    break;
+                case "ResponseStatus version=":
+                    ////////////////// External Alarm Input ///////////////
+                    if (content
+                            .contains("<requestURL>/ISAPI/System/IO/inputs/" + nvrChannel + "/status</requestURL>")) {
+                        // Stops checking the external alarm if camera does not have feature.
+                        if (content.contains("<statusString>Invalid Operation</statusString>")) {
+                            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);
         }
index 4d9d96fd21aa44fa8c08b0d65f65f0e73be0897b..0c3f5f2ab7059a9e7dcad57213d1e166d5bbf503 100644 (file)
@@ -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,
index e43c05f09aaccdf7e63e9a12da8fb1119caba59d..a973dfd651c3c9b191bc71d579a5916ed91bdfd4 100644 (file)
@@ -583,8 +583,8 @@ public class IpCameraHandler extends BaseThingHandler {
                                     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 class IpCameraHandler extends BaseThingHandler {
                                     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 class IpCameraHandler extends BaseThingHandler {
                     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: