[ipcamera] Improve support for newer 2k+ Instar cameras (#13773)

* 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>
pull/13779/head
Matthew Skinner 2022-11-26 18:15:29 +11:00 committed by GitHub
parent 698bee7c3e
commit ea134d8215
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 67 additions and 17 deletions

View 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. |

View 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);
}
}
}

View 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";
}

View 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;

View 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());

View File

@ -2002,6 +2002,10 @@
<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"/>
@ -2520,6 +2524,14 @@
<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>