Fix IndexOutOfBoundsException and remove Sleep. (#11089)

Signed-off-by: Matthew Skinner <matt@pcmus.com>
This commit is contained in:
Matthew Skinner 2021-08-11 20:02:19 +10:00 committed by GitHub
parent 9f35e7ba31
commit 333e7d2ef2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 158 additions and 141 deletions

View File

@ -768,6 +768,10 @@ public class IpCameraHandler extends BaseThingHandler {
} }
} }
private void openMjpegStream() {
sendHttpGET(mjpegUri);
}
// If start is true the CTX is added to the list to stream video to, false stops // If start is true the CTX is added to the list to stream video to, false stops
// the stream. // the stream.
public void setupMjpegStreaming(boolean start, ChannelHandlerContext ctx) { public void setupMjpegStreaming(boolean start, ChannelHandlerContext ctx) {
@ -777,13 +781,8 @@ public class IpCameraHandler extends BaseThingHandler {
if (mjpegUri.isEmpty() || "ffmpeg".equals(mjpegUri)) { if (mjpegUri.isEmpty() || "ffmpeg".equals(mjpegUri)) {
sendMjpegFirstPacket(ctx); sendMjpegFirstPacket(ctx);
setupFfmpegFormat(FFmpegFormat.MJPEG); setupFfmpegFormat(FFmpegFormat.MJPEG);
} else { } else {// Delay fixes Dahua reboots when refreshing a mjpeg stream.
try { threadPool.schedule(this::openMjpegStream, 500, TimeUnit.MILLISECONDS);
// fix Dahua reboots when refreshing a mjpeg stream.
TimeUnit.MILLISECONDS.sleep(500);
} catch (InterruptedException e) {
}
sendHttpGET(mjpegUri);
} }
} else if (ffmpegMjpeg != null) {// not first stream and we will use ffmpeg } else if (ffmpegMjpeg != null) {// not first stream and we will use ffmpeg
sendMjpegFirstPacket(ctx); sendMjpegFirstPacket(ctx);
@ -1779,7 +1778,6 @@ public class IpCameraHandler extends BaseThingHandler {
public void dispose() { public void dispose() {
isOnline = false; isOnline = false;
snapshotPolling = false; snapshotPolling = false;
onvifCamera.disconnect();
Future<?> localFuture = pollCameraJob; Future<?> localFuture = pollCameraJob;
if (localFuture != null) { if (localFuture != null) {
localFuture.cancel(true); localFuture.cancel(true);
@ -1832,6 +1830,7 @@ public class IpCameraHandler extends BaseThingHandler {
localFfmpeg.stopConverting(); localFfmpeg.stopConverting();
} }
channelTrackingMap.clear(); channelTrackingMap.clear();
onvifCamera.disconnect();
} }
public void setStreamServerHandler(StreamServerHandler streamServerHandler2) { public void setStreamServerHandler(StreamServerHandler streamServerHandler2) {

View File

@ -27,6 +27,8 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.TimeZone; import java.util.TimeZone;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
@ -110,6 +112,7 @@ public class OnvifConnection {
} }
private final Logger logger = LoggerFactory.getLogger(getClass()); private final Logger logger = LoggerFactory.getLogger(getClass());
private ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(2);
private @Nullable Bootstrap bootstrap; private @Nullable Bootstrap bootstrap;
private EventLoopGroup mainEventLoopGroup = new NioEventLoopGroup(); private EventLoopGroup mainEventLoopGroup = new NioEventLoopGroup();
private String ipAddress = ""; private String ipAddress = "";
@ -162,129 +165,138 @@ public class OnvifConnection {
} }
} }
String getXml(RequestType requestType) { private String getXml(RequestType requestType) {
switch (requestType) { try {
case AbsoluteMove: switch (requestType) {
return "<AbsoluteMove xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>" case AbsoluteMove:
+ mediaProfileTokens.get(mediaProfileIndex) + "</ProfileToken><Position><PanTilt x=\"" return "<AbsoluteMove xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>"
+ currentPanCamValue + "\" y=\"" + currentTiltCamValue + mediaProfileTokens.get(mediaProfileIndex) + "</ProfileToken><Position><PanTilt x=\""
+ "\" space=\"http://www.onvif.org/ver10/tptz/PanTiltSpaces/PositionGenericSpace\">\n" + currentPanCamValue + "\" y=\"" + currentTiltCamValue
+ "</PanTilt>\n" + "<Zoom x=\"" + currentZoomCamValue + "\" space=\"http://www.onvif.org/ver10/tptz/PanTiltSpaces/PositionGenericSpace\">\n"
+ "\" space=\"http://www.onvif.org/ver10/tptz/ZoomSpaces/PositionGenericSpace\">\n" + "</PanTilt>\n" + "<Zoom x=\"" + currentZoomCamValue
+ "</Zoom>\n" + "</Position>\n" + "\" space=\"http://www.onvif.org/ver10/tptz/ZoomSpaces/PositionGenericSpace\">\n"
+ "<Speed><PanTilt x=\"0.1\" y=\"0.1\" space=\"http://www.onvif.org/ver10/tptz/PanTiltSpaces/GenericSpeedSpace\"></PanTilt><Zoom x=\"1.0\" space=\"http://www.onvif.org/ver10/tptz/ZoomSpaces/ZoomGenericSpeedSpace\"></Zoom>\n" + "</Zoom>\n" + "</Position>\n"
+ "</Speed></AbsoluteMove>"; + "<Speed><PanTilt x=\"0.1\" y=\"0.1\" space=\"http://www.onvif.org/ver10/tptz/PanTiltSpaces/GenericSpeedSpace\"></PanTilt><Zoom x=\"1.0\" space=\"http://www.onvif.org/ver10/tptz/ZoomSpaces/ZoomGenericSpeedSpace\"></Zoom>\n"
case AddPTZConfiguration: // not tested to work yet + "</Speed></AbsoluteMove>";
return "<AddPTZConfiguration xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>" case AddPTZConfiguration: // not tested to work yet
+ mediaProfileTokens.get(mediaProfileIndex) + "</ProfileToken><ConfigurationToken>" return "<AddPTZConfiguration xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>"
+ ptzConfigToken + "</ConfigurationToken></AddPTZConfiguration>"; + mediaProfileTokens.get(mediaProfileIndex) + "</ProfileToken><ConfigurationToken>"
case ContinuousMoveLeft: + ptzConfigToken + "</ConfigurationToken></AddPTZConfiguration>";
return "<ContinuousMove xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>" case ContinuousMoveLeft:
+ mediaProfileTokens.get(mediaProfileIndex) return "<ContinuousMove xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>"
+ "</ProfileToken><Velocity><PanTilt x=\"-0.5\" y=\"0\" xmlns=\"http://www.onvif.org/ver10/schema\"/></Velocity></ContinuousMove>"; + mediaProfileTokens.get(mediaProfileIndex)
case ContinuousMoveRight: + "</ProfileToken><Velocity><PanTilt x=\"-0.5\" y=\"0\" xmlns=\"http://www.onvif.org/ver10/schema\"/></Velocity></ContinuousMove>";
return "<ContinuousMove xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>" case ContinuousMoveRight:
+ mediaProfileTokens.get(mediaProfileIndex) return "<ContinuousMove xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>"
+ "</ProfileToken><Velocity><PanTilt x=\"0.5\" y=\"0\" xmlns=\"http://www.onvif.org/ver10/schema\"/></Velocity></ContinuousMove>"; + mediaProfileTokens.get(mediaProfileIndex)
case ContinuousMoveUp: + "</ProfileToken><Velocity><PanTilt x=\"0.5\" y=\"0\" xmlns=\"http://www.onvif.org/ver10/schema\"/></Velocity></ContinuousMove>";
return "<ContinuousMove xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>" case ContinuousMoveUp:
+ mediaProfileTokens.get(mediaProfileIndex) return "<ContinuousMove xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>"
+ "</ProfileToken><Velocity><PanTilt x=\"0\" y=\"-0.5\" xmlns=\"http://www.onvif.org/ver10/schema\"/></Velocity></ContinuousMove>"; + mediaProfileTokens.get(mediaProfileIndex)
case ContinuousMoveDown: + "</ProfileToken><Velocity><PanTilt x=\"0\" y=\"-0.5\" xmlns=\"http://www.onvif.org/ver10/schema\"/></Velocity></ContinuousMove>";
return "<ContinuousMove xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>" case ContinuousMoveDown:
+ mediaProfileTokens.get(mediaProfileIndex) return "<ContinuousMove xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>"
+ "</ProfileToken><Velocity><PanTilt x=\"0\" y=\"0.5\" xmlns=\"http://www.onvif.org/ver10/schema\"/></Velocity></ContinuousMove>"; + mediaProfileTokens.get(mediaProfileIndex)
case Stop: + "</ProfileToken><Velocity><PanTilt x=\"0\" y=\"0.5\" xmlns=\"http://www.onvif.org/ver10/schema\"/></Velocity></ContinuousMove>";
return "<Stop xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>" case Stop:
+ mediaProfileTokens.get(mediaProfileIndex) return "<Stop xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>"
+ "</ProfileToken><PanTilt>true</PanTilt><Zoom>true</Zoom></Stop>"; + mediaProfileTokens.get(mediaProfileIndex)
case ContinuousMoveIn: + "</ProfileToken><PanTilt>true</PanTilt><Zoom>true</Zoom></Stop>";
return "<ContinuousMove xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>" case ContinuousMoveIn:
+ mediaProfileTokens.get(mediaProfileIndex) return "<ContinuousMove xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>"
+ "</ProfileToken><Velocity><Zoom x=\"0.5\" xmlns=\"http://www.onvif.org/ver10/schema\"/></Velocity></ContinuousMove>"; + mediaProfileTokens.get(mediaProfileIndex)
case ContinuousMoveOut: + "</ProfileToken><Velocity><Zoom x=\"0.5\" xmlns=\"http://www.onvif.org/ver10/schema\"/></Velocity></ContinuousMove>";
return "<ContinuousMove xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>" case ContinuousMoveOut:
+ mediaProfileTokens.get(mediaProfileIndex) return "<ContinuousMove xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>"
+ "</ProfileToken><Velocity><Zoom x=\"-0.5\" xmlns=\"http://www.onvif.org/ver10/schema\"/></Velocity></ContinuousMove>"; + mediaProfileTokens.get(mediaProfileIndex)
case CreatePullPointSubscription: + "</ProfileToken><Velocity><Zoom x=\"-0.5\" xmlns=\"http://www.onvif.org/ver10/schema\"/></Velocity></ContinuousMove>";
return "<CreatePullPointSubscription xmlns=\"http://www.onvif.org/ver10/events/wsdl\"><InitialTerminationTime>PT600S</InitialTerminationTime></CreatePullPointSubscription>"; case CreatePullPointSubscription:
case GetCapabilities: return "<CreatePullPointSubscription xmlns=\"http://www.onvif.org/ver10/events/wsdl\"><InitialTerminationTime>PT600S</InitialTerminationTime></CreatePullPointSubscription>";
return "<GetCapabilities xmlns=\"http://www.onvif.org/ver10/device/wsdl\"><Category>All</Category></GetCapabilities>"; case GetCapabilities:
return "<GetCapabilities xmlns=\"http://www.onvif.org/ver10/device/wsdl\"><Category>All</Category></GetCapabilities>";
case GetDeviceInformation: case GetDeviceInformation:
return "<GetDeviceInformation xmlns=\"http://www.onvif.org/ver10/device/wsdl\"/>"; return "<GetDeviceInformation xmlns=\"http://www.onvif.org/ver10/device/wsdl\"/>";
case GetProfiles: case GetProfiles:
return "<GetProfiles xmlns=\"http://www.onvif.org/ver10/media/wsdl\"/>"; return "<GetProfiles xmlns=\"http://www.onvif.org/ver10/media/wsdl\"/>";
case GetServiceCapabilities: case GetServiceCapabilities:
return "<GetServiceCapabilities xmlns=\"http://docs.oasis-open.org/wsn/b-2/\"></GetServiceCapabilities>"; return "<GetServiceCapabilities xmlns=\"http://docs.oasis-open.org/wsn/b-2/\"></GetServiceCapabilities>";
case GetSnapshotUri: case GetSnapshotUri:
return "<GetSnapshotUri xmlns=\"http://www.onvif.org/ver10/media/wsdl\"><ProfileToken>" return "<GetSnapshotUri xmlns=\"http://www.onvif.org/ver10/media/wsdl\"><ProfileToken>"
+ mediaProfileTokens.get(mediaProfileIndex) + "</ProfileToken></GetSnapshotUri>"; + mediaProfileTokens.get(mediaProfileIndex) + "</ProfileToken></GetSnapshotUri>";
case GetStreamUri: case GetStreamUri:
return "<GetStreamUri xmlns=\"http://www.onvif.org/ver10/media/wsdl\"><StreamSetup><Stream xmlns=\"http://www.onvif.org/ver10/schema\">RTP-Unicast</Stream><Transport xmlns=\"http://www.onvif.org/ver10/schema\"><Protocol>RTSP</Protocol></Transport></StreamSetup><ProfileToken>" return "<GetStreamUri xmlns=\"http://www.onvif.org/ver10/media/wsdl\"><StreamSetup><Stream xmlns=\"http://www.onvif.org/ver10/schema\">RTP-Unicast</Stream><Transport xmlns=\"http://www.onvif.org/ver10/schema\"><Protocol>RTSP</Protocol></Transport></StreamSetup><ProfileToken>"
+ mediaProfileTokens.get(mediaProfileIndex) + "</ProfileToken></GetStreamUri>"; + mediaProfileTokens.get(mediaProfileIndex) + "</ProfileToken></GetStreamUri>";
case GetSystemDateAndTime: case GetSystemDateAndTime:
return "<GetSystemDateAndTime xmlns=\"http://www.onvif.org/ver10/device/wsdl\"/>"; return "<GetSystemDateAndTime xmlns=\"http://www.onvif.org/ver10/device/wsdl\"/>";
case Subscribe: case Subscribe:
return "<Subscribe xmlns=\"http://docs.oasis-open.org/wsn/b-2/\"><ConsumerReference><Address>http://" return "<Subscribe xmlns=\"http://docs.oasis-open.org/wsn/b-2/\"><ConsumerReference><Address>http://"
+ ipCameraHandler.hostIp + ":" + ipCameraHandler.cameraConfig.getServerPort() + ipCameraHandler.hostIp + ":" + ipCameraHandler.cameraConfig.getServerPort()
+ "/OnvifEvent</Address></ConsumerReference></Subscribe>"; + "/OnvifEvent</Address></ConsumerReference></Subscribe>";
case Unsubscribe: case Unsubscribe:
return "<Unsubscribe xmlns=\"http://docs.oasis-open.org/wsn/b-2/\"></Unsubscribe>"; return "<Unsubscribe xmlns=\"http://docs.oasis-open.org/wsn/b-2/\"></Unsubscribe>";
case PullMessages: case PullMessages:
return "<PullMessages xmlns=\"http://www.onvif.org/ver10/events/wsdl\"><Timeout>PT8S</Timeout><MessageLimit>1</MessageLimit></PullMessages>"; return "<PullMessages xmlns=\"http://www.onvif.org/ver10/events/wsdl\"><Timeout>PT8S</Timeout><MessageLimit>1</MessageLimit></PullMessages>";
case GetEventProperties: case GetEventProperties:
return "<GetEventProperties xmlns=\"http://www.onvif.org/ver10/events/wsdl\"/>"; return "<GetEventProperties xmlns=\"http://www.onvif.org/ver10/events/wsdl\"/>";
case RelativeMoveLeft: case RelativeMoveLeft:
return "<RelativeMove xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>" return "<RelativeMove xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>"
+ mediaProfileTokens.get(mediaProfileIndex) + mediaProfileTokens.get(mediaProfileIndex)
+ "</ProfileToken><Translation><PanTilt x=\"0.05000000\" y=\"0\" xmlns=\"http://www.onvif.org/ver10/schema\"/></Translation></RelativeMove>"; + "</ProfileToken><Translation><PanTilt x=\"0.05000000\" y=\"0\" xmlns=\"http://www.onvif.org/ver10/schema\"/></Translation></RelativeMove>";
case RelativeMoveRight: case RelativeMoveRight:
return "<RelativeMove xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>" return "<RelativeMove xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>"
+ mediaProfileTokens.get(mediaProfileIndex) + mediaProfileTokens.get(mediaProfileIndex)
+ "</ProfileToken><Translation><PanTilt x=\"-0.05000000\" y=\"0\" xmlns=\"http://www.onvif.org/ver10/schema\"/></Translation></RelativeMove>"; + "</ProfileToken><Translation><PanTilt x=\"-0.05000000\" y=\"0\" xmlns=\"http://www.onvif.org/ver10/schema\"/></Translation></RelativeMove>";
case RelativeMoveUp: case RelativeMoveUp:
return "<RelativeMove xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>" return "<RelativeMove xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>"
+ mediaProfileTokens.get(mediaProfileIndex) + mediaProfileTokens.get(mediaProfileIndex)
+ "</ProfileToken><Translation><PanTilt x=\"0\" y=\"0.100000000\" xmlns=\"http://www.onvif.org/ver10/schema\"/></Translation></RelativeMove>"; + "</ProfileToken><Translation><PanTilt x=\"0\" y=\"0.100000000\" xmlns=\"http://www.onvif.org/ver10/schema\"/></Translation></RelativeMove>";
case RelativeMoveDown: case RelativeMoveDown:
return "<RelativeMove xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>" return "<RelativeMove xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>"
+ mediaProfileTokens.get(mediaProfileIndex) + mediaProfileTokens.get(mediaProfileIndex)
+ "</ProfileToken><Translation><PanTilt x=\"0\" y=\"-0.100000000\" xmlns=\"http://www.onvif.org/ver10/schema\"/></Translation></RelativeMove>"; + "</ProfileToken><Translation><PanTilt x=\"0\" y=\"-0.100000000\" xmlns=\"http://www.onvif.org/ver10/schema\"/></Translation></RelativeMove>";
case RelativeMoveIn: case RelativeMoveIn:
return "<RelativeMove xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>" return "<RelativeMove xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>"
+ mediaProfileTokens.get(mediaProfileIndex) + mediaProfileTokens.get(mediaProfileIndex)
+ "</ProfileToken><Translation><Zoom x=\"0.0240506344\" xmlns=\"http://www.onvif.org/ver10/schema\"/></Translation></RelativeMove>"; + "</ProfileToken><Translation><Zoom x=\"0.0240506344\" xmlns=\"http://www.onvif.org/ver10/schema\"/></Translation></RelativeMove>";
case RelativeMoveOut: case RelativeMoveOut:
return "<RelativeMove xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>" return "<RelativeMove xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>"
+ mediaProfileTokens.get(mediaProfileIndex) + mediaProfileTokens.get(mediaProfileIndex)
+ "</ProfileToken><Translation><Zoom x=\"-0.0240506344\" xmlns=\"http://www.onvif.org/ver10/schema\"/></Translation></RelativeMove>"; + "</ProfileToken><Translation><Zoom x=\"-0.0240506344\" xmlns=\"http://www.onvif.org/ver10/schema\"/></Translation></RelativeMove>";
case Renew: case Renew:
return "<Renew xmlns=\"http://docs.oasis-open.org/wsn/b-2\"><TerminationTime>PT1M</TerminationTime></Renew>"; return "<Renew xmlns=\"http://docs.oasis-open.org/wsn/b-2\"><TerminationTime>PT1M</TerminationTime></Renew>";
case GetConfigurations: case GetConfigurations:
return "<GetConfigurations xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"></GetConfigurations>"; return "<GetConfigurations xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"></GetConfigurations>";
case GetConfigurationOptions: case GetConfigurationOptions:
return "<GetConfigurationOptions xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ConfigurationToken>" return "<GetConfigurationOptions xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ConfigurationToken>"
+ ptzConfigToken + "</ConfigurationToken></GetConfigurationOptions>"; + ptzConfigToken + "</ConfigurationToken></GetConfigurationOptions>";
case GetConfiguration: case GetConfiguration:
return "<GetConfiguration xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><PTZConfigurationToken>" return "<GetConfiguration xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><PTZConfigurationToken>"
+ ptzConfigToken + "</PTZConfigurationToken></GetConfiguration>"; + ptzConfigToken + "</PTZConfigurationToken></GetConfiguration>";
case SetConfiguration:// not tested to work yet case SetConfiguration:// not tested to work yet
return "<SetConfiguration xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><PTZConfiguration><NodeToken>" return "<SetConfiguration xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><PTZConfiguration><NodeToken>"
+ ptzNodeToken + ptzNodeToken
+ "</NodeToken><DefaultAbsolutePantTiltPositionSpace>AbsolutePanTiltPositionSpace</DefaultAbsolutePantTiltPositionSpace><DefaultAbsoluteZoomPositionSpace>AbsoluteZoomPositionSpace</DefaultAbsoluteZoomPositionSpace></PTZConfiguration></SetConfiguration>"; + "</NodeToken><DefaultAbsolutePantTiltPositionSpace>AbsolutePanTiltPositionSpace</DefaultAbsolutePantTiltPositionSpace><DefaultAbsoluteZoomPositionSpace>AbsoluteZoomPositionSpace</DefaultAbsoluteZoomPositionSpace></PTZConfiguration></SetConfiguration>";
case GetNodes: case GetNodes:
return "<GetNodes xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"></GetNodes>"; return "<GetNodes xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"></GetNodes>";
case GetStatus: case GetStatus:
return "<GetStatus xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>" return "<GetStatus xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>"
+ mediaProfileTokens.get(mediaProfileIndex) + "</ProfileToken></GetStatus>"; + mediaProfileTokens.get(mediaProfileIndex) + "</ProfileToken></GetStatus>";
case GotoPreset: case GotoPreset:
return "<GotoPreset xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>" return "<GotoPreset xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>"
+ mediaProfileTokens.get(mediaProfileIndex) + "</ProfileToken><PresetToken>" + mediaProfileTokens.get(mediaProfileIndex) + "</ProfileToken><PresetToken>"
+ presetTokens.get(presetTokenIndex) + "</PresetToken></GotoPreset>"; + presetTokens.get(presetTokenIndex) + "</PresetToken></GotoPreset>";
case GetPresets: case GetPresets:
return "<GetPresets xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>" return "<GetPresets xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>"
+ mediaProfileTokens.get(mediaProfileIndex) + "</ProfileToken></GetPresets>"; + mediaProfileTokens.get(mediaProfileIndex) + "</ProfileToken></GetPresets>";
}
} catch (IndexOutOfBoundsException e) {
if (!isConnected) {
logger.debug("IndexOutOfBoundsException occured, camera is not connected via ONVIF: {}",
e.getMessage());
} else {
logger.debug("IndexOutOfBoundsException occured, {}", e.getMessage());
}
} }
return "notfound"; return "notfound";
} }
@ -805,6 +817,10 @@ public class OnvifConnection {
} }
public void sendPTZRequest(RequestType requestType) { public void sendPTZRequest(RequestType requestType) {
if (!isConnected) {
logger.debug("ONVIF was not connected when a PTZ request was made, connecting now");
connect(usingEvents);
}
sendOnvifRequest(requestBuilder(requestType, ptzXAddr)); sendOnvifRequest(requestBuilder(requestType, ptzXAddr));
} }
@ -823,26 +839,28 @@ public class OnvifConnection {
return isConnected; return isConnected;
} }
public void disconnect() { private void cleanup() {
if (usingEvents && isConnected) { mainEventLoopGroup.shutdownGracefully();
sendOnvifRequest(requestBuilder(RequestType.Unsubscribe, subscriptionXAddr));
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
}
isConnected = false; isConnected = false;
presetTokens.clear();
mediaProfileTokens.clear();
if (!mainEventLoopGroup.isShutdown()) { if (!mainEventLoopGroup.isShutdown()) {
try { try {
mainEventLoopGroup.awaitTermination(3, TimeUnit.SECONDS); mainEventLoopGroup.awaitTermination(3, TimeUnit.SECONDS);
} catch (InterruptedException e) { } catch (InterruptedException e) {
logger.info("Onvif was not shutdown correctly due to being interrupted"); logger.warn("ONVIF was not cleanly shutdown, due to being interrupted");
} finally { } finally {
logger.debug("Eventloop is shutdown:{}", mainEventLoopGroup.isShutdown());
mainEventLoopGroup = new NioEventLoopGroup(); mainEventLoopGroup = new NioEventLoopGroup();
bootstrap = null; bootstrap = null;
} }
} }
threadPool.shutdown();
}
public void disconnect() {
if (usingEvents && isConnected && !mainEventLoopGroup.isShuttingDown()) {
sendOnvifRequest(requestBuilder(RequestType.Unsubscribe, subscriptionXAddr));
}
// Some cameras may continue to send event callbacks even when they cant reach a server.
threadPool.schedule(this::cleanup, 500, TimeUnit.MILLISECONDS);
} }
} }