]> git.basschouten.com Git - openhab-addons.git/commitdiff
[ipcamera] Improve support for newer 2k+ Instar cameras (#13773)
authorMatthew Skinner <matt@pcmus.com>
Sat, 26 Nov 2022 07:15:29 +0000 (18:15 +1100)
committerGitHub <noreply@github.com>
Sat, 26 Nov 2022 07:15:29 +0000 (08:15 +0100)
* Fix never ending WARN when HIK camera does not support alarm inputs.
* Streamline code.
* Update Instar support for 2k+ Generation.
* Fix alarm codes.
* Add CHANNEL_LAST_EVENT_DATA

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/InstarHandler.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/IpCameraHandler.java
bundles/org.openhab.binding.ipcamera/src/main/resources/OH-INF/thing/thing-types.xml

index 037163166d4fe05559fc324fdd56d945efb25989..1828b92581819a11ad6e59010eb450d7cde851d3 100644 (file)
@@ -167,7 +167,7 @@ If you do not specify any of these, the binding will use the default which shoul
 |-|-|
 | `ipAddress`| The IP address or host name of your camera. |
 | `port`| This port will be used for HTTP calls for fetching the snapshot and any API calls. |
-| `onvifPort`| The port your camera uses for ONVIF connections. This is needed for PTZ movement, events, and the auto discovery of RTSP and snapshot URLs. |
+| `onvifPort`| The port your camera uses for ONVIF connections. This is needed for PTZ movement, events, and the auto discovery of RTSP and snapshot URLs. A value of 0 will prevent the binding from trying to connect to ONVIF. |
 | `username`| Leave blank if your camera does not use login details. |
 | `password`| Leave blank if your camera does not use login details. |
 | `onvifMediaProfile`| 0 (default) is your cameras Mainstream and the numbers above 0 are the substreams. Any auto discovered URLs will use the streams that this indicates. You can always override the URLs should you wish to use something different for one of them. |
index 64e7705ce454a09f4d1722321d2826952165f4be..4c3ff3cc8613d19cb68c893ebc982f4d695f4dd7 100644 (file)
@@ -185,26 +185,53 @@ public class InstarHandler extends ChannelDuplexHandler {
     }
 
     public void alarmTriggered(String alarm) {
-        ipCameraHandler.logger.debug("Alarm has been triggered:{}", alarm);
-        switch (alarm) {
-            case "/instar?&active=1":// The motion area boxes 1-4
-            case "/instar?&active=2":
-            case "/instar?&active=3":
-            case "/instar?&active=4":
+        // older cameras placed the & for the first query, whilst newer cameras do not.
+        // examples are /instar?&active=6 vs /instar?active=6&object=0
+        ipCameraHandler.setChannelState(CHANNEL_LAST_EVENT_DATA, new StringType(alarm));
+        String alarmCode = alarm.replaceAll(".+active=", "");
+        alarmCode = alarmCode.replaceAll("&.+", "");
+        String objectCode = alarm.replaceAll(".+object=", "");
+        switch (alarmCode) {
+            case "1":// The motion area boxes 1-4
+            case "2":
+            case "3":
+            case "4":
                 ipCameraHandler.motionDetected(CHANNEL_MOTION_ALARM);
                 break;
-            case "/instar?&active=5":// PIR
+            case "5":// PIR
                 ipCameraHandler.motionDetected(CHANNEL_PIR_ALARM);
                 break;
-            case "/instar?&active=6":// Audio Alarm
+            case "6":// Audio Alarm
                 ipCameraHandler.audioDetected();
                 break;
-            case "/instar?&active=7":// Motion Area 1
-            case "/instar?&active=8":// Motion Area 2
-            case "/instar?&active=9":// Motion Area 3
-            case "/instar?&active=10":// Motion Area 4
+            case "7":// Motion area 1 + PIR
+            case "8":// Motion area 2 + PIR
+            case "9":// Motion area 3 + PIR
+            case "10":// Motion area 4 + PIR
                 ipCameraHandler.motionDetected(CHANNEL_MOTION_ALARM);
+                ipCameraHandler.motionDetected(CHANNEL_PIR_ALARM);
                 break;
+            default:
+                ipCameraHandler.logger.debug("Unknown alarm code:{}", alarmCode);
+        }
+        if (!objectCode.isEmpty()) {
+            switch (objectCode) {
+                case "0":// no object
+                    break;
+                case "1":// person/human
+                    ipCameraHandler.motionDetected(CHANNEL_HUMAN_ALARM);
+                    break;
+                case "2":// car/vehicles
+                    ipCameraHandler.motionDetected(CHANNEL_CAR_ALARM);
+                    break;
+                case "3":// animals
+                case "4":
+                case "5":
+                    ipCameraHandler.motionDetected(CHANNEL_ANIMAL_ALARM);
+                    break;
+                default:
+                    ipCameraHandler.logger.debug("Unknown object detection code:{}", objectCode);
+            }
         }
     }
 
index 678d1a12772aa66b30abb85630fbd878c0b44cd8..8ebbe96b5e7d838b8e62a9899b2c3e6f41806e93 100644 (file)
@@ -138,4 +138,5 @@ public class IpCameraBindingConstants {
     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";
+    public static final String CHANNEL_ANIMAL_ALARM = "animalAlarm";
 }
index 615f9beb30260049d602daebab7aa90786cd76f1..8d2a15dba64bd27c81ec2cf65e5da0ad1b72a10f 100644 (file)
@@ -74,7 +74,7 @@ public class MyNettyAuthHandler extends ChannelDuplexHandler {
     // First run it should not have authenticate as null
     // nonce is reused if authenticate is null so the NC needs to increment to allow this//
     public void processAuth(String authenticate, String httpMethod, String requestURI, boolean reSend) {
-        if (authenticate.contains("Basic realm=\"")) {
+        if (authenticate.contains("Basic realm=")) {
             if (ipCameraHandler.useDigestAuth) {
                 // Possible downgrade authenticate attack avoided.
                 return;
index 12b3daf2dc1e59dfb23ae5177c7d861a7a1a28ab..cc6b8f5d222bdf954d9997747b69a934e648f41a 100644 (file)
@@ -1371,7 +1371,7 @@ public class IpCameraHandler extends BaseThingHandler {
             }
             return;
         }
-        if (!onvifCamera.isConnected()) {
+        if (cameraConfig.getOnvifPort() > 0 && !onvifCamera.isConnected()) {
             logger.debug("About to connect to the IP Camera using the ONVIF PORT at IP:{}:{}", cameraConfig.getIp(),
                     cameraConfig.getOnvifPort());
             onvifCamera.connect(thing.getThingTypeUID().getId().equals(ONVIF_THING));
@@ -1521,6 +1521,9 @@ public class IpCameraHandler extends BaseThingHandler {
                 }
                 noMotionDetected(CHANNEL_MOTION_ALARM);
                 noMotionDetected(CHANNEL_PIR_ALARM);
+                noMotionDetected(CHANNEL_HUMAN_ALARM);
+                noMotionDetected(CHANNEL_CAR_ALARM);
+                noMotionDetected(CHANNEL_ANIMAL_ALARM);
                 noAudioDetected();
                 break;
             case HIKVISION_THING:
@@ -1639,11 +1642,18 @@ public class IpCameraHandler extends BaseThingHandler {
                 if (mjpegUri.isEmpty()) {
                     mjpegUri = "/mjpegstream.cgi?-chn=12";
                 }
+                // Newer Instar cameras use this to setup the Alarm Server
+                sendHttpGET(
+                        "/param.cgi?cmd=setasaction&-server=1&enable=1&-interval=1&cmd=setasattr&-as_index=1&-as_server="
+                                + hostIp + "&-as_port=" + SERVLET_PORT + "&-as_path=/ipcamera/"
+                                + getThing().getUID().getId()
+                                + "/instar&-as_ssl=0&-as_insecure=0&-as_mode=0&-as_activequery=1&-as_auth=0&-as_query1=0&-as_query2=0&-as_query3=0&-as_query4=0&-as_query5=0");
+                // Older Instar cameras use this to setup the Alarm Server
                 sendHttpGET(
                         "/param.cgi?cmd=setmdalarm&-aname=server2&-switch=on&-interval=1&cmd=setalarmserverattr&-as_index=3&-as_server="
                                 + hostIp + "&-as_port=" + SERVLET_PORT + "&-as_path=/ipcamera/"
                                 + getThing().getUID().getId()
-                                + "/instar&-as_queryattr1=&-as_queryval1=&-as_queryattr2=&-as_queryval2=&-as_queryattr3=&-as_queryval3=&-as_activequery=1&-as_auth=0&-as_query1=0&-as_query2=0&-as_query3=0");
+                                + "/instar&-as_ssl=0&-as_mode=1&-as_activequery=1&-as_auth=0&-as_query1=0&-as_query2=0&-as_query3=0&-as_query4=0&-as_query5=0");
                 break;
         }
         // for poll times 9 seconds and above don't display a warning about the Image channel.
@@ -1658,7 +1668,7 @@ public class IpCameraHandler extends BaseThingHandler {
 
     private void tryConnecting() {
         if (!thing.getThingTypeUID().getId().equals(GENERIC_THING)
-                && !thing.getThingTypeUID().getId().equals(DOORBIRD_THING)) {
+                && !thing.getThingTypeUID().getId().equals(DOORBIRD_THING) && cameraConfig.getOnvifPort() > 0) {
             onvifCamera = new OnvifConnection(this, cameraConfig.getIp() + ":" + cameraConfig.getOnvifPort(),
                     cameraConfig.getUser(), cameraConfig.getPassword());
             onvifCamera.setSelectedMediaProfile(cameraConfig.getOnvifMediaProfile());
index 62090a3ff7c6278e5534fdff17cae8baa647c7c5..131f0a5132dcd7931a3fc58a4edfe3a0f1dfc5d9 100644 (file)
                        <channel id="lastMotionType" typeId="lastMotionType"/>
                        <channel id="ffmpegMotionControl" typeId="ffmpegMotionControl"/>
                        <channel id="ffmpegMotionAlarm" typeId="ffmpegMotionAlarm"/>
+                       <channel id="carAlarm" typeId="carAlarm"/>
+                       <channel id="humanAlarm" typeId="humanAlarm"/>
+                       <channel id="animalAlarm" typeId="animalAlarm"/>
+                       <channel id="lastEventData" typeId="lastEventData"/>
                        <channel id="enableMotionAlarm" typeId="enableMotionAlarm"/>
                        <channel id="motionAlarm" typeId="motionAlarm"/>
                        <channel id="externalMotion" typeId="externalMotion"/>
                <state readOnly="true"/>
        </channel-type>
 
+       <channel-type id="animalAlarm" advanced="true">
+               <item-type>Switch</item-type>
+               <label>Animal Alarm</label>
+               <description>An animal has triggered the object 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>