From 565acaefb53e860ec8796cfdf2ef45c24f13b605 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Mon, 29 Jan 2024 12:32:35 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=B4=E6=97=B6=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gb28181/GB28181ResourceServiceImpl.java | 114 +++++++++++++----- .../gb28181/transmit/cmd/ISIPCommander.java | 4 +- .../transmit/cmd/impl/SIPCommander.java | 1 + .../cmd/DeviceControlQueryMessageHandler.java | 44 +++++-- .../iot/vmp/gb28181/utils/SipUtils.java | 33 +++++ .../vmp/media/zlm/ZLMHttpHookListener.java | 2 +- .../iot/vmp/service/IResourceService.java | 10 +- .../service/impl/MediaServerServiceImpl.java | 2 +- .../impl/StreamProxyResourceServiceImpl.java | 3 +- .../impl/StreamPushResourceServiceImpl.java | 3 +- 10 files changed, 159 insertions(+), 57 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/GB28181ResourceServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/gb28181/GB28181ResourceServiceImpl.java index d18049cd..ec19918c 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/GB28181ResourceServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/GB28181ResourceServiceImpl.java @@ -5,6 +5,9 @@ import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.conf.exception.ControllerException; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; +import com.genersoft.iot.vmp.gb28181.bean.command.PTZCommand; +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; +import com.genersoft.iot.vmp.gb28181.utils.SipUtils; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.service.IPlayService; import com.genersoft.iot.vmp.service.IResourcePlayCallback; @@ -14,11 +17,16 @@ import com.genersoft.iot.vmp.service.bean.InviteErrorCode; import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper; import com.genersoft.iot.vmp.storager.dao.DeviceMapper; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; +import org.aspectj.bridge.ICommand; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import javax.sip.InvalidArgumentException; +import javax.sip.SipException; +import java.text.ParseException; + /** * 国标的资源实现类 @@ -37,6 +45,9 @@ public class GB28181ResourceServiceImpl implements IResourceService { @Autowired private IPlayService playService; + @Autowired + private ISIPCommander commander; + @Override public boolean deleteChannel(CommonGbChannel commonGbChannel) { if (!CommonGbChannelType.GB28181.equals(commonGbChannel.getType())) { @@ -49,26 +60,19 @@ public class GB28181ResourceServiceImpl implements IResourceService { @Override public void startPlay(CommonGbChannel commonGbChannel, IResourcePlayCallback callback) { assert callback != null; - if (!CommonGbChannelType.GB28181.equals(commonGbChannel.getType())) { - logger.warn("[资源类-国标28181] 收到播放通道: {} 时发现类型不为28181", commonGbChannel.getCommonGbId()); - callback.call(commonGbChannel, null, ErrorCode.ERROR100.getCode(), "数据关系错误", null); + CheckCommonGbChannelResult checkResult = checkCommonGbChannel(commonGbChannel); + + if (checkResult.errorMsg != null) { + callback.call(commonGbChannel, null, ErrorCode.SUCCESS.getCode(), checkResult.errorMsg, null); return; } - DeviceChannel channel = deviceChannelMapper.getChannelByCommonChannelId(commonGbChannel.getCommonGbId()); - if (channel == null) { - logger.warn("[资源类-国标28181] 收到播放通道: {} 时未找到国标通道", commonGbChannel.getCommonGbId()); - callback.call(commonGbChannel, null, ErrorCode.ERROR100.getCode(), "未找到通道", null); + if (checkResult.device == null || checkResult.channel == null) { + callback.call(commonGbChannel, null, ErrorCode.SUCCESS.getCode(), "设备获取失败", null); return; } - Device device = deviceMapper.getDeviceByDeviceId(channel.getDeviceId()); - if (device == null) { - logger.warn("[资源类-国标28181] 收到播放通道: {} 时未找到通道 {} 所属的国标设备", - commonGbChannel.getCommonGbId(), channel.getDeviceId()); - callback.call(commonGbChannel, null, ErrorCode.ERROR100.getCode(), "未找到设备", null); - return; - } - MediaServerItem mediaServerItem = playService.getNewMediaServerItem(device); - playService.play(mediaServerItem, channel.getDeviceId(), channel.getChannelId(), null, (code, msg, data) -> { + + MediaServerItem mediaServerItem = playService.getNewMediaServerItem(checkResult.device); + playService.play(mediaServerItem, checkResult.channel.getDeviceId(), checkResult.channel.getChannelId(), null, (code, msg, data) -> { if (code == InviteErrorCode.SUCCESS.getCode()) { StreamInfo streamInfo = (StreamInfo)data; callback.call(commonGbChannel, mediaServerItem, ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo); @@ -80,23 +84,18 @@ public class GB28181ResourceServiceImpl implements IResourceService { @Override public void stopPlay(CommonGbChannel commonGbChannel, IResourcePlayCallback callback) { - if (!CommonGbChannelType.GB28181.equals(commonGbChannel.getType())) { - logger.warn("[资源类-国标28181] 收到停止播放通道: {} 时发现类型不为28181", commonGbChannel.getCommonGbId()); - if (callback != null) { - callback.call(commonGbChannel,null, ErrorCode.ERROR100.getCode(), "数据关系错误", null); - } + CheckCommonGbChannelResult checkResult = checkCommonGbChannel(commonGbChannel); + + if (checkResult.errorMsg != null) { + callback.call(commonGbChannel, null, ErrorCode.SUCCESS.getCode(), checkResult.errorMsg, null); return; } - DeviceChannel channel = deviceChannelMapper.getChannelByCommonChannelId(commonGbChannel.getCommonGbId()); - if (channel == null) { - logger.warn("[资源类-国标28181] 收到停止播放通道: {} 时未找到国标通道", commonGbChannel.getCommonGbId()); - if (callback != null) { - callback.call(commonGbChannel, null, ErrorCode.ERROR100.getCode(), "未找到通道", null); - } + if (checkResult.device == null || checkResult.channel == null) { + callback.call(commonGbChannel, null, ErrorCode.SUCCESS.getCode(), "设备获取失败", null); return; } try { - playService.stop(channel.getDeviceId(), channel.getChannelId()); + playService.stop(checkResult.channel.getDeviceId(), checkResult.channel.getChannelId()); } catch (ControllerException exception) { if (callback != null) { callback.call(commonGbChannel, null,exception.getCode(), exception.getMsg(), null); @@ -105,9 +104,22 @@ public class GB28181ResourceServiceImpl implements IResourceService { } @Override - public boolean ptzControl(CommonGbChannel commonGbChannel, - String command, Integer horizonSpeed, - Integer verticalSpeed, Integer zoomSpeed) { + public boolean ptzControl(CommonGbChannel commonGbChannel, PTZCommand ptzCommand) { + CheckCommonGbChannelResult checkResult = checkCommonGbChannel(commonGbChannel); + + if (checkResult.errorMsg != null) { + logger.warn("[资源类-国标28181] 云台控制失败: {}", checkResult.errorMsg); + return false; + } + if (checkResult.device == null || checkResult.channel == null) { + logger.warn("[资源类-国标28181] 云台控制失败: 设备获取失败"); + return false; + } + try { + commander.ptzCmd(checkResult.device, checkResult.channel.getChannelId(), ptzCommand); + } catch (InvalidArgumentException | SipException | ParseException e) { + logger.error("[命令发送失败]: ", e); + } return false; } @@ -125,4 +137,44 @@ public class GB28181ResourceServiceImpl implements IResourceService { public void startDownload(CommonGbChannel channel, Long startTime, Long stopTime, Integer downloadSpeed, IResourcePlayCallback playCallback) { } + + static class CheckCommonGbChannelResult { + Device device; + + DeviceChannel channel; + + String errorMsg; + + public CheckCommonGbChannelResult(String errorMsg) { + this.errorMsg = errorMsg; + } + + public CheckCommonGbChannelResult(Device device, DeviceChannel channel) { + this.device = device; + this.channel = channel; + } + } + + private CheckCommonGbChannelResult checkCommonGbChannel(CommonGbChannel commonGbChannel) { + if (commonGbChannel == null) { + logger.warn("[资源类-检验参数] 通道不可为NULL"); + return new CheckCommonGbChannelResult("通道不可为NULL"); + } + if (!CommonGbChannelType.GB28181.equals(commonGbChannel.getType())) { + logger.warn("[资源类-国标28181] 收到通道: {} 时发现类型不为28181", commonGbChannel.getCommonGbId()); + return new CheckCommonGbChannelResult("数据关系错误"); + } + DeviceChannel channel = deviceChannelMapper.getChannelByCommonChannelId(commonGbChannel.getCommonGbId()); + if (channel == null) { + logger.warn("[资源类-国标28181] 收到通道: {} 时未找到国标通道", commonGbChannel.getCommonGbId()); + return new CheckCommonGbChannelResult("未找到通道"); + } + Device device = deviceMapper.getDeviceByDeviceId(channel.getDeviceId()); + if (device == null) { + logger.warn("[资源类-国标28181] 收到通道: {} 时未找到通道 {} 所属的国标设备", + commonGbChannel.getCommonGbId(), channel.getDeviceId()); + return new CheckCommonGbChannelResult("未找到设备"); + } + return new CheckCommonGbChannelResult(device, channel); + } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java index ebf53d4b..80d5ee5f 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java @@ -4,6 +4,7 @@ import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm; +import com.genersoft.iot.vmp.gb28181.bean.command.PTZCommand; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; @@ -72,7 +73,8 @@ public interface ISIPCommander { * @param zoomSpeed 镜头缩放速度 */ void ptzCmd(Device device,String channelId,int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed) throws InvalidArgumentException, SipException, ParseException; - + void ptzCmd(Device device, String channelId, PTZCommand ptzCommand) throws InvalidArgumentException, SipException, ParseException; + /** * 前端控制,包括PTZ指令、FI指令、预置位指令、巡航指令、扫描指令和辅助开关指令 * diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java index 25f5bf14..48c1bfb0 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java @@ -9,6 +9,7 @@ import com.genersoft.iot.vmp.gb28181.SipLayer; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm; import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction; +import com.genersoft.iot.vmp.gb28181.bean.command.PTZCommand; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; import com.genersoft.iot.vmp.gb28181.transmit.SIPSender; diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/control/cmd/DeviceControlQueryMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/control/cmd/DeviceControlQueryMessageHandler.java index 3dc19cb2..de31422c 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/control/cmd/DeviceControlQueryMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/control/cmd/DeviceControlQueryMessageHandler.java @@ -2,10 +2,10 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.contro import com.genersoft.iot.vmp.common.CommonGbChannel; import com.genersoft.iot.vmp.common.enums.DeviceControlType; -import com.genersoft.iot.vmp.gb28181.bean.Device; -import com.genersoft.iot.vmp.gb28181.bean.DragZoomRequest; -import com.genersoft.iot.vmp.gb28181.bean.HomePositionRequest; -import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; +import com.genersoft.iot.vmp.gb28181.bean.*; +import com.genersoft.iot.vmp.gb28181.bean.command.CommandType; +import com.genersoft.iot.vmp.gb28181.bean.command.ICommandInfo; +import com.genersoft.iot.vmp.gb28181.bean.command.PTZCommand; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; @@ -143,18 +143,36 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent } return; } - // 解析云台控制参数 - -// resourceService.ptzControl(commonGbChannel) String cmdString = getText(rootElement, type.getVal()); - byte[] bytes = cmdString.getBytes(); - System.out.println(cmdString); - for (byte aByte : bytes) { - System.out.print(aByte); - System.out.print(" "); + // 解析云台控制参数 + ICommandInfo commandInfo = ControlCommand.analysisCommand(cmdString); + if (commandInfo == null || !commandInfo.getType().equals(CommandType.PTZ)) { + try { + responseAck(request, Response.OK); + } catch (SipException | InvalidArgumentException | ParseException e) { + logger.error("[命令发送失败] 错误信息: {}", e.getMessage()); + } + return; } - System.out.println(" "); + PTZCommand ptzCommand = (PTZCommand)commandInfo; + logger.info("\r\n[云台控制]: \r\n镜头变倍: 放大: {},缩小: {}, " + + " \r\n垂直方向控制: 上: {}, 下: {}, 左: {},右: {}" + + " \r\n平控制速度相对值: {}, 垂直控制速度相对值: {}, 变倍控制速度相对值: {}", + ptzCommand.isIn(), ptzCommand.isOut(), + ptzCommand.isUp(), ptzCommand.isDown(), ptzCommand.isLeft(), ptzCommand.isRight(), + ptzCommand.getxSpeed(), ptzCommand.getySpeed(), ptzCommand.getzSpeed()); + + resourceService.ptzControl(commonGbChannel, ptzCommand); + +// System.out.println(); +// byte[] bytes = cmdString.getBytes(); +// System.out.println(cmdString); +// for (byte aByte : bytes) { +// System.out.print(aByte); +// System.out.print(" "); +// } +// System.out.println(" "); // try { // cmder.fronEndCmd(device, channelId, cmdString, // errorResult -> onError(request, errorResult), diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/SipUtils.java b/src/main/java/com/genersoft/iot/vmp/gb28181/utils/SipUtils.java index 65f26ce0..cda0694c 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/SipUtils.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/utils/SipUtils.java @@ -1,6 +1,7 @@ package com.genersoft.iot.vmp.gb28181.utils; import com.genersoft.iot.vmp.gb28181.bean.*; +import com.genersoft.iot.vmp.gb28181.bean.command.PTZCommand; import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.utils.GitUtil; import gov.nist.javax.sdp.TimeDescriptionImpl; @@ -143,6 +144,38 @@ public class SipUtils { return builder.toString(); } + public static String cmdString(PTZCommand command) { + int byte4Int = 0; + if (command.isRight()) { + byte4Int += 1; + } + if (command.isLeft()) { + byte4Int += 2; + } + if (command.isDown()) { + byte4Int += 4; + } + if (command.isUp()) { + byte4Int += 8; + } + if (command.isIn()) { + byte4Int += 16; + } + if (command.isOut()) { + byte4Int += 32; + } + StringBuilder builder = new StringBuilder("A50F01"); + builder.append(Integer.toHexString(byte4Int), 0, 2); + builder.append(Integer.toHexString(command.getxSpeed()), 0, 2); + builder.append(Integer.toHexString(command.getySpeed()), 0, 2); + builder.append(Integer.toHexString(command.getzSpeed()), 0, 1); + + //计算校验码 + int checkCode = (0XA5 + 0X0F + 0X01 + byte4Int + command.getxSpeed() + command.getySpeed() + (command.getzSpeed() /*<< 4*/ & 0XF0)) % 0X100; + builder.append(String.format("%02X", checkCode), 0, 2); + return builder.toString(); + } + /** * 从请求中获取设备ip地址和端口号 * @param request 请求 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java index 99e7be8c..00676f6b 100755 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java @@ -498,7 +498,7 @@ public class ZLMHttpHookListener { } // 收到无人观看说明流也没有在往上级推送 List sendRtpItems = streamSendManager.getByByChanelId(inviteInfo.getChannelId()); - if (!sendRtpItems.isEmpty()) { + if (sendRtpItems != null && !sendRtpItems.isEmpty()) { for (SendRtpItem sendRtpItem : sendRtpItems) { ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getDestId()); try { diff --git a/src/main/java/com/genersoft/iot/vmp/service/IResourceService.java b/src/main/java/com/genersoft/iot/vmp/service/IResourceService.java index 00befa24..365ecc2b 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/IResourceService.java +++ b/src/main/java/com/genersoft/iot/vmp/service/IResourceService.java @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.service; import com.genersoft.iot.vmp.common.CommonGbChannel; import com.genersoft.iot.vmp.common.StreamInfo; +import com.genersoft.iot.vmp.gb28181.bean.command.PTZCommand; /** * 同用资源接入接口,待接入的资源实现此接口即可自动接入, @@ -28,15 +29,8 @@ public interface IResourceService { /** * 云台控制 - * @param commonGbChannel 通道 - * @param command 控制指令,允许值: left, right, up, down, upleft, upright, downleft, downright, zoomin, zoomout, stop - * @param horizonSpeed 水平速度 0-255 - * @param verticalSpeed 垂直速度 0-255 - * @param zoomSpeed 缩放速度 - * @return 结果 */ - boolean ptzControl(CommonGbChannel commonGbChannel, String command, - Integer horizonSpeed, Integer verticalSpeed, Integer zoomSpeed); + boolean ptzControl(CommonGbChannel commonGbChannel, PTZCommand ptzCommand); /** * 流离线 diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java index 8ad3fd46..aa2b8252 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java @@ -201,7 +201,7 @@ public class MediaServerServiceImpl implements IMediaServerService { @Override public void closeRTPServer(String mediaServerId, String streamId) { MediaServerItem mediaServerItem = this.getOne(mediaServerId); - if (mediaServerItem.isRtpEnable()) { + if (mediaServerItem != null && mediaServerItem.isRtpEnable()) { closeRTPServer(mediaServerItem, streamId); } zlmresTfulUtils.closeStreams(mediaServerItem, "rtp", streamId); diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyResourceServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyResourceServiceImpl.java index eb6ce815..f503c498 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyResourceServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyResourceServiceImpl.java @@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.service.impl; import com.genersoft.iot.vmp.common.CommonGbChannel; import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.gb28181.GB28181ResourceServiceImpl; +import com.genersoft.iot.vmp.gb28181.bean.command.PTZCommand; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.StreamProxy; import com.genersoft.iot.vmp.service.*; @@ -75,7 +76,7 @@ public class StreamProxyResourceServiceImpl implements IResourceService { } @Override - public boolean ptzControl(CommonGbChannel commonGbChannel, String command, Integer horizonSpeed, Integer verticalSpeed, Integer zoomSpeed) { + public boolean ptzControl(CommonGbChannel commonGbChannel, PTZCommand ptzCommand) { return false; } diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushResourceServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushResourceServiceImpl.java index de918b9d..2dec3457 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushResourceServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushResourceServiceImpl.java @@ -1,6 +1,7 @@ package com.genersoft.iot.vmp.service.impl; import com.genersoft.iot.vmp.common.CommonGbChannel; +import com.genersoft.iot.vmp.gb28181.bean.command.PTZCommand; import com.genersoft.iot.vmp.service.IResourcePlayCallback; import com.genersoft.iot.vmp.service.IResourceService; import com.genersoft.iot.vmp.service.bean.CommonGbChannelType; @@ -24,7 +25,7 @@ public class StreamPushResourceServiceImpl implements IResourceService { } @Override - public boolean ptzControl(CommonGbChannel commonGbChannel, String command, Integer horizonSpeed, Integer verticalSpeed, Integer zoomSpeed) { + public boolean ptzControl(CommonGbChannel commonGbChannel, PTZCommand ptzCommand) { return false; }