[ipcamera] Improve Dahua alarms (#10078)

Signed-off-by: Matthew Skinner <matt@pcmus.com>
This commit is contained in:
Matthew Skinner 2021-02-25 04:07:48 +11:00 committed by GitHub
parent 7050a1478e
commit 6b624f0e1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 230 additions and 93 deletions

View 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. | | `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. | | `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. | | `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. | | `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. | | `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. | | `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`. | | `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. | | `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. | | `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. | | `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. | | `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. | | `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 ## 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. To get some of the video formats working, you need to install FFmpeg.
Visit their site here to learn how <https://ffmpeg.org/> Visit their site here to learn how <https://ffmpeg.org/>

View File

@ -14,7 +14,7 @@ package org.openhab.binding.ipcamera.internal;
import static org.openhab.binding.ipcamera.internal.IpCameraBindingConstants.*; 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.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jdt.annotation.Nullable;
@ -48,6 +48,150 @@ public class DahuaHandler extends ChannelDuplexHandler {
this.nvrChannel = nvrChannel; 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. // This handles the incoming http replies back from the camera.
@Override @Override
public void channelRead(@Nullable ChannelHandlerContext ctx, @Nullable Object msg) throws Exception { public void channelRead(@Nullable ChannelHandlerContext ctx, @Nullable Object msg) throws Exception {
@ -56,6 +200,10 @@ public class DahuaHandler extends ChannelDuplexHandler {
} }
try { try {
String content = msg.toString(); String content = msg.toString();
if (content.startsWith("--myboundary")) {
processEvent(content);
return;
}
ipCameraHandler.logger.trace("HTTP Result back from camera is \t:{}:", content); ipCameraHandler.logger.trace("HTTP Result back from camera is \t:{}:", content);
// determine if the motion detection is turned on or off. // determine if the motion detection is turned on or off.
if (content.contains("table.MotionDetect[0].Enable=true")) { 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")) { } else if (content.contains("table.MotionDetect[" + nvrChannel + "].Enable=false")) {
ipCameraHandler.setChannelState(CHANNEL_ENABLE_MOTION_ALARM, OnOffType.OFF); 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. // determine if the audio alarm is turned on or off.
if (content.contains("table.AudioDetect[0].MutationDetect=true")) { if (content.contains("table.AudioDetect[0].MutationDetect=true")) {
ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.ON); ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.ON);
} else if (content.contains("table.AudioDetect[0].MutationDetect=false")) { } else if (content.contains("table.AudioDetect[0].MutationDetect=false")) {
ipCameraHandler.setChannelState(CHANNEL_ENABLE_AUDIO_ALARM, OnOffType.OFF); 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 // Handle AudioMutationThreshold alarm
if (content.contains("table.AudioDetect[0].MutationThreold=")) { if (content.contains("table.AudioDetect[0].MutationThreold=")) {
String value = ipCameraHandler.returnValueFromString(content, "table.AudioDetect[0].MutationThreold="); String value = ipCameraHandler.returnValueFromString(content, "table.AudioDetect[0].MutationThreold=");
ipCameraHandler.setChannelState(CHANNEL_THRESHOLD_AUDIO_ALARM, PercentType.valueOf(value)); 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 // CrossLineDetection alarm on/off
if (content.contains("table.VideoAnalyseRule[0][1].Enable=true")) { if (content.contains("table.VideoAnalyseRule[0][1].Enable=true")) {
ipCameraHandler.setChannelState(CHANNEL_ENABLE_LINE_CROSSING_ALARM, OnOffType.ON); 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); ipCameraHandler.setChannelState(CHANNEL_ENABLE_LINE_CROSSING_ALARM, OnOffType.OFF);
} }
// Privacy Mode on/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); ipCameraHandler.setChannelState(CHANNEL_ENABLE_PRIVACY_MODE, OnOffType.ON);
} else if (content.contains("Code=LensMaskClose;") } else if (content.contains("table.LeLensMask[0].Enable=false")) {
|| content.contains("table.LeLensMask[0].Enable=false")) {
ipCameraHandler.setChannelState(CHANNEL_ENABLE_PRIVACY_MODE, OnOffType.OFF); ipCameraHandler.setChannelState(CHANNEL_ENABLE_PRIVACY_MODE, OnOffType.OFF);
} }
} finally { } 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) { public void handleCommand(ChannelUID channelUID, Command command) {
if (command instanceof RefreshType) { if (command instanceof RefreshType) {
switch (channelUID.getId()) { 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: case CHANNEL_ENABLE_AUDIO_ALARM:
ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=AudioDetect[0]"); ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=AudioDetect[0]");
return; return;
@ -172,8 +259,7 @@ public class DahuaHandler extends ChannelDuplexHandler {
ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=LeLensMask[0]"); ipCameraHandler.sendHttpGET("/cgi-bin/configManager.cgi?action=getConfig&name=LeLensMask[0]");
return; return;
} }
return; // Return as we have handled the refresh command above and don't need to return;
// continue further.
} // end of "REFRESH" } // end of "REFRESH"
switch (channelUID.getId()) { switch (channelUID.getId()) {
case CHANNEL_TEXT_OVERLAY: 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 // If a camera does not need to poll a request as often as snapshots, it can be
// added here. Binding steps through the list. // added here. Binding steps through the list.
public ArrayList<String> getLowPriorityRequests() { public List<String> getLowPriorityRequests() {
ArrayList<String> lowPriorityRequests = new ArrayList<String>(1); return List.of();
return lowPriorityRequests;
} }
} }

View File

@ -53,16 +53,14 @@ public class DoorBirdHandler extends ChannelDuplexHandler {
try { try {
String content = msg.toString(); String content = msg.toString();
ipCameraHandler.logger.trace("HTTP Result back from camera is \t:{}:", content); 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")) { if (content.contains("doorbell:L")) {
ipCameraHandler.setChannelState(CHANNEL_DOORBELL, OnOffType.OFF); ipCameraHandler.setChannelState(CHANNEL_DOORBELL, OnOffType.OFF);
} else if (content.contains("doorbell:H")) {
ipCameraHandler.setChannelState(CHANNEL_DOORBELL, OnOffType.ON);
} }
if (content.contains("motionsensor:L")) { if (content.contains("motionsensor:L")) {
ipCameraHandler.noMotionDetected(CHANNEL_MOTION_ALARM); ipCameraHandler.noMotionDetected(CHANNEL_MOTION_ALARM);
} } else if (content.contains("motionsensor:H")) {
if (content.contains("motionsensor:H")) {
ipCameraHandler.motionDetected(CHANNEL_MOTION_ALARM); ipCameraHandler.motionDetected(CHANNEL_MOTION_ALARM);
} }
} finally { } finally {

View File

@ -14,7 +14,7 @@ package org.openhab.binding.ipcamera.internal;
import static org.openhab.binding.ipcamera.internal.IpCameraBindingConstants.*; 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.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable; 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 // If a camera does not need to poll a request as often as snapshots, it can be
// added here. Binding steps through the list. // added here. Binding steps through the list.
public ArrayList<String> getLowPriorityRequests() { public List<String> getLowPriorityRequests() {
ArrayList<String> lowPriorityRequests = new ArrayList<String>(1); return List.of();
lowPriorityRequests.add("/cgi-bin/CGIProxy.fcgi?cmd=getDevState&usr=" + username + "&pwd=" + password);
return lowPriorityRequests;
} }
} }

View File

@ -129,4 +129,6 @@ public class IpCameraBindingConstants {
public static final String CHANNEL_GOTO_PRESET = "gotoPreset"; public static final String CHANNEL_GOTO_PRESET = "gotoPreset";
public static final String CHANNEL_START_STREAM = "startStream"; public static final String CHANNEL_START_STREAM = "startStream";
public static final String CHANNEL_ENABLE_PRIVACY_MODE = "enablePrivacyMode"; 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";
} }

View File

@ -95,7 +95,6 @@ public class MyNettyAuthHandler extends ChannelDuplexHandler {
nonce = Helper.searchString(authenticate, "nonce=\""); nonce = Helper.searchString(authenticate, "nonce=\"");
opaque = Helper.searchString(authenticate, "opaque=\""); opaque = Helper.searchString(authenticate, "opaque=\"");
qop = Helper.searchString(authenticate, "qop=\""); qop = Helper.searchString(authenticate, "qop=\"");
if (!qop.isEmpty() && !realm.isEmpty()) { if (!qop.isEmpty() && !realm.isEmpty()) {
ipCameraHandler.useDigestAuth = true; ipCameraHandler.useDigestAuth = true;
} else { } else {
@ -128,8 +127,10 @@ public class MyNettyAuthHandler extends ChannelDuplexHandler {
String digestString = "username=\"" + username + "\", realm=\"" + realm + "\", nonce=\"" + nonce + "\", uri=\"" String digestString = "username=\"" + username + "\", realm=\"" + realm + "\", nonce=\"" + nonce + "\", uri=\""
+ requestURI + "\", cnonce=\"" + cnonce + "\", nc=" + nc + ", qop=\"" + qop + "\", response=\"" + requestURI + "\", cnonce=\"" + cnonce + "\", nc=" + nc + ", qop=\"" + qop + "\", response=\""
+ response + "\", opaque=\"" + opaque + "\""; + response + "\"";
if (!opaque.isEmpty()) {
digestString += ", opaque=\"" + opaque + "\"";
}
if (reSend) { if (reSend) {
ipCameraHandler.sendHttpRequest(httpMethod, requestURI, digestString); ipCameraHandler.sendHttpRequest(httpMethod, requestURI, digestString);
return; return;

View File

@ -353,7 +353,7 @@ public class IpCameraGroupHandler extends BaseThingHandler {
startStreamServer(true); startStreamServer(true);
} }
updateStatus(ThingStatus.ONLINE); updateStatus(ThingStatus.ONLINE);
pollCameraGroupJob = pollCameraGroup.scheduleAtFixedRate(this::pollCameraGroup, 10000, pollCameraGroupJob = pollCameraGroup.scheduleWithFixedDelay(this::pollCameraGroup, 10000,
groupConfig.getPollTime(), TimeUnit.MILLISECONDS); groupConfig.getPollTime(), TimeUnit.MILLISECONDS);
} }

View File

@ -591,8 +591,8 @@ public class IpCameraHandler extends BaseThingHandler {
} }
logger.trace("Sending camera: {}: http://{}:{}{}", httpMethod, cameraConfig.getIp(), port, logger.trace("Sending camera: {}: http://{}:{}{}", httpMethod, cameraConfig.getIp(), port,
httpRequestURL); httpRequestURL);
channelTrackingMap.put(httpRequestURL, new ChannelTracking(ch, httpRequestURL));
openChannel(ch, httpRequestURL);
CommonCameraHandler commonHandler = (CommonCameraHandler) ch.pipeline().get(COMMON_HANDLER); CommonCameraHandler commonHandler = (CommonCameraHandler) ch.pipeline().get(COMMON_HANDLER);
commonHandler.setURL(httpRequestURLFull); commonHandler.setURL(httpRequestURLFull);
MyNettyAuthHandler authHandler = (MyNettyAuthHandler) ch.pipeline().get(AUTH_HANDLER); 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) { void closeChannel(String url) {
ChannelTracking channelTracking = channelTrackingMap.get(url); ChannelTracking channelTracking = channelTrackingMap.get(url);
if (channelTracking != null) { if (channelTracking != null) {
@ -1412,9 +1421,22 @@ public class IpCameraHandler extends BaseThingHandler {
localFuture.cancel(false); 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")) { if (cameraConfig.getGifPreroll() > 0 || cameraConfig.getUpdateImageWhen().contains("1")) {
snapshotPolling = true; snapshotPolling = true;
snapshotJob = threadPool.scheduleAtFixedRate(this::snapshotRunnable, 1000, cameraConfig.getPollTime(), snapshotJob = threadPool.scheduleWithFixedDelay(this::snapshotRunnable, 1000, cameraConfig.getPollTime(),
TimeUnit.MILLISECONDS); TimeUnit.MILLISECONDS);
} }
@ -1537,11 +1559,11 @@ public class IpCameraHandler extends BaseThingHandler {
} }
if (streamingSnapshotMjpeg || streamingAutoFps) { if (streamingSnapshotMjpeg || streamingAutoFps) {
snapshotPolling = true; snapshotPolling = true;
snapshotJob = threadPool.scheduleAtFixedRate(this::snapshotRunnable, 200, cameraConfig.getPollTime(), snapshotJob = threadPool.scheduleWithFixedDelay(this::snapshotRunnable, 200, cameraConfig.getPollTime(),
TimeUnit.MILLISECONDS); TimeUnit.MILLISECONDS);
} else if (cameraConfig.getUpdateImageWhen().contains("4")) { // During Motion Alarms } else if (cameraConfig.getUpdateImageWhen().contains("4")) { // During Motion Alarms
snapshotPolling = true; snapshotPolling = true;
snapshotJob = threadPool.scheduleAtFixedRate(this::snapshotRunnable, 200, cameraConfig.getPollTime(), snapshotJob = threadPool.scheduleWithFixedDelay(this::snapshotRunnable, 200, cameraConfig.getPollTime(),
TimeUnit.MILLISECONDS); TimeUnit.MILLISECONDS);
} }
} }
@ -1610,6 +1632,10 @@ public class IpCameraHandler extends BaseThingHandler {
sendHttpGET("/bha-api/monitor.cgi?ring=doorbell,motionsensor"); sendHttpGET("/bha-api/monitor.cgi?ring=doorbell,motionsensor");
} }
break; break;
case FOSCAM_THING:
sendHttpGET("/cgi-bin/CGIProxy.fcgi?cmd=getDevState&usr=" + cameraConfig.getUser() + "&pwd="
+ cameraConfig.getPassword());
break;
} }
Ffmpeg localHLS = ffmpegHLS; Ffmpeg localHLS = ffmpegHLS;
if (localHLS != null) { if (localHLS != null) {
@ -1747,6 +1773,7 @@ public class IpCameraHandler extends BaseThingHandler {
Ffmpeg localFfmpeg = ffmpegHLS; Ffmpeg localFfmpeg = ffmpegHLS;
if (localFfmpeg != null) { if (localFfmpeg != null) {
localFfmpeg.stopConverting(); localFfmpeg.stopConverting();
localFfmpeg = null;
} }
localFfmpeg = ffmpegRecord; localFfmpeg = ffmpegRecord;
if (localFfmpeg != null) { if (localFfmpeg != null) {

View File

@ -124,9 +124,9 @@ public class OnvifDiscovery {
void processCameraReplys() { void processCameraReplys() {
for (DatagramPacket packet : listOfReplys) { for (DatagramPacket packet : listOfReplys) {
logger.trace("Device replied to discovery with:{}", packet.toString());
String xml = packet.content().toString(CharsetUtil.UTF_8); 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("")) { if (!xAddr.equals("")) {
searchReply(xAddr, xml); searchReply(xAddr, xml);
} else if (xml.contains("onvif")) { } else if (xml.contains("onvif")) {

View File

@ -936,6 +936,11 @@
<channel id="imageUrl" typeId="imageUrl"/> <channel id="imageUrl" typeId="imageUrl"/>
<channel id="hlsUrl" typeId="hlsUrl"/> <channel id="hlsUrl" typeId="hlsUrl"/>
<channel id="enablePrivacyMode" typeId="enablePrivacyMode"/> <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> </channels>
<config-description> <config-description>
@ -2542,6 +2547,22 @@
<state readOnly="true"/> <state readOnly="true"/>
</channel-type> </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"> <channel-type id="parkingAlarm" advanced="true">
<item-type>Switch</item-type> <item-type>Switch</item-type>
<label>Parking Alarm</label> <label>Parking Alarm</label>