]> git.basschouten.com Git - openhab-addons.git/commitdiff
[ipcamera] Improve Dahua alarms (#10078)
authorMatthew Skinner <matt@pcmus.com>
Wed, 24 Feb 2021 17:07:48 +0000 (04:07 +1100)
committerGitHub <noreply@github.com>
Wed, 24 Feb 2021 17:07:48 +0000 (18:07 +0100)
Signed-off-by: Matthew Skinner <matt@pcmus.com>
bundles/org.openhab.binding.ipcamera/README.md
bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/DahuaHandler.java
bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/DoorBirdHandler.java
bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/FoscamHandler.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/MyNettyAuthHandler.java
bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/handler/IpCameraGroupHandler.java
bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/handler/IpCameraHandler.java
bundles/org.openhab.binding.ipcamera/src/main/java/org/openhab/binding/ipcamera/internal/onvif/OnvifDiscovery.java
bundles/org.openhab.binding.ipcamera/src/main/resources/OH-INF/thing/thing-types.xml

index fd826ff21c0d0152d362ad26c1a9f14faff3fb41..44ad00c73830d5cbe2f8a9a8f4202f0453082d47 100644 (file)
@@ -213,6 +213,7 @@ The channels are kept consistent as much as possible from brand to brand to make
 | `activateAlarmOutput2` | Switch | Toggles a cameras relay output 2. |
 | `audioAlarm` | Switch (read only) | When the camera detects noise above a threshold this switch will move to ON. |
 | `autoLED` | Switch | When ON this sets a cameras IR LED to automatically turn on or off. |
+| `carAlarm` | Switch | When a car is detected the switch will turn ON. |
 | `cellMotionAlarm` | Switch (read only) | ONVIF cameras only will reflect the status of the ONVIF event of the same name. |
 | `doorBell` | Switch (read only) | Doorbird only, will reflect the status of the doorbell button. |
 | `enableAudioAlarm` | Switch | Allows the audio alarm to be turned ON or OFF. |
@@ -234,6 +235,7 @@ The channels are kept consistent as much as possible from brand to brand to make
 | `gifHistoryLength` | Number | How many filenames are in the `gifHistory`. |
 | `gotoPreset` | String | ONVIF cameras that can move only. Will cause the camera to move to a preset location. |
 | `hlsUrl` | String | The URL for the ipcamera.m3u8 file. |
+| `humanAlarm` | Switch | When a camera detects a human this switch will turn ON. |
 | `imageUrl` | String | The URL for the ipcamera.jpg file. |
 | `itemLeft` | Switch (read only) | Will turn ON if an API camera detects an item has been left behind. |
 | `itemTaken` | Switch (read only) | Will turn ON if an API camera detects an item has been stolen. |
@@ -379,6 +381,9 @@ See this forum thread for examples of how to use snapshots and streams in a site
 
 ## Video Streams
 
+To get video streams working, this forum thread has working widget examples that you can use.
+<https://community.openhab.org/t/oh3-widget-building-a-camera-widget/110069>
+
 To get some of the video formats working, you need to install FFmpeg. 
 Visit their site here to learn how <https://ffmpeg.org/>
 
index 19daffebc565b658b57b513634e53e6eeffda0f8..65234b506364afa679eecf1fb63b4608702bb243 100644 (file)
@@ -14,7 +14,7 @@ package org.openhab.binding.ipcamera.internal;
 
 import static org.openhab.binding.ipcamera.internal.IpCameraBindingConstants.*;
 
-import java.util.ArrayList;
+import java.util.List;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
@@ -48,6 +48,150 @@ public class DahuaHandler extends ChannelDuplexHandler {
         this.nvrChannel = nvrChannel;
     }
 
+    private void processEvent(String content) {
+        int startIndex = content.indexOf("Code=", 12) + 5;// skip --myboundary
+        int endIndex = content.indexOf(";", startIndex + 1);
+        if (startIndex == -1 || endIndex == -1) {
+            ipCameraHandler.logger.debug("Code= not found in Dahua event. Content was:{}", content);
+            return;
+        }
+        String code = content.substring(startIndex, endIndex);
+        startIndex = endIndex + 8;// skip ;action=
+        endIndex = content.indexOf(";", startIndex);
+        if (startIndex == -1 || endIndex == -1) {
+            ipCameraHandler.logger.debug(";action= not found in Dahua event. Content was:{}", content);
+            return;
+        }
+        String action = content.substring(startIndex, endIndex);
+        switch (code) {
+            case "VideoMotion":
+                if (action.equals("Start")) {
+                    ipCameraHandler.motionDetected(CHANNEL_MOTION_ALARM);
+                } else if (action.equals("Stop")) {
+                    ipCameraHandler.noMotionDetected(CHANNEL_MOTION_ALARM);
+                }
+                break;
+            case "TakenAwayDetection":
+                if (action.equals("Start")) {
+                    ipCameraHandler.motionDetected(CHANNEL_ITEM_TAKEN);
+                } else if (action.equals("Stop")) {
+                    ipCameraHandler.noMotionDetected(CHANNEL_ITEM_TAKEN);
+                }
+                break;
+            case "LeftDetection":
+                if (action.equals("Start")) {
+                    ipCameraHandler.motionDetected(CHANNEL_ITEM_LEFT);
+                } else if (action.equals("Stop")) {
+                    ipCameraHandler.noMotionDetected(CHANNEL_ITEM_LEFT);
+                }
+                break;
+            case "SmartMotionVehicle":
+                if (action.equals("Start")) {
+                    ipCameraHandler.motionDetected(CHANNEL_CAR_ALARM);
+                } else if (action.equals("Stop")) {
+                    ipCameraHandler.noMotionDetected(CHANNEL_CAR_ALARM);
+                }
+                break;
+            case "SmartMotionHuman":
+                if (action.equals("Start")) {
+                    ipCameraHandler.motionDetected(CHANNEL_HUMAN_ALARM);
+                } else if (action.equals("Stop")) {
+                    ipCameraHandler.noMotionDetected(CHANNEL_HUMAN_ALARM);
+                }
+                break;
+            case "CrossLineDetection":
+                if (action.equals("Start")) {
+                    ipCameraHandler.motionDetected(CHANNEL_LINE_CROSSING_ALARM);
+                } else if (action.equals("Stop")) {
+                    ipCameraHandler.noMotionDetected(CHANNEL_LINE_CROSSING_ALARM);
+                }
+                break;
+            case "AudioMutation":
+                if (action.equals("Start")) {
+                    ipCameraHandler.audioDetected();
+                } else if (action.equals("Stop")) {
+                    ipCameraHandler.noAudioDetected();
+                }
+                break;
+            case "FaceDetection":
+                if (action.equals("Start")) {
+                    ipCameraHandler.motionDetected(CHANNEL_FACE_DETECTED);
+                } else if (action.equals("Stop")) {
+                    ipCameraHandler.noMotionDetected(CHANNEL_FACE_DETECTED);
+                }
+                break;
+            case "ParkingDetection":
+                if (action.equals("Start")) {
+                    ipCameraHandler.setChannelState(CHANNEL_PARKING_ALARM, OnOffType.ON);
+                } else if (action.equals("Stop")) {
+                    ipCameraHandler.setChannelState(CHANNEL_PARKING_ALARM, OnOffType.OFF);
+                }
+                break;
+            case "CrossRegionDetection":
+                if (action.equals("Start")) {
+                    ipCameraHandler.motionDetected(CHANNEL_FIELD_DETECTION_ALARM);
+                } else if (action.equals("Stop")) {
+                    ipCameraHandler.noMotionDetected(CHANNEL_FIELD_DETECTION_ALARM);
+                }
+                break;
+            case "VideoLoss":
+            case "VideoBlind":
+                if (action.equals("Start")) {
+                    ipCameraHandler.setChannelState(CHANNEL_TOO_DARK_ALARM, OnOffType.ON);
+                } else if (action.equals("Stop")) {
+                    ipCameraHandler.setChannelState(CHANNEL_TOO_DARK_ALARM, OnOffType.OFF);
+                }
+                break;
+            case "VideoAbnormalDetection":
+                if (action.equals("Start")) {
+                    ipCameraHandler.setChannelState(CHANNEL_SCENE_CHANGE_ALARM, OnOffType.ON);
+                } else if (action.equals("Stop")) {
+                    ipCameraHandler.setChannelState(CHANNEL_SCENE_CHANGE_ALARM, OnOffType.OFF);
+                }
+                break;
+            case "VideoUnFocus":
+                if (action.equals("Start")) {
+                    ipCameraHandler.setChannelState(CHANNEL_TOO_BLURRY_ALARM, OnOffType.ON);
+                } else if (action.equals("Stop")) {
+                    ipCameraHandler.setChannelState(CHANNEL_TOO_BLURRY_ALARM, OnOffType.OFF);
+                }
+                break;
+            case "AlarmLocal":
+                if (action.equals("Start")) {
+                    if (content.contains("index=0")) {
+                        ipCameraHandler.setChannelState(CHANNEL_EXTERNAL_ALARM_INPUT, OnOffType.ON);
+                    } else {
+                        ipCameraHandler.setChannelState(CHANNEL_EXTERNAL_ALARM_INPUT2, OnOffType.ON);
+                    }
+                } else if (action.equals("Stop")) {
+                    if (content.contains("index=0")) {
+                        ipCameraHandler.setChannelState(CHANNEL_EXTERNAL_ALARM_INPUT, OnOffType.OFF);
+                    } else {
+                        ipCameraHandler.setChannelState(CHANNEL_EXTERNAL_ALARM_INPUT2, OnOffType.OFF);
+                    }
+                }
+                break;
+            case "LensMaskOpen":
+                ipCameraHandler.setChannelState(CHANNEL_ENABLE_PRIVACY_MODE, OnOffType.ON);
+                break;
+            case "LensMaskClose":
+                ipCameraHandler.setChannelState(CHANNEL_ENABLE_PRIVACY_MODE, OnOffType.OFF);
+                break;
+            case "TimeChange":
+            case "NTPAdjustTime":
+            case "StorageChange":
+            case "Reboot":
+            case "NewFile":
+            case "VideoMotionInfo":
+            case "RtspSessionDisconnect":
+            case "LeFunctionStatusSync":
+            case "RecordDelete":
+                break;
+            default:
+                ipCameraHandler.logger.debug("Unrecognised Dahua event, Code={}, action={}", code, action);
+        }
+    }
+
     // This handles the incoming http replies back from the camera.
     @Override
     public void channelRead(@Nullable ChannelHandlerContext ctx, @Nullable Object msg) throws Exception {
@@ -56,6 +200,10 @@ public class DahuaHandler extends ChannelDuplexHandler {
         }
         try {
             String content = msg.toString();
+            if (content.startsWith("--myboundary")) {
+                processEvent(content);
+                return;
+            }
             ipCameraHandler.logger.trace("HTTP Result back from camera is \t:{}:", content);
             // determine if the motion detection is turned on or off.
             if (content.contains("table.MotionDetect[0].Enable=true")) {
@@ -63,77 +211,20 @@ public class DahuaHandler extends ChannelDuplexHandler {
             } else if (content.contains("table.MotionDetect[" + nvrChannel + "].Enable=false")) {
                 ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.OFF);
             }
-            // Handle motion alarm
-            if (content.contains("Code=VideoMotion;action=Start;index=0")) {
-                ipCameraHandler.motionDetected(CHANNEL_MOTION_ALARM);
-            } else if (content.contains("Code=VideoMotion;action=Stop;index=0")) {
-                ipCameraHandler.noMotionDetected(CHANNEL_MOTION_ALARM);
-            }
-            // Handle item taken alarm
-            if (content.contains("Code=TakenAwayDetection;action=Start;index=0")) {
-                ipCameraHandler.motionDetected(CHANNEL_ITEM_TAKEN);
-            } else if (content.contains("Code=TakenAwayDetection;action=Stop;index=0")) {
-                ipCameraHandler.noMotionDetected(CHANNEL_ITEM_TAKEN);
-            }
-            // Handle item left alarm
-            if (content.contains("Code=LeftDetection;action=Start;index=0")) {
-                ipCameraHandler.motionDetected(CHANNEL_ITEM_LEFT);
-            } else if (content.contains("Code=LeftDetection;action=Stop;index=0")) {
-                ipCameraHandler.noMotionDetected(CHANNEL_ITEM_LEFT);
-            }
-            // Handle CrossLineDetection alarm
-            if (content.contains("Code=CrossLineDetection;action=Start;index=0")) {
-                ipCameraHandler.motionDetected(CHANNEL_LINE_CROSSING_ALARM);
-            } else if (content.contains("Code=CrossLineDetection;action=Stop;index=0")) {
-                ipCameraHandler.noMotionDetected(CHANNEL_LINE_CROSSING_ALARM);
-            }
+
             // determine if the audio alarm is turned on or off.
             if (content.contains("table.AudioDetect[0].MutationDetect=true")) {
                 ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.ON);
             } else if (content.contains("table.AudioDetect[0].MutationDetect=false")) {
                 ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.OFF);
             }
-            // Handle AudioMutation alarm
-            if (content.contains("Code=AudioMutation;action=Start;index=0")) {
-                ipCameraHandler.audioDetected();
-            } else if (content.contains("Code=AudioMutation;action=Stop;index=0")) {
-                ipCameraHandler.noAudioDetected();
-            }
+
             // Handle AudioMutationThreshold alarm
             if (content.contains("table.AudioDetect[0].MutationThreold=")) {
                 String value = ipCameraHandler.returnValueFromString(content, "table.AudioDetect[0].MutationThreold=");
                 ipCameraHandler.setChannelState(CHANNEL_THRESHOLD_AUDIO_ALARM, PercentType.valueOf(value));
             }
-            // Handle FaceDetection alarm
-            if (content.contains("Code=FaceDetection;action=Start;index=0")) {
-                ipCameraHandler.motionDetected(CHANNEL_FACE_DETECTED);
-            } else if (content.contains("Code=FaceDetection;action=Stop;index=0")) {
-                ipCameraHandler.noMotionDetected(CHANNEL_FACE_DETECTED);
-            }
-            // Handle ParkingDetection alarm
-            if (content.contains("Code=ParkingDetection;action=Start;index=0")) {
-                ipCameraHandler.motionDetected(CHANNEL_PARKING_ALARM);
-            } else if (content.contains("Code=ParkingDetection;action=Stop;index=0")) {
-                ipCameraHandler.noMotionDetected(CHANNEL_PARKING_ALARM);
-            }
-            // Handle CrossRegionDetection alarm
-            if (content.contains("Code=CrossRegionDetection;action=Start;index=0")) {
-                ipCameraHandler.motionDetected(CHANNEL_FIELD_DETECTION_ALARM);
-            } else if (content.contains("Code=CrossRegionDetection;action=Stop;index=0")) {
-                ipCameraHandler.noMotionDetected(CHANNEL_FIELD_DETECTION_ALARM);
-            }
-            // Handle External Input alarm
-            if (content.contains("Code=AlarmLocal;action=Start;index=0")) {
-                ipCameraHandler.setChannelState(CHANNEL_EXTERNAL_ALARM_INPUT, OnOffType.ON);
-            } else if (content.contains("Code=AlarmLocal;action=Stop;index=0")) {
-                ipCameraHandler.setChannelState(CHANNEL_EXTERNAL_ALARM_INPUT, OnOffType.OFF);
-            }
-            // Handle External Input alarm2
-            if (content.contains("Code=AlarmLocal;action=Start;index=1")) {
-                ipCameraHandler.setChannelState(CHANNEL_EXTERNAL_ALARM_INPUT2, OnOffType.ON);
-            } else if (content.contains("Code=AlarmLocal;action=Stop;index=1")) {
-                ipCameraHandler.setChannelState(CHANNEL_EXTERNAL_ALARM_INPUT2, OnOffType.OFF);
-            }
+
             // CrossLineDetection alarm on/off
             if (content.contains("table.VideoAnalyseRule[0][1].Enable=true")) {
                 ipCameraHandler.setChannelState(CHANNEL_ENABLE_LINE_CROSSING_ALARM, OnOffType.ON);
@@ -141,10 +232,9 @@ public class DahuaHandler extends ChannelDuplexHandler {
                 ipCameraHandler.setChannelState(CHANNEL_ENABLE_LINE_CROSSING_ALARM, OnOffType.OFF);
             }
             // Privacy Mode on/off
-            if (content.contains("Code=LensMaskOpen;") || content.contains("table.LeLensMask[0].Enable=true")) {
+            if (content.contains("table.LeLensMask[0].Enable=true")) {
                 ipCameraHandler.setChannelState(CHANNEL_ENABLE_PRIVACY_MODE, OnOffType.ON);
-            } else if (content.contains("Code=LensMaskClose;")
-                    || content.contains("table.LeLensMask[0].Enable=false")) {
+            } else if (content.contains("table.LeLensMask[0].Enable=false")) {
                 ipCameraHandler.setChannelState(CHANNEL_ENABLE_PRIVACY_MODE, OnOffType.OFF);
             }
         } finally {
@@ -152,13 +242,10 @@ public class DahuaHandler extends ChannelDuplexHandler {
         }
     }
 
-    // This handles the commands that come from the Openhab event bus.
+    // This handles the commands that come from the openHAB event bus.
     public void handleCommand(ChannelUID channelUID, Command command) {
         if (command instanceof RefreshType) {
             switch (channelUID.getId()) {
-                case CHANNEL_THRESHOLD_AUDIO_ALARM:
-                    // ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=AudioDetect[0]");
-                    return;
                 case CHANNEL_ENABLE_AUDIO_ALARM:
                     ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=AudioDetect[0]");
                     return;
@@ -172,8 +259,7 @@ public class DahuaHandler extends ChannelDuplexHandler {
                     ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=LeLensMask[0]");
                     return;
             }
-            return; // Return as we have handled the refresh command above and don't need to
-                    // continue further.
+            return;
         } // end of "REFRESH"
         switch (channelUID.getId()) {
             case CHANNEL_TEXT_OVERLAY:
@@ -272,8 +358,7 @@ public class DahuaHandler extends ChannelDuplexHandler {
 
     // If a camera does not need to poll a request as often as snapshots, it can be
     // added here. Binding steps through the list.
-    public ArrayList<String> getLowPriorityRequests() {
-        ArrayList<String> lowPriorityRequests = new ArrayList<String>(1);
-        return lowPriorityRequests;
+    public List<String> getLowPriorityRequests() {
+        return List.of();
     }
 }
index c23295b76f92d05a36bf36084283b51b26f5f6f3..f6ab9bc8d19cbf17cc9e9f243bfb7f78270cbf0b 100644 (file)
@@ -53,16 +53,14 @@ public class DoorBirdHandler extends ChannelDuplexHandler {
         try {
             String content = msg.toString();
             ipCameraHandler.logger.trace("HTTP Result back from camera is \t:{}:", content);
-            if (content.contains("doorbell:H")) {
-                ipCameraHandler.setChannelState(CHANNEL_DOORBELL, OnOffType.ON);
-            }
             if (content.contains("doorbell:L")) {
                 ipCameraHandler.setChannelState(CHANNEL_DOORBELL, OnOffType.OFF);
+            } else if (content.contains("doorbell:H")) {
+                ipCameraHandler.setChannelState(CHANNEL_DOORBELL, OnOffType.ON);
             }
             if (content.contains("motionsensor:L")) {
                 ipCameraHandler.noMotionDetected(CHANNEL_MOTION_ALARM);
-            }
-            if (content.contains("motionsensor:H")) {
+            } else if (content.contains("motionsensor:H")) {
                 ipCameraHandler.motionDetected(CHANNEL_MOTION_ALARM);
             }
         } finally {
index d85680b7ff5ba3cdbcc664a0b411e01aa804912b..ff314392e6804a7af5da22537afe05da71eb6f30 100644 (file)
@@ -14,7 +14,7 @@ package org.openhab.binding.ipcamera.internal;
 
 import static org.openhab.binding.ipcamera.internal.IpCameraBindingConstants.*;
 
-import java.util.ArrayList;
+import java.util.List;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
@@ -212,9 +212,7 @@ public class FoscamHandler extends ChannelDuplexHandler {
 
     // If a camera does not need to poll a request as often as snapshots, it can be
     // added here. Binding steps through the list.
-    public ArrayList<String> getLowPriorityRequests() {
-        ArrayList<String> lowPriorityRequests = new ArrayList<String>(1);
-        lowPriorityRequests.add("/cgi-bin/CGIProxy.fcgi?cmd=getDevState&usr=" + username + "&pwd=" + password);
-        return lowPriorityRequests;
+    public List<String> getLowPriorityRequests() {
+        return List.of();
     }
 }
index e01c7118a356c6f44d08af4dac12b2933cbccad8..475f91a53d761533c4f6630ee6af27463462e3fe 100644 (file)
@@ -129,4 +129,6 @@ public class IpCameraBindingConstants {
     public static final String CHANNEL_GOTO_PRESET = "gotoPreset";
     public static final String CHANNEL_START_STREAM = "startStream";
     public static final String CHANNEL_ENABLE_PRIVACY_MODE = "enablePrivacyMode";
+    public static final String CHANNEL_CAR_ALARM = "carAlarm";
+    public static final String CHANNEL_HUMAN_ALARM = "humanAlarm";
 }
index 58386308ed97ff4c6f66661ce1c5f927be4998bf..e59b4055f5b6bb1f320099ddef77f57b6c404765 100644 (file)
@@ -95,7 +95,6 @@ public class MyNettyAuthHandler extends ChannelDuplexHandler {
         nonce = Helper.searchString(authenticate, "nonce=\"");
         opaque = Helper.searchString(authenticate, "opaque=\"");
         qop = Helper.searchString(authenticate, "qop=\"");
-
         if (!qop.isEmpty() && !realm.isEmpty()) {
             ipCameraHandler.useDigestAuth = true;
         } else {
@@ -128,8 +127,10 @@ public class MyNettyAuthHandler extends ChannelDuplexHandler {
 
         String digestString = "username=\"" + username + "\", realm=\"" + realm + "\", nonce=\"" + nonce + "\", uri=\""
                 + requestURI + "\", cnonce=\"" + cnonce + "\", nc=" + nc + ", qop=\"" + qop + "\", response=\""
-                + response + "\", opaque=\"" + opaque + "\"";
-
+                + response + "\"";
+        if (!opaque.isEmpty()) {
+            digestString += ", opaque=\"" + opaque + "\"";
+        }
         if (reSend) {
             ipCameraHandler.sendHttpRequest(httpMethod, requestURI, digestString);
             return;
index 6d2ffe0766bc3a5a2155fc04a8573812b12a4cba..c089e77681b950c6d67a3f04811a8676c6c656e7 100644 (file)
@@ -353,7 +353,7 @@ public class IpCameraGroupHandler extends BaseThingHandler {
             startStreamServer(true);
         }
         updateStatus(ThingStatus.ONLINE);
-        pollCameraGroupJob = pollCameraGroup.scheduleAtFixedRate(this::pollCameraGroup, 10000,
+        pollCameraGroupJob = pollCameraGroup.scheduleWithFixedDelay(this::pollCameraGroup, 10000,
                 groupConfig.getPollTime(), TimeUnit.MILLISECONDS);
     }
 
index ea43387e15c43c1a551f2d0a01e1d53308d00b61..09a59477f3d1b693b206e1a7e6a1ecce7db6b8ad 100644 (file)
@@ -591,8 +591,8 @@ public class IpCameraHandler extends BaseThingHandler {
                             }
                             logger.trace("Sending camera: {}: http://{}:{}{}", httpMethod, cameraConfig.getIp(), port,
                                     httpRequestURL);
-                            channelTrackingMap.put(httpRequestURL, new ChannelTracking(ch, httpRequestURL));
 
+                            openChannel(ch, httpRequestURL);
                             CommonCameraHandler commonHandler = (CommonCameraHandler) ch.pipeline().get(COMMON_HANDLER);
                             commonHandler.setURL(httpRequestURLFull);
                             MyNettyAuthHandler authHandler = (MyNettyAuthHandler) ch.pipeline().get(AUTH_HANDLER);
@@ -782,6 +782,15 @@ public class IpCameraHandler extends BaseThingHandler {
         }
     }
 
+    void openChannel(Channel channel, String httpRequestURL) {
+        ChannelTracking tracker = channelTrackingMap.get(httpRequestURL);
+        if (tracker != null && !tracker.getReply().isEmpty()) {// We need to keep the stored reply
+            tracker.setChannel(channel);
+            return;
+        }
+        channelTrackingMap.put(httpRequestURL, new ChannelTracking(channel, httpRequestURL));
+    }
+
     void closeChannel(String url) {
         ChannelTracking channelTracking = channelTrackingMap.get(url);
         if (channelTracking != null) {
@@ -1412,9 +1421,22 @@ public class IpCameraHandler extends BaseThingHandler {
             localFuture.cancel(false);
         }
 
+        switch (thing.getThingTypeUID().getId()) {
+            case HIKVISION_THING:
+                sendHttpGET("/ISAPI/Smart/AudioDetection/channels/" + cameraConfig.getNvrChannel() + "01");
+                sendHttpGET("/ISAPI/Smart/LineDetection/" + cameraConfig.getNvrChannel() + "01");
+                sendHttpGET("/ISAPI/Smart/FieldDetection/" + cameraConfig.getNvrChannel() + "01");
+                sendHttpGET(
+                        "/ISAPI/System/Video/inputs/channels/" + cameraConfig.getNvrChannel() + "01/motionDetection");
+                sendHttpGET("/ISAPI/System/Video/inputs/channels/" + cameraConfig.getNvrChannel() + "/overlays/text/1");
+                sendHttpGET("/ISAPI/System/IO/inputs/" + cameraConfig.getNvrChannel());
+                sendHttpGET("/ISAPI/System/IO/inputs/" + cameraConfig.getNvrChannel());
+                break;
+        }
+
         if (cameraConfig.getGifPreroll() > 0 || cameraConfig.getUpdateImageWhen().contains("1")) {
             snapshotPolling = true;
-            snapshotJob = threadPool.scheduleAtFixedRate(this::snapshotRunnable, 1000, cameraConfig.getPollTime(),
+            snapshotJob = threadPool.scheduleWithFixedDelay(this::snapshotRunnable, 1000, cameraConfig.getPollTime(),
                     TimeUnit.MILLISECONDS);
         }
 
@@ -1537,11 +1559,11 @@ public class IpCameraHandler extends BaseThingHandler {
         }
         if (streamingSnapshotMjpeg || streamingAutoFps) {
             snapshotPolling = true;
-            snapshotJob = threadPool.scheduleAtFixedRate(this::snapshotRunnable, 200, cameraConfig.getPollTime(),
+            snapshotJob = threadPool.scheduleWithFixedDelay(this::snapshotRunnable, 200, cameraConfig.getPollTime(),
                     TimeUnit.MILLISECONDS);
         } else if (cameraConfig.getUpdateImageWhen().contains("4")) { // During Motion Alarms
             snapshotPolling = true;
-            snapshotJob = threadPool.scheduleAtFixedRate(this::snapshotRunnable, 200, cameraConfig.getPollTime(),
+            snapshotJob = threadPool.scheduleWithFixedDelay(this::snapshotRunnable, 200, cameraConfig.getPollTime(),
                     TimeUnit.MILLISECONDS);
         }
     }
@@ -1610,6 +1632,10 @@ public class IpCameraHandler extends BaseThingHandler {
                     sendHttpGET("/bha-api/monitor.cgi?ring=doorbell,motionsensor");
                 }
                 break;
+            case FOSCAM_THING:
+                sendHttpGET("/cgi-bin/CGIProxy.fcgi?cmd=getDevState&usr=" + cameraConfig.getUser() + "&pwd="
+                        + cameraConfig.getPassword());
+                break;
         }
         Ffmpeg localHLS = ffmpegHLS;
         if (localHLS != null) {
@@ -1747,6 +1773,7 @@ public class IpCameraHandler extends BaseThingHandler {
         Ffmpeg localFfmpeg = ffmpegHLS;
         if (localFfmpeg != null) {
             localFfmpeg.stopConverting();
+            localFfmpeg = null;
         }
         localFfmpeg = ffmpegRecord;
         if (localFfmpeg != null) {
index 10c744c817b515909af60edf6efb2729ee408891..1705733152adb337ecc56cb4b165b20ef8f74c17 100644 (file)
@@ -124,9 +124,9 @@ public class OnvifDiscovery {
 
     void processCameraReplys() {
         for (DatagramPacket packet : listOfReplys) {
-            logger.trace("Device replied to discovery with:{}", packet.toString());
             String xml = packet.content().toString(CharsetUtil.UTF_8);
-            String xAddr = Helper.fetchXML(xml, "", "<d:XAddrs>");
+            logger.trace("Device replied to discovery with:{}", xml);
+            String xAddr = Helper.fetchXML(xml, "", "d:XAddrs>");// Foscam <wsdd:XAddrs> and all other brands <d:XAddrs>
             if (!xAddr.equals("")) {
                 searchReply(xAddr, xml);
             } else if (xml.contains("onvif")) {
index 1e354d4a30e9f01f74036510489169ffac05474e..12624ebc1f1f14489230c458ae7c12cfa4771da0 100644 (file)
                        <channel id="imageUrl" typeId="imageUrl"/>
                        <channel id="hlsUrl" typeId="hlsUrl"/>
                        <channel id="enablePrivacyMode" typeId="enablePrivacyMode"/>
+                       <channel id="carAlarm" typeId="carAlarm"/>
+                       <channel id="humanAlarm" typeId="humanAlarm"/>
+                       <channel id="tooDarkAlarm" typeId="tooDarkAlarm"/>
+                       <channel id="sceneChangeAlarm" typeId="sceneChangeAlarm"/>
+                       <channel id="tooBlurryAlarm" typeId="tooBlurryAlarm"/>
                </channels>
                <config-description>
 
                <state readOnly="true"/>
        </channel-type>
 
+       <channel-type id="humanAlarm" advanced="true">
+               <item-type>Switch</item-type>
+               <label>Human Alarm</label>
+               <description>A person has triggered the Human Detection.</description>
+               <category>Alarm</category>
+               <state readOnly="true"/>
+       </channel-type>
+
+       <channel-type id="carAlarm" advanced="true">
+               <item-type>Switch</item-type>
+               <label>Car Alarm</label>
+               <description>A car has triggered the Vehicle Detection.</description>
+               <category>Alarm</category>
+               <state readOnly="true"/>
+       </channel-type>
+
        <channel-type id="parkingAlarm" advanced="true">
                <item-type>Switch</item-type>
                <label>Parking Alarm</label>