[ipcamera] Fix warnings and improve logging (#15703)
Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
parent
7cb94f9238
commit
1e090bddae
|
@ -39,7 +39,6 @@ import org.slf4j.LoggerFactory;
|
||||||
/**
|
/**
|
||||||
* The {@link Ffmpeg} class is responsible for handling multiple ffmpeg conversions which are used for many tasks
|
* The {@link Ffmpeg} class is responsible for handling multiple ffmpeg conversions which are used for many tasks
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* @author Matthew Skinner - Initial contribution
|
* @author Matthew Skinner - Initial contribution
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -82,7 +81,7 @@ public class Ffmpeg {
|
||||||
public void setKeepAlive(int numberOfEightSeconds) {
|
public void setKeepAlive(int numberOfEightSeconds) {
|
||||||
// We poll every 8 seconds due to mjpeg stream requirement.
|
// We poll every 8 seconds due to mjpeg stream requirement.
|
||||||
if (keepAlive == -1 && numberOfEightSeconds > 1) {
|
if (keepAlive == -1 && numberOfEightSeconds > 1) {
|
||||||
return;// When set to -1 this will not auto turn off stream.
|
return; // When set to -1 this will not auto turn off stream.
|
||||||
}
|
}
|
||||||
keepAlive = numberOfEightSeconds;
|
keepAlive = numberOfEightSeconds;
|
||||||
}
|
}
|
||||||
|
@ -90,7 +89,7 @@ public class Ffmpeg {
|
||||||
public void checkKeepAlive() {
|
public void checkKeepAlive() {
|
||||||
if (keepAlive == 1) {
|
if (keepAlive == 1) {
|
||||||
stopConverting();
|
stopConverting();
|
||||||
} else if (keepAlive <= -1 && !getIsAlive()) {
|
} else if (keepAlive <= -1 && !isAlive()) {
|
||||||
logger.warn("HLS stream was not running, restarting it now.");
|
logger.warn("HLS stream was not running, restarting it now.");
|
||||||
startConverting();
|
startConverting();
|
||||||
}
|
}
|
||||||
|
@ -124,65 +123,63 @@ public class Ffmpeg {
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
process = Runtime.getRuntime().exec(commandArrayList.toArray(new String[commandArrayList.size()]));
|
process = Runtime.getRuntime().exec(commandArrayList.toArray(new String[commandArrayList.size()]));
|
||||||
Process localProcess = process;
|
|
||||||
if (localProcess != null) {
|
InputStream errorStream = process.getErrorStream();
|
||||||
InputStream errorStream = localProcess.getErrorStream();
|
InputStreamReader errorStreamReader = new InputStreamReader(errorStream);
|
||||||
InputStreamReader errorStreamReader = new InputStreamReader(errorStream);
|
BufferedReader bufferedReader = new BufferedReader(errorStreamReader);
|
||||||
BufferedReader bufferedReader = new BufferedReader(errorStreamReader);
|
String line = null;
|
||||||
String line = null;
|
while ((line = bufferedReader.readLine()) != null) {
|
||||||
while ((line = bufferedReader.readLine()) != null) {
|
logger.trace("{}", line);
|
||||||
logger.trace("{}", line);
|
switch (format) {
|
||||||
switch (format) {
|
case RTSP_ALARMS:
|
||||||
case RTSP_ALARMS:
|
if (line.contains("lavfi.")) {
|
||||||
if (line.contains("lavfi.")) {
|
// When the number of pixels that change are below the noise floor we need to look
|
||||||
// When the number of pixels that change are below the noise floor we need to look
|
// across frames to confirm it is motion and not noise.
|
||||||
// across frames to confirm it is motion and not noise.
|
if (countOfMotions < 10) { // Stop increasing otherwise it takes too long to go OFF
|
||||||
if (countOfMotions < 10) {// Stop increasing otherwise it takes too long to go OFF
|
countOfMotions++;
|
||||||
countOfMotions++;
|
|
||||||
}
|
|
||||||
if (countOfMotions > 9) {
|
|
||||||
ipCameraHandler.motionDetected(CHANNEL_FFMPEG_MOTION_ALARM);
|
|
||||||
} else if (countOfMotions > 4 && ipCameraHandler.motionThreshold.intValue() > 10) {
|
|
||||||
ipCameraHandler.motionDetected(CHANNEL_FFMPEG_MOTION_ALARM);
|
|
||||||
} else if (countOfMotions > 3 && ipCameraHandler.motionThreshold.intValue() > 15) {
|
|
||||||
ipCameraHandler.motionDetected(CHANNEL_FFMPEG_MOTION_ALARM);
|
|
||||||
} else if (countOfMotions > 2 && ipCameraHandler.motionThreshold.intValue() > 30) {
|
|
||||||
ipCameraHandler.motionDetected(CHANNEL_FFMPEG_MOTION_ALARM);
|
|
||||||
} else if (countOfMotions > 0 && ipCameraHandler.motionThreshold.intValue() > 89) {
|
|
||||||
ipCameraHandler.motionDetected(CHANNEL_FFMPEG_MOTION_ALARM);
|
|
||||||
countOfMotions = 4;// Used to debounce the Alarm.
|
|
||||||
}
|
|
||||||
} else if (line.contains("speed=")) {
|
|
||||||
if (countOfMotions > 0) {
|
|
||||||
if (ipCameraHandler.motionThreshold.intValue() > 89) {
|
|
||||||
countOfMotions--;
|
|
||||||
}
|
|
||||||
if (ipCameraHandler.motionThreshold.intValue() > 10) {
|
|
||||||
countOfMotions -= 2;
|
|
||||||
} else {
|
|
||||||
countOfMotions -= 4;
|
|
||||||
}
|
|
||||||
if (countOfMotions <= 0) {
|
|
||||||
ipCameraHandler.noMotionDetected(CHANNEL_FFMPEG_MOTION_ALARM);
|
|
||||||
countOfMotions = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (line.contains("silence_start")) {
|
|
||||||
ipCameraHandler.noAudioDetected();
|
|
||||||
} else if (line.contains("silence_end")) {
|
|
||||||
ipCameraHandler.audioDetected();
|
|
||||||
}
|
}
|
||||||
case MJPEG:
|
if (countOfMotions > 9) {
|
||||||
case SNAPSHOT:
|
ipCameraHandler.motionDetected(CHANNEL_FFMPEG_MOTION_ALARM);
|
||||||
notFrozen = true;// RTSP_ALARMS, MJPEG and SNAPSHOT all set this to true, no break.
|
} else if (countOfMotions > 4 && ipCameraHandler.motionThreshold.intValue() > 10) {
|
||||||
break;
|
ipCameraHandler.motionDetected(CHANNEL_FFMPEG_MOTION_ALARM);
|
||||||
default:
|
} else if (countOfMotions > 3 && ipCameraHandler.motionThreshold.intValue() > 15) {
|
||||||
break;
|
ipCameraHandler.motionDetected(CHANNEL_FFMPEG_MOTION_ALARM);
|
||||||
}
|
} else if (countOfMotions > 2 && ipCameraHandler.motionThreshold.intValue() > 30) {
|
||||||
|
ipCameraHandler.motionDetected(CHANNEL_FFMPEG_MOTION_ALARM);
|
||||||
|
} else if (countOfMotions > 0 && ipCameraHandler.motionThreshold.intValue() > 89) {
|
||||||
|
ipCameraHandler.motionDetected(CHANNEL_FFMPEG_MOTION_ALARM);
|
||||||
|
countOfMotions = 4; // Used to debounce the Alarm.
|
||||||
|
}
|
||||||
|
} else if (line.contains("speed=")) {
|
||||||
|
if (countOfMotions > 0) {
|
||||||
|
if (ipCameraHandler.motionThreshold.intValue() > 89) {
|
||||||
|
countOfMotions--;
|
||||||
|
}
|
||||||
|
if (ipCameraHandler.motionThreshold.intValue() > 10) {
|
||||||
|
countOfMotions -= 2;
|
||||||
|
} else {
|
||||||
|
countOfMotions -= 4;
|
||||||
|
}
|
||||||
|
if (countOfMotions <= 0) {
|
||||||
|
ipCameraHandler.noMotionDetected(CHANNEL_FFMPEG_MOTION_ALARM);
|
||||||
|
countOfMotions = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (line.contains("silence_start")) {
|
||||||
|
ipCameraHandler.noAudioDetected();
|
||||||
|
} else if (line.contains("silence_end")) {
|
||||||
|
ipCameraHandler.audioDetected();
|
||||||
|
}
|
||||||
|
case MJPEG:
|
||||||
|
case SNAPSHOT:
|
||||||
|
notFrozen = true; // RTSP_ALARMS, MJPEG and SNAPSHOT all set this to true, no break.
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.warn("An IO error occured trying to start FFmpeg:{}", e.getMessage());
|
logger.warn("An IO error occurred trying to start FFmpeg: {}", e.getMessage());
|
||||||
} finally {
|
} finally {
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case GIF:
|
case GIF:
|
||||||
|
@ -202,10 +199,10 @@ public class Ffmpeg {
|
||||||
if (!ipCameraFfmpegThread.isAlive()) {
|
if (!ipCameraFfmpegThread.isAlive()) {
|
||||||
ipCameraFfmpegThread = new IpCameraFfmpegThread();
|
ipCameraFfmpegThread = new IpCameraFfmpegThread();
|
||||||
if (!password.isEmpty()) {
|
if (!password.isEmpty()) {
|
||||||
logger.debug("Starting ffmpeg with this command now:{}",
|
logger.debug("Starting ffmpeg with this command now: {}",
|
||||||
ffmpegCommand.replaceAll(password, "********"));
|
ffmpegCommand.replaceAll(password, "********"));
|
||||||
} else {
|
} else {
|
||||||
logger.debug("Starting ffmpeg with this command now:{}", ffmpegCommand);
|
logger.debug("Starting ffmpeg with this command now: {}", ffmpegCommand);
|
||||||
}
|
}
|
||||||
ipCameraFfmpegThread.start();
|
ipCameraFfmpegThread.start();
|
||||||
if (format.equals(FFmpegFormat.HLS)) {
|
if (format.equals(FFmpegFormat.HLS)) {
|
||||||
|
@ -217,7 +214,7 @@ public class Ffmpeg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getIsAlive() {
|
public boolean isAlive() {
|
||||||
Process localProcess = process;
|
Process localProcess = process;
|
||||||
if (localProcess != null) {
|
if (localProcess != null) {
|
||||||
if (localProcess.isAlive() && notFrozen) {
|
if (localProcess.isAlive() && notFrozen) {
|
||||||
|
@ -230,7 +227,7 @@ public class Ffmpeg {
|
||||||
|
|
||||||
public void stopConverting() {
|
public void stopConverting() {
|
||||||
if (ipCameraFfmpegThread.isAlive()) {
|
if (ipCameraFfmpegThread.isAlive()) {
|
||||||
logger.debug("Stopping ffmpeg {} now when keepalive is:{}", format, keepAlive);
|
logger.debug("Stopping ffmpeg {} now when keepalive is: {}", format, keepAlive);
|
||||||
Process localProcess = process;
|
Process localProcess = process;
|
||||||
if (localProcess != null) {
|
if (localProcess != null) {
|
||||||
localProcess.destroyForcibly();
|
localProcess.destroyForcibly();
|
||||||
|
|
|
@ -120,12 +120,10 @@ public class ReolinkHandler extends ChannelDuplexHandler {
|
||||||
ipCameraHandler.logger.debug("The GetAiStateResponse could not be parsed");
|
ipCameraHandler.logger.debug("The GetAiStateResponse could not be parsed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (aiResponse[0].value.dog_cat != null) {
|
if (aiResponse[0].value.dog_cat.alarm_state == 1) {
|
||||||
if (aiResponse[0].value.dog_cat.alarm_state == 1) {
|
ipCameraHandler.setChannelState(CHANNEL_ANIMAL_ALARM, OnOffType.ON);
|
||||||
ipCameraHandler.setChannelState(CHANNEL_ANIMAL_ALARM, OnOffType.ON);
|
} else {
|
||||||
} else {
|
ipCameraHandler.setChannelState(CHANNEL_ANIMAL_ALARM, OnOffType.OFF);
|
||||||
ipCameraHandler.setChannelState(CHANNEL_ANIMAL_ALARM, OnOffType.OFF);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (aiResponse[0].value.face.alarm_state == 1) {
|
if (aiResponse[0].value.face.alarm_state == 1) {
|
||||||
ipCameraHandler.setChannelState(CHANNEL_FACE_DETECTED, OnOffType.ON);
|
ipCameraHandler.setChannelState(CHANNEL_FACE_DETECTED, OnOffType.ON);
|
||||||
|
|
|
@ -50,7 +50,6 @@ import org.slf4j.LoggerFactory;
|
||||||
*
|
*
|
||||||
* @author Matthew Skinner - Initial contribution
|
* @author Matthew Skinner - Initial contribution
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class IpCameraGroupHandler extends BaseThingHandler {
|
public class IpCameraGroupHandler extends BaseThingHandler {
|
||||||
private final Logger logger = LoggerFactory.getLogger(getClass());
|
private final Logger logger = LoggerFactory.getLogger(getClass());
|
||||||
|
|
|
@ -123,7 +123,6 @@ import io.netty.util.concurrent.GlobalEventExecutor;
|
||||||
*
|
*
|
||||||
* @author Matthew Skinner - Initial contribution
|
* @author Matthew Skinner - Initial contribution
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class IpCameraHandler extends BaseThingHandler {
|
public class IpCameraHandler extends BaseThingHandler {
|
||||||
public final Logger logger = LoggerFactory.getLogger(getClass());
|
public final Logger logger = LoggerFactory.getLogger(getClass());
|
||||||
|
@ -245,7 +244,7 @@ public class IpCameraHandler extends BaseThingHandler {
|
||||||
mjpegContentType = contentType;
|
mjpegContentType = contentType;
|
||||||
CameraServlet localServlet = servlet;
|
CameraServlet localServlet = servlet;
|
||||||
if (localServlet != null) {
|
if (localServlet != null) {
|
||||||
logger.debug("Setting Content-Type to:{}", contentType);
|
logger.debug("Setting Content-Type to: {}", contentType);
|
||||||
localServlet.openStreams.updateContentType(contentType, boundary);
|
localServlet.openStreams.updateContentType(contentType, boundary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -384,7 +383,7 @@ public class IpCameraHandler extends BaseThingHandler {
|
||||||
return; // don't auto close this as it is for the alarms.
|
return; // don't auto close this as it is for the alarms.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.debug("Closing an idle channel for camera:{}", cameraConfig.getIp());
|
logger.debug("Closing an idle channel for camera: {}", cameraConfig.getIp());
|
||||||
ctx.close();
|
ctx.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -511,15 +510,15 @@ public class IpCameraHandler extends BaseThingHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkCameraConnection() {
|
private void checkCameraConnection() {
|
||||||
if (snapshotPolling) {// Currently polling a real URL for snapshots, so camera must be online.
|
if (snapshotPolling) { // Currently polling a real URL for snapshots, so camera must be online.
|
||||||
return;
|
return;
|
||||||
} else if (ffmpegSnapshotGeneration) {// Use RTSP stream creating snapshots to know camera is online.
|
} else if (ffmpegSnapshotGeneration) { // Use RTSP stream creating snapshots to know camera is online.
|
||||||
Ffmpeg localSnapshot = ffmpegSnapshot;
|
Ffmpeg localSnapshot = ffmpegSnapshot;
|
||||||
if (localSnapshot != null && !localSnapshot.getIsAlive()) {
|
if (localSnapshot != null && !localSnapshot.isAlive()) {
|
||||||
cameraCommunicationError("FFmpeg Snapshots Stopped: Check your camera can be reached.");
|
cameraCommunicationError("FFmpeg Snapshots Stopped: Check that your camera can be reached.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return;// ffmpeg snapshot stream is still alive
|
return; // ffmpeg snapshot stream is still alive
|
||||||
}
|
}
|
||||||
|
|
||||||
// if ONVIF cam also use connection state which is updated by regular messages to camera
|
// if ONVIF cam also use connection state which is updated by regular messages to camera
|
||||||
|
@ -614,7 +613,7 @@ public class IpCameraHandler extends BaseThingHandler {
|
||||||
|
|
||||||
if (!basicAuth.isEmpty()) {
|
if (!basicAuth.isEmpty()) {
|
||||||
if (useDigestAuth) {
|
if (useDigestAuth) {
|
||||||
logger.warn("Camera at IP:{} had both Basic and Digest set to be used", cameraConfig.getIp());
|
logger.warn("Camera at IP: {} had both Basic and Digest set to be used", cameraConfig.getIp());
|
||||||
setBasicAuth(false);
|
setBasicAuth(false);
|
||||||
} else {
|
} else {
|
||||||
request.headers().set("Authorization", "Basic " + basicAuth);
|
request.headers().set("Authorization", "Basic " + basicAuth);
|
||||||
|
@ -755,7 +754,7 @@ public class IpCameraHandler extends BaseThingHandler {
|
||||||
channelTrackingMap.remove(channelTracking.getRequestUrl());
|
channelTrackingMap.remove(channelTracking.getRequestUrl());
|
||||||
}
|
}
|
||||||
if (channelTracking.getChannel().equals(channel)) {
|
if (channelTracking.getChannel().equals(channel)) {
|
||||||
logger.debug("Open channel to camera is used for URL:{}", channelTracking.getRequestUrl());
|
logger.debug("Open channel to camera is used for URL: {}", channelTracking.getRequestUrl());
|
||||||
oldChannel = false;
|
oldChannel = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -882,17 +881,14 @@ public class IpCameraHandler extends BaseThingHandler {
|
||||||
ffmpegRecord = new Ffmpeg(this, format, cameraConfig.getFfmpegLocation(), inputOptions, rtspUri,
|
ffmpegRecord = new Ffmpeg(this, format, cameraConfig.getFfmpegLocation(), inputOptions, rtspUri,
|
||||||
cameraConfig.getMp4OutOptions(), cameraConfig.getFfmpegOutput() + mp4Filename + ".mp4",
|
cameraConfig.getMp4OutOptions(), cameraConfig.getFfmpegOutput() + mp4Filename + ".mp4",
|
||||||
cameraConfig.getUser(), cameraConfig.getPassword());
|
cameraConfig.getUser(), cameraConfig.getPassword());
|
||||||
Ffmpeg localRecord = ffmpegRecord;
|
ffmpegRecord.startConverting();
|
||||||
if (localRecord != null) {
|
if (mp4History.isEmpty()) {
|
||||||
localRecord.startConverting();
|
mp4History = mp4Filename;
|
||||||
if (mp4History.isEmpty()) {
|
} else if (!"ipcamera".equals(mp4Filename)) {
|
||||||
mp4History = mp4Filename;
|
mp4History = mp4Filename + "," + mp4History;
|
||||||
} else if (!"ipcamera".equals(mp4Filename)) {
|
if (mp4HistoryLength > 49) {
|
||||||
mp4History = mp4Filename + "," + mp4History;
|
int endIndex = mp4History.lastIndexOf(",");
|
||||||
if (mp4HistoryLength > 49) {
|
mp4History = mp4History.substring(0, endIndex);
|
||||||
int endIndex = mp4History.lastIndexOf(",");
|
|
||||||
mp4History = mp4History.substring(0, endIndex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setChannelState(CHANNEL_MP4_HISTORY, new StringType(mp4History));
|
setChannelState(CHANNEL_MP4_HISTORY, new StringType(mp4History));
|
||||||
|
@ -930,10 +926,7 @@ public class IpCameraHandler extends BaseThingHandler {
|
||||||
}
|
}
|
||||||
ffmpegRtspHelper = new Ffmpeg(this, format, cameraConfig.getFfmpegLocation(), inputOptions, input,
|
ffmpegRtspHelper = new Ffmpeg(this, format, cameraConfig.getFfmpegLocation(), inputOptions, input,
|
||||||
filterOptions, "-f null -", cameraConfig.getUser(), cameraConfig.getPassword());
|
filterOptions, "-f null -", cameraConfig.getUser(), cameraConfig.getPassword());
|
||||||
localAlarms = ffmpegRtspHelper;
|
ffmpegRtspHelper.startConverting();
|
||||||
if (localAlarms != null) {
|
|
||||||
localAlarms.startConverting();
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case MJPEG:
|
case MJPEG:
|
||||||
if (ffmpegMjpeg == null) {
|
if (ffmpegMjpeg == null) {
|
||||||
|
@ -1429,7 +1422,7 @@ public class IpCameraHandler extends BaseThingHandler {
|
||||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||||
"Camera refused connection on ONVIF ports.");
|
"Camera refused connection on ONVIF ports.");
|
||||||
}
|
}
|
||||||
logger.debug("About to connect to the IP Camera using the ONVIF PORT at IP:{}:{}", cameraConfig.getIp(),
|
logger.debug("About to connect to the IP Camera using the ONVIF PORT at IP: {}:{}", cameraConfig.getIp(),
|
||||||
cameraConfig.getOnvifPort());
|
cameraConfig.getOnvifPort());
|
||||||
onvifCamera.connect(thing.getThingTypeUID().getId().equals(ONVIF_THING));
|
onvifCamera.connect(thing.getThingTypeUID().getId().equals(ONVIF_THING));
|
||||||
return;
|
return;
|
||||||
|
@ -1448,7 +1441,7 @@ public class IpCameraHandler extends BaseThingHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cameraConfigError(String reason) {
|
public void cameraConfigError(String reason) {
|
||||||
// wont try to reconnect again due to a config error being the cause.
|
// won't try to reconnect again due to a config error being the cause.
|
||||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, reason);
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, reason);
|
||||||
dispose();
|
dispose();
|
||||||
}
|
}
|
||||||
|
@ -1456,7 +1449,7 @@ public class IpCameraHandler extends BaseThingHandler {
|
||||||
public void cameraCommunicationError(String reason) {
|
public void cameraCommunicationError(String reason) {
|
||||||
// will try to reconnect again as camera may be rebooting.
|
// will try to reconnect again as camera may be rebooting.
|
||||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, reason);
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, reason);
|
||||||
if (isOnline) {// if already offline dont try reconnecting in 6 seconds, we want 30sec wait.
|
if (isOnline) { // if already offline dont try reconnecting in 6 seconds, we want 30sec wait.
|
||||||
resetAndRetryConnecting();
|
resetAndRetryConnecting();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1640,13 +1633,13 @@ public class IpCameraHandler extends BaseThingHandler {
|
||||||
}
|
}
|
||||||
if (ffmpegMotionAlarmEnabled || ffmpegAudioAlarmEnabled) {
|
if (ffmpegMotionAlarmEnabled || ffmpegAudioAlarmEnabled) {
|
||||||
localFfmpeg = ffmpegRtspHelper;
|
localFfmpeg = ffmpegRtspHelper;
|
||||||
if (localFfmpeg == null || !localFfmpeg.getIsAlive()) {
|
if (localFfmpeg == null || !localFfmpeg.isAlive()) {
|
||||||
setupFfmpegFormat(FFmpegFormat.RTSP_ALARMS);
|
setupFfmpegFormat(FFmpegFormat.RTSP_ALARMS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// check if the thread has frozen due to camera doing a soft reboot
|
// check if the thread has frozen due to camera doing a soft reboot
|
||||||
localFfmpeg = ffmpegMjpeg;
|
localFfmpeg = ffmpegMjpeg;
|
||||||
if (localFfmpeg != null && !localFfmpeg.getIsAlive()) {
|
if (localFfmpeg != null && !localFfmpeg.isAlive()) {
|
||||||
logger.debug("MJPEG was not being produced by FFmpeg when it should have been, restarting FFmpeg.");
|
logger.debug("MJPEG was not being produced by FFmpeg when it should have been, restarting FFmpeg.");
|
||||||
setupFfmpegFormat(FFmpegFormat.MJPEG);
|
setupFfmpegFormat(FFmpegFormat.MJPEG);
|
||||||
}
|
}
|
||||||
|
@ -1871,7 +1864,7 @@ public class IpCameraHandler extends BaseThingHandler {
|
||||||
localFfmpeg.stopConverting();
|
localFfmpeg.stopConverting();
|
||||||
ffmpegSnapshot = null;
|
ffmpegSnapshot = null;
|
||||||
}
|
}
|
||||||
if (!thing.getThingTypeUID().getId().equals(GENERIC_THING)) {// generic cameras do not have ONVIF support
|
if (!thing.getThingTypeUID().getId().equals(GENERIC_THING)) { // generic cameras do not have ONVIF support
|
||||||
onvifCamera.disconnect();
|
onvifCamera.disconnect();
|
||||||
}
|
}
|
||||||
openChannels.close();
|
openChannels.close();
|
||||||
|
|
|
@ -28,7 +28,6 @@ import io.netty.util.ReferenceCountUtil;
|
||||||
/**
|
/**
|
||||||
* The {@link OnvifCodec} is used by Netty to decode Onvif traffic into message Strings.
|
* The {@link OnvifCodec} is used by Netty to decode Onvif traffic into message Strings.
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* @author Matthew Skinner - Initial contribution
|
* @author Matthew Skinner - Initial contribution
|
||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
|
@ -66,11 +65,11 @@ public class OnvifCodec extends ChannelDuplexHandler {
|
||||||
}
|
}
|
||||||
if (evt instanceof IdleStateEvent) {
|
if (evt instanceof IdleStateEvent) {
|
||||||
IdleStateEvent e = (IdleStateEvent) evt;
|
IdleStateEvent e = (IdleStateEvent) evt;
|
||||||
logger.trace("IdleStateEvent received {}", e.state());
|
logger.trace("IdleStateEvent received: {}", e.state());
|
||||||
onvifConnection.setIsConnected(false);
|
onvifConnection.setIsConnected(false);
|
||||||
ctx.close();
|
ctx.close();
|
||||||
} else {
|
} else {
|
||||||
logger.trace("Other ONVIF netty channel event occured {}", evt);
|
logger.trace("Other ONVIF netty channel event occurred: {}", evt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,8 +67,6 @@ import io.netty.handler.timeout.IdleStateHandler;
|
||||||
/**
|
/**
|
||||||
* The {@link OnvifConnection} This is a basic Netty implementation for connecting and communicating to ONVIF cameras.
|
* The {@link OnvifConnection} This is a basic Netty implementation for connecting and communicating to ONVIF cameras.
|
||||||
*
|
*
|
||||||
*
|
|
||||||
*
|
|
||||||
* @author Matthew Skinner - Initial contribution
|
* @author Matthew Skinner - Initial contribution
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -146,7 +144,7 @@ public class OnvifConnection {
|
||||||
private Float tiltRangeMax = 1.0f;
|
private Float tiltRangeMax = 1.0f;
|
||||||
private Float zoomMin = 0.0f;
|
private Float zoomMin = 0.0f;
|
||||||
private Float zoomMax = 1.0f;
|
private Float zoomMax = 1.0f;
|
||||||
// These hold the PTZ values for updating Openhabs controls in 0-100 range
|
// These hold the PTZ values for updating openHABs controls in 0-100 range
|
||||||
private Float currentPanPercentage = 0.0f;
|
private Float currentPanPercentage = 0.0f;
|
||||||
private Float currentTiltPercentage = 0.0f;
|
private Float currentTiltPercentage = 0.0f;
|
||||||
private Float currentZoomPercentage = 0.0f;
|
private Float currentZoomPercentage = 0.0f;
|
||||||
|
@ -308,7 +306,7 @@ public class OnvifConnection {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void processReply(String message) {
|
public void processReply(String message) {
|
||||||
logger.trace("Onvif reply is:{}", message);
|
logger.trace("ONVIF reply is: {}", message);
|
||||||
if (message.contains("PullMessagesResponse")) {
|
if (message.contains("PullMessagesResponse")) {
|
||||||
eventRecieved(message);
|
eventRecieved(message);
|
||||||
} else if (message.contains("RenewResponse")) {
|
} else if (message.contains("RenewResponse")) {
|
||||||
|
@ -317,7 +315,7 @@ public class OnvifConnection {
|
||||||
setIsConnected(true);
|
setIsConnected(true);
|
||||||
sendOnvifRequest(RequestType.GetCapabilities, deviceXAddr);
|
sendOnvifRequest(RequestType.GetCapabilities, deviceXAddr);
|
||||||
parseDateAndTime(message);
|
parseDateAndTime(message);
|
||||||
logger.debug("Openhabs UTC dateTime is:{}", getUTCdateTime());
|
logger.debug("openHAB UTC dateTime is: {}", getUTCdateTime());
|
||||||
} else if (message.contains("GetCapabilitiesResponse")) {// 2nd to be sent.
|
} else if (message.contains("GetCapabilitiesResponse")) {// 2nd to be sent.
|
||||||
parseXAddr(message);
|
parseXAddr(message);
|
||||||
sendOnvifRequest(RequestType.GetProfiles, mediaXAddr);
|
sendOnvifRequest(RequestType.GetProfiles, mediaXAddr);
|
||||||
|
@ -358,7 +356,7 @@ public class OnvifConnection {
|
||||||
logger.debug("ptzNodeToken={}", ptzNodeToken);
|
logger.debug("ptzNodeToken={}", ptzNodeToken);
|
||||||
sendPTZRequest(RequestType.GetConfigurations);
|
sendPTZRequest(RequestType.GetConfigurations);
|
||||||
} else if (message.contains("GetDeviceInformationResponse")) {
|
} else if (message.contains("GetDeviceInformationResponse")) {
|
||||||
logger.debug("GetDeviceInformationResponse recieved");
|
logger.debug("GetDeviceInformationResponse received");
|
||||||
} else if (message.contains("GetSnapshotUriResponse")) {
|
} else if (message.contains("GetSnapshotUriResponse")) {
|
||||||
snapshotUri = removeIPfromUrl(Helper.fetchXML(message, ":MediaUri", ":Uri"));
|
snapshotUri = removeIPfromUrl(Helper.fetchXML(message, ":MediaUri", ":Uri"));
|
||||||
logger.debug("GetSnapshotUri:{}", snapshotUri);
|
logger.debug("GetSnapshotUri:{}", snapshotUri);
|
||||||
|
@ -387,7 +385,7 @@ public class OnvifConnection {
|
||||||
index = url.indexOf("/", index + 2);
|
index = url.indexOf("/", index + 2);
|
||||||
}
|
}
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
logger.debug("We hit an issue parsing url:{}", url);
|
logger.debug("We hit an issue parsing url: {}", url);
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
return url.substring(index);
|
return url.substring(index);
|
||||||
|
@ -399,7 +397,7 @@ public class OnvifConnection {
|
||||||
if (startIndex != -1 && endIndex != -1) {
|
if (startIndex != -1 && endIndex != -1) {
|
||||||
return url.substring(startIndex, endIndex);
|
return url.substring(startIndex, endIndex);
|
||||||
}
|
}
|
||||||
logger.debug("We hit an issue extracting IP:PORT from url:{}", url);
|
logger.debug("We hit an issue extracting IP:PORT from url: {}", url);
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -421,17 +419,17 @@ public class OnvifConnection {
|
||||||
String temp = Helper.fetchXML(message, "<tt:Device", "tt:XAddr");
|
String temp = Helper.fetchXML(message, "<tt:Device", "tt:XAddr");
|
||||||
if (!temp.isEmpty()) {
|
if (!temp.isEmpty()) {
|
||||||
deviceXAddr = temp;
|
deviceXAddr = temp;
|
||||||
logger.debug("deviceXAddr:{}", deviceXAddr);
|
logger.debug("deviceXAddr: {}", deviceXAddr);
|
||||||
}
|
}
|
||||||
temp = Helper.fetchXML(message, "<tt:Events", "tt:XAddr");
|
temp = Helper.fetchXML(message, "<tt:Events", "tt:XAddr");
|
||||||
if (!temp.isEmpty()) {
|
if (!temp.isEmpty()) {
|
||||||
subscriptionXAddr = eventXAddr = temp;
|
subscriptionXAddr = eventXAddr = temp;
|
||||||
logger.debug("eventsXAddr:{}", eventXAddr);
|
logger.debug("eventsXAddr: {}", eventXAddr);
|
||||||
}
|
}
|
||||||
temp = Helper.fetchXML(message, "<tt:Media", "tt:XAddr");
|
temp = Helper.fetchXML(message, "<tt:Media", "tt:XAddr");
|
||||||
if (!temp.isEmpty()) {
|
if (!temp.isEmpty()) {
|
||||||
mediaXAddr = temp;
|
mediaXAddr = temp;
|
||||||
logger.debug("mediaXAddr:{}", mediaXAddr);
|
logger.debug("mediaXAddr: {}", mediaXAddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ptzXAddr = Helper.fetchXML(message, "<tt:PTZ", "tt:XAddr");
|
ptzXAddr = Helper.fetchXML(message, "<tt:PTZ", "tt:XAddr");
|
||||||
|
@ -453,7 +451,7 @@ public class OnvifConnection {
|
||||||
}
|
}
|
||||||
ipCameraHandler.removeChannels(removeChannels);
|
ipCameraHandler.removeChannels(removeChannels);
|
||||||
} else {
|
} else {
|
||||||
logger.debug("ptzXAddr:{}", ptzXAddr);
|
logger.debug("ptzXAddr: {}", ptzXAddr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -464,7 +462,7 @@ public class OnvifConnection {
|
||||||
String day = Helper.fetchXML(message, "UTCDateTime", "Day>");
|
String day = Helper.fetchXML(message, "UTCDateTime", "Day>");
|
||||||
String month = Helper.fetchXML(message, "UTCDateTime", "Month>");
|
String month = Helper.fetchXML(message, "UTCDateTime", "Month>");
|
||||||
String year = Helper.fetchXML(message, "UTCDateTime", "Year>");
|
String year = Helper.fetchXML(message, "UTCDateTime", "Year>");
|
||||||
logger.debug("Cameras UTC dateTime is:{}-{}-{}T{}:{}:{}", year, month, day, hour, minute, second);
|
logger.debug("Camera UTC dateTime is: {}-{}-{}T{}:{}:{}", year, month, day, hour, minute, second);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getUTCdateTime() {
|
private String getUTCdateTime() {
|
||||||
|
@ -497,7 +495,7 @@ public class OnvifConnection {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendOnvifRequest(RequestType requestType, String xAddr) {
|
public void sendOnvifRequest(RequestType requestType, String xAddr) {
|
||||||
logger.trace("Sending ONVIF request:{}", requestType);
|
logger.trace("Sending ONVIF request: {}", requestType);
|
||||||
String security = "";
|
String security = "";
|
||||||
String extraEnvelope = "";
|
String extraEnvelope = "";
|
||||||
String headerTo = "";
|
String headerTo = "";
|
||||||
|
@ -565,7 +563,7 @@ public class OnvifConnection {
|
||||||
bootstrap = localBootstap;
|
bootstrap = localBootstap;
|
||||||
}
|
}
|
||||||
if (!mainEventLoopGroup.isShuttingDown()) {
|
if (!mainEventLoopGroup.isShuttingDown()) {
|
||||||
bootstrap.connect(new InetSocketAddress(ipAddress, onvifPort)).addListener(new ChannelFutureListener() {
|
localBootstap.connect(new InetSocketAddress(ipAddress, onvifPort)).addListener(new ChannelFutureListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void operationComplete(@Nullable ChannelFuture future) {
|
public void operationComplete(@Nullable ChannelFuture future) {
|
||||||
|
@ -576,15 +574,16 @@ public class OnvifConnection {
|
||||||
connectError = false;
|
connectError = false;
|
||||||
Channel ch = future.channel();
|
Channel ch = future.channel();
|
||||||
ch.writeAndFlush(request);
|
ch.writeAndFlush(request);
|
||||||
} else { // an error occured
|
} else { // an error occurred
|
||||||
if (future.isDone() && !future.isCancelled()) {
|
if (future.isDone() && !future.isCancelled()) {
|
||||||
Throwable cause = future.cause();
|
Throwable cause = future.cause();
|
||||||
|
String msg = cause.getMessage();
|
||||||
logger.trace("connect failed - cause {}", cause.getMessage());
|
logger.trace("connect failed - cause {}", cause.getMessage());
|
||||||
if (cause instanceof ConnectTimeoutException) {
|
if (cause instanceof ConnectTimeoutException) {
|
||||||
logger.debug("Camera is not reachable on IP {}", ipAddress);
|
logger.debug("Camera is not reachable on IP {}", ipAddress);
|
||||||
connectError = true;
|
connectError = true;
|
||||||
} else if ((cause instanceof ConnectException)
|
} else if ((cause instanceof ConnectException) && msg != null
|
||||||
&& cause.getMessage().contains("Connection refused")) {
|
&& msg.contains("Connection refused")) {
|
||||||
logger.debug("Camera ONVIF port {} is refused.", onvifPort);
|
logger.debug("Camera ONVIF port {} is refused.", onvifPort);
|
||||||
refusedError = true;
|
refusedError = true;
|
||||||
}
|
}
|
||||||
|
@ -616,7 +615,7 @@ public class OnvifConnection {
|
||||||
} else {// 192.168.1.1
|
} else {// 192.168.1.1
|
||||||
ipAddress = url;
|
ipAddress = url;
|
||||||
deviceXAddr = "http://" + ipAddress + "/onvif/device_service";
|
deviceXAddr = "http://" + ipAddress + "/onvif/device_service";
|
||||||
logger.debug("No Onvif Port found when parsing:{}", url);
|
logger.debug("No ONVIF Port found when parsing: {}", url);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
deviceXAddr = "http://" + ipAddress + ":" + onvifPort + "/onvif/device_service";
|
deviceXAddr = "http://" + ipAddress + ":" + onvifPort + "/onvif/device_service";
|
||||||
|
@ -644,7 +643,7 @@ public class OnvifConnection {
|
||||||
}
|
}
|
||||||
String dataName = Helper.fetchXML(eventMessage, "tt:Data", "Name=\"");
|
String dataName = Helper.fetchXML(eventMessage, "tt:Data", "Name=\"");
|
||||||
String dataValue = Helper.fetchXML(eventMessage, "tt:Data", "Value=\"");
|
String dataValue = Helper.fetchXML(eventMessage, "tt:Data", "Value=\"");
|
||||||
logger.debug("Onvif Event Topic:{}, Data:{}, Value:{}", topic, dataName, dataValue);
|
logger.debug("ONVIF Event Topic: {}, Data: {}, Value: {}", topic, dataName, dataValue);
|
||||||
switch (topic) {
|
switch (topic) {
|
||||||
case "RuleEngine/CellMotionDetector/Motion":
|
case "RuleEngine/CellMotionDetector/Motion":
|
||||||
if ("true".equals(dataValue)) {
|
if ("true".equals(dataValue)) {
|
||||||
|
@ -767,7 +766,7 @@ public class OnvifConnection {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
logger.debug("Please report this camera has an un-implemented ONVIF event. Topic:{}", topic);
|
logger.debug("Please report this camera has an un-implemented ONVIF event. Topic: {}", topic);
|
||||||
}
|
}
|
||||||
sendOnvifRequest(RequestType.Renew, subscriptionXAddr);
|
sendOnvifRequest(RequestType.Renew, subscriptionXAddr);
|
||||||
}
|
}
|
||||||
|
@ -833,7 +832,7 @@ public class OnvifConnection {
|
||||||
if (startLookingFromIndex >= 0) {
|
if (startLookingFromIndex >= 0) {
|
||||||
temp = Helper.fetchXML(message.substring(startLookingFromIndex), heading, key);
|
temp = Helper.fetchXML(message.substring(startLookingFromIndex), heading, key);
|
||||||
if (!temp.isEmpty()) {
|
if (!temp.isEmpty()) {
|
||||||
logger.trace("String was found:{}", temp);
|
logger.trace("String was found: {}", temp);
|
||||||
results.add(temp);
|
results.add(temp);
|
||||||
} else {
|
} else {
|
||||||
return results;// key string must not exist so stop looking.
|
return results;// key string must not exist so stop looking.
|
||||||
|
@ -879,7 +878,7 @@ public class OnvifConnection {
|
||||||
currentPanCamValue = Float.parseFloat(result.substring(beginIndex + 3, endIndex));
|
currentPanCamValue = Float.parseFloat(result.substring(beginIndex + 3, endIndex));
|
||||||
currentPanPercentage = (((panRangeMin - currentPanCamValue) * -1) / ((panRangeMin - panRangeMax) * -1))
|
currentPanPercentage = (((panRangeMin - currentPanCamValue) * -1) / ((panRangeMin - panRangeMax) * -1))
|
||||||
* 100;
|
* 100;
|
||||||
logger.debug("Pan is updating to:{} and the cam value is {}", Math.round(currentPanPercentage),
|
logger.debug("Pan is updating to: {} and the cam value is {}", Math.round(currentPanPercentage),
|
||||||
currentPanCamValue);
|
currentPanCamValue);
|
||||||
} else {
|
} else {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
|
@ -893,7 +892,7 @@ public class OnvifConnection {
|
||||||
currentTiltCamValue = Float.parseFloat(result.substring(beginIndex + 3, endIndex));
|
currentTiltCamValue = Float.parseFloat(result.substring(beginIndex + 3, endIndex));
|
||||||
currentTiltPercentage = (((tiltRangeMin - currentTiltCamValue) * -1) / ((tiltRangeMin - tiltRangeMax) * -1))
|
currentTiltPercentage = (((tiltRangeMin - currentTiltCamValue) * -1) / ((tiltRangeMin - tiltRangeMax) * -1))
|
||||||
* 100;
|
* 100;
|
||||||
logger.debug("Tilt is updating to:{} and the cam value is {}", Math.round(currentTiltPercentage),
|
logger.debug("Tilt is updating to: {} and the cam value is {}", Math.round(currentTiltPercentage),
|
||||||
currentTiltCamValue);
|
currentTiltCamValue);
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
|
@ -904,7 +903,7 @@ public class OnvifConnection {
|
||||||
if (beginIndex >= 0 && endIndex >= 0) {
|
if (beginIndex >= 0 && endIndex >= 0) {
|
||||||
currentZoomCamValue = Float.parseFloat(result.substring(beginIndex + 3, endIndex));
|
currentZoomCamValue = Float.parseFloat(result.substring(beginIndex + 3, endIndex));
|
||||||
currentZoomPercentage = (((zoomMin - currentZoomCamValue) * -1) / ((zoomMin - zoomMax) * -1)) * 100;
|
currentZoomPercentage = (((zoomMin - currentZoomCamValue) * -1) / ((zoomMin - zoomMax) * -1)) * 100;
|
||||||
logger.debug("Zoom is updating to:{} and the cam value is {}", Math.round(currentZoomPercentage),
|
logger.debug("Zoom is updating to: {} and the cam value is {}", Math.round(currentZoomPercentage),
|
||||||
currentZoomCamValue);
|
currentZoomCamValue);
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
|
@ -974,7 +973,7 @@ public class OnvifConnection {
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
logger.warn("ONVIF was not cleanly shutdown, due to being interrupted");
|
logger.warn("ONVIF was not cleanly shutdown, due to being interrupted");
|
||||||
} finally {
|
} finally {
|
||||||
logger.debug("Eventloop is shutdown:{}", mainEventLoopGroup.isShutdown());
|
logger.debug("Eventloop is shutdown: {}", mainEventLoopGroup.isShutdown());
|
||||||
bootstrap = null;
|
bootstrap = null;
|
||||||
threadPool.shutdown();
|
threadPool.shutdown();
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,6 @@ import io.netty.util.concurrent.GlobalEventExecutor;
|
||||||
*
|
*
|
||||||
* @author Matthew Skinner - Initial contribution
|
* @author Matthew Skinner - Initial contribution
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
@io.netty.channel.ChannelHandler.Sharable
|
@io.netty.channel.ChannelHandler.Sharable
|
||||||
public class OnvifDiscovery {
|
public class OnvifDiscovery {
|
||||||
|
@ -110,7 +109,7 @@ public class OnvifDiscovery {
|
||||||
String temp = url;
|
String temp = url;
|
||||||
BigDecimal onvifPort = new BigDecimal(80);
|
BigDecimal onvifPort = new BigDecimal(80);
|
||||||
|
|
||||||
logger.info("Camera found at xAddr:{}", url);
|
logger.info("Camera found at xAddr: {}", url);
|
||||||
int endIndex = temp.indexOf(" ");// Some xAddr have two urls with a space in between.
|
int endIndex = temp.indexOf(" ");// Some xAddr have two urls with a space in between.
|
||||||
if (endIndex > 0) {
|
if (endIndex > 0) {
|
||||||
temp = temp.substring(0, endIndex);// Use only the first url from now on.
|
temp = temp.substring(0, endIndex);// Use only the first url from now on.
|
||||||
|
@ -139,7 +138,7 @@ public class OnvifDiscovery {
|
||||||
void processCameraReplys() {
|
void processCameraReplys() {
|
||||||
for (DatagramPacket packet : listOfReplys) {
|
for (DatagramPacket packet : listOfReplys) {
|
||||||
String xml = packet.content().toString(CharsetUtil.UTF_8);
|
String xml = packet.content().toString(CharsetUtil.UTF_8);
|
||||||
logger.trace("Device replied to discovery with:{}", xml);
|
logger.trace("Device replied to discovery with: {}", xml);
|
||||||
String xAddr = Helper.fetchXML(xml, "", "d:XAddrs>");// Foscam <wsdd:XAddrs> and all other brands <d:XAddrs>
|
String xAddr = Helper.fetchXML(xml, "", "d:XAddrs>");// Foscam <wsdd:XAddrs> and all other brands <d:XAddrs>
|
||||||
if (!xAddr.isEmpty()) {
|
if (!xAddr.isEmpty()) {
|
||||||
searchReply(xAddr, xml);
|
searchReply(xAddr, xml);
|
||||||
|
@ -150,7 +149,7 @@ public class OnvifDiscovery {
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
brand = "onvif";
|
brand = "onvif";
|
||||||
}
|
}
|
||||||
logger.info("Possible {} camera found at:{}", brand, packet.sender().getHostString());
|
logger.debug("Possible {} camera found at: {}", brand, packet.sender().getHostString());
|
||||||
if ("reolink".equals(brand)) {
|
if ("reolink".equals(brand)) {
|
||||||
ipCameraDiscoveryService.newCameraFound(brand, packet.sender().getHostString(), 8000);
|
ipCameraDiscoveryService.newCameraFound(brand, packet.sender().getHostString(), 8000);
|
||||||
} else {
|
} else {
|
||||||
|
@ -200,7 +199,7 @@ public class OnvifDiscovery {
|
||||||
response += temp;
|
response += temp;
|
||||||
}
|
}
|
||||||
reply.close();
|
reply.close();
|
||||||
logger.trace("Cameras Login page is:{}", response);
|
logger.trace("Cameras Login page is: {}", response);
|
||||||
brand = checkForBrand(response);
|
brand = checkForBrand(response);
|
||||||
} catch (MalformedURLException e) {
|
} catch (MalformedURLException e) {
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -22,7 +22,6 @@ import io.netty.handler.codec.http.LastHttpContent;
|
||||||
/**
|
/**
|
||||||
* The {@link NettyRtspHandler} is used to decode RTSP traffic into message Strings.
|
* The {@link NettyRtspHandler} is used to decode RTSP traffic into message Strings.
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* @author Matthew Skinner - Initial contribution
|
* @author Matthew Skinner - Initial contribution
|
||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
|
|
|
@ -43,7 +43,6 @@ import io.netty.handler.timeout.IdleStateHandler;
|
||||||
* The {@link RtspConnection} is a WIP and not currently used, but will talk directly to RTSP and collect information
|
* The {@link RtspConnection} is a WIP and not currently used, but will talk directly to RTSP and collect information
|
||||||
* about the camera and streams.
|
* about the camera and streams.
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* @author Matthew Skinner - Initial contribution
|
* @author Matthew Skinner - Initial contribution
|
||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
|
|
|
@ -109,7 +109,7 @@ public class CameraServlet extends IpCameraServlet {
|
||||||
Ffmpeg localFfmpeg = handler.ffmpegHLS;
|
Ffmpeg localFfmpeg = handler.ffmpegHLS;
|
||||||
if (localFfmpeg == null) {
|
if (localFfmpeg == null) {
|
||||||
handler.setupFfmpegFormat(FFmpegFormat.HLS);
|
handler.setupFfmpegFormat(FFmpegFormat.HLS);
|
||||||
} else if (!localFfmpeg.getIsAlive()) {
|
} else if (!localFfmpeg.isAlive()) {
|
||||||
localFfmpeg.startConverting();
|
localFfmpeg.startConverting();
|
||||||
} else {
|
} else {
|
||||||
localFfmpeg.setKeepAlive(8);
|
localFfmpeg.setKeepAlive(8);
|
||||||
|
|
|
@ -63,7 +63,7 @@ public abstract class IpCameraServlet extends HttpServlet {
|
||||||
httpService.registerServlet("/ipcamera/" + handler.getThing().getUID().getId(), this, initParameters,
|
httpService.registerServlet("/ipcamera/" + handler.getThing().getUID().getId(), this, initParameters,
|
||||||
httpService.createDefaultHttpContext());
|
httpService.createDefaultHttpContext());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.warn("Registering servlet failed:{}", e.getMessage());
|
logger.warn("Registering servlet failed: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,10 +22,8 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
* The {@link OpenStreams} Keeps track of all open mjpeg streams so the byte[] can be given to all FIFO buffers to allow
|
* The {@link OpenStreams} Keeps track of all open mjpeg streams so the byte[] can be given to all FIFO buffers to allow
|
||||||
* 1 to many streams without needing to open more than 1 source stream.
|
* 1 to many streams without needing to open more than 1 source stream.
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* @author Matthew Skinner - Initial contribution
|
* @author Matthew Skinner - Initial contribution
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class OpenStreams {
|
public class OpenStreams {
|
||||||
private List<StreamOutput> openStreams = Collections.synchronizedList(new ArrayList<StreamOutput>());
|
private List<StreamOutput> openStreams = Collections.synchronizedList(new ArrayList<StreamOutput>());
|
||||||
|
|
|
@ -28,7 +28,6 @@ import org.slf4j.LoggerFactory;
|
||||||
*
|
*
|
||||||
* @author Matthew Skinner - Initial contribution
|
* @author Matthew Skinner - Initial contribution
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class StreamOutput {
|
public class StreamOutput {
|
||||||
public final Logger logger = LoggerFactory.getLogger(getClass());
|
public final Logger logger = LoggerFactory.getLogger(getClass());
|
||||||
|
@ -79,7 +78,7 @@ public class StreamOutput {
|
||||||
try {
|
try {
|
||||||
fifo.add(frame);
|
fifo.add(frame);
|
||||||
} catch (IllegalStateException e) {
|
} catch (IllegalStateException e) {
|
||||||
logger.debug("FIFO buffer has run out of space:{}", e.getMessage());
|
logger.debug("FIFO buffer has run out of space: {}", e.getMessage());
|
||||||
fifo.remove();
|
fifo.remove();
|
||||||
fifo.add(frame);
|
fifo.add(frame);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue