[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. |
| `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/>

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

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

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

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

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

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

View 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) {

View 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")) {

View File

@ -936,6 +936,11 @@
<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>
@ -2542,6 +2547,22 @@
<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>