Commit 2ff3cdb6a1550941dbd36585749499064db4f8d5

Authored by 648540858
2 parents d7a1b94f 30979eb6

Merge branch 'wvp-28181-2.0'

# Conflicts:
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java
#	src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
#	src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
Showing 75 changed files with 3188 additions and 3471 deletions
src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java
... ... @@ -2,6 +2,9 @@ package com.genersoft.iot.vmp.conf;
2 2  
3 3 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
4 4 import com.genersoft.iot.vmp.utils.DateUtil;
  5 +import com.genersoft.iot.vmp.vmanager.gb28181.device.DeviceQuery;
  6 +import org.slf4j.Logger;
  7 +import org.slf4j.LoggerFactory;
5 8 import org.springframework.beans.factory.annotation.Value;
6 9 import org.springframework.context.annotation.Configuration;
7 10 import org.springframework.util.ObjectUtils;
... ... @@ -15,6 +18,8 @@ import java.util.regex.Pattern;
15 18 @Configuration("mediaConfig")
16 19 public class MediaConfig{
17 20  
  21 + private final static Logger logger = LoggerFactory.getLogger(MediaConfig.class);
  22 +
18 23 // 修改必须配置,不再支持自动获取
19 24 @Value("${media.id}")
20 25 private String id;
... ... @@ -174,7 +179,7 @@ public class MediaConfig{
174 179 try {
175 180 hostAddress = InetAddress.getByName(sdpIp).getHostAddress();
176 181 } catch (UnknownHostException e) {
177   - throw new RuntimeException(e);
  182 + logger.error("[获取SDP IP]: 域名解析失败");
178 183 }
179 184 return hostAddress;
180 185 }
... ...
src/main/java/com/genersoft/iot/vmp/conf/SystemInfoTimerTask.java
1 1 package com.genersoft.iot.vmp.conf;
2 2  
  3 +import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.cmd.AlarmQueryMessageHandler;
3 4 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
4 5 import com.genersoft.iot.vmp.utils.SystemInfoUtils;
  6 +import org.slf4j.Logger;
  7 +import org.slf4j.LoggerFactory;
5 8 import org.springframework.beans.factory.annotation.Autowired;
6 9 import org.springframework.scheduling.annotation.Scheduled;
7 10 import org.springframework.stereotype.Component;
... ... @@ -14,6 +17,8 @@ import java.util.Map;
14 17 @Component
15 18 public class SystemInfoTimerTask {
16 19  
  20 + private Logger logger = LoggerFactory.getLogger(SystemInfoTimerTask.class);
  21 +
17 22 @Autowired
18 23 private IRedisCatchStorage redisCatchStorage;
19 24  
... ... @@ -27,7 +32,7 @@ public class SystemInfoTimerTask {
27 32 Map<String, String> networkInterfaces = SystemInfoUtils.getNetworkInterfaces();
28 33 redisCatchStorage.addNetInfo(networkInterfaces);
29 34 } catch (InterruptedException e) {
30   - e.printStackTrace();
  35 + logger.error("[获取系统信息失败] {}", e.getMessage());
31 36 }
32 37  
33 38 }
... ...
src/main/java/com/genersoft/iot/vmp/conf/VersionInfo.java
... ... @@ -2,35 +2,23 @@ package com.genersoft.iot.vmp.conf;
2 2  
3 3 import com.genersoft.iot.vmp.common.VersionPo;
4 4 import com.genersoft.iot.vmp.utils.GitUtil;
5   -import com.genersoft.iot.vmp.utils.JarFileUtils;
6 5 import org.springframework.beans.factory.annotation.Autowired;
7 6 import org.springframework.stereotype.Component;
8 7  
9   -import java.util.Map;
10   -
11 8 @Component
12 9 public class VersionInfo {
13 10  
14 11 @Autowired
15   - VersionConfig config;
16   - @Autowired
17 12 GitUtil gitUtil;
18   - @Autowired
19   - JarFileUtils jarFileUtils;
20 13  
21 14 public VersionPo getVersion() {
22 15 VersionPo versionPo = new VersionPo();
23   - Map<String,String> map=jarFileUtils.readJarFile();
24 16 versionPo.setGIT_Revision(gitUtil.getGitCommitId());
25   - versionPo.setCreate_By(map.get("Created-By"));
26 17 versionPo.setGIT_BRANCH(gitUtil.getBranch());
27 18 versionPo.setGIT_URL(gitUtil.getGitUrl());
28 19 versionPo.setBUILD_DATE(gitUtil.getBuildDate());
29   - versionPo.setArtifactId(config.getArtifactId());
30 20 versionPo.setGIT_Revision_SHORT(gitUtil.getCommitIdShort());
31   - versionPo.setVersion(config.getVersion());
32   - versionPo.setProject(config.getDescription());
33   - versionPo.setBuild_Jdk(map.get("Build-Jdk"));
  21 + versionPo.setVersion(gitUtil.getBuildVersion());
34 22  
35 23 return versionPo;
36 24 }
... ...
src/main/java/com/genersoft/iot/vmp/conf/exception/SsrcTransactionNotFoundException.java 0 → 100644
  1 +package com.genersoft.iot.vmp.conf.exception;
  2 +
  3 +import com.sun.javafx.binding.StringFormatter;
  4 +
  5 +/**
  6 + * @author lin
  7 + */
  8 +public class SsrcTransactionNotFoundException extends Exception{
  9 + private String deviceId;
  10 + private String channelId;
  11 + private String callId;
  12 + private String stream;
  13 +
  14 +
  15 +
  16 + public SsrcTransactionNotFoundException(String deviceId, String channelId, String callId, String stream) {
  17 + this.deviceId = deviceId;
  18 + this.channelId = channelId;
  19 + this.callId = callId;
  20 + this.stream = stream;
  21 + }
  22 +
  23 + public String getDeviceId() {
  24 + return deviceId;
  25 + }
  26 +
  27 + public String getChannelId() {
  28 + return channelId;
  29 + }
  30 +
  31 + public String getCallId() {
  32 + return callId;
  33 + }
  34 +
  35 + public String getStream() {
  36 + return stream;
  37 + }
  38 +
  39 + @Override
  40 + public String getMessage() {
  41 + StringBuffer msg = new StringBuffer();
  42 + msg.append(StringFormatter.format("缓存事务信息未找到,device:%s channel: %s ", deviceId, channelId));
  43 + if (callId != null) {
  44 + msg.append("callId: " + callId);
  45 + }
  46 + if (stream != null) {
  47 + msg.append("stream: " + stream);
  48 + }
  49 + return msg.toString();
  50 + }
  51 +}
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java
... ... @@ -41,7 +41,7 @@ public class SipLayer{
41 41  
42 42 @Bean("sipStack")
43 43 @DependsOn({"sipFactory"})
44   - SipStack createSipStack() throws PeerUnavailableException {
  44 + SipStackImpl createSipStack() throws PeerUnavailableException {
45 45 sipStack = ( SipStackImpl )sipFactory.createSipStack(DefaultProperties.getProperties(sipConfig.getMonitorIp(), false));
46 46 return sipStack;
47 47 }
... ... @@ -56,7 +56,6 @@ public class SipLayer{
56 56 tcpSipProvider = (SipProviderImpl)sipStack.createSipProvider(tcpListeningPoint);
57 57 tcpSipProvider.setDialogErrorsAutomaticallyHandled();
58 58 tcpSipProvider.addSipListener(sipProcessorObserver);
59   -// tcpSipProvider.setAutomaticDialogSupportEnabled(false);
60 59 logger.info("[Sip Server] TCP 启动成功 {}:{}", sipConfig.getMonitorIp(), sipConfig.getPort());
61 60 } catch (TransportNotSupportedException e) {
62 61 e.printStackTrace();
... ... @@ -80,7 +79,6 @@ public class SipLayer{
80 79 udpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getPort(), "UDP");
81 80 udpSipProvider = (SipProviderImpl)sipStack.createSipProvider(udpListeningPoint);
82 81 udpSipProvider.addSipListener(sipProcessorObserver);
83   -// udpSipProvider.setAutomaticDialogSupportEnabled(false);
84 82 } catch (TransportNotSupportedException e) {
85 83 e.printStackTrace();
86 84 } catch (InvalidArgumentException e) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/auth/RegisterLogicHandler.java deleted 100644 → 0
1   -package com.genersoft.iot.vmp.gb28181.auth;
2   -
3   -import com.genersoft.iot.vmp.storager.impl.VideoManagerStorageImpl;
4   -import org.slf4j.Logger;
5   -import org.slf4j.LoggerFactory;
6   -import org.springframework.beans.factory.annotation.Autowired;
7   -import org.springframework.stereotype.Component;
8   -
9   -import com.genersoft.iot.vmp.gb28181.bean.Device;
10   -import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
11   -
12   -/**
13   - * @description:注册逻辑处理,当设备注册后触发逻辑。
14   - * @author: swwheihei
15   - * @date: 2020年5月8日 下午9:41:46
16   - */
17   -@Component
18   -public class RegisterLogicHandler {
19   -
20   - private Logger logger = LoggerFactory.getLogger(RegisterLogicHandler.class);
21   -
22   - @Autowired
23   - private SIPCommander cmder;
24   -
25   - @Autowired
26   - private VideoManagerStorageImpl storager;
27   -
28   - public void onRegister(Device device) {
29   - // 只有第一次注册时调用查询设备信息,如需更新调用更新API接口
30   -// // TODO 此处错误无法获取到通道
31   -// Device device1 = storager.queryVideoDevice(device.getDeviceId());
32   -// if (device.isFirsRegister()) {
33   -// logger.info("[{}] 首次注册,查询设备信息以及通道信息", device.getDeviceId());
34   -// try {
35   -// Thread.sleep(100);
36   -// cmder.deviceInfoQuery(device);
37   -// Thread.sleep(100);
38   -// cmder.catalogQuery(device, null);
39   -// } catch (InterruptedException e) {
40   -// e.printStackTrace();
41   -// }
42   -// }
43   - }
44   -}
src/main/java/com/genersoft/iot/vmp/gb28181/bean/CmdSendFailEvent.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.bean;
  2 +
  3 +import javax.sip.Dialog;
  4 +import java.util.EventObject;
  5 +
  6 +public class CmdSendFailEvent extends EventObject {
  7 +
  8 + private String callId;
  9 +
  10 + /**
  11 + * Constructs a prototypical Event.
  12 + *
  13 + * @param dialog
  14 + * @throws IllegalArgumentException if source is null.
  15 + */
  16 + public CmdSendFailEvent(Dialog dialog) {
  17 + super(dialog);
  18 + }
  19 +
  20 + public String getCallId() {
  21 + return callId;
  22 + }
  23 +
  24 + public void setCallId(String callId) {
  25 + this.callId = callId;
  26 + }
  27 +}
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceNotFoundEvent.java
... ... @@ -4,6 +4,9 @@ import javax.sip.Dialog;
4 4 import java.util.EventObject;
5 5  
6 6 public class DeviceNotFoundEvent extends EventObject {
  7 +
  8 + private String callId;
  9 +
7 10 /**
8 11 * Constructs a prototypical Event.
9 12 *
... ... @@ -14,8 +17,11 @@ public class DeviceNotFoundEvent extends EventObject {
14 17 super(dialog);
15 18 }
16 19  
  20 + public String getCallId() {
  21 + return callId;
  22 + }
17 23  
18   - public Dialog getDialog() {
19   - return (Dialog)super.getSource();
  24 + public void setCallId(String callId) {
  25 + this.callId = callId;
20 26 }
21 27 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SipTransactionInfo.java
1 1 package com.genersoft.iot.vmp.gb28181.bean;
2 2  
3 3 import gov.nist.javax.sip.message.SIPRequest;
  4 +import gov.nist.javax.sip.message.SIPResponse;
4 5  
5 6 public class SipTransactionInfo {
6 7  
... ... @@ -9,11 +10,11 @@ public class SipTransactionInfo {
9 10 private String toTag;
10 11 private String viaBranch;
11 12  
12   - public SipTransactionInfo(SIPRequest request) {
13   - this.callId = request.getCallIdHeader().getCallId();
14   - this.fromTag = request.getFromTag();
15   - this.toTag = request.getToTag();
16   - this.viaBranch = request.getTopmostViaHeader().getBranch();
  13 + public SipTransactionInfo(SIPResponse response) {
  14 + this.callId = response.getCallIdHeader().getCallId();
  15 + this.fromTag = response.getFromTag();
  16 + this.toTag = response.getToTag();
  17 + this.viaBranch = response.getTopmostViaHeader().getBranch();
17 18 }
18 19  
19 20 public SipTransactionInfo() {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SsrcTransaction.java
... ... @@ -8,10 +8,11 @@ public class SsrcTransaction {
8 8 private String channelId;
9 9 private String callId;
10 10 private String stream;
11   - private byte[] transaction;
12   - private byte[] dialog;
13 11 private String mediaServerId;
14 12 private String ssrc;
  13 +
  14 + private SipTransactionInfo sipTransactionInfo;
  15 +
15 16 private VideoStreamSessionManager.SessionType type;
16 17  
17 18 public String getDeviceId() {
... ... @@ -46,22 +47,6 @@ public class SsrcTransaction {
46 47 this.stream = stream;
47 48 }
48 49  
49   - public byte[] getTransaction() {
50   - return transaction;
51   - }
52   -
53   - public void setTransaction(byte[] transaction) {
54   - this.transaction = transaction;
55   - }
56   -
57   - public byte[] getDialog() {
58   - return dialog;
59   - }
60   -
61   - public void setDialog(byte[] dialog) {
62   - this.dialog = dialog;
63   - }
64   -
65 50 public String getMediaServerId() {
66 51 return mediaServerId;
67 52 }
... ... @@ -85,4 +70,12 @@ public class SsrcTransaction {
85 70 public void setType(VideoStreamSessionManager.SessionType type) {
86 71 this.type = type;
87 72 }
  73 +
  74 + public SipTransactionInfo getSipTransactionInfo() {
  75 + return sipTransactionInfo;
  76 + }
  77 +
  78 + public void setSipTransactionInfo(SipTransactionInfo sipTransactionInfo) {
  79 + this.sipTransactionInfo = sipTransactionInfo;
  80 + }
88 81 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeInfo.java
1 1 package com.genersoft.iot.vmp.gb28181.bean;
2 2  
3   -import com.genersoft.iot.vmp.utils.SerializeUtils;
4 3 import gov.nist.javax.sip.message.SIPRequest;
5 4 import gov.nist.javax.sip.message.SIPResponse;
6 5  
7   -import javax.sip.ClientTransaction;
8   -import javax.sip.Dialog;
9   -import javax.sip.RequestEvent;
10 6 import javax.sip.ServerTransaction;
11 7 import javax.sip.header.*;
12   -import javax.sip.message.Request;
13 8  
14 9 public class SubscribeInfo {
15 10  
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java
... ... @@ -10,6 +10,7 @@ import org.springframework.stereotype.Component;
10 10 import javax.sip.*;
11 11 import javax.sip.header.CallIdHeader;
12 12 import javax.sip.message.Response;
  13 +import java.text.ParseException;
13 14 import java.time.Instant;
14 15 import java.util.Map;
15 16 import java.util.concurrent.ConcurrentHashMap;
... ... @@ -56,8 +57,7 @@ public class SipSubscribe {
56 57 logger.debug("errorSubscribes.size:{}",errorSubscribes.size());
57 58 }
58 59  
59   - public interface Event {
60   - void response(EventResult eventResult);
  60 + public interface Event { void response(EventResult eventResult) ;
61 61 }
62 62  
63 63 /**
... ... @@ -81,18 +81,13 @@ public class SipSubscribe {
81 81 public EventResultType type;
82 82 public String msg;
83 83 public String callId;
84   - public Dialog dialog;
85 84 public EventObject event;
86 85  
87   - public EventResult() {
88   - }
89   -
90 86 public EventResult(EventObject event) {
91 87 this.event = event;
92 88 if (event instanceof ResponseEvent) {
93 89 ResponseEvent responseEvent = (ResponseEvent)event;
94 90 Response response = responseEvent.getResponse();
95   - this.dialog = responseEvent.getDialog();
96 91 this.type = EventResultType.response;
97 92 if (response != null) {
98 93 this.msg = response.getReasonPhrase();
... ... @@ -127,12 +122,10 @@ public class SipSubscribe {
127 122 this.statusCode = -1024;
128 123 this.callId = dialogTerminatedEvent.getDialog().getCallId().getCallId();
129 124 }else if (event instanceof DeviceNotFoundEvent) {
130   - DeviceNotFoundEvent deviceNotFoundEvent = (DeviceNotFoundEvent)event;
131 125 this.type = EventResultType.deviceNotFoundEvent;
132 126 this.msg = "设备未找到";
133 127 this.statusCode = -1024;
134   - this.dialog = deviceNotFoundEvent.getDialog();
135   - this.callId = this.dialog != null ?deviceNotFoundEvent.getDialog().getCallId().getCallId() : null;
  128 + this.callId = ((DeviceNotFoundEvent) event).getCallId();
136 129 }
137 130 }
138 131 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/event/alarm/AlarmEventListener.java
... ... @@ -51,7 +51,6 @@ public class AlarmEventListener implements ApplicationListener&lt;AlarmEvent&gt; {
51 51 }
52 52 // 移除已关闭的连接
53 53 it.remove();
54   - // e.printStackTrace();
55 54 }
56 55 }
57 56 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/event/device/RequestTimeoutEventImpl.java
... ... @@ -36,6 +36,7 @@ public class RequestTimeoutEventImpl implements ApplicationListener&lt;RequestTimeo
36 36 }
37 37 deviceService.offline(device.getDeviceId());
38 38 }
  39 +
39 40 }
40 41 }
41 42 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java
... ... @@ -18,6 +18,9 @@ import org.springframework.stereotype.Component;
18 18 import org.springframework.util.ObjectUtils;
19 19 import org.springframework.util.StringUtils;
20 20  
  21 +import javax.sip.InvalidArgumentException;
  22 +import javax.sip.SipException;
  23 +import java.text.ParseException;
21 24 import java.util.*;
22 25  
23 26 /**
... ... @@ -96,7 +99,12 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
96 99 }
97 100 if (deviceChannelList.size() > 0) {
98 101 logger.info("[Catalog事件: {}]平台:{},影响通道{}个", event.getType(), event.getPlatformId(), deviceChannelList.size());
99   - sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), parentPlatform, deviceChannelList, subscribe, null);
  102 + try {
  103 + sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), parentPlatform, deviceChannelList, subscribe, null);
  104 + } catch (InvalidArgumentException | ParseException | NoSuchFieldException | SipException |
  105 + IllegalAccessException e) {
  106 + logger.error("[命令发送失败] 国标级联 Catalog通知: {}", e.getMessage());
  107 + }
100 108 }
101 109 }else if (parentPlatformMap.keySet().size() > 0) {
102 110 for (String gbId : parentPlatformMap.keySet()) {
... ... @@ -112,7 +120,12 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
112 120 DeviceChannel deviceChannel = new DeviceChannel();
113 121 deviceChannel.setChannelId(gbId);
114 122 deviceChannelList.add(deviceChannel);
115   - sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), platform, deviceChannelList, subscribeInfo, null);
  123 + try {
  124 + sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), platform, deviceChannelList, subscribeInfo, null);
  125 + } catch (InvalidArgumentException | ParseException | NoSuchFieldException | SipException |
  126 + IllegalAccessException e) {
  127 + logger.error("[命令发送失败] 国标级联 Catalog通知: {}", e.getMessage());
  128 + }
116 129 }
117 130 }
118 131 }
... ... @@ -137,7 +150,12 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
137 150 }
138 151 if (deviceChannelList.size() > 0) {
139 152 logger.info("[Catalog事件: {}]平台:{},影响通道{}个", event.getType(), event.getPlatformId(), deviceChannelList.size());
140   - sipCommanderFroPlatform.sendNotifyForCatalogAddOrUpdate(event.getType(), parentPlatform, deviceChannelList, subscribe, null);
  153 + try {
  154 + sipCommanderFroPlatform.sendNotifyForCatalogAddOrUpdate(event.getType(), parentPlatform, deviceChannelList, subscribe, null);
  155 + } catch (InvalidArgumentException | ParseException | NoSuchFieldException | SipException |
  156 + IllegalAccessException e) {
  157 + logger.error("[命令发送失败] 国标级联 Catalog通知: {}", e.getMessage());
  158 + }
141 159 }
142 160 }else if (parentPlatformMap.keySet().size() > 0) {
143 161 for (String gbId : parentPlatformMap.keySet()) {
... ... @@ -157,7 +175,12 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
157 175 DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStreamWithStatus(gbStream, gbStream.getCatalogId(), platform);
158 176 deviceChannelList.add(deviceChannelByStream);
159 177 }
160   - sipCommanderFroPlatform.sendNotifyForCatalogAddOrUpdate(event.getType(), platform, deviceChannelList, subscribeInfo, null);
  178 + try {
  179 + sipCommanderFroPlatform.sendNotifyForCatalogAddOrUpdate(event.getType(), platform, deviceChannelList, subscribeInfo, null);
  180 + } catch (InvalidArgumentException | ParseException | NoSuchFieldException |
  181 + SipException | IllegalAccessException e) {
  182 + logger.error("[命令发送失败] 国标级联 Catalog通知: {}", e.getMessage());
  183 + }
161 184 }
162 185 }
163 186 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java
... ... @@ -3,19 +3,15 @@ package com.genersoft.iot.vmp.gb28181.session;
3 3 import java.util.ArrayList;
4 4 import java.util.List;
5 5  
6   -import javax.sip.ClientTransaction;
7   -import javax.sip.Dialog;
8   -
9 6 import com.genersoft.iot.vmp.common.VideoManagerConstants;
10 7 import com.genersoft.iot.vmp.conf.UserSetting;
  8 +import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
11 9 import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
12   -import com.genersoft.iot.vmp.utils.SerializeUtils;
13 10 import com.genersoft.iot.vmp.utils.redis.RedisUtil;
14   -import gov.nist.javax.sip.stack.SIPDialog;
  11 +import gov.nist.javax.sip.message.SIPResponse;
15 12 import org.springframework.beans.factory.annotation.Autowired;
16 13 import org.springframework.stereotype.Component;
17 14 import org.springframework.util.ObjectUtils;
18   -import org.springframework.util.StringUtils;
19 15  
20 16 /**
21 17 * @description:视频流session管理器,管理视频预览、预览回放的通信句柄
... ... @@ -42,15 +38,14 @@ public class VideoStreamSessionManager {
42 38 * @param callId 一次请求的CallID
43 39 * @param stream 流名称
44 40 * @param mediaServerId 所使用的流媒体ID
45   - * @param transaction 事务
  41 + * @param response 回复
46 42 */
47   - public void put(String deviceId, String channelId, String callId, String stream, String ssrc, String mediaServerId, ClientTransaction transaction, SessionType type){
  43 + public void put(String deviceId, String channelId, String callId, String stream, String ssrc, String mediaServerId, SIPResponse response, SessionType type){
48 44 SsrcTransaction ssrcTransaction = new SsrcTransaction();
49 45 ssrcTransaction.setDeviceId(deviceId);
50 46 ssrcTransaction.setChannelId(channelId);
51 47 ssrcTransaction.setStream(stream);
52   - byte[] transactionByteArray = SerializeUtils.serialize(transaction);
53   - ssrcTransaction.setTransaction(transactionByteArray);
  48 + ssrcTransaction.setSipTransactionInfo(new SipTransactionInfo(response));
54 49 ssrcTransaction.setCallId(callId);
55 50 ssrcTransaction.setSsrc(ssrc);
56 51 ssrcTransaction.setMediaServerId(mediaServerId);
... ... @@ -62,53 +57,6 @@ public class VideoStreamSessionManager {
62 57 + "_" + deviceId + "_" + channelId + "_" + callId + "_" + stream, ssrcTransaction);
63 58 }
64 59  
65   - public void put(String deviceId, String channelId, String callId, Dialog dialog){
66   - SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, callId, null);
67   - if (ssrcTransaction != null) {
68   - byte[] dialogByteArray = SerializeUtils.serialize(dialog);
69   - ssrcTransaction.setDialog(dialogByteArray);
70   - }
71   - RedisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId()
72   - + "_" + deviceId + "_" + channelId + "_" + ssrcTransaction.getCallId() + "_"
73   - + ssrcTransaction.getStream(), ssrcTransaction);
74   - }
75   -
76   -
77   - public ClientTransaction getTransaction(String deviceId, String channelId, String stream, String callId){
78   - SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, callId, stream);
79   - if (ssrcTransaction == null) {
80   - return null;
81   - }
82   - byte[] transactionByteArray = ssrcTransaction.getTransaction();
83   - ClientTransaction clientTransaction = (ClientTransaction)SerializeUtils.deSerialize(transactionByteArray);
84   - return clientTransaction;
85   - }
86   -
87   - public SIPDialog getDialogByStream(String deviceId, String channelId, String stream){
88   - SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
89   - if (ssrcTransaction == null) {
90   - return null;
91   - }
92   - byte[] dialogByteArray = ssrcTransaction.getDialog();
93   - if (dialogByteArray == null) {
94   - return null;
95   - }
96   - SIPDialog dialog = (SIPDialog)SerializeUtils.deSerialize(dialogByteArray);
97   - return dialog;
98   - }
99   -
100   - public SIPDialog getDialogByCallId(String deviceId, String channelId, String callId){
101   - SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, callId, null);
102   - if (ssrcTransaction == null) {
103   - return null;
104   - }
105   - byte[] dialogByteArray = ssrcTransaction.getDialog();
106   - if (dialogByteArray == null) {
107   - return null;
108   - }
109   - return (SIPDialog)SerializeUtils.deSerialize(dialogByteArray);
110   - }
111   -
112 60 public SsrcTransaction getSsrcTransaction(String deviceId, String channelId, String callId, String stream){
113 61  
114 62 if (ObjectUtils.isEmpty(deviceId)) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/CatalogSubscribeTask.java
... ... @@ -10,9 +10,7 @@ import org.slf4j.LoggerFactory;
10 10 import org.springframework.scheduling.annotation.Async;
11 11 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
12 12  
13   -import javax.sip.Dialog;
14   -import javax.sip.DialogState;
15   -import javax.sip.ResponseEvent;
  13 +import javax.sip.*;
16 14 import javax.sip.header.ToHeader;
17 15 import java.text.ParseException;
18 16 import java.util.Timer;
... ... @@ -44,23 +42,29 @@ public class CatalogSubscribeTask implements ISubscribeTask {
44 42 if (dynamicTask.get(taskKey) != null) {
45 43 dynamicTask.stop(taskKey);
46 44 }
47   - SIPRequest sipRequest = sipCommander.catalogSubscribe(device, request, eventResult -> {
48   - ResponseEvent event = (ResponseEvent) eventResult.event;
49   - // 成功
50   - logger.info("[目录订阅]成功: {}", device.getDeviceId());
51   - ToHeader toHeader = (ToHeader)event.getResponse().getHeader(ToHeader.NAME);
52   - try {
53   - this.request.getToHeader().setTag(toHeader.getTag());
54   - } catch (ParseException e) {
55   - logger.info("[目录订阅]成功: 但为request设置ToTag失败");
  45 + SIPRequest sipRequest = null;
  46 + try {
  47 + sipRequest = sipCommander.catalogSubscribe(device, request, eventResult -> {
  48 + ResponseEvent event = (ResponseEvent) eventResult.event;
  49 + // 成功
  50 + logger.info("[目录订阅]成功: {}", device.getDeviceId());
  51 + ToHeader toHeader = (ToHeader)event.getResponse().getHeader(ToHeader.NAME);
  52 + try {
  53 + this.request.getToHeader().setTag(toHeader.getTag());
  54 + } catch (ParseException e) {
  55 + logger.info("[目录订阅]成功: 但为request设置ToTag失败");
  56 + this.request = null;
  57 + }
  58 + },eventResult -> {
56 59 this.request = null;
57   - }
58   - },eventResult -> {
59   - this.request = null;
60   - // 失败
61   - logger.warn("[目录订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
62   - dynamicTask.startDelay(taskKey, CatalogSubscribeTask.this, 2000);
63   - });
  60 + // 失败
  61 + logger.warn("[目录订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
  62 + dynamicTask.startDelay(taskKey, CatalogSubscribeTask.this, 2000);
  63 + });
  64 + } catch (InvalidArgumentException | SipException | ParseException e) {
  65 + logger.error("[命令发送失败] 目录订阅: {}", e.getMessage());
  66 +
  67 + }
64 68 if (sipRequest != null) {
65 69 this.request = sipRequest;
66 70 }
... ... @@ -80,18 +84,22 @@ public class CatalogSubscribeTask implements ISubscribeTask {
80 84 dynamicTask.stop(taskKey);
81 85 }
82 86 device.setSubscribeCycleForCatalog(0);
83   - sipCommander.catalogSubscribe(device, request, eventResult -> {
84   - ResponseEvent event = (ResponseEvent) eventResult.event;
85   - if (event.getResponse().getRawContent() != null) {
86   - // 成功
87   - logger.info("[取消目录订阅订阅]成功: {}", device.getDeviceId());
88   - }else {
89   - // 成功
90   - logger.info("[取消目录订阅订阅]成功: {}", device.getDeviceId());
91   - }
92   - },eventResult -> {
93   - // 失败
94   - logger.warn("[取消目录订阅订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
95   - });
  87 + try {
  88 + sipCommander.catalogSubscribe(device, request, eventResult -> {
  89 + ResponseEvent event = (ResponseEvent) eventResult.event;
  90 + if (event.getResponse().getRawContent() != null) {
  91 + // 成功
  92 + logger.info("[取消目录订阅订阅]成功: {}", device.getDeviceId());
  93 + }else {
  94 + // 成功
  95 + logger.info("[取消目录订阅订阅]成功: {}", device.getDeviceId());
  96 + }
  97 + },eventResult -> {
  98 + // 失败
  99 + logger.warn("[取消目录订阅订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
  100 + });
  101 + } catch (InvalidArgumentException | SipException | ParseException e) {
  102 + logger.error("[命令发送失败] 取消目录订阅订阅: {}", e.getMessage());
  103 + }
96 104 }
97 105 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeTask.java
... ... @@ -11,9 +11,7 @@ import org.slf4j.Logger;
11 11 import org.slf4j.LoggerFactory;
12 12 import org.springframework.scheduling.annotation.Async;
13 13  
14   -import javax.sip.Dialog;
15   -import javax.sip.DialogState;
16   -import javax.sip.ResponseEvent;
  14 +import javax.sip.*;
17 15 import javax.sip.header.ToHeader;
18 16 import java.text.ParseException;
19 17 import java.util.Timer;
... ... @@ -43,23 +41,28 @@ public class MobilePositionSubscribeTask implements ISubscribeTask {
43 41 if (dynamicTask.get(taskKey) != null) {
44 42 dynamicTask.stop(taskKey);
45 43 }
46   - SIPRequest sipRequest = sipCommander.mobilePositionSubscribe(device, request, eventResult -> {
47   - // 成功
48   - logger.info("[移动位置订阅]成功: {}", device.getDeviceId());
49   - ResponseEvent event = (ResponseEvent) eventResult.event;
50   - ToHeader toHeader = (ToHeader)event.getResponse().getHeader(ToHeader.NAME);
51   - try {
52   - this.request.getToHeader().setTag(toHeader.getTag());
53   - } catch (ParseException e) {
54   - logger.info("[移动位置订阅]成功: 为request设置ToTag失败");
  44 + SIPRequest sipRequest = null;
  45 + try {
  46 + sipRequest = sipCommander.mobilePositionSubscribe(device, request, eventResult -> {
  47 + // 成功
  48 + logger.info("[移动位置订阅]成功: {}", device.getDeviceId());
  49 + ResponseEvent event = (ResponseEvent) eventResult.event;
  50 + ToHeader toHeader = (ToHeader)event.getResponse().getHeader(ToHeader.NAME);
  51 + try {
  52 + this.request.getToHeader().setTag(toHeader.getTag());
  53 + } catch (ParseException e) {
  54 + logger.info("[移动位置订阅]成功: 为request设置ToTag失败");
  55 + this.request = null;
  56 + }
  57 + },eventResult -> {
55 58 this.request = null;
56   - }
57   - },eventResult -> {
58   - this.request = null;
59   - // 失败
60   - logger.warn("[移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
61   - dynamicTask.startDelay(taskKey, MobilePositionSubscribeTask.this, 2000);
62   - });
  59 + // 失败
  60 + logger.warn("[移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
  61 + dynamicTask.startDelay(taskKey, MobilePositionSubscribeTask.this, 2000);
  62 + });
  63 + } catch (InvalidArgumentException | SipException | ParseException e) {
  64 + logger.error("[命令发送失败] 移动位置订阅: {}", e.getMessage());
  65 + }
63 66 if (sipRequest != null) {
64 67 this.request = sipRequest;
65 68 }
... ... @@ -79,18 +82,22 @@ public class MobilePositionSubscribeTask implements ISubscribeTask {
79 82 dynamicTask.stop(taskKey);
80 83 }
81 84 device.setSubscribeCycleForMobilePosition(0);
82   - sipCommander.mobilePositionSubscribe(device, request, eventResult -> {
83   - ResponseEvent event = (ResponseEvent) eventResult.event;
84   - if (event.getResponse().getRawContent() != null) {
85   - // 成功
86   - logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId());
87   - }else {
88   - // 成功
89   - logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId());
90   - }
91   - },eventResult -> {
92   - // 失败
93   - logger.warn("[取消移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
94   - });
  85 + try {
  86 + sipCommander.mobilePositionSubscribe(device, request, eventResult -> {
  87 + ResponseEvent event = (ResponseEvent) eventResult.event;
  88 + if (event.getResponse().getRawContent() != null) {
  89 + // 成功
  90 + logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId());
  91 + }else {
  92 + // 成功
  93 + logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId());
  94 + }
  95 + },eventResult -> {
  96 + // 失败
  97 + logger.warn("[取消移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
  98 + });
  99 + } catch (InvalidArgumentException | SipException | ParseException e) {
  100 + logger.error("[命令发送失败] 取消移动位置订阅: {}", e.getMessage());
  101 + }
95 102 }
96 103 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
1 1 package com.genersoft.iot.vmp.gb28181.transmit.cmd;
2 2  
3 3 import com.genersoft.iot.vmp.common.StreamInfo;
  4 +import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
4 5 import com.genersoft.iot.vmp.gb28181.bean.*;
5 6 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
6 7 import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
... ... @@ -14,6 +15,11 @@ import javax.sip.Dialog;
14 15 import javax.sip.InvalidArgumentException;
15 16 import javax.sip.SipException;
16 17 import java.text.ParseException;
  18 +import javax.sip.InvalidArgumentException;
  19 +import javax.sip.PeerUnavailableException;
  20 +import javax.sip.SipException;
  21 +import javax.sip.message.Request;
  22 +import java.text.ParseException;
17 23  
18 24 /**
19 25 * @description:设备能力接口,用于定义设备的控制、查询能力
... ... @@ -30,7 +36,7 @@ public interface ISIPCommander {
30 36 * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
31 37 * @param upDown 镜头上移下移 0:停止 1:上移 2:下移
32 38 */
33   - boolean ptzdirectCmd(Device device,String channelId,int leftRight, int upDown);
  39 + void ptzdirectCmd(Device device,String channelId,int leftRight, int upDown) throws InvalidArgumentException, ParseException, SipException;
34 40  
35 41 /**
36 42 * 云台方向放控制
... ... @@ -41,7 +47,7 @@ public interface ISIPCommander {
41 47 * @param upDown 镜头上移下移 0:停止 1:上移 2:下移
42 48 * @param moveSpeed 镜头移动速度
43 49 */
44   - boolean ptzdirectCmd(Device device,String channelId,int leftRight, int upDown, int moveSpeed);
  50 + void ptzdirectCmd(Device device,String channelId,int leftRight, int upDown, int moveSpeed) throws InvalidArgumentException, ParseException, SipException;
45 51  
46 52 /**
47 53 * 云台缩放控制,使用配置文件中的默认镜头缩放速度
... ... @@ -50,7 +56,7 @@ public interface ISIPCommander {
50 56 * @param channelId 预览通道
51 57 * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
52 58 */
53   - boolean ptzZoomCmd(Device device,String channelId,int inOut);
  59 + void ptzZoomCmd(Device device,String channelId,int inOut) throws InvalidArgumentException, ParseException, SipException;
54 60  
55 61 /**
56 62 * 云台缩放控制
... ... @@ -59,7 +65,7 @@ public interface ISIPCommander {
59 65 * @param channelId 预览通道
60 66 * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
61 67 */
62   - boolean ptzZoomCmd(Device device,String channelId,int inOut, int moveSpeed);
  68 + void ptzZoomCmd(Device device,String channelId,int inOut, int moveSpeed) throws InvalidArgumentException, ParseException, SipException;
63 69  
64 70 /**
65 71 * 云台控制,支持方向与缩放控制
... ... @@ -72,7 +78,7 @@ public interface ISIPCommander {
72 78 * @param moveSpeed 镜头移动速度
73 79 * @param zoomSpeed 镜头缩放速度
74 80 */
75   - boolean ptzCmd(Device device,String channelId,int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed);
  81 + void ptzCmd(Device device,String channelId,int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed) throws InvalidArgumentException, SipException, ParseException;
76 82  
77 83 /**
78 84 * 前端控制,包括PTZ指令、FI指令、预置位指令、巡航指令、扫描指令和辅助开关指令
... ... @@ -84,7 +90,7 @@ public interface ISIPCommander {
84 90 * @param parameter2 数据2
85 91 * @param combineCode2 组合码2
86 92 */
87   - boolean frontEndCmd(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combineCode2);
  93 + void frontEndCmd(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combineCode2) throws SipException, InvalidArgumentException, ParseException;
88 94  
89 95 /**
90 96 * 前端控制指令(用于转发上级指令)
... ... @@ -92,14 +98,14 @@ public interface ISIPCommander {
92 98 * @param channelId 预览通道
93 99 * @param cmdString 前端控制指令串
94 100 */
95   - boolean fronEndCmd(Device device, String channelId, String cmdString, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent);
  101 + void fronEndCmd(Device device, String channelId, String cmdString, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
96 102  
97 103 /**
98 104 * 请求预览视频流
99 105 * @param device 视频设备
100 106 * @param channelId 预览通道
101 107 */
102   - void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent);
  108 + void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
103 109  
104 110 /**
105 111 * 请求回放视频流
... ... @@ -109,7 +115,7 @@ public interface ISIPCommander {
109 115 * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
110 116 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
111 117 */
112   - void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInf, Device device, String channelId, String startTime, String endTime,InviteStreamCallback inviteStreamCallback, InviteStreamCallback event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent);
  118 + void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInf, Device device, String channelId, String startTime, String endTime,InviteStreamCallback inviteStreamCallback, InviteStreamCallback event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
113 119  
114 120 /**
115 121 * 请求历史媒体下载
... ... @@ -122,34 +128,35 @@ public interface ISIPCommander {
122 128 */
123 129 void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
124 130 String startTime, String endTime, int downloadSpeed, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent,
125   - SipSubscribe.Event errorEvent);
  131 + SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
126 132  
127 133 /**
128 134 * 视频流停止
129 135 */
130 136 void streamByeCmd(String deviceId, String channelId, String stream, String callId, SipSubscribe.Event okEvent);
131 137 void streamByeCmd(String deviceId, String channelId, String stream, String callId);
132   - void streamByeCmd(SIPDialog dialog, String channelId, SIPRequest request, SipSubscribe.Event okEvent) throws SipException, ParseException, InvalidArgumentException;
  138 + void streamByeCmd(Device device, String channelId, String stream, String callId, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException;
  139 + void streamByeCmd(Device device, String channelId, String stream, String callId) throws InvalidArgumentException, ParseException, SipException, SsrcTransactionNotFoundException;
133 140  
134 141 /**
135 142 * 回放暂停
136 143 */
137   - void playPauseCmd(Device device, StreamInfo streamInfo);
  144 + void playPauseCmd(Device device, StreamInfo streamInfo) throws InvalidArgumentException, ParseException, SipException;
138 145  
139 146 /**
140 147 * 回放恢复
141 148 */
142   - void playResumeCmd(Device device, StreamInfo streamInfo);
  149 + void playResumeCmd(Device device, StreamInfo streamInfo) throws InvalidArgumentException, ParseException, SipException;
143 150  
144 151 /**
145 152 * 回放拖动播放
146 153 */
147   - void playSeekCmd(Device device, StreamInfo streamInfo, long seekTime);
  154 + void playSeekCmd(Device device, StreamInfo streamInfo, long seekTime) throws InvalidArgumentException, ParseException, SipException;
148 155  
149 156 /**
150 157 * 回放倍速播放
151 158 */
152   - void playSpeedCmd(Device device, StreamInfo streamInfo, Double speed);
  159 + void playSpeedCmd(Device device, StreamInfo streamInfo, Double speed) throws InvalidArgumentException, ParseException, SipException;
153 160  
154 161 /**
155 162 * 回放控制
... ... @@ -157,8 +164,10 @@ public interface ISIPCommander {
157 164 * @param streamInfo
158 165 * @param content
159 166 */
160   - void playbackControlCmd(Device device, StreamInfo streamInfo, String content,SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent);
  167 + void playbackControlCmd(Device device, StreamInfo streamInfo, String content,SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws SipException, InvalidArgumentException, ParseException;
  168 +
161 169  
  170 + /**
162 171  
163 172 /**
164 173 * 语音广播
... ... @@ -166,7 +175,16 @@ public interface ISIPCommander {
166 175 * @param device 视频设备
167 176 */
168 177 boolean audioBroadcastCmd(Device device, String channelId, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent);
169   -
  178 + void audioBroadcastCmd(Device device,String channelId);
  179 +
  180 + /**
  181 + * 语音广播
  182 + *
  183 + * @param device 视频设备
  184 + */
  185 + void audioBroadcastCmd(Device device, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
  186 + void audioBroadcastCmd(Device device) throws InvalidArgumentException, SipException, ParseException;
  187 +
170 188 /**
171 189 * 音视频录像控制
172 190 *
... ... @@ -174,21 +192,21 @@ public interface ISIPCommander {
174 192 * @param channelId 预览通道
175 193 * @param recordCmdStr 录像命令:Record / StopRecord
176 194 */
177   - boolean recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent);
  195 + void recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
178 196  
179 197 /**
180 198 * 远程启动控制命令
181 199 *
182 200 * @param device 视频设备
183 201 */
184   - boolean teleBootCmd(Device device);
  202 + void teleBootCmd(Device device) throws InvalidArgumentException, SipException, ParseException;
185 203  
186 204 /**
187 205 * 报警布防/撤防命令
188 206 *
189 207 * @param device 视频设备
190 208 */
191   - boolean guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent);
  209 + void guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
192 210  
193 211 /**
194 212 * 报警复位命令
... ... @@ -197,7 +215,7 @@ public interface ISIPCommander {
197 215 * @param alarmMethod 报警方式(可选)
198 216 * @param alarmType 报警类型(可选)
199 217 */
200   - boolean alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent);
  218 + void alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
201 219  
202 220 /**
203 221 * 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧
... ... @@ -205,7 +223,7 @@ public interface ISIPCommander {
205 223 * @param device 视频设备
206 224 * @param channelId 预览通道
207 225 */
208   - boolean iFrameCmd(Device device, String channelId);
  226 + void iFrameCmd(Device device, String channelId) throws InvalidArgumentException, SipException, ParseException;
209 227  
210 228 /**
211 229 * 看守位控制命令
... ... @@ -215,14 +233,14 @@ public interface ISIPCommander {
215 233 * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s)
216 234 * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255
217 235 */
218   - boolean homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent);
  236 + void homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
219 237  
220 238 /**
221 239 * 设备配置命令
222 240 *
223 241 * @param device 视频设备
224 242 */
225   - boolean deviceConfigCmd(Device device);
  243 + void deviceConfigCmd(Device device);
226 244  
227 245 /**
228 246 * 设备配置命令:basicParam
... ... @@ -234,14 +252,14 @@ public interface ISIPCommander {
234 252 * @param heartBeatInterval 心跳间隔时间(可选)
235 253 * @param heartBeatCount 心跳超时次数(可选)
236 254 */
237   - boolean deviceBasicConfigCmd(Device device, String channelId, String name, String expiration, String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent);
  255 + void deviceBasicConfigCmd(Device device, String channelId, String name, String expiration, String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
238 256  
239 257 /**
240 258 * 查询设备状态
241 259 *
242 260 * @param device 视频设备
243 261 */
244   - boolean deviceStatusQuery(Device device, SipSubscribe.Event errorEvent);
  262 + void deviceStatusQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
245 263  
246 264 /**
247 265 * 查询设备信息
... ... @@ -249,14 +267,14 @@ public interface ISIPCommander {
249 267 * @param device 视频设备
250 268 * @return
251 269 */
252   - boolean deviceInfoQuery(Device device);
  270 + void deviceInfoQuery(Device device) throws InvalidArgumentException, SipException, ParseException;
253 271  
254 272 /**
255 273 * 查询目录列表
256 274 *
257 275 * @param device 视频设备
258 276 */
259   - boolean catalogQuery(Device device, int sn, SipSubscribe.Event errorEvent);
  277 + void catalogQuery(Device device, int sn, SipSubscribe.Event errorEvent) throws SipException, InvalidArgumentException, ParseException;
260 278  
261 279 /**
262 280 * 查询录像信息
... ... @@ -266,7 +284,7 @@ public interface ISIPCommander {
266 284 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
267 285 * @param sn
268 286 */
269   - boolean recordInfoQuery(Device device, String channelId, String startTime, String endTime, int sn, Integer Secrecy, String type, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent);
  287 + void recordInfoQuery(Device device, String channelId, String startTime, String endTime, int sn, Integer Secrecy, String type, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
270 288  
271 289 /**
272 290 * 查询报警信息
... ... @@ -280,8 +298,8 @@ public interface ISIPCommander {
280 298 * @param endTime 报警发生终止时间(可选)
281 299 * @return true = 命令发送成功
282 300 */
283   - boolean alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod,
284   - String alarmType, String startTime, String endTime, SipSubscribe.Event errorEvent);
  301 + void alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod,
  302 + String alarmType, String startTime, String endTime, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
285 303  
286 304 /**
287 305 * 查询设备配置
... ... @@ -290,21 +308,21 @@ public interface ISIPCommander {
290 308 * @param channelId 通道编码(可选)
291 309 * @param configType 配置类型:
292 310 */
293   - boolean deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent);
  311 + void deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
294 312  
295 313 /**
296 314 * 查询设备预置位置
297 315 *
298 316 * @param device 视频设备
299 317 */
300   - boolean presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent);
  318 + void presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
301 319  
302 320 /**
303 321 * 查询移动设备位置数据
304 322 *
305 323 * @param device 视频设备
306 324 */
307   - boolean mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent);
  325 + void mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
308 326  
309 327 /**
310 328 * 订阅、取消订阅移动位置
... ... @@ -312,7 +330,7 @@ public interface ISIPCommander {
312 330 * @param device 视频设备
313 331 * @return true = 命令发送成功
314 332 */
315   - SIPRequest mobilePositionSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent , SipSubscribe.Event errorEvent);
  333 + SIPRequest mobilePositionSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent , SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
316 334  
317 335 /**
318 336 * 订阅、取消订阅报警信息
... ... @@ -325,14 +343,14 @@ public interface ISIPCommander {
325 343 * @param endTime 报警发生终止时间(可选)
326 344 * @return true = 命令发送成功
327 345 */
328   - boolean alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime);
  346 + void alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime) throws InvalidArgumentException, SipException, ParseException;
329 347  
330 348 /**
331 349 * 订阅、取消订阅目录信息
332 350 * @param device 视频设备
333 351 * @return true = 命令发送成功
334 352 */
335   - SIPRequest catalogSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent);
  353 + SIPRequest catalogSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
336 354  
337 355 /**
338 356 * 拉框控制命令
... ... @@ -341,7 +359,7 @@ public interface ISIPCommander {
341 359 * @param channelId 通道id
342 360 * @param cmdString 前端控制指令串
343 361 */
344   - boolean dragZoomCmd(Device device, String channelId, String cmdString);
  362 + void dragZoomCmd(Device device, String channelId, String cmdString) throws InvalidArgumentException, SipException, ParseException;
345 363  
346 364  
347 365 /**
... ... @@ -350,5 +368,11 @@ public interface ISIPCommander {
350 368 * @param deviceAlarm 报警信息信息
351 369 * @return
352 370 */
353   - boolean sendAlarmMessage(Device device, DeviceAlarm deviceAlarm);
  371 + void sendAlarmMessage(Device device, DeviceAlarm deviceAlarm) throws InvalidArgumentException, SipException, ParseException;
  372 +
  373 + void transmitRequest(String transport, Request request) throws SipException, ParseException ;
  374 +
  375 + void transmitRequest(String transport, Request request, SipSubscribe.Event errorEvent) throws SipException, ParseException;
  376 +
  377 + void transmitRequest(String transport, Request request, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws SipException, ParseException;
354 378 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java
... ... @@ -4,7 +4,10 @@ import com.genersoft.iot.vmp.gb28181.bean.*;
4 4 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
5 5 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
6 6  
  7 +import javax.sip.InvalidArgumentException;
  8 +import javax.sip.SipException;
7 9 import javax.sip.header.WWWAuthenticateHeader;
  10 +import java.text.ParseException;
8 11 import java.util.List;
9 12  
10 13 public interface ISIPCommanderForPlatform {
... ... @@ -14,15 +17,15 @@ public interface ISIPCommanderForPlatform {
14 17 * @param parentPlatform
15 18 * @return
16 19 */
17   - boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent);
18   - boolean register(ParentPlatform parentPlatform, String callId, WWWAuthenticateHeader www, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain, boolean isRegister);
  20 + void register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException;
  21 + void register(ParentPlatform parentPlatform, String callId, WWWAuthenticateHeader www, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain, boolean isRegister) throws SipException, InvalidArgumentException, ParseException;
19 22  
20 23 /**
21 24 * 向上级平台注销
22 25 * @param parentPlatform
23 26 * @return
24 27 */
25   - boolean unregister(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent);
  28 + void unregister(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException;
26 29  
27 30  
28 31 /**
... ... @@ -30,7 +33,7 @@ public interface ISIPCommanderForPlatform {
30 33 * @param parentPlatform
31 34 * @return callId(作为接受回复的判定)
32 35 */
33   - String keepalive(ParentPlatform parentPlatform,SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent);
  36 + String keepalive(ParentPlatform parentPlatform,SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws SipException, InvalidArgumentException, ParseException;
34 37  
35 38  
36 39 /**
... ... @@ -42,8 +45,8 @@ public interface ISIPCommanderForPlatform {
42 45 * @param size
43 46 * @return
44 47 */
45   - boolean catalogQuery(DeviceChannel channel, ParentPlatform parentPlatform, String sn, String fromTag, int size);
46   - boolean catalogQuery(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag);
  48 + void catalogQuery(DeviceChannel channel, ParentPlatform parentPlatform, String sn, String fromTag, int size) throws SipException, InvalidArgumentException, ParseException;
  49 + void catalogQuery(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag) throws InvalidArgumentException, ParseException, SipException;
47 50  
48 51 /**
49 52 * 向上级回复DeviceInfo查询信息
... ... @@ -52,7 +55,7 @@ public interface ISIPCommanderForPlatform {
52 55 * @param fromTag
53 56 * @return
54 57 */
55   - boolean deviceInfoResponse(ParentPlatform parentPlatform, String sn, String fromTag);
  58 + void deviceInfoResponse(ParentPlatform parentPlatform, String sn, String fromTag) throws SipException, InvalidArgumentException, ParseException;
56 59  
57 60 /**
58 61 * 向上级回复DeviceStatus查询信息
... ... @@ -61,7 +64,7 @@ public interface ISIPCommanderForPlatform {
61 64 * @param fromTag
62 65 * @return
63 66 */
64   - boolean deviceStatusResponse(ParentPlatform parentPlatform, String sn, String fromTag);
  67 + void deviceStatusResponse(ParentPlatform parentPlatform, String sn, String fromTag) throws SipException, InvalidArgumentException, ParseException;
65 68  
66 69 /**
67 70 * 向上级回复移动位置订阅消息
... ... @@ -70,7 +73,7 @@ public interface ISIPCommanderForPlatform {
70 73 * @param subscribeInfo 订阅相关的信息
71 74 * @return
72 75 */
73   - boolean sendNotifyMobilePosition(ParentPlatform parentPlatform, GPSMsgInfo gpsMsgInfo, SubscribeInfo subscribeInfo);
  76 + void sendNotifyMobilePosition(ParentPlatform parentPlatform, GPSMsgInfo gpsMsgInfo, SubscribeInfo subscribeInfo) throws InvalidArgumentException, ParseException, NoSuchFieldException, SipException, IllegalAccessException;
74 77  
75 78 /**
76 79 * 向上级回复报警消息
... ... @@ -78,21 +81,21 @@ public interface ISIPCommanderForPlatform {
78 81 * @param deviceAlarm 报警信息信息
79 82 * @return
80 83 */
81   - boolean sendAlarmMessage(ParentPlatform parentPlatform, DeviceAlarm deviceAlarm);
  84 + void sendAlarmMessage(ParentPlatform parentPlatform, DeviceAlarm deviceAlarm) throws SipException, InvalidArgumentException, ParseException;
82 85  
83 86 /**
84 87 * 回复catalog事件-增加/更新
85 88 * @param parentPlatform
86 89 * @param deviceChannels
87 90 */
88   - boolean sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index);
  91 + void sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index) throws InvalidArgumentException, ParseException, NoSuchFieldException, SipException, IllegalAccessException;
89 92  
90 93 /**
91 94 * 回复catalog事件-删除
92 95 * @param parentPlatform
93 96 * @param deviceChannels
94 97 */
95   - boolean sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index);
  98 + void sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index) throws InvalidArgumentException, ParseException, NoSuchFieldException, SipException, IllegalAccessException;
96 99  
97 100 /**
98 101 * 回复recordInfo
... ... @@ -101,7 +104,7 @@ public interface ISIPCommanderForPlatform {
101 104 * @param fromTag fromTag
102 105 * @param recordInfo 录像信息
103 106 */
104   - boolean recordInfo(DeviceChannel deviceChannel, ParentPlatform parentPlatform, String fromTag, RecordInfo recordInfo);
  107 + void recordInfo(DeviceChannel deviceChannel, ParentPlatform parentPlatform, String fromTag, RecordInfo recordInfo) throws SipException, InvalidArgumentException, ParseException;
105 108  
106 109 /**
107 110 * 录像播放推送完成时发送MediaStatus消息
... ... @@ -109,13 +112,13 @@ public interface ISIPCommanderForPlatform {
109 112 * @param sendRtpItem
110 113 * @return
111 114 */
112   - boolean sendMediaStatusNotify(ParentPlatform platform, SendRtpItem sendRtpItem);
  115 + void sendMediaStatusNotify(ParentPlatform platform, SendRtpItem sendRtpItem) throws SipException, InvalidArgumentException, ParseException;
113 116  
114 117 /**
115 118 * 向发起点播的上级回复bye
116 119 * @param platform 平台信息
117 120 * @param callId callId
118 121 */
119   - void streamByeCmd(ParentPlatform platform, String callId);
120   - void streamByeCmd(ParentPlatform platform, SendRtpItem sendRtpItem);
  122 + void streamByeCmd(ParentPlatform platform, String callId) throws SipException, InvalidArgumentException, ParseException;
  123 + void streamByeCmd(ParentPlatform platform, SendRtpItem sendRtpItem) throws SipException, InvalidArgumentException, ParseException;
121 124 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
... ... @@ -10,6 +10,9 @@ import javax.sip.header.*;
10 10 import javax.sip.message.Request;
11 11  
12 12 import com.genersoft.iot.vmp.common.StreamInfo;
  13 +import com.genersoft.iot.vmp.gb28181.bean.SipMsgInfo;
  14 +import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
  15 +import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
13 16 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
14 17 import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
15 18 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
... ... @@ -17,6 +20,7 @@ import com.genersoft.iot.vmp.utils.GitUtil;
17 20 import gov.nist.javax.sip.SipProviderImpl;
18 21 import gov.nist.javax.sip.SipStackImpl;
19 22 import gov.nist.javax.sip.message.SIPRequest;
  23 +import gov.nist.javax.sip.message.SIPResponse;
20 24 import gov.nist.javax.sip.stack.SIPDialog;
21 25 import org.springframework.beans.factory.annotation.Autowired;
22 26 import org.springframework.beans.factory.annotation.Qualifier;
... ... @@ -168,34 +172,37 @@ public class SIPRequestHeaderProvider {
168 172 return request;
169 173 }
170 174  
171   - public Request createByteRequest(Device device, String channelId, String viaTag, String fromTag, String toTag, String callId) throws ParseException, InvalidArgumentException, PeerUnavailableException {
  175 + public Request createByteRequest(Device device, String channelId, SipTransactionInfo transactionInfo) throws ParseException, InvalidArgumentException, PeerUnavailableException {
172 176 Request request = null;
173 177 //请求行
174 178 SipURI requestLine = sipFactory.createAddressFactory().createSipURI(channelId, device.getHostAddress());
175 179 // via
176 180 ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
177   - ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(sipConfig.getIp(), sipConfig.getPort(), device.getTransport(), viaTag);
  181 + ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(sipConfig.getIp(), sipConfig.getPort(), device.getTransport(), SipUtils.getNewViaTag());
178 182 viaHeaders.add(viaHeader);
179 183 //from
180 184 SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain());
181 185 Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI);
182   - FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag); //必须要有标记,否则无法创建会话,无法回应ack
  186 + FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, transactionInfo.getFromTag());
183 187 //to
184 188 SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(channelId,device.getHostAddress());
185 189 Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
186   - ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress,toTag);
  190 + ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, transactionInfo.getToTag());
187 191  
188 192 //Forwards
189 193 MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
190 194  
191 195 //ceq
192 196 CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.BYE);
193   - CallIdHeader callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(callId);
  197 + CallIdHeader callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(transactionInfo.getCallId());
194 198 request = sipFactory.createMessageFactory().createRequest(requestLine, Request.BYE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
195 199  
196 200 request.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil));
197 201  
198 202 Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getIp()+":"+sipConfig.getPort()));
  203 + request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
  204 +
  205 + request.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil));
199 206  
200 207 return request;
201 208 }
... ... @@ -251,47 +258,72 @@ public class SIPRequestHeaderProvider {
251 258 return request;
252 259 }
253 260  
254   - public Request createInfoRequest(Device device, StreamInfo streamInfo, String content)
  261 + public SIPRequest createInfoRequest(Device device, String channelId, String content, SipTransactionInfo transactionInfo)
255 262 throws SipException, ParseException, InvalidArgumentException {
256   - if (streamInfo == null) {
257   - return null;
258   - }
259   - Request request = null;
260   - SIPDialog dialog = streamSession.getDialogByStream(streamInfo.getDeviceID(), streamInfo.getChannelId(), streamInfo.getStream());
261   - if (dialog == null) {
  263 + if (device == null || transactionInfo == null) {
262 264 return null;
263 265 }
  266 + SIPRequest request = null;
  267 + //请求行
  268 + SipURI requestLine = sipFactory.createAddressFactory().createSipURI(channelId, device.getHostAddress());
  269 + // via
  270 + ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
  271 + ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(sipConfig.getIp(), sipConfig.getPort(), device.getTransport(), SipUtils.getNewViaTag());
  272 + viaHeaders.add(viaHeader);
  273 + //from
  274 + SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain());
  275 + Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI);
  276 + FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, transactionInfo.getFromTag());
  277 + //to
  278 + SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(channelId,device.getHostAddress());
  279 + Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
  280 + ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, transactionInfo.getToTag());
  281 +
  282 + //Forwards
  283 + MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
  284 +
  285 + //ceq
  286 + CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INFO);
  287 + CallIdHeader callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(transactionInfo.getCallId());
  288 + request = (SIPRequest)sipFactory.createMessageFactory().createRequest(requestLine, Request.INFO, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
264 289  
265   - SipStack sipStack = udpSipProvider.getSipStack();
266   - SIPDialog sipDialog = ((SipStackImpl) sipStack).putDialog(dialog);
267   - if (dialog != sipDialog) {
268   - dialog = sipDialog;
269   - }else {
270   - dialog.setSipProvider(udpSipProvider);
  290 + request.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil));
  291 +
  292 + Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getIp()+":"+sipConfig.getPort()));
  293 + request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
  294 +
  295 + request.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil));
  296 +
  297 + if (content != null) {
  298 + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application",
  299 + "MANSRTSP");
  300 + request.setContent(content, contentTypeHeader);
271 301 }
272   - streamSession.put(streamInfo.getDeviceID(), streamInfo.getChannelId(), dialog.getCallId().getCallId(), dialog);
273   - Request infoRequest = dialog.createRequest(Request.INFO);
274   - SipURI sipURI = (SipURI) infoRequest.getRequestURI();
275   - sipURI.setHost(device.getIp());
276   - sipURI.setPort(device.getPort());
277   - sipURI.setUser(streamInfo.getChannelId());
278   -
279   - ViaHeader viaHeader = (ViaHeader) infoRequest.getHeader(ViaHeader.NAME);
280   - viaHeader.setRPort();
281   - // 增加Contact header
282   - Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory()
283   - .createSipURI(sipConfig.getId(), sipConfig.getIp() + ":" + sipConfig.getPort()));
284   - infoRequest.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
285   - infoRequest.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil));
286   -
287   - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application",
288   - "MANSRTSP");
289   - infoRequest.setContent(content, contentTypeHeader);
290   -
291   - CSeqHeader cSeqHeader = (CSeqHeader)infoRequest.getHeader(CSeqHeader.NAME);
292   - cSeqHeader.setSeqNumber(redisCatchStorage.getCSEQ());
293   - // ceq
294   - infoRequest.addHeader(cSeqHeader);
295   - return infoRequest;
  302 + return request;
  303 + }
  304 +
  305 + public Request createAckRequest(SipURI sipURI, SIPResponse sipResponse) throws ParseException, InvalidArgumentException, PeerUnavailableException {
  306 +
  307 + // via
  308 + ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
  309 + ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(sipConfig.getIp(), sipConfig.getPort(), sipResponse.getTopmostViaHeader().getTransport(), SipUtils.getNewViaTag());
  310 + viaHeaders.add(viaHeader);
  311 +
  312 + //Forwards
  313 + MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
  314 +
  315 + //ceq
  316 + CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(sipResponse.getCSeqHeader().getSeqNumber(), Request.ACK);
  317 +
  318 + Request request = sipFactory.createMessageFactory().createRequest(sipURI, Request.ACK, sipResponse.getCallIdHeader(), cSeqHeader, sipResponse.getFromHeader(), sipResponse.getToHeader(), viaHeaders, maxForwards);
  319 +
  320 + request.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil));
  321 +
  322 + Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getIp()+":"+sipConfig.getPort()));
  323 + request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
  324 +
  325 + request.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil));
  326 +
  327 + return request;
296 328 }
297 329 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
... ... @@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.common.StreamInfo;
5 5 import com.genersoft.iot.vmp.conf.DynamicTask;
6 6 import com.genersoft.iot.vmp.conf.SipConfig;
7 7 import com.genersoft.iot.vmp.conf.UserSetting;
  8 +import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
8 9 import com.genersoft.iot.vmp.gb28181.bean.*;
9 10 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
10 11 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
... ... @@ -22,17 +23,20 @@ import com.genersoft.iot.vmp.service.bean.SSRCInfo;
22 23 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
23 24 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
24 25 import com.genersoft.iot.vmp.utils.GitUtil;
  26 +import gov.nist.javax.sip.SIPConstants;
25 27 import gov.nist.javax.sip.SipProviderImpl;
26 28 import gov.nist.javax.sip.SipStackImpl;
27   -import gov.nist.javax.sip.message.MessageFactoryImpl;
28 29 import gov.nist.javax.sip.message.SIPRequest;
  30 +import gov.nist.javax.sip.message.SIPResponse;
29 31 import gov.nist.javax.sip.stack.SIPClientTransaction;
  32 +import gov.nist.javax.sip.stack.SIPClientTransactionImpl;
30 33 import gov.nist.javax.sip.stack.SIPDialog;
31 34 import org.slf4j.Logger;
32 35 import org.slf4j.LoggerFactory;
33 36 import org.springframework.beans.factory.annotation.Autowired;
34 37 import org.springframework.beans.factory.annotation.Qualifier;
35 38 import org.springframework.context.annotation.DependsOn;
  39 +import org.springframework.context.annotation.Lazy;
36 40 import org.springframework.stereotype.Component;
37 41 import org.springframework.util.ObjectUtils;
38 42  
... ... @@ -41,765 +45,598 @@ import javax.sip.address.Address;
41 45 import javax.sip.address.SipURI;
42 46 import javax.sip.header.*;
43 47 import javax.sip.message.Request;
  48 +import javax.sip.message.Response;
44 49 import java.lang.reflect.Field;
45 50 import java.text.ParseException;
46 51 import java.util.ArrayList;
47 52 import java.util.HashSet;
48 53 import java.util.List;
49 54  
50   -/**
51   - * @description:设备能力接口,用于定义设备的控制、查询能力
  55 +/**
  56 + * @description:设备能力接口,用于定义设备的控制、查询能力
52 57 * @author: swwheihei
53   - * @date: 2020年5月3日 下午9:22:48
  58 + * @date: 2020年5月3日 下午9:22:48
54 59 */
55 60 @Component
56 61 @DependsOn("sipLayer")
57 62 public class SIPCommander implements ISIPCommander {
58 63  
59   - private final Logger logger = LoggerFactory.getLogger(SIPCommander.class);
60   -
61   - @Autowired
62   - private SipConfig sipConfig;
63   -
64   - @Autowired
65   - private SipFactory sipFactory;
66   -
67   - @Autowired
68   - private GitUtil gitUtil;
69   -
70   - @Autowired
71   - @Qualifier(value="tcpSipProvider")
72   - private SipProviderImpl tcpSipProvider;
73   -
74   - @Autowired
75   - @Qualifier(value="udpSipProvider")
76   - private SipProviderImpl udpSipProvider;
77   -
78   - @Autowired
79   - private SIPRequestHeaderProvider headerProvider;
80   -
81   - @Autowired
82   - private VideoStreamSessionManager streamSession;
83   -
84   - @Autowired
85   - private IVideoManagerStorage storager;
86   -
87   - @Autowired
88   - private IRedisCatchStorage redisCatchStorage;
89   -
90   - @Autowired
91   - private UserSetting userSetting;
92   -
93   - @Autowired
94   - private ZlmHttpHookSubscribe subscribe;
95   -
96   - @Autowired
97   - private SipSubscribe sipSubscribe;
98   -
99   - @Autowired
100   - private IMediaServerService mediaServerService;
101   -
102   - @Autowired
103   - private DynamicTask dynamicTask;
104   -
105   -
106   - /**
107   - * 云台方向放控制,使用配置文件中的默认镜头移动速度
108   - *
109   - * @param device 控制设备
110   - * @param channelId 预览通道
111   - * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
112   - * @param upDown 镜头上移下移 0:停止 1:上移 2:下移
113   - */
114   - @Override
115   - public boolean ptzdirectCmd(Device device, String channelId, int leftRight, int upDown) {
116   - return ptzCmd(device, channelId, leftRight, upDown, 0, sipConfig.getPtzSpeed(), 0);
117   - }
118   -
119   - /**
120   - * 云台方向放控制
121   - *
122   - * @param device 控制设备
123   - * @param channelId 预览通道
124   - * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
125   - * @param upDown 镜头上移下移 0:停止 1:上移 2:下移
126   - * @param moveSpeed 镜头移动速度
127   - */
128   - @Override
129   - public boolean ptzdirectCmd(Device device, String channelId, int leftRight, int upDown, int moveSpeed) {
130   - return ptzCmd(device, channelId, leftRight, upDown, 0, moveSpeed, 0);
131   - }
132   -
133   - /**
134   - * 云台缩放控制,使用配置文件中的默认镜头缩放速度
135   - *
136   - * @param device 控制设备
137   - * @param channelId 预览通道
138   - * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
139   - */
140   - @Override
141   - public boolean ptzZoomCmd(Device device, String channelId, int inOut) {
142   - return ptzCmd(device, channelId, 0, 0, inOut, 0, sipConfig.getPtzSpeed());
143   - }
144   -
145   - /**
146   - * 云台缩放控制
147   - *
148   - * @param device 控制设备
149   - * @param channelId 预览通道
150   - * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
151   - * @param zoomSpeed 镜头缩放速度
152   - */
153   - @Override
154   - public boolean ptzZoomCmd(Device device, String channelId, int inOut, int zoomSpeed) {
155   - return ptzCmd(device, channelId, 0, 0, inOut, 0, zoomSpeed);
156   - }
157   -
158   - /**
159   - * 云台指令码计算
160   - *
161   - * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
162   - * @param upDown 镜头上移下移 0:停止 1:上移 2:下移
163   - * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
164   - * @param moveSpeed 镜头移动速度 默认 0XFF (0-255)
165   - * @param zoomSpeed 镜头缩放速度 默认 0X1 (0-255)
166   - */
167   - public static String cmdString(int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed) {
168   - int cmdCode = 0;
169   - if (leftRight == 2) {
170   - cmdCode|=0x01; // 右移
171   - } else if(leftRight == 1) {
172   - cmdCode|=0x02; // 左移
173   - }
174   - if (upDown == 2) {
175   - cmdCode|=0x04; // 下移
176   - } else if(upDown == 1) {
177   - cmdCode|=0x08; // 上移
178   - }
179   - if (inOut == 2) {
180   - cmdCode |= 0x10; // 放大
181   - } else if(inOut == 1) {
182   - cmdCode |= 0x20; // 缩小
183   - }
184   - StringBuilder builder = new StringBuilder("A50F01");
185   - String strTmp;
186   - strTmp = String.format("%02X", cmdCode);
187   - builder.append(strTmp, 0, 2);
188   - strTmp = String.format("%02X", moveSpeed);
189   - builder.append(strTmp, 0, 2);
190   - builder.append(strTmp, 0, 2);
191   - strTmp = String.format("%X", zoomSpeed);
192   - builder.append(strTmp, 0, 1).append("0");
193   - //计算校验码
194   - int checkCode = (0XA5 + 0X0F + 0X01 + cmdCode + moveSpeed + moveSpeed + (zoomSpeed /*<< 4*/ & 0XF0)) % 0X100;
195   - strTmp = String.format("%02X", checkCode);
196   - builder.append(strTmp, 0, 2);
197   - return builder.toString();
198   -}
199   -
200   - /**
201   - * 云台指令码计算
202   - *
203   - * @param cmdCode 指令码
204   - * @param parameter1 数据1
205   - * @param parameter2 数据2
206   - * @param combineCode2 组合码2
207   - */
  64 + private final Logger logger = LoggerFactory.getLogger(SIPCommander.class);
  65 +
  66 + @Autowired
  67 + private SipConfig sipConfig;
  68 +
  69 + @Autowired
  70 + private SipFactory sipFactory;
  71 +
  72 + @Autowired
  73 + private GitUtil gitUtil;
  74 +
  75 + @Autowired
  76 + @Qualifier(value = "tcpSipProvider")
  77 + private SipProviderImpl tcpSipProvider;
  78 +
  79 + @Autowired
  80 + @Qualifier(value = "udpSipProvider")
  81 + private SipProviderImpl udpSipProvider;
  82 +
  83 + @Autowired
  84 + private SIPRequestHeaderProvider headerProvider;
  85 +
  86 + @Autowired
  87 + private VideoStreamSessionManager streamSession;
  88 +
  89 + @Autowired
  90 + private UserSetting userSetting;
  91 +
  92 + @Autowired
  93 + private ZlmHttpHookSubscribe subscribe;
  94 +
  95 + @Autowired
  96 + private SipSubscribe sipSubscribe;
  97 +
  98 + @Autowired
  99 + private IMediaServerService mediaServerService;
  100 +
  101 +
  102 + /**
  103 + * 云台方向放控制,使用配置文件中的默认镜头移动速度
  104 + *
  105 + * @param device 控制设备
  106 + * @param channelId 预览通道
  107 + * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
  108 + * @param upDown 镜头上移下移 0:停止 1:上移 2:下移
  109 + */
  110 + @Override
  111 + public void ptzdirectCmd(Device device, String channelId, int leftRight, int upDown) throws InvalidArgumentException, ParseException, SipException {
  112 + ptzCmd(device, channelId, leftRight, upDown, 0, sipConfig.getPtzSpeed(), 0);
  113 + }
  114 +
  115 + /**
  116 + * 云台方向放控制
  117 + *
  118 + * @param device 控制设备
  119 + * @param channelId 预览通道
  120 + * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
  121 + * @param upDown 镜头上移下移 0:停止 1:上移 2:下移
  122 + * @param moveSpeed 镜头移动速度
  123 + */
  124 + @Override
  125 + public void ptzdirectCmd(Device device, String channelId, int leftRight, int upDown, int moveSpeed) throws InvalidArgumentException, ParseException, SipException {
  126 + ptzCmd(device, channelId, leftRight, upDown, 0, moveSpeed, 0);
  127 + }
  128 +
  129 + /**
  130 + * 云台缩放控制,使用配置文件中的默认镜头缩放速度
  131 + *
  132 + * @param device 控制设备
  133 + * @param channelId 预览通道
  134 + * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
  135 + */
  136 + @Override
  137 + public void ptzZoomCmd(Device device, String channelId, int inOut) throws InvalidArgumentException, ParseException, SipException {
  138 + ptzCmd(device, channelId, 0, 0, inOut, 0, sipConfig.getPtzSpeed());
  139 + }
  140 +
  141 + /**
  142 + * 云台缩放控制
  143 + *
  144 + * @param device 控制设备
  145 + * @param channelId 预览通道
  146 + * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
  147 + * @param zoomSpeed 镜头缩放速度
  148 + */
  149 + @Override
  150 + public void ptzZoomCmd(Device device, String channelId, int inOut, int zoomSpeed) throws InvalidArgumentException, ParseException, SipException {
  151 + ptzCmd(device, channelId, 0, 0, inOut, 0, zoomSpeed);
  152 + }
  153 +
  154 + /**
  155 + * 云台指令码计算
  156 + *
  157 + * @param cmdCode 指令码
  158 + * @param parameter1 数据1
  159 + * @param parameter2 数据2
  160 + * @param combineCode2 组合码2
  161 + */
208 162 public static String frontEndCmdString(int cmdCode, int parameter1, int parameter2, int combineCode2) {
209   - StringBuilder builder = new StringBuilder("A50F01");
210   - String strTmp;
211   - strTmp = String.format("%02X", cmdCode);
212   - builder.append(strTmp, 0, 2);
213   - strTmp = String.format("%02X", parameter1);
214   - builder.append(strTmp, 0, 2);
215   - strTmp = String.format("%02X", parameter2);
216   - builder.append(strTmp, 0, 2);
217   - strTmp = String.format("%X", combineCode2);
218   - builder.append(strTmp, 0, 1).append("0");
219   - //计算校验码
220   - int checkCode = (0XA5 + 0X0F + 0X01 + cmdCode + parameter1 + parameter2 + (combineCode2 & 0XF0)) % 0X100;
221   - strTmp = String.format("%02X", checkCode);
222   - builder.append(strTmp, 0, 2);
223   - return builder.toString();
224   - }
225   -
226   - /**
227   - * 云台控制,支持方向与缩放控制
228   - *
229   - * @param device 控制设备
230   - * @param channelId 预览通道
231   - * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
232   - * @param upDown 镜头上移下移 0:停止 1:上移 2:下移
233   - * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
234   - * @param moveSpeed 镜头移动速度
235   - * @param zoomSpeed 镜头缩放速度
236   - */
237   - @Override
238   - public boolean ptzCmd(Device device, String channelId, int leftRight, int upDown, int inOut, int moveSpeed,
239   - int zoomSpeed) {
240   - try {
241   - String cmdStr= cmdString(leftRight, upDown, inOut, moveSpeed, zoomSpeed);
242   - StringBuffer ptzXml = new StringBuffer(200);
243   - String charset = device.getCharset();
244   - ptzXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
245   - ptzXml.append("<Control>\r\n");
246   - ptzXml.append("<CmdType>DeviceControl</CmdType>\r\n");
247   - ptzXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
248   - ptzXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
249   - ptzXml.append("<PTZCmd>" + cmdStr + "</PTZCmd>\r\n");
250   - ptzXml.append("<Info>\r\n");
251   - ptzXml.append("<ControlPriority>5</ControlPriority>\r\n");
252   - ptzXml.append("</Info>\r\n");
253   - ptzXml.append("</Control>\r\n");
254   -
255   - CallIdHeader callIdHeader = device.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
256   - : udpSipProvider.getNewCallId();
257   -
258   - Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
259   -
260   - transmitRequest(device, request);
261   - return true;
262   - } catch (SipException | ParseException | InvalidArgumentException e) {
263   - e.printStackTrace();
264   - }
265   - return false;
266   - }
267   -
268   - /**
269   - * 前端控制,包括PTZ指令、FI指令、预置位指令、巡航指令、扫描指令和辅助开关指令
270   - *
271   - * @param device 控制设备
272   - * @param channelId 预览通道
273   - * @param cmdCode 指令码
274   - * @param parameter1 数据1
275   - * @param parameter2 数据2
276   - * @param combineCode2 组合码2
277   - */
278   - @Override
279   - public boolean frontEndCmd(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combineCode2) {
280   - try {
281   - String cmdStr= frontEndCmdString(cmdCode, parameter1, parameter2, combineCode2);
282   - logger.debug("控制字符串:" + cmdStr);
283   - StringBuffer ptzXml = new StringBuffer(200);
284   - String charset = device.getCharset();
285   - ptzXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
286   - ptzXml.append("<Control>\r\n");
287   - ptzXml.append("<CmdType>DeviceControl</CmdType>\r\n");
288   - ptzXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
289   - ptzXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
290   - ptzXml.append("<PTZCmd>" + cmdStr + "</PTZCmd>\r\n");
291   - ptzXml.append("<Info>\r\n");
292   - ptzXml.append("<ControlPriority>5</ControlPriority>\r\n");
293   - ptzXml.append("</Info>\r\n");
294   - ptzXml.append("</Control>\r\n");
295   -
296   -
297   - CallIdHeader callIdHeader = device.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
298   - : udpSipProvider.getNewCallId();
299   -
300   - Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
301   - transmitRequest(device, request);
302   - return true;
303   - } catch (SipException | ParseException | InvalidArgumentException e) {
304   - e.printStackTrace();
305   - }
306   - return false;
307   - }
308   -
309   - /**
310   - * 前端控制指令(用于转发上级指令)
311   - * @param device 控制设备
312   - * @param channelId 预览通道
313   - * @param cmdString 前端控制指令串
314   - */
315   - @Override
316   - public boolean fronEndCmd(Device device, String channelId, String cmdString, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) {
317   - try {
318   - StringBuffer ptzXml = new StringBuffer(200);
319   - String charset = device.getCharset();
320   - ptzXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
321   - ptzXml.append("<Control>\r\n");
322   - ptzXml.append("<CmdType>DeviceControl</CmdType>\r\n");
323   - ptzXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
324   - ptzXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
325   - ptzXml.append("<PTZCmd>" + cmdString + "</PTZCmd>\r\n");
326   - ptzXml.append("<Info>\r\n");
327   - ptzXml.append("<ControlPriority>5</ControlPriority>\r\n");
328   - ptzXml.append("</Info>\r\n");
329   - ptzXml.append("</Control>\r\n");
330   -
331   -
332   - CallIdHeader callIdHeader = device.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
333   - : udpSipProvider.getNewCallId();
334   -
335   - Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
336   - transmitRequest(device, request, errorEvent, okEvent);
337   - return true;
338   - } catch (SipException | ParseException | InvalidArgumentException e) {
339   - e.printStackTrace();
340   - }
341   - return false;
342   - }
343   -
344   - /**
345   - * 请求预览视频流
346   - * @param device 视频设备
347   - * @param channelId 预览通道
348   - * @param event hook订阅
349   - * @param errorEvent sip错误订阅
350   - */
351   - @Override
352   - public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
353   - ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) {
354   - String stream = ssrcInfo.getStream();
355   - try {
356   - if (device == null) {
357   - return;
358   - }
359   -// String streamMode = device.getStreamMode().toUpperCase();
360   -
361   - logger.info("{} 分配的ZLM为: {} [{}:{}]", stream, mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
362   - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtsp", mediaServerItem.getId());
363   - subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json)->{
364   - if (event != null) {
365   - event.response(mediaServerItemInUse, json);
366   - subscribe.removeSubscribe(hookSubscribe);
367   - }
368   - });
369   - //
370   - StringBuffer content = new StringBuffer(200);
371   - content.append("v=0\r\n");
372   - content.append("o="+ channelId+" 0 0 IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n");
373   - content.append("s=Play\r\n");
374   - content.append("c=IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n");
375   - content.append("t=0 0\r\n");
376   -
377   - if (userSetting.isSeniorSdp()) {
378   - if("TCP-PASSIVE".equalsIgnoreCase(device.getStreamMode())) {
379   - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
380   - }else if ("TCP-ACTIVE".equalsIgnoreCase(device.getStreamMode())) {
381   - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
382   - }else if("UDP".equalsIgnoreCase(device.getStreamMode())) {
383   - content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 126 125 99 34 98 97\r\n");
384   - }
385   - content.append("a=recvonly\r\n");
386   - content.append("a=rtpmap:96 PS/90000\r\n");
387   - content.append("a=fmtp:126 profile-level-id=42e01e\r\n");
388   - content.append("a=rtpmap:126 H264/90000\r\n");
389   - content.append("a=rtpmap:125 H264S/90000\r\n");
390   - content.append("a=fmtp:125 profile-level-id=42e01e\r\n");
391   - content.append("a=rtpmap:99 H265/90000\r\n");
392   - content.append("a=rtpmap:98 H264/90000\r\n");
393   - content.append("a=rtpmap:97 MPEG4/90000\r\n");
394   - if("TCP-PASSIVE".equalsIgnoreCase(device.getStreamMode())){ // tcp被动模式
395   - content.append("a=setup:passive\r\n");
396   - content.append("a=connection:new\r\n");
397   - }else if ("TCP-ACTIVE".equalsIgnoreCase(device.getStreamMode())) { // tcp主动模式
398   - content.append("a=setup:active\r\n");
399   - content.append("a=connection:new\r\n");
400   - }
401   - }else {
402   - if("TCP-PASSIVE".equalsIgnoreCase(device.getStreamMode())) {
403   - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 97 98 99\r\n");
404   - }else if ("TCP-ACTIVE".equalsIgnoreCase(device.getStreamMode())) {
405   - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 97 98 99\r\n");
406   - }else if("UDP".equalsIgnoreCase(device.getStreamMode())) {
407   - content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 97 98 99\r\n");
408   - }
409   - content.append("a=recvonly\r\n");
410   - content.append("a=rtpmap:96 PS/90000\r\n");
411   - content.append("a=rtpmap:98 H264/90000\r\n");
412   - content.append("a=rtpmap:97 MPEG4/90000\r\n");
413   - content.append("a=rtpmap:99 H265/90000\r\n");
414   - if ("TCP-PASSIVE".equalsIgnoreCase(device.getStreamMode())) { // tcp被动模式
415   - content.append("a=setup:passive\r\n");
416   - content.append("a=connection:new\r\n");
417   - } else if ("TCP-ACTIVE".equalsIgnoreCase(device.getStreamMode())) { // tcp主动模式
418   - content.append("a=setup:active\r\n");
419   - content.append("a=connection:new\r\n");
420   - }
421   - }
422   -
423   - content.append("y="+ssrcInfo.getSsrc()+"\r\n");//ssrc
424   - // f字段:f= v/编码格式/分辨率/帧率/码率类型/码率大小a/编码格式/码率大小/采样率
  163 + StringBuilder builder = new StringBuilder("A50F01");
  164 + String strTmp;
  165 + strTmp = String.format("%02X", cmdCode);
  166 + builder.append(strTmp, 0, 2);
  167 + strTmp = String.format("%02X", parameter1);
  168 + builder.append(strTmp, 0, 2);
  169 + strTmp = String.format("%02X", parameter2);
  170 + builder.append(strTmp, 0, 2);
  171 + strTmp = String.format("%X", combineCode2);
  172 + builder.append(strTmp, 0, 1).append("0");
  173 + //计算校验码
  174 + int checkCode = (0XA5 + 0X0F + 0X01 + cmdCode + parameter1 + parameter2 + (combineCode2 & 0XF0)) % 0X100;
  175 + strTmp = String.format("%02X", checkCode);
  176 + builder.append(strTmp, 0, 2);
  177 + return builder.toString();
  178 + }
  179 +
  180 + /**
  181 + * 云台控制,支持方向与缩放控制
  182 + *
  183 + * @param device 控制设备
  184 + * @param channelId 预览通道
  185 + * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
  186 + * @param upDown 镜头上移下移 0:停止 1:上移 2:下移
  187 + * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
  188 + * @param moveSpeed 镜头移动速度
  189 + * @param zoomSpeed 镜头缩放速度
  190 + */
  191 + @Override
  192 + public void ptzCmd(Device device, String channelId, int leftRight, int upDown, int inOut, int moveSpeed,
  193 + int zoomSpeed) throws InvalidArgumentException, SipException, ParseException {
  194 + String cmdStr = SipUtils.cmdString(leftRight, upDown, inOut, moveSpeed, zoomSpeed);
  195 + StringBuffer ptzXml = new StringBuffer(200);
  196 + String charset = device.getCharset();
  197 + ptzXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  198 + ptzXml.append("<Control>\r\n");
  199 + ptzXml.append("<CmdType>DeviceControl</CmdType>\r\n");
  200 + ptzXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  201 + ptzXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
  202 + ptzXml.append("<PTZCmd>" + cmdStr + "</PTZCmd>\r\n");
  203 + ptzXml.append("<Info>\r\n");
  204 + ptzXml.append("<ControlPriority>5</ControlPriority>\r\n");
  205 + ptzXml.append("</Info>\r\n");
  206 + ptzXml.append("</Control>\r\n");
  207 +
  208 + CallIdHeader callIdHeader = device.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
  209 + : udpSipProvider.getNewCallId();
  210 +
  211 + Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
  212 +
  213 + transmitRequest(device.getTransport(), request);
  214 + }
  215 +
  216 + /**
  217 + * 前端控制,包括PTZ指令、FI指令、预置位指令、巡航指令、扫描指令和辅助开关指令
  218 + *
  219 + * @param device 控制设备
  220 + * @param channelId 预览通道
  221 + * @param cmdCode 指令码
  222 + * @param parameter1 数据1
  223 + * @param parameter2 数据2
  224 + * @param combineCode2 组合码2
  225 + */
  226 + @Override
  227 + public void frontEndCmd(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combineCode2) throws SipException, InvalidArgumentException, ParseException {
  228 +
  229 + String cmdStr = frontEndCmdString(cmdCode, parameter1, parameter2, combineCode2);
  230 + StringBuffer ptzXml = new StringBuffer(200);
  231 + String charset = device.getCharset();
  232 + ptzXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  233 + ptzXml.append("<Control>\r\n");
  234 + ptzXml.append("<CmdType>DeviceControl</CmdType>\r\n");
  235 + ptzXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  236 + ptzXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
  237 + ptzXml.append("<PTZCmd>" + cmdStr + "</PTZCmd>\r\n");
  238 + ptzXml.append("<Info>\r\n");
  239 + ptzXml.append("<ControlPriority>5</ControlPriority>\r\n");
  240 + ptzXml.append("</Info>\r\n");
  241 + ptzXml.append("</Control>\r\n");
  242 +
  243 +
  244 + CallIdHeader callIdHeader = device.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
  245 + : udpSipProvider.getNewCallId();
  246 +
  247 + SIPRequest request = (SIPRequest) headerProvider.createMessageRequest(device, ptzXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
  248 + transmitRequest(device.getTransport(), request);
  249 +
  250 + }
  251 +
  252 + /**
  253 + * 前端控制指令(用于转发上级指令)
  254 + *
  255 + * @param device 控制设备
  256 + * @param channelId 预览通道
  257 + * @param cmdString 前端控制指令串
  258 + */
  259 + @Override
  260 + public void fronEndCmd(Device device, String channelId, String cmdString, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException {
  261 +
  262 + StringBuffer ptzXml = new StringBuffer(200);
  263 + String charset = device.getCharset();
  264 + ptzXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  265 + ptzXml.append("<Control>\r\n");
  266 + ptzXml.append("<CmdType>DeviceControl</CmdType>\r\n");
  267 + ptzXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  268 + ptzXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
  269 + ptzXml.append("<PTZCmd>" + cmdString + "</PTZCmd>\r\n");
  270 + ptzXml.append("<Info>\r\n");
  271 + ptzXml.append("<ControlPriority>5</ControlPriority>\r\n");
  272 + ptzXml.append("</Info>\r\n");
  273 + ptzXml.append("</Control>\r\n");
  274 +
  275 +
  276 + CallIdHeader callIdHeader = device.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
  277 + : udpSipProvider.getNewCallId();
  278 +
  279 + Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
  280 + transmitRequest(device.getTransport(), request, errorEvent, okEvent);
  281 +
  282 + }
  283 +
  284 + /**
  285 + * 请求预览视频流
  286 + *
  287 + * @param device 视频设备
  288 + * @param channelId 预览通道
  289 + * @param event hook订阅
  290 + * @param errorEvent sip错误订阅
  291 + */
  292 + @Override
  293 + public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
  294 + ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  295 + String stream = ssrcInfo.getStream();
  296 +
  297 + if (device == null) {
  298 + return;
  299 + }
  300 +
  301 + logger.info("{} 分配的ZLM为: {} [{}:{}]", stream, mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
  302 + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtsp", mediaServerItem.getId());
  303 + subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json) -> {
  304 + if (event != null) {
  305 + event.response(mediaServerItemInUse, json);
  306 + subscribe.removeSubscribe(hookSubscribe);
  307 + }
  308 + });
  309 + //
  310 + StringBuffer content = new StringBuffer(200);
  311 + content.append("v=0\r\n");
  312 + content.append("o=" + channelId + " 0 0 IN IP4 " + mediaServerItem.getSdpIp() + "\r\n");
  313 + content.append("s=Play\r\n");
  314 + content.append("c=IN IP4 " + mediaServerItem.getSdpIp() + "\r\n");
  315 + content.append("t=0 0\r\n");
  316 +
  317 + if (userSetting.isSeniorSdp()) {
  318 + if ("TCP-PASSIVE".equalsIgnoreCase(device.getStreamMode())) {
  319 + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
  320 + } else if ("TCP-ACTIVE".equalsIgnoreCase(device.getStreamMode())) {
  321 + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
  322 + } else if ("UDP".equalsIgnoreCase(device.getStreamMode())) {
  323 + content.append("m=video " + ssrcInfo.getPort() + " RTP/AVP 96 126 125 99 34 98 97\r\n");
  324 + }
  325 + content.append("a=recvonly\r\n");
  326 + content.append("a=rtpmap:96 PS/90000\r\n");
  327 + content.append("a=fmtp:126 profile-level-id=42e01e\r\n");
  328 + content.append("a=rtpmap:126 H264/90000\r\n");
  329 + content.append("a=rtpmap:125 H264S/90000\r\n");
  330 + content.append("a=fmtp:125 profile-level-id=42e01e\r\n");
  331 + content.append("a=rtpmap:99 H265/90000\r\n");
  332 + content.append("a=rtpmap:98 H264/90000\r\n");
  333 + content.append("a=rtpmap:97 MPEG4/90000\r\n");
  334 + if ("TCP-PASSIVE".equalsIgnoreCase(device.getStreamMode())) { // tcp被动模式
  335 + content.append("a=setup:passive\r\n");
  336 + content.append("a=connection:new\r\n");
  337 + } else if ("TCP-ACTIVE".equalsIgnoreCase(device.getStreamMode())) { // tcp主动模式
  338 + content.append("a=setup:active\r\n");
  339 + content.append("a=connection:new\r\n");
  340 + }
  341 + } else {
  342 + if ("TCP-PASSIVE".equalsIgnoreCase(device.getStreamMode())) {
  343 + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 97 98 99\r\n");
  344 + } else if ("TCP-ACTIVE".equalsIgnoreCase(device.getStreamMode())) {
  345 + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 97 98 99\r\n");
  346 + } else if ("UDP".equalsIgnoreCase(device.getStreamMode())) {
  347 + content.append("m=video " + ssrcInfo.getPort() + " RTP/AVP 96 97 98 99\r\n");
  348 + }
  349 + content.append("a=recvonly\r\n");
  350 + content.append("a=rtpmap:96 PS/90000\r\n");
  351 + content.append("a=rtpmap:98 H264/90000\r\n");
  352 + content.append("a=rtpmap:97 MPEG4/90000\r\n");
  353 + content.append("a=rtpmap:99 H265/90000\r\n");
  354 + if ("TCP-PASSIVE".equalsIgnoreCase(device.getStreamMode())) { // tcp被动模式
  355 + content.append("a=setup:passive\r\n");
  356 + content.append("a=connection:new\r\n");
  357 + } else if ("TCP-ACTIVE".equalsIgnoreCase(device.getStreamMode())) { // tcp主动模式
  358 + content.append("a=setup:active\r\n");
  359 + content.append("a=connection:new\r\n");
  360 + }
  361 + }
  362 +
  363 + content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc
  364 + // f字段:f= v/编码格式/分辨率/帧率/码率类型/码率大小a/编码格式/码率大小/采样率
425 365 // content.append("f=v/2/5/25/1/4000a/1/8/1" + "\r\n"); // 未发现支持此特性的设备
426 366  
427   - CallIdHeader callIdHeader = device.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
428   - : udpSipProvider.getNewCallId();
429   -
430   - Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), null, SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(), callIdHeader);
431   -
432   - transmitRequest(device, request, (e -> {
433   - streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
434   - mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
435   - errorEvent.response(e);
436   - }), e ->{
437   - // 这里为例避免一个通道的点播只有一个callID这个参数使用一个固定值
438   - streamSession.put(device.getDeviceId(), channelId ,"play", stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), ((ResponseEvent)e.event).getClientTransaction(), VideoStreamSessionManager.SessionType.play);
439   - Dialog sipDialog = null;
440   - if (e.dialog == null) {
441   - SIPClientTransaction clientTransaction = (SIPClientTransaction)((ResponseEvent)e.event).getClientTransaction();
442   - sipDialog = new SIPDialog(clientTransaction, clientTransaction.getLastResponse());
443   - }else {
444   - sipDialog = e.dialog;
445   - }
446   - streamSession.put(device.getDeviceId(), channelId ,"play", sipDialog);
447   - okEvent.response(e);
448   - });
449   -
450   -
451   - } catch ( SipException | ParseException | InvalidArgumentException e) {
452   - e.printStackTrace();
453   - }
454   - }
455   -
456   - /**
457   - * 请求回放视频流
458   - *
459   - * @param device 视频设备
460   - * @param channelId 预览通道
461   - * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
462   - * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
463   - */
464   - @Override
465   - public void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
466   - String startTime, String endTime, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent,
467   - SipSubscribe.Event okEvent,SipSubscribe.Event errorEvent) {
468   - try {
469   -
470   - logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
471   -
472   - StringBuffer content = new StringBuffer(200);
473   - content.append("v=0\r\n");
474   - content.append("o="+channelId+" 0 0 IN IP4 " + mediaServerItem.getSdpIp() + "\r\n");
475   - content.append("s=Playback\r\n");
476   - content.append("u="+channelId+":0\r\n");
477   - content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n");
478   - content.append("t="+DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime)+" "
479   - +DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime) +"\r\n");
480   -
481   - String streamMode = device.getStreamMode();
482   -
483   - if (userSetting.isSeniorSdp()) {
484   - if("TCP-PASSIVE".equalsIgnoreCase(streamMode)) {
485   - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
486   - }else if ("TCP-ACTIVE".equalsIgnoreCase(streamMode)) {
487   - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
488   - }else if("UDP".equalsIgnoreCase(streamMode)) {
489   - content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 126 125 99 34 98 97\r\n");
490   - }
491   - content.append("a=recvonly\r\n");
492   - content.append("a=rtpmap:96 PS/90000\r\n");
493   - content.append("a=fmtp:126 profile-level-id=42e01e\r\n");
494   - content.append("a=rtpmap:126 H264/90000\r\n");
495   - content.append("a=rtpmap:125 H264S/90000\r\n");
496   - content.append("a=fmtp:125 profile-level-id=42e01e\r\n");
497   - content.append("a=rtpmap:99 H265/90000\r\n");
498   - content.append("a=rtpmap:98 H264/90000\r\n");
499   - content.append("a=rtpmap:97 MPEG4/90000\r\n");
500   - if("TCP-PASSIVE".equalsIgnoreCase(streamMode)){ // tcp被动模式
501   - content.append("a=setup:passive\r\n");
502   - content.append("a=connection:new\r\n");
503   - }else if ("TCP-ACTIVE".equalsIgnoreCase(streamMode)) { // tcp主动模式
504   - content.append("a=setup:active\r\n");
505   - content.append("a=connection:new\r\n");
506   - }
507   - }else {
508   - if("TCP-PASSIVE".equalsIgnoreCase(streamMode)) {
509   - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 97 98 99\r\n");
510   - }else if ("TCP-ACTIVE".equalsIgnoreCase(streamMode)) {
511   - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 97 98 99\r\n");
512   - }else if("UDP".equalsIgnoreCase(streamMode)) {
513   - content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 97 98 99\r\n");
514   - }
515   - content.append("a=recvonly\r\n");
516   - content.append("a=rtpmap:96 PS/90000\r\n");
517   - content.append("a=rtpmap:97 MPEG4/90000\r\n");
518   - content.append("a=rtpmap:98 H264/90000\r\n");
519   - content.append("a=rtpmap:99 H265/90000\r\n");
520   - if("TCP-PASSIVE".equalsIgnoreCase(streamMode)){ // tcp被动模式
521   - content.append("a=setup:passive\r\n");
522   - content.append("a=connection:new\r\n");
523   - }else if ("TCP-ACTIVE".equalsIgnoreCase(streamMode)) { // tcp主动模式
524   - content.append("a=setup:active\r\n");
525   - content.append("a=connection:new\r\n");
526   - }
527   - }
528   -
529   - content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc
530   -
531   - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
532   - : udpSipProvider.getNewCallId();
533   - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId());
534   - // 添加订阅
535   - subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json)->{
536   - if (hookEvent != null) {
537   - InviteStreamInfo inviteStreamInfo = new InviteStreamInfo(mediaServerItemInUse, json, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream());
538   - hookEvent.call(inviteStreamInfo);
539   - }
540   - subscribe.removeSubscribe(hookSubscribe);
541   - });
542   - Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader, ssrcInfo.getSsrc());
543   -
544   - transmitRequest(device, request, errorEvent, event -> {
545   - ResponseEvent responseEvent = (ResponseEvent) event.event;
546   - streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), responseEvent.getClientTransaction(), VideoStreamSessionManager.SessionType.playback);
547   - streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), event.dialog);
548   - okEvent.response(event);
549   - });
550   - if (inviteStreamCallback != null) {
551   - inviteStreamCallback.call(new InviteStreamInfo(mediaServerItem, null, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream()));
552   - }
553   - } catch ( SipException | ParseException | InvalidArgumentException e) {
554   - e.printStackTrace();
555   - }
556   - }
557   -
558   - /**
559   - * 请求历史媒体下载
560   - *
561   - * @param device 视频设备
562   - * @param channelId 预览通道
563   - * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
564   - * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
565   - * @param downloadSpeed 下载倍速参数
566   - */
567   - @Override
568   - public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
569   - String startTime, String endTime, int downloadSpeed, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent,
570   - SipSubscribe.Event errorEvent) {
571   - try {
572   - logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
573   -
574   - StringBuffer content = new StringBuffer(200);
575   - content.append("v=0\r\n");
576   - content.append("o="+channelId+" 0 0 IN IP4 " + mediaServerItem.getSdpIp() + "\r\n");
577   - content.append("s=Download\r\n");
578   - content.append("u="+channelId+":0\r\n");
579   - content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n");
580   - content.append("t="+DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime)+" "
581   - +DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime) +"\r\n");
582   -
583   - String streamMode = device.getStreamMode().toUpperCase();
584   -
585   - if (userSetting.isSeniorSdp()) {
586   - if("TCP-PASSIVE".equals(streamMode)) {
587   - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
588   - }else if ("TCP-ACTIVE".equals(streamMode)) {
589   - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
590   - }else if("UDP".equals(streamMode)) {
591   - content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 126 125 99 34 98 97\r\n");
592   - }
593   - content.append("a=recvonly\r\n");
594   - content.append("a=rtpmap:96 PS/90000\r\n");
595   - content.append("a=fmtp:126 profile-level-id=42e01e\r\n");
596   - content.append("a=rtpmap:126 H264/90000\r\n");
597   - content.append("a=rtpmap:125 H264S/90000\r\n");
598   - content.append("a=fmtp:125 profile-level-id=42e01e\r\n");
599   - content.append("a=rtpmap:99 MP4V-ES/90000\r\n");
600   - content.append("a=fmtp:99 profile-level-id=3\r\n");
601   - content.append("a=rtpmap:98 H264/90000\r\n");
602   - content.append("a=rtpmap:97 MPEG4/90000\r\n");
603   - if("TCP-PASSIVE".equals(streamMode)){ // tcp被动模式
604   - content.append("a=setup:passive\r\n");
605   - content.append("a=connection:new\r\n");
606   - }else if ("TCP-ACTIVE".equals(streamMode)) { // tcp主动模式
607   - content.append("a=setup:active\r\n");
608   - content.append("a=connection:new\r\n");
609   - }
610   - }else {
611   - if("TCP-PASSIVE".equals(streamMode)) {
612   - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 97 98 99\r\n");
613   - }else if ("TCP-ACTIVE".equals(streamMode)) {
614   - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 97 98 99\r\n");
615   - }else if("UDP".equals(streamMode)) {
616   - content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 97 98 99\r\n");
617   - }
618   - content.append("a=recvonly\r\n");
619   - content.append("a=rtpmap:96 PS/90000\r\n");
620   - content.append("a=rtpmap:97 MPEG4/90000\r\n");
621   - content.append("a=rtpmap:98 H264/90000\r\n");
622   - content.append("a=rtpmap:99 H265/90000\r\n");
623   - if("TCP-PASSIVE".equals(streamMode)){ // tcp被动模式
624   - content.append("a=setup:passive\r\n");
625   - content.append("a=connection:new\r\n");
626   - }else if ("TCP-ACTIVE".equals(streamMode)) { // tcp主动模式
627   - content.append("a=setup:active\r\n");
628   - content.append("a=connection:new\r\n");
629   - }
630   - }
631   - content.append("a=downloadspeed:" + downloadSpeed + "\r\n");
632   -
633   - content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc
634   -
635   - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
636   - : udpSipProvider.getNewCallId();
637   -
638   - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, null, mediaServerItem.getId());
639   - // 添加订阅
640   - subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json)->{
641   - hookEvent.call(new InviteStreamInfo(mediaServerItem, json, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream()));
642   - subscribe.removeSubscribe(hookSubscribe);
643   - hookSubscribe.getContent().put("regist", false);
644   - hookSubscribe.getContent().put("schema", "rtsp");
645   - // 添加流注销的订阅,注销了后向设备发送bye
646   - subscribe.addSubscribe(hookSubscribe,
647   - (MediaServerItem mediaServerItemForEnd, JSONObject jsonForEnd)->{
648   - ClientTransaction transaction = streamSession.getTransaction(device.getDeviceId(), channelId, ssrcInfo.getStream(), callIdHeader.getCallId());
649   - if (transaction != null) {
650   - logger.info("[录像]下载结束, 发送BYE");
651   - streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), callIdHeader.getCallId());
652   - }
653   - });
654   - });
655   -
656   - Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader, ssrcInfo.getSsrc());
657   - if (inviteStreamCallback != null) {
658   - inviteStreamCallback.call(new InviteStreamInfo(mediaServerItem, null, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream()));
659   - }
660   - transmitRequest(device, request, errorEvent, okEvent->{
661   - ResponseEvent responseEvent = (ResponseEvent) okEvent.event;
662   - streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), responseEvent.getClientTransaction(), VideoStreamSessionManager.SessionType.download);
663   - streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), okEvent.dialog);
664   - });
665   -
666   -
667   - } catch ( SipException | ParseException | InvalidArgumentException e) {
668   - e.printStackTrace();
669   - }
670   - }
671   -
672   - /**
673   - * 视频流停止, 不使用回调
674   - */
675   - @Override
676   - public void streamByeCmd(String deviceId, String channelId, String stream, String callId) {
677   - streamByeCmd(deviceId, channelId, stream, callId, null);
678   - }
679   -
680   - @Override
681   - public void streamByeCmd(SIPDialog dialog, String channelId, SIPRequest request, SipSubscribe.Event okEvent) throws SipException, ParseException, InvalidArgumentException {
682   - Request byeRequest = dialog.createRequest(Request.BYE);
683   - SipURI byeURI = (SipURI) byeRequest.getRequestURI();
684   - byeURI.setHost(request.getRemoteAddress().getHostAddress());
685   - byeURI.setPort(request.getRemotePort());
686   - byeURI.setUser(channelId);
687   - ViaHeader viaHeader = (ViaHeader) byeRequest.getHeader(ViaHeader.NAME);
688   - String protocol = viaHeader.getTransport().toUpperCase();
689   - viaHeader.setRPort();
690   - // 增加Contact header
691   - Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getIp()+":"+sipConfig.getPort()));
692   - byeRequest.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
693   - UserAgentHeader userAgentHeader = HeaderUtils.createUserAgentHeader(sipFactory);
694   - byeRequest.addHeader(userAgentHeader);
695   - ClientTransaction clientTransaction = null;
696   - if("TCP".equals(protocol)) {
697   - clientTransaction = tcpSipProvider.getNewClientTransaction(byeRequest);
698   - } else if("UDP".equals(protocol)) {
699   - clientTransaction = udpSipProvider.getNewClientTransaction(byeRequest);
700   - }
701   -
702   - CallIdHeader callIdHeader = (CallIdHeader) byeRequest.getHeader(CallIdHeader.NAME);
703   - if (okEvent != null) {
704   - sipSubscribe.addOkSubscribe(callIdHeader.getCallId(), okEvent);
705   - }
706   - CSeqHeader cSeqHeader = (CSeqHeader)byeRequest.getHeader(CSeqHeader.NAME);
707   - cSeqHeader.setSeqNumber(redisCatchStorage.getCSEQ());
708   - dialog.sendRequest(clientTransaction);
709   -
710   - }
711   -
712   - /**
713   - * 视频流停止
714   - */
715   - @Override
716   - public void streamByeCmd(String deviceId, String channelId, String stream, String callId, SipSubscribe.Event okEvent) {
717   - try {
718   - SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(deviceId, channelId, callId, stream);
719   - ClientTransaction transaction = streamSession.getTransaction(deviceId, channelId, stream, callId);
720   -
721   - if (transaction == null ) {
722   - logger.warn("[ {} -> {}]停止视频流的时候发现事务已丢失", deviceId, channelId);
723   - SipSubscribe.EventResult<Object> eventResult = new SipSubscribe.EventResult<>();
724   - if (okEvent != null) {
725   - okEvent.response(eventResult);
726   - }
727   - return;
728   - }
729   - SIPDialog dialog;
730   - if (callId != null) {
731   - dialog = streamSession.getDialogByCallId(ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId(), callId);
732   - }else {
733   - if (stream == null && ssrcTransaction == null && ssrcTransaction.getStream() == null) {
734   - return;
735   - }
736   - dialog = streamSession.getDialogByStream(ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId(), ssrcTransaction.getStream());
737   - }
738   - mediaServerService.releaseSsrc(ssrcTransaction.getMediaServerId(), ssrcTransaction.getSsrc());
739   - mediaServerService.closeRTPServer(ssrcTransaction.getMediaServerId(), ssrcTransaction.getStream());
740   - streamSession.remove(ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId(), ssrcTransaction.getStream());
741   -
742   - if (dialog == null) {
743   - logger.warn("[ {} -> {}]停止视频流的时候发现对话已丢失", ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId());
744   - return;
745   - }
746   - SipStack sipStack = udpSipProvider.getSipStack();
747   - SIPDialog sipDialog = ((SipStackImpl) sipStack).putDialog(dialog);
748   - if (dialog != sipDialog) {
749   - dialog = sipDialog;
750   - }else {
751   - dialog.setSipProvider(udpSipProvider);
752   - try {
753   - Field sipStackField = SIPDialog.class.getDeclaredField("sipStack");
754   - sipStackField.setAccessible(true);
755   - sipStackField.set(dialog, sipStack);
756   - Field eventListenersField = SIPDialog.class.getDeclaredField("eventListeners");
757   - eventListenersField.setAccessible(true);
758   - eventListenersField.set(dialog, new HashSet<>());
759   - } catch (NoSuchFieldException | IllegalAccessException e) {
760   - e.printStackTrace();
761   - }
762   - }
763   -
764   - Request byeRequest = dialog.createRequest(Request.BYE);
765   - SipURI byeURI = (SipURI) byeRequest.getRequestURI();
766   - SIPRequest request = (SIPRequest)transaction.getRequest();
767   - byeURI.setHost(request.getRemoteAddress().getHostAddress());
768   - byeURI.setPort(request.getRemotePort());
769   - byeURI.setUser(channelId);
770   - ViaHeader viaHeader = (ViaHeader) byeRequest.getHeader(ViaHeader.NAME);
771   - String protocol = viaHeader.getTransport().toUpperCase();
772   - viaHeader.setRPort();
773   - // 增加Contact header
774   - Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getIp()+":"+sipConfig.getPort()));
775   - byeRequest.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
776   - UserAgentHeader userAgentHeader = SipUtils.createUserAgentHeader(sipFactory, gitUtil);
777   - byeRequest.addHeader(userAgentHeader);
778   - ClientTransaction clientTransaction = null;
779   - if("TCP".equals(protocol)) {
780   - clientTransaction = tcpSipProvider.getNewClientTransaction(byeRequest);
781   - } else if("UDP".equals(protocol)) {
782   - clientTransaction = udpSipProvider.getNewClientTransaction(byeRequest);
783   - }
784   -
785   - CallIdHeader callIdHeader = (CallIdHeader) byeRequest.getHeader(CallIdHeader.NAME);
786   - if (okEvent != null) {
787   - sipSubscribe.addOkSubscribe(callIdHeader.getCallId(), okEvent);
788   - }
789   - CSeqHeader cSeqHeader = (CSeqHeader)byeRequest.getHeader(CSeqHeader.NAME);
790   - cSeqHeader.setSeqNumber(redisCatchStorage.getCSEQ());
791   - dialog.sendRequest(clientTransaction);
792   -
793   - } catch (SipException | ParseException e) {
794   - e.printStackTrace();
795   - } catch (InvalidArgumentException e) {
796   - throw new RuntimeException(e);
797   - }
798   - }
799   -
  367 + CallIdHeader callIdHeader = device.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
  368 + : udpSipProvider.getNewCallId();
  369 +
  370 + Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), null, SipUtils.getNewFromTag(), null, ssrcInfo.getSsrc(), callIdHeader);
  371 + transmitRequest(device.getTransport(), request, (e -> {
  372 + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
  373 + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
  374 + errorEvent.response(e);
  375 + }), e -> {
  376 + // 这里为例避免一个通道的点播只有一个callID这个参数使用一个固定值
  377 + ResponseEvent responseEvent = (ResponseEvent) e.event;
  378 + SIPResponse response = (SIPResponse) responseEvent.getResponse();
  379 + streamSession.put(device.getDeviceId(), channelId, "play", stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.play);
  380 + okEvent.response(e);
  381 + });
  382 + }
  383 +
  384 + /**
  385 + * 请求回放视频流
  386 + *
  387 + * @param device 视频设备
  388 + * @param channelId 预览通道
  389 + * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
  390 + * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
  391 + */
  392 + @Override
  393 + public void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
  394 + String startTime, String endTime, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent,
  395 + SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  396 +
  397 +
  398 + logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
  399 +
  400 + StringBuffer content = new StringBuffer(200);
  401 + content.append("v=0\r\n");
  402 + content.append("o=" + channelId + " 0 0 IN IP4 " + mediaServerItem.getSdpIp() + "\r\n");
  403 + content.append("s=Playback\r\n");
  404 + content.append("u=" + channelId + ":0\r\n");
  405 + content.append("c=IN IP4 " + mediaServerItem.getSdpIp() + "\r\n");
  406 + content.append("t=" + DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime) + " "
  407 + + DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime) + "\r\n");
  408 +
  409 + String streamMode = device.getStreamMode();
  410 +
  411 + if (userSetting.isSeniorSdp()) {
  412 + if ("TCP-PASSIVE".equalsIgnoreCase(streamMode)) {
  413 + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
  414 + } else if ("TCP-ACTIVE".equalsIgnoreCase(streamMode)) {
  415 + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
  416 + } else if ("UDP".equalsIgnoreCase(streamMode)) {
  417 + content.append("m=video " + ssrcInfo.getPort() + " RTP/AVP 96 126 125 99 34 98 97\r\n");
  418 + }
  419 + content.append("a=recvonly\r\n");
  420 + content.append("a=rtpmap:96 PS/90000\r\n");
  421 + content.append("a=fmtp:126 profile-level-id=42e01e\r\n");
  422 + content.append("a=rtpmap:126 H264/90000\r\n");
  423 + content.append("a=rtpmap:125 H264S/90000\r\n");
  424 + content.append("a=fmtp:125 profile-level-id=42e01e\r\n");
  425 + content.append("a=rtpmap:99 H265/90000\r\n");
  426 + content.append("a=rtpmap:98 H264/90000\r\n");
  427 + content.append("a=rtpmap:97 MPEG4/90000\r\n");
  428 + if ("TCP-PASSIVE".equalsIgnoreCase(streamMode)) { // tcp被动模式
  429 + content.append("a=setup:passive\r\n");
  430 + content.append("a=connection:new\r\n");
  431 + } else if ("TCP-ACTIVE".equalsIgnoreCase(streamMode)) { // tcp主动模式
  432 + content.append("a=setup:active\r\n");
  433 + content.append("a=connection:new\r\n");
  434 + }
  435 + } else {
  436 + if ("TCP-PASSIVE".equalsIgnoreCase(streamMode)) {
  437 + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 97 98 99\r\n");
  438 + } else if ("TCP-ACTIVE".equalsIgnoreCase(streamMode)) {
  439 + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 97 98 99\r\n");
  440 + } else if ("UDP".equalsIgnoreCase(streamMode)) {
  441 + content.append("m=video " + ssrcInfo.getPort() + " RTP/AVP 96 97 98 99\r\n");
  442 + }
  443 + content.append("a=recvonly\r\n");
  444 + content.append("a=rtpmap:96 PS/90000\r\n");
  445 + content.append("a=rtpmap:97 MPEG4/90000\r\n");
  446 + content.append("a=rtpmap:98 H264/90000\r\n");
  447 + content.append("a=rtpmap:99 H265/90000\r\n");
  448 + if ("TCP-PASSIVE".equalsIgnoreCase(streamMode)) { // tcp被动模式
  449 + content.append("a=setup:passive\r\n");
  450 + content.append("a=connection:new\r\n");
  451 + } else if ("TCP-ACTIVE".equalsIgnoreCase(streamMode)) { // tcp主动模式
  452 + content.append("a=setup:active\r\n");
  453 + content.append("a=connection:new\r\n");
  454 + }
  455 + }
  456 +
  457 + content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc
  458 +
  459 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  460 + : udpSipProvider.getNewCallId();
  461 + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId());
  462 + // 添加订阅
  463 + subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json) -> {
  464 + if (hookEvent != null) {
  465 + InviteStreamInfo inviteStreamInfo = new InviteStreamInfo(mediaServerItemInUse, json, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream());
  466 + hookEvent.call(inviteStreamInfo);
  467 + }
  468 + subscribe.removeSubscribe(hookSubscribe);
  469 + });
  470 + Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader, ssrcInfo.getSsrc());
  471 +
  472 + transmitRequest(device.getTransport(), request, errorEvent, event -> {
  473 + ResponseEvent responseEvent = (ResponseEvent) event.event;
  474 + SIPResponse response = (SIPResponse) responseEvent.getResponse();
  475 + streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.playback);
  476 + okEvent.response(event);
  477 + });
  478 + if (inviteStreamCallback != null) {
  479 + inviteStreamCallback.call(new InviteStreamInfo(mediaServerItem, null, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream()));
  480 + }
  481 + }
  482 +
  483 + /**
  484 + * 请求历史媒体下载
  485 + *
  486 + * @param device 视频设备
  487 + * @param channelId 预览通道
  488 + * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
  489 + * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
  490 + * @param downloadSpeed 下载倍速参数
  491 + */
  492 + @Override
  493 + public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
  494 + String startTime, String endTime, int downloadSpeed, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent,
  495 + SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  496 +
  497 + logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
  498 +
  499 + StringBuffer content = new StringBuffer(200);
  500 + content.append("v=0\r\n");
  501 + content.append("o=" + channelId + " 0 0 IN IP4 " + mediaServerItem.getSdpIp() + "\r\n");
  502 + content.append("s=Download\r\n");
  503 + content.append("u=" + channelId + ":0\r\n");
  504 + content.append("c=IN IP4 " + mediaServerItem.getSdpIp() + "\r\n");
  505 + content.append("t=" + DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime) + " "
  506 + + DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime) + "\r\n");
  507 +
  508 + String streamMode = device.getStreamMode().toUpperCase();
  509 +
  510 + if (userSetting.isSeniorSdp()) {
  511 + if ("TCP-PASSIVE".equals(streamMode)) {
  512 + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
  513 + } else if ("TCP-ACTIVE".equals(streamMode)) {
  514 + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
  515 + } else if ("UDP".equals(streamMode)) {
  516 + content.append("m=video " + ssrcInfo.getPort() + " RTP/AVP 96 126 125 99 34 98 97\r\n");
  517 + }
  518 + content.append("a=recvonly\r\n");
  519 + content.append("a=rtpmap:96 PS/90000\r\n");
  520 + content.append("a=fmtp:126 profile-level-id=42e01e\r\n");
  521 + content.append("a=rtpmap:126 H264/90000\r\n");
  522 + content.append("a=rtpmap:125 H264S/90000\r\n");
  523 + content.append("a=fmtp:125 profile-level-id=42e01e\r\n");
  524 + content.append("a=rtpmap:99 MP4V-ES/90000\r\n");
  525 + content.append("a=fmtp:99 profile-level-id=3\r\n");
  526 + content.append("a=rtpmap:98 H264/90000\r\n");
  527 + content.append("a=rtpmap:97 MPEG4/90000\r\n");
  528 + if ("TCP-PASSIVE".equals(streamMode)) { // tcp被动模式
  529 + content.append("a=setup:passive\r\n");
  530 + content.append("a=connection:new\r\n");
  531 + } else if ("TCP-ACTIVE".equals(streamMode)) { // tcp主动模式
  532 + content.append("a=setup:active\r\n");
  533 + content.append("a=connection:new\r\n");
  534 + }
  535 + } else {
  536 + if ("TCP-PASSIVE".equals(streamMode)) {
  537 + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 97 98 99\r\n");
  538 + } else if ("TCP-ACTIVE".equals(streamMode)) {
  539 + content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 97 98 99\r\n");
  540 + } else if ("UDP".equals(streamMode)) {
  541 + content.append("m=video " + ssrcInfo.getPort() + " RTP/AVP 96 97 98 99\r\n");
  542 + }
  543 + content.append("a=recvonly\r\n");
  544 + content.append("a=rtpmap:96 PS/90000\r\n");
  545 + content.append("a=rtpmap:97 MPEG4/90000\r\n");
  546 + content.append("a=rtpmap:98 H264/90000\r\n");
  547 + content.append("a=rtpmap:99 H265/90000\r\n");
  548 + if ("TCP-PASSIVE".equals(streamMode)) { // tcp被动模式
  549 + content.append("a=setup:passive\r\n");
  550 + content.append("a=connection:new\r\n");
  551 + } else if ("TCP-ACTIVE".equals(streamMode)) { // tcp主动模式
  552 + content.append("a=setup:active\r\n");
  553 + content.append("a=connection:new\r\n");
  554 + }
  555 + }
  556 + content.append("a=downloadspeed:" + downloadSpeed + "\r\n");
  557 +
  558 + content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc
  559 +
  560 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  561 + : udpSipProvider.getNewCallId();
  562 +
  563 + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, null, mediaServerItem.getId());
  564 + // 添加订阅
  565 + subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json) -> {
  566 + hookEvent.call(new InviteStreamInfo(mediaServerItem, json, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream()));
  567 + subscribe.removeSubscribe(hookSubscribe);
  568 + hookSubscribe.getContent().put("regist", false);
  569 + hookSubscribe.getContent().put("schema", "rtsp");
  570 + // 添加流注销的订阅,注销了后向设备发送bye
  571 + subscribe.addSubscribe(hookSubscribe,
  572 + (MediaServerItem mediaServerItemForEnd, JSONObject jsonForEnd) -> {
  573 + logger.info("[录像]下载结束, 发送BYE");
  574 + try {
  575 + streamByeCmd(device, channelId, ssrcInfo.getStream(), callIdHeader.getCallId());
  576 + } catch (InvalidArgumentException | ParseException | SipException |
  577 + SsrcTransactionNotFoundException e) {
  578 + logger.error("[录像]下载结束, 发送BYE失败 {}", e.getMessage());
  579 + }
  580 + });
  581 + });
  582 +
  583 + Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader, ssrcInfo.getSsrc());
  584 + if (inviteStreamCallback != null) {
  585 + inviteStreamCallback.call(new InviteStreamInfo(mediaServerItem, null, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream()));
  586 + }
  587 + transmitRequest(device.getTransport(), request, errorEvent, okEvent -> {
  588 + ResponseEvent responseEvent = (ResponseEvent) okEvent.event;
  589 + SIPResponse response = (SIPResponse) responseEvent.getResponse();
  590 + streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.download);
  591 + });
  592 + }
  593 +
  594 + /**
  595 + * 视频流停止, 不使用回调
  596 + */
  597 + @Override
  598 + public void streamByeCmd(Device device, String channelId, String stream, String callId) throws InvalidArgumentException, ParseException, SipException, SsrcTransactionNotFoundException {
  599 + streamByeCmd(device, channelId, stream, callId, null);
  600 + }
  601 +
  602 + /**
  603 + * 视频流停止
  604 + */
  605 + @Override
  606 + public void streamByeCmd(Device device, String channelId, String stream, String callId, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException {
  607 + SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, callId, stream);
  608 + if (ssrcTransaction == null) {
  609 + throw new SsrcTransactionNotFoundException(device.getDeviceId(), channelId, callId, stream);
  610 + }
  611 +
  612 + mediaServerService.releaseSsrc(ssrcTransaction.getMediaServerId(), ssrcTransaction.getSsrc());
  613 + mediaServerService.closeRTPServer(ssrcTransaction.getMediaServerId(), ssrcTransaction.getStream());
  614 + streamSession.remove(ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId(), ssrcTransaction.getStream());
  615 +
  616 + Request byteRequest = headerProvider.createByteRequest(device, channelId, ssrcTransaction.getSipTransactionInfo());
  617 + transmitRequest(device.getTransport(), byteRequest, null, okEvent);
  618 + }
  619 +
  620 + /**
  621 + * 语音广播
  622 + *
  623 + * @param device 视频设备
  624 + */
  625 + @Override
  626 + public void audioBroadcastCmd(Device device) throws InvalidArgumentException, SipException, ParseException {
  627 +
  628 + StringBuffer broadcastXml = new StringBuffer(200);
  629 + String charset = device.getCharset();
  630 + broadcastXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  631 + broadcastXml.append("<Notify>\r\n");
  632 + broadcastXml.append("<CmdType>Broadcast</CmdType>\r\n");
  633 + broadcastXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  634 + broadcastXml.append("<SourceID>" + sipConfig.getId() + "</SourceID>\r\n");
  635 + broadcastXml.append("<TargetID>" + device.getDeviceId() + "</TargetID>\r\n");
  636 + broadcastXml.append("</Notify>\r\n");
800 637 /**
801 638 * 语音广播
802   - *
  639 + *
803 640 * @param device 视频设备
804 641 */
805 642 @Override
... ... @@ -815,1039 +652,846 @@ public class SIPCommander implements ISIPCommander {
815 652 broadcastXml.append("<TargetID>" + channelId + "</TargetID>\r\n");
816 653 broadcastXml.append("</Notify>\r\n");
817 654  
818   - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
819   - : udpSipProvider.getNewCallId();
820   -
821   - Request request = headerProvider.createMessageRequest(device, broadcastXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
822   - transmitRequest(device, request);
823   - return true;
824   - } catch (SipException | ParseException | InvalidArgumentException e) {
825   - e.printStackTrace();
826   - }
827   - return false;
828   - }
829   - @Override
830   - public void audioBroadcastCmd(Device device, SipSubscribe.Event errorEvent) {
831   - try {
832   - StringBuffer broadcastXml = new StringBuffer(200);
833   - String charset = device.getCharset();
834   - broadcastXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
835   - broadcastXml.append("<Notify>\r\n");
836   - broadcastXml.append("<CmdType>Broadcast</CmdType>\r\n");
837   - broadcastXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
838   - broadcastXml.append("<SourceID>" + sipConfig.getId() + "</SourceID>\r\n");
839   - broadcastXml.append("<TargetID>" + device.getDeviceId() + "</TargetID>\r\n");
840   - broadcastXml.append("</Notify>\r\n");
841   -
842   - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
843   - : udpSipProvider.getNewCallId();
844   -
845   - Request request = headerProvider.createMessageRequest(device, broadcastXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
846   - transmitRequest(device, request, errorEvent);
847   - } catch (SipException | ParseException | InvalidArgumentException e) {
848   - e.printStackTrace();
849   - }
850   - }
851   -
852   -
853   - /**
854   - * 音视频录像控制
855   - *
856   - * @param device 视频设备
857   - * @param channelId 预览通道
858   - * @param recordCmdStr 录像命令:Record / StopRecord
859   - */
860   - @Override
861   - public boolean recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent) {
862   - try {
863   - StringBuffer cmdXml = new StringBuffer(200);
864   - String charset = device.getCharset();
865   - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
866   - cmdXml.append("<Control>\r\n");
867   - cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
868   - cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
869   - if (ObjectUtils.isEmpty(channelId)) {
870   - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
871   - } else {
872   - cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
873   - }
874   - cmdXml.append("<RecordCmd>" + recordCmdStr + "</RecordCmd>\r\n");
875   - cmdXml.append("</Control>\r\n");
876   -
877   - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
878   - : udpSipProvider.getNewCallId();
879   -
880   - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
881   - transmitRequest(device, request, errorEvent);
882   - return true;
883   - } catch (SipException | ParseException | InvalidArgumentException e) {
884   - e.printStackTrace();
885   - return false;
886   - }
887   - }
888   -
889   - /**
890   - * 远程启动控制命令
891   - *
892   - * @param device 视频设备
893   - */
894   - @Override
895   - public boolean teleBootCmd(Device device) {
896   - try {
897   - StringBuffer cmdXml = new StringBuffer(200);
898   - String charset = device.getCharset();
899   - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
900   - cmdXml.append("<Control>\r\n");
901   - cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
902   - cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
903   - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
904   - cmdXml.append("<TeleBoot>Boot</TeleBoot>\r\n");
905   - cmdXml.append("</Control>\r\n");
906   -
907   - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
908   - : udpSipProvider.getNewCallId();
909   -
910   - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
911   - transmitRequest(device, request);
912   - return true;
913   - } catch (SipException | ParseException | InvalidArgumentException e) {
914   - e.printStackTrace();
915   - return false;
916   - }
917   - }
918   -
919   - /**
920   - * 报警布防/撤防命令
921   - *
922   - * @param device 视频设备
923   - * @param guardCmdStr "SetGuard"/"ResetGuard"
924   - */
925   - @Override
926   - public boolean guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent) {
927   - try {
928   - StringBuffer cmdXml = new StringBuffer(200);
929   - String charset = device.getCharset();
930   - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
931   - cmdXml.append("<Control>\r\n");
932   - cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
933   - cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
934   - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
935   - cmdXml.append("<GuardCmd>" + guardCmdStr + "</GuardCmd>\r\n");
936   - cmdXml.append("</Control>\r\n");
937   -
938   - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
939   - : udpSipProvider.getNewCallId();
940   -
941   - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
942   - transmitRequest(device, request, errorEvent);
943   - return true;
944   - } catch (SipException | ParseException | InvalidArgumentException e) {
945   - e.printStackTrace();
946   - return false;
947   - }
948   - }
949   -
950   - /**
951   - * 报警复位命令
952   - *
953   - * @param device 视频设备
954   - */
955   - @Override
956   - public boolean alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent) {
957   - try {
958   - StringBuffer cmdXml = new StringBuffer(200);
959   - String charset = device.getCharset();
960   - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
961   - cmdXml.append("<Control>\r\n");
962   - cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
963   - cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
964   - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
965   - cmdXml.append("<AlarmCmd>ResetAlarm</AlarmCmd>\r\n");
966   - if (!ObjectUtils.isEmpty(alarmMethod) || !ObjectUtils.isEmpty(alarmType)) {
967   - cmdXml.append("<Info>\r\n");
968   - }
969   - if (!ObjectUtils.isEmpty(alarmMethod)) {
970   - cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n");
971   - }
972   - if (!ObjectUtils.isEmpty(alarmType)) {
973   - cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n");
974   - }
975   - if (!ObjectUtils.isEmpty(alarmMethod) || !ObjectUtils.isEmpty(alarmType)) {
976   - cmdXml.append("</Info>\r\n");
977   - }
978   - cmdXml.append("</Control>\r\n");
979   -
980   - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
981   - : udpSipProvider.getNewCallId();
982   -
983   - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
984   - transmitRequest(device, request, errorEvent);
985   - return true;
986   - } catch (SipException | ParseException | InvalidArgumentException e) {
987   - e.printStackTrace();
988   - return false;
989   - }
990   - }
991   -
992   - /**
993   - * 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧
994   - *
995   - * @param device 视频设备
996   - * @param channelId 预览通道
997   - */
998   - @Override
999   - public boolean iFrameCmd(Device device, String channelId) {
1000   - try {
1001   - StringBuffer cmdXml = new StringBuffer(200);
1002   - String charset = device.getCharset();
1003   - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
1004   - cmdXml.append("<Control>\r\n");
1005   - cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
1006   - cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
1007   - if (ObjectUtils.isEmpty(channelId)) {
1008   - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
1009   - } else {
1010   - cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
1011   - }
1012   - cmdXml.append("<IFameCmd>Send</IFameCmd>\r\n");
1013   - cmdXml.append("</Control>\r\n");
1014   -
1015   - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
1016   - : udpSipProvider.getNewCallId();
1017   -
1018   - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
1019   - transmitRequest(device, request);
1020   - return true;
1021   - } catch (SipException | ParseException | InvalidArgumentException e) {
1022   - e.printStackTrace();
1023   - return false;
1024   - }
1025   - }
1026   -
1027   - /**
1028   - * 看守位控制命令
1029   - *
1030   - * @param device 视频设备
1031   - * @param enabled 看守位使能:1 = 开启,0 = 关闭
1032   - * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s)
1033   - * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255
1034   - */
1035   - @Override
1036   - public boolean homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent) {
1037   - try {
1038   - StringBuffer cmdXml = new StringBuffer(200);
1039   - String charset = device.getCharset();
1040   - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
1041   - cmdXml.append("<Control>\r\n");
1042   - cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
1043   - cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
1044   - if (ObjectUtils.isEmpty(channelId)) {
1045   - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
1046   - } else {
1047   - cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
1048   - }
1049   - cmdXml.append("<HomePosition>\r\n");
1050   - if (NumericUtil.isInteger(enabled) && (!enabled.equals("0"))) {
1051   - cmdXml.append("<Enabled>1</Enabled>\r\n");
1052   - if (NumericUtil.isInteger(resetTime)) {
1053   - cmdXml.append("<ResetTime>" + resetTime + "</ResetTime>\r\n");
1054   - } else {
1055   - cmdXml.append("<ResetTime>0</ResetTime>\r\n");
1056   - }
1057   - if (NumericUtil.isInteger(presetIndex)) {
1058   - cmdXml.append("<PresetIndex>" + presetIndex + "</PresetIndex>\r\n");
1059   - } else {
1060   - cmdXml.append("<PresetIndex>0</PresetIndex>\r\n");
1061   - }
1062   - } else {
1063   - cmdXml.append("<Enabled>0</Enabled>\r\n");
1064   - }
1065   - cmdXml.append("</HomePosition>\r\n");
1066   - cmdXml.append("</Control>\r\n");
1067   -
1068   - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
1069   - : udpSipProvider.getNewCallId();
1070   -
1071   - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
1072   - transmitRequest(device, request, errorEvent);
1073   - return true;
1074   - } catch (SipException | ParseException | InvalidArgumentException e) {
1075   - e.printStackTrace();
1076   - return false;
1077   - }
1078   - }
1079   -
1080   - /**
1081   - * 设备配置命令
1082   - *
1083   - * @param device 视频设备
1084   - */
1085   - @Override
1086   - public boolean deviceConfigCmd(Device device) {
1087   - // TODO Auto-generated method stub
1088   - return false;
1089   - }
1090   -
1091   - /**
1092   - * 设备配置命令:basicParam
1093   - *
1094   - * @param device 视频设备
1095   - * @param channelId 通道编码(可选)
1096   - * @param name 设备/通道名称(可选)
1097   - * @param expiration 注册过期时间(可选)
1098   - * @param heartBeatInterval 心跳间隔时间(可选)
1099   - * @param heartBeatCount 心跳超时次数(可选)
1100   - */
1101   - @Override
1102   - public boolean deviceBasicConfigCmd(Device device, String channelId, String name, String expiration,
1103   - String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent) {
1104   - try {
1105   - StringBuffer cmdXml = new StringBuffer(200);
1106   - String charset = device.getCharset();
1107   - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
1108   - cmdXml.append("<Control>\r\n");
1109   - cmdXml.append("<CmdType>DeviceConfig</CmdType>\r\n");
1110   - cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
1111   - if (ObjectUtils.isEmpty(channelId)) {
1112   - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
1113   - } else {
1114   - cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
1115   - }
1116   - cmdXml.append("<BasicParam>\r\n");
1117   - if (!ObjectUtils.isEmpty(name)) {
1118   - cmdXml.append("<Name>" + name + "</Name>\r\n");
1119   - }
1120   - if (NumericUtil.isInteger(expiration)) {
1121   - if (Integer.valueOf(expiration) > 0) {
1122   - cmdXml.append("<Expiration>" + expiration + "</Expiration>\r\n");
1123   - }
1124   - }
1125   - if (NumericUtil.isInteger(heartBeatInterval)) {
1126   - if (Integer.valueOf(heartBeatInterval) > 0) {
1127   - cmdXml.append("<HeartBeatInterval>" + heartBeatInterval + "</HeartBeatInterval>\r\n");
1128   - }
1129   - }
1130   - if (NumericUtil.isInteger(heartBeatCount)) {
1131   - if (Integer.valueOf(heartBeatCount) > 0) {
1132   - cmdXml.append("<HeartBeatCount>" + heartBeatCount + "</HeartBeatCount>\r\n");
1133   - }
1134   - }
1135   - cmdXml.append("</BasicParam>\r\n");
1136   - cmdXml.append("</Control>\r\n");
1137   -
1138   - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
1139   - : udpSipProvider.getNewCallId();
1140   -
1141   - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
1142   - transmitRequest(device, request, errorEvent);
1143   - return true;
1144   - } catch (SipException | ParseException | InvalidArgumentException e) {
1145   - e.printStackTrace();
1146   - return false;
1147   - }
1148   - }
1149   -
1150   - /**
1151   - * 查询设备状态
1152   - *
1153   - * @param device 视频设备
1154   - */
1155   - @Override
1156   - public boolean deviceStatusQuery(Device device, SipSubscribe.Event errorEvent) {
1157   - try {
1158   - String charset = device.getCharset();
1159   - StringBuffer catalogXml = new StringBuffer(200);
1160   - catalogXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
1161   - catalogXml.append("<Query>\r\n");
1162   - catalogXml.append("<CmdType>DeviceStatus</CmdType>\r\n");
1163   - catalogXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
1164   - catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
1165   - catalogXml.append("</Query>\r\n");
1166   -
1167   - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
1168   - : udpSipProvider.getNewCallId();
1169   -
1170   - Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
1171   -
1172   - transmitRequest(device, request, errorEvent);
1173   - return true;
1174   -
1175   - } catch (SipException | ParseException | InvalidArgumentException e) {
1176   - e.printStackTrace();
1177   - return false;
1178   - }
1179   - }
1180   -
1181   - /**
1182   - * 查询设备信息
1183   - *
1184   - * @param device 视频设备
1185   - */
1186   - @Override
1187   - public boolean deviceInfoQuery(Device device) {
1188   - try {
1189   - StringBuffer catalogXml = new StringBuffer(200);
1190   - String charset = device.getCharset();
1191   - catalogXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
1192   - catalogXml.append("<Query>\r\n");
1193   - catalogXml.append("<CmdType>DeviceInfo</CmdType>\r\n");
1194   - catalogXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
1195   - catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
1196   - catalogXml.append("</Query>\r\n");
1197   -
1198   - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
1199   - : udpSipProvider.getNewCallId();
1200   -
1201   - Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
1202   -
1203   - transmitRequest(device, request);
1204   -
1205   - } catch (SipException | ParseException | InvalidArgumentException e) {
1206   - e.printStackTrace();
1207   - return false;
1208   - }
1209   - return true;
1210   - }
1211   -
1212   - /**
1213   - * 查询目录列表
1214   - *
1215   - * @param device 视频设备
1216   - */
1217   - @Override
1218   - public boolean catalogQuery(Device device, int sn, SipSubscribe.Event errorEvent) {
1219   - try {
1220   - StringBuffer catalogXml = new StringBuffer(200);
1221   - String charset = device.getCharset();
1222   - catalogXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
1223   - catalogXml.append("<Query>\r\n");
1224   - catalogXml.append(" <CmdType>Catalog</CmdType>\r\n");
1225   - catalogXml.append(" <SN>" + sn + "</SN>\r\n");
1226   - catalogXml.append(" <DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
1227   - catalogXml.append("</Query>\r\n");
1228   -
1229   - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
1230   - : udpSipProvider.getNewCallId();
1231   -
1232   - Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
1233   -
1234   - transmitRequest(device, request, errorEvent);
1235   - } catch (SipException | ParseException | InvalidArgumentException e) {
1236   - e.printStackTrace();
1237   - return false;
1238   - }
1239   - return true;
1240   - }
1241   -
1242   - /**
1243   - * 查询录像信息
1244   - *
1245   - * @param device 视频设备
1246   - * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
1247   - * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
1248   - */
1249   - @Override
1250   - public boolean recordInfoQuery(Device device, String channelId, String startTime, String endTime, int sn, Integer secrecy, String type, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) {
1251   - if (secrecy == null) {
1252   - secrecy = 0;
1253   - }
1254   - if (type == null) {
1255   - type = "all";
1256   - }
1257   - try {
1258   - StringBuffer recordInfoXml = new StringBuffer(200);
1259   - String charset = device.getCharset();
1260   - recordInfoXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
1261   - recordInfoXml.append("<Query>\r\n");
1262   - recordInfoXml.append("<CmdType>RecordInfo</CmdType>\r\n");
1263   - recordInfoXml.append("<SN>" + sn + "</SN>\r\n");
1264   - recordInfoXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
1265   - if (startTime != null) {
1266   - recordInfoXml.append("<StartTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(startTime) + "</StartTime>\r\n");
1267   - }
1268   - if (endTime != null) {
1269   - recordInfoXml.append("<EndTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(endTime) + "</EndTime>\r\n");
1270   - }
1271   - if (secrecy != null) {
1272   - recordInfoXml.append("<Secrecy> "+ secrecy + " </Secrecy>\r\n");
1273   - }
1274   - if (type != null) {
1275   - // 大华NVR要求必须增加一个值为all的文本元素节点Type
1276   - recordInfoXml.append("<Type>" + type+"</Type>\r\n");
1277   - }
1278   - recordInfoXml.append("</Query>\r\n");
1279   -
1280   - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
1281   - : udpSipProvider.getNewCallId();
1282   -
1283   - Request request = headerProvider.createMessageRequest(device, recordInfoXml.toString(),
1284   - SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
1285   -
1286   - transmitRequest(device, request, errorEvent, okEvent);
1287   - } catch (SipException | ParseException | InvalidArgumentException e) {
1288   - e.printStackTrace();
1289   - return false;
1290   - }
1291   - return true;
1292   - }
1293   -
1294   - /**
1295   - * 查询报警信息
1296   - *
1297   - * @param device 视频设备
1298   - * @param startPriority 报警起始级别(可选)
1299   - * @param endPriority 报警终止级别(可选)
1300   - * @param alarmMethod 报警方式条件(可选)
1301   - * @param alarmType 报警类型
1302   - * @param startTime 报警发生起始时间(可选)
1303   - * @param endTime 报警发生终止时间(可选)
1304   - * @return true = 命令发送成功
1305   - */
1306   - @Override
1307   - public boolean alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod, String alarmType,
1308   - String startTime, String endTime, SipSubscribe.Event errorEvent) {
1309   - try {
1310   - StringBuffer cmdXml = new StringBuffer(200);
1311   - String charset = device.getCharset();
1312   - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
1313   - cmdXml.append("<Query>\r\n");
1314   - cmdXml.append("<CmdType>Alarm</CmdType>\r\n");
1315   - cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
1316   - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
1317   - if (!ObjectUtils.isEmpty(startPriority)) {
1318   - cmdXml.append("<StartAlarmPriority>" + startPriority + "</StartAlarmPriority>\r\n");
1319   - }
1320   - if (!ObjectUtils.isEmpty(endPriority)) {
1321   - cmdXml.append("<EndAlarmPriority>" + endPriority + "</EndAlarmPriority>\r\n");
1322   - }
1323   - if (!ObjectUtils.isEmpty(alarmMethod)) {
1324   - cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n");
1325   - }
1326   - if (!ObjectUtils.isEmpty(alarmType)) {
1327   - cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n");
1328   - }
1329   - if (!ObjectUtils.isEmpty(startTime)) {
1330   - cmdXml.append("<StartAlarmTime>" + startTime + "</StartAlarmTime>\r\n");
1331   - }
1332   - if (!ObjectUtils.isEmpty(endTime)) {
1333   - cmdXml.append("<EndAlarmTime>" + endTime + "</EndAlarmTime>\r\n");
1334   - }
1335   - cmdXml.append("</Query>\r\n");
1336   -
1337   - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
1338   - : udpSipProvider.getNewCallId();
1339   -
1340   - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
1341   - transmitRequest(device, request, errorEvent);
1342   - return true;
1343   - } catch (SipException | ParseException | InvalidArgumentException e) {
1344   - e.printStackTrace();
1345   - return false;
1346   - }
1347   - }
1348   -
1349   - /**
1350   - * 查询设备配置
1351   - *
1352   - * @param device 视频设备
1353   - * @param channelId 通道编码(可选)
1354   - * @param configType 配置类型:
1355   - */
1356   - @Override
1357   - public boolean deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent) {
1358   - try {
1359   - StringBuffer cmdXml = new StringBuffer(200);
1360   - String charset = device.getCharset();
1361   - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
1362   - cmdXml.append("<Query>\r\n");
1363   - cmdXml.append("<CmdType>ConfigDownload</CmdType>\r\n");
1364   - cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
1365   - if (ObjectUtils.isEmpty(channelId)) {
1366   - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
1367   - } else {
1368   - cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
1369   - }
1370   - cmdXml.append("<ConfigType>" + configType + "</ConfigType>\r\n");
1371   - cmdXml.append("</Query>\r\n");
1372   -
1373   - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
1374   - : udpSipProvider.getNewCallId();
1375   -
1376   - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
1377   - transmitRequest(device, request, errorEvent);
1378   - return true;
1379   - } catch (SipException | ParseException | InvalidArgumentException e) {
1380   - e.printStackTrace();
1381   - return false;
1382   - }
1383   - }
1384   -
1385   - /**
1386   - * 查询设备预置位置
1387   - *
1388   - * @param device 视频设备
1389   - */
1390   - @Override
1391   - public boolean presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent) {
1392   - try {
1393   - StringBuffer cmdXml = new StringBuffer(200);
1394   - String charset = device.getCharset();
1395   - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
1396   - cmdXml.append("<Query>\r\n");
1397   - cmdXml.append("<CmdType>PresetQuery</CmdType>\r\n");
1398   - cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
1399   - if (ObjectUtils.isEmpty(channelId)) {
1400   - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
1401   - } else {
1402   - cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
1403   - }
1404   - cmdXml.append("</Query>\r\n");
1405   -
1406   - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
1407   - : udpSipProvider.getNewCallId();
1408   -
1409   - Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
1410   - transmitRequest(device, request, errorEvent);
1411   - return true;
1412   - } catch (SipException | ParseException | InvalidArgumentException e) {
1413   - e.printStackTrace();
1414   - return false;
1415   - }
1416   - }
1417   -
1418   - /**
1419   - * 查询移动设备位置数据
1420   - *
1421   - * @param device 视频设备
1422   - */
1423   - @Override
1424   - public boolean mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent) {
1425   - try {
1426   - StringBuffer mobilePostitionXml = new StringBuffer(200);
1427   - String charset = device.getCharset();
1428   - mobilePostitionXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
1429   - mobilePostitionXml.append("<Query>\r\n");
1430   - mobilePostitionXml.append("<CmdType>MobilePosition</CmdType>\r\n");
1431   - mobilePostitionXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
1432   - mobilePostitionXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
1433   - mobilePostitionXml.append("<Interval>60</Interval>\r\n");
1434   - mobilePostitionXml.append("</Query>\r\n");
1435   -
1436   - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
1437   - : udpSipProvider.getNewCallId();
1438   -
1439   - Request request = headerProvider.createMessageRequest(device, mobilePostitionXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
1440   -
1441   - transmitRequest(device, request, errorEvent);
1442   -
1443   - } catch (SipException | ParseException | InvalidArgumentException e) {
1444   - e.printStackTrace();
1445   - return false;
1446   - }
1447   - return true;
1448   - }
1449   -
1450   - /**
1451   - * 订阅、取消订阅移动位置
1452   - *
1453   - * @param device 视频设备
1454   - * @return true = 命令发送成功
1455   - */
1456   - @Override
1457   - public SIPRequest mobilePositionSubscribe(Device device, SIPRequest requestOld, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent) {
1458   - try {
1459   - StringBuffer subscribePostitionXml = new StringBuffer(200);
1460   - String charset = device.getCharset();
1461   - subscribePostitionXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
1462   - subscribePostitionXml.append("<Query>\r\n");
1463   - subscribePostitionXml.append("<CmdType>MobilePosition</CmdType>\r\n");
1464   - subscribePostitionXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
1465   - subscribePostitionXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
1466   - if (device.getSubscribeCycleForMobilePosition() > 0) {
1467   - subscribePostitionXml.append("<Interval>" + device.getMobilePositionSubmissionInterval() + "</Interval>\r\n");
1468   - }
1469   - subscribePostitionXml.append("</Query>\r\n");
1470   -
1471   - CallIdHeader callIdHeader;
1472   -
1473   - if (requestOld != null) {
1474   - callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(requestOld.getCallIdHeader().getCallId());
1475   - }else {
1476   - callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
1477   - : udpSipProvider.getNewCallId();
1478   - }
1479   - SIPRequest request = (SIPRequest)headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), requestOld, device.getSubscribeCycleForMobilePosition(), "presence" ,callIdHeader); //Position;id=" + tm.substring(tm.length() - 4));
1480   -
1481   - transmitRequest(device, request, errorEvent, okEvent);
1482   -
1483   - return request;
1484   -
1485   - } catch ( NumberFormatException | ParseException | InvalidArgumentException | SipException e) {
1486   - e.printStackTrace();
1487   - return null;
1488   - }
1489   - }
1490   -
1491   - /**
1492   - * 订阅、取消订阅报警信息
1493   - *
1494   - * @param device 视频设备
1495   - * @param expires 订阅过期时间(0 = 取消订阅)
1496   - * @param startPriority 报警起始级别(可选)
1497   - * @param endPriority 报警终止级别(可选)
1498   - * @param alarmMethod 报警方式条件(可选)
1499   - * @param alarmType 报警类型
1500   - * @param startTime 报警发生起始时间(可选)
1501   - * @param endTime 报警发生终止时间(可选)
1502   - * @return true = 命令发送成功
1503   - */
1504   - @Override
1505   - public boolean alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime) {
1506   - try {
1507   - StringBuffer cmdXml = new StringBuffer(200);
1508   - String charset = device.getCharset();
1509   - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
1510   - cmdXml.append("<Query>\r\n");
1511   - cmdXml.append("<CmdType>Alarm</CmdType>\r\n");
1512   - cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
1513   - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
1514   - if (!ObjectUtils.isEmpty(startPriority)) {
1515   - cmdXml.append("<StartAlarmPriority>" + startPriority + "</StartAlarmPriority>\r\n");
1516   - }
1517   - if (!ObjectUtils.isEmpty(endPriority)) {
1518   - cmdXml.append("<EndAlarmPriority>" + endPriority + "</EndAlarmPriority>\r\n");
1519   - }
1520   - if (!ObjectUtils.isEmpty(alarmMethod)) {
1521   - cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n");
1522   - }
1523   - if (!ObjectUtils.isEmpty(alarmType)) {
1524   - cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n");
1525   - }
1526   - if (!ObjectUtils.isEmpty(startTime)) {
1527   - cmdXml.append("<StartAlarmTime>" + startTime + "</StartAlarmTime>\r\n");
1528   - }
1529   - if (!ObjectUtils.isEmpty(endTime)) {
1530   - cmdXml.append("<EndAlarmTime>" + endTime + "</EndAlarmTime>\r\n");
1531   - }
1532   - cmdXml.append("</Query>\r\n");
1533   -
1534   - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
1535   - : udpSipProvider.getNewCallId();
1536   -
1537   - Request request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), null, expires, "presence" , callIdHeader);
1538   - transmitRequest(device, request);
1539   -
1540   - return true;
1541   -
1542   - } catch ( NumberFormatException | ParseException | InvalidArgumentException | SipException e) {
1543   - e.printStackTrace();
1544   - return false;
1545   - }
1546   - }
1547   -
1548   - @Override
1549   - public SIPRequest catalogSubscribe(Device device, SIPRequest requestOld, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) {
1550   - try {
1551   - StringBuffer cmdXml = new StringBuffer(200);
1552   - String charset = device.getCharset();
1553   - cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
1554   - cmdXml.append("<Query>\r\n");
1555   - cmdXml.append("<CmdType>Catalog</CmdType>\r\n");
1556   - cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
1557   - cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
1558   - cmdXml.append("</Query>\r\n");
1559   -
1560   - CallIdHeader callIdHeader ;
1561   -
1562   - if (requestOld != null) {
1563   - callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(requestOld.getCallIdHeader().getCallId());
1564   - }else {
1565   - callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
1566   - : udpSipProvider.getNewCallId();
1567   - }
1568   -
1569   - // 有效时间默认为60秒以上
1570   - SIPRequest request = (SIPRequest)headerProvider.createSubscribeRequest(device, cmdXml.toString(), requestOld, device.getSubscribeCycleForCatalog(), "Catalog" ,
1571   - callIdHeader);
1572   - transmitRequest(device, request, errorEvent, okEvent);
1573   - return request;
1574   -
1575   - } catch ( NumberFormatException | ParseException | InvalidArgumentException | SipException e) {
1576   - e.printStackTrace();
1577   - return null;
1578   - }
1579   - }
1580   -
1581   - @Override
1582   - public boolean dragZoomCmd(Device device, String channelId, String cmdString) {
1583   - try {
1584   - StringBuffer dragXml = new StringBuffer(200);
1585   - String charset = device.getCharset();
1586   - dragXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
1587   - dragXml.append("<Control>\r\n");
1588   - dragXml.append("<CmdType>DeviceControl</CmdType>\r\n");
1589   - dragXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
1590   - if (ObjectUtils.isEmpty(channelId)) {
1591   - dragXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
1592   - } else {
1593   - dragXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
1594   - }
1595   - dragXml.append(cmdString);
1596   - dragXml.append("</Control>\r\n");
1597   - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
1598   - : udpSipProvider.getNewCallId();
1599   - Request request = headerProvider.createMessageRequest(device, dragXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
1600   - logger.debug("拉框信令: " + request.toString());
1601   - transmitRequest(device, request);
1602   - return true;
1603   - } catch (SipException | ParseException | InvalidArgumentException e) {
1604   - e.printStackTrace();
1605   - }
1606   - return false;
1607   - }
1608   -
1609   -
1610   - private ClientTransaction transmitRequest(Device device, Request request) throws SipException {
1611   - return transmitRequest(device, request, null, null);
1612   - }
1613   -
1614   - private ClientTransaction transmitRequest(Device device, Request request, SipSubscribe.Event errorEvent) throws SipException {
1615   - return transmitRequest(device, request, errorEvent, null);
1616   - }
1617   -
1618   - private ClientTransaction transmitRequest(Device device, Request request, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws SipException {
1619   - ClientTransaction clientTransaction = null;
1620   - if("TCP".equals(device.getTransport())) {
1621   - clientTransaction = tcpSipProvider.getNewClientTransaction(request);
1622   - } else if("UDP".equals(device.getTransport())) {
1623   - clientTransaction = udpSipProvider.getNewClientTransaction(request);
1624   - }
1625   - if (request.getHeader(UserAgentHeader.NAME) == null) {
1626   - try {
1627   - request.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil));
1628   - } catch (ParseException e) {
1629   - logger.error("添加UserAgentHeader失败", e);
1630   - }
1631   - }
1632   - CallIdHeader callIdHeader = (CallIdHeader)request.getHeader(CallIdHeader.NAME);
1633   - // 添加错误订阅
1634   - if (errorEvent != null) {
1635   - sipSubscribe.addErrorSubscribe(callIdHeader.getCallId(), (eventResult -> {
1636   - errorEvent.response(eventResult);
1637   - sipSubscribe.removeErrorSubscribe(eventResult.callId);
1638   - sipSubscribe.removeOkSubscribe(eventResult.callId);
1639   - }));
1640   - }
1641   - // 添加订阅
1642   - if (okEvent != null) {
1643   - sipSubscribe.addOkSubscribe(callIdHeader.getCallId(), eventResult ->{
1644   - okEvent.response(eventResult);
1645   - sipSubscribe.removeOkSubscribe(eventResult.callId);
1646   - sipSubscribe.removeErrorSubscribe(eventResult.callId);
1647   - });
1648   - }
1649   -
1650   - clientTransaction.sendRequest();
1651   - return clientTransaction;
1652   - }
1653   -
1654   - /**
1655   - * 回放暂停
1656   - */
1657   - @Override
1658   - public void playPauseCmd(Device device, StreamInfo streamInfo) {
1659   - try {
1660   - StringBuffer content = new StringBuffer(200);
1661   - content.append("PAUSE RTSP/1.0\r\n");
1662   - content.append("CSeq: " + getInfoCseq() + "\r\n");
1663   - content.append("PauseTime: now\r\n");
1664   - Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString());
1665   - if (request == null) {
1666   - return;
1667   - }
1668   - logger.info(request.toString());
1669   - ClientTransaction clientTransaction = null;
1670   - if ("TCP".equals(device.getTransport())) {
1671   - clientTransaction = tcpSipProvider.getNewClientTransaction(request);
1672   - } else if ("UDP".equals(device.getTransport())) {
1673   - clientTransaction = udpSipProvider.getNewClientTransaction(request);
1674   - }
1675   - if (clientTransaction != null) {
1676   - clientTransaction.sendRequest();
1677   - }
1678   -
1679   - } catch (SipException | ParseException | InvalidArgumentException e) {
1680   - e.printStackTrace();
1681   - }
1682   - }
1683   -
1684   - /**
1685   - * 回放恢复
1686   - */
1687   - @Override
1688   - public void playResumeCmd(Device device, StreamInfo streamInfo) {
1689   - try {
1690   - StringBuffer content = new StringBuffer(200);
1691   - content.append("PLAY RTSP/1.0\r\n");
1692   - content.append("CSeq: " + getInfoCseq() + "\r\n");
1693   - content.append("Range: npt=now-\r\n");
1694   - Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString());
1695   - if (request == null) {
1696   - return;
1697   - }
1698   - logger.info(request.toString());
1699   - ClientTransaction clientTransaction = null;
1700   - if ("TCP".equals(device.getTransport())) {
1701   - clientTransaction = tcpSipProvider.getNewClientTransaction(request);
1702   - } else if ("UDP".equals(device.getTransport())) {
1703   - clientTransaction = udpSipProvider.getNewClientTransaction(request);
1704   - }
1705   -
1706   - clientTransaction.sendRequest();
1707   -
1708   - } catch (SipException | ParseException | InvalidArgumentException e) {
1709   - e.printStackTrace();
1710   - }
1711   - }
1712   -
1713   - /**
1714   - * 回放拖动播放
1715   - */
1716   - @Override
1717   - public void playSeekCmd(Device device, StreamInfo streamInfo, long seekTime) {
1718   - try {
1719   - StringBuffer content = new StringBuffer(200);
1720   - content.append("PLAY RTSP/1.0\r\n");
1721   - content.append("CSeq: " + getInfoCseq() + "\r\n");
1722   - content.append("Range: npt=" + Math.abs(seekTime) + "-\r\n");
1723   -
1724   - Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString());
1725   - if (request == null) {
1726   - return;
1727   - }
1728   - logger.info(request.toString());
1729   - ClientTransaction clientTransaction = null;
1730   - if ("TCP".equals(device.getTransport())) {
1731   - clientTransaction = tcpSipProvider.getNewClientTransaction(request);
1732   - } else if ("UDP".equals(device.getTransport())) {
1733   - clientTransaction = udpSipProvider.getNewClientTransaction(request);
1734   - }
1735   -
1736   - clientTransaction.sendRequest();
1737   -
1738   - } catch (SipException | ParseException | InvalidArgumentException e) {
1739   - e.printStackTrace();
1740   - }
1741   - }
1742   -
1743   - /**
1744   - * 回放倍速播放
1745   - */
1746   - @Override
1747   - public void playSpeedCmd(Device device, StreamInfo streamInfo, Double speed) {
1748   - try {
1749   -
1750   - StringBuffer content = new StringBuffer(200);
1751   - content.append("PLAY RTSP/1.0\r\n");
1752   - content.append("CSeq: " + getInfoCseq() + "\r\n");
1753   - content.append("Scale: " + String.format("%.6f",speed) + "\r\n");
1754   - Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString());
1755   - if (request == null) {
1756   - return;
1757   - }
1758   - logger.info(request.toString());
1759   - ClientTransaction clientTransaction = null;
1760   - if ("TCP".equals(device.getTransport())) {
1761   - clientTransaction = tcpSipProvider.getNewClientTransaction(request);
1762   - } else if ("UDP".equals(device.getTransport())) {
1763   - clientTransaction = udpSipProvider.getNewClientTransaction(request);
1764   - }
1765   -
1766   - clientTransaction.sendRequest();
1767   -
1768   - } catch (SipException | ParseException | InvalidArgumentException e) {
1769   - e.printStackTrace();
1770   - }
1771   - }
1772   -
1773   - private int getInfoCseq() {
1774   - return (int) ((Math.random() * 9 + 1) * Math.pow(10, 8));
1775   - }
1776   -
1777   - @Override
1778   - public void playbackControlCmd(Device device, StreamInfo streamInfo, String content,SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) {
1779   - try {
1780   - Request request = headerProvider.createInfoRequest(device, streamInfo, content);
1781   - if (request == null) {
1782   - return;
1783   - }
1784   - ClientTransaction clientTransaction = null;
1785   - if ("TCP".equals(device.getTransport())) {
1786   - clientTransaction = tcpSipProvider.getNewClientTransaction(request);
1787   - } else if ("UDP".equals(device.getTransport())) {
1788   - clientTransaction = udpSipProvider.getNewClientTransaction(request);
1789   - }
1790   - CallIdHeader callIdHeader = (CallIdHeader)request.getHeader(CallIdHeader.NAME);
1791   - if(errorEvent != null) {
1792   - sipSubscribe.addErrorSubscribe(callIdHeader.getCallId(), (eventResult -> {
1793   - errorEvent.response(eventResult);
1794   - sipSubscribe.removeErrorSubscribe(eventResult.callId);
1795   - sipSubscribe.removeOkSubscribe(eventResult.callId);
1796   - }));
1797   - }
1798   -
1799   - if(okEvent != null) {
1800   - sipSubscribe.addOkSubscribe(callIdHeader.getCallId(), eventResult -> {
1801   - okEvent.response(eventResult);
1802   - sipSubscribe.removeOkSubscribe(eventResult.callId);
1803   - sipSubscribe.removeErrorSubscribe(eventResult.callId);
1804   - });
1805   - }
1806   - clientTransaction.sendRequest();
1807   -
1808   - } catch (SipException | ParseException | InvalidArgumentException e) {
1809   - e.printStackTrace();
1810   - }
1811   - }
1812   -
1813   - @Override
1814   - public boolean sendAlarmMessage(Device device, DeviceAlarm deviceAlarm) {
1815   - if (device == null) {
1816   - return false;
1817   - }
1818   - logger.info("[发送 报警通知] {}/{}->{},{}", device.getDeviceId(), deviceAlarm.getChannelId(),
1819   - deviceAlarm.getLongitude(), deviceAlarm.getLatitude());
1820   - try {
1821   - String characterSet = device.getCharset();
1822   - StringBuffer deviceStatusXml = new StringBuffer(600);
1823   - deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
1824   - deviceStatusXml.append("<Notify>\r\n");
1825   - deviceStatusXml.append("<CmdType>Alarm</CmdType>\r\n");
1826   - deviceStatusXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
1827   - deviceStatusXml.append("<DeviceID>" + deviceAlarm.getChannelId() + "</DeviceID>\r\n");
1828   - deviceStatusXml.append("<AlarmPriority>" + deviceAlarm.getAlarmPriority() + "</AlarmPriority>\r\n");
1829   - deviceStatusXml.append("<AlarmMethod>" + deviceAlarm.getAlarmMethod() + "</AlarmMethod>\r\n");
1830   - deviceStatusXml.append("<AlarmTime>" + deviceAlarm.getAlarmTime() + "</AlarmTime>\r\n");
1831   - deviceStatusXml.append("<AlarmDescription>" + deviceAlarm.getAlarmDescription() + "</AlarmDescription>\r\n");
1832   - deviceStatusXml.append("<Longitude>" + deviceAlarm.getLongitude() + "</Longitude>\r\n");
1833   - deviceStatusXml.append("<Latitude>" + deviceAlarm.getLatitude() + "</Latitude>\r\n");
1834   - deviceStatusXml.append("<info>\r\n");
1835   - deviceStatusXml.append("<AlarmType>" + deviceAlarm.getAlarmType() + "</AlarmType>\r\n");
1836   - deviceStatusXml.append("</info>\r\n");
1837   - deviceStatusXml.append("</Notify>\r\n");
1838   -
1839   - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
1840   - : udpSipProvider.getNewCallId();
1841   - Request request = headerProvider.createMessageRequest(device, deviceStatusXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
1842   - transmitRequest(device, request);
1843   -
1844   -
1845   - } catch (SipException | ParseException e) {
1846   - e.printStackTrace();
1847   - return false;
1848   - } catch (InvalidArgumentException e) {
1849   - throw new RuntimeException(e);
1850   - }
1851   - return true;
1852   - }
  655 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  656 + : udpSipProvider.getNewCallId();
  657 +
  658 + Request request = headerProvider.createMessageRequest(device, broadcastXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
  659 + transmitRequest(device.getTransport(), request);
  660 +
  661 + }
  662 +
  663 + @Override
  664 + public void audioBroadcastCmd(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  665 +
  666 + StringBuffer broadcastXml = new StringBuffer(200);
  667 + String charset = device.getCharset();
  668 + broadcastXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  669 + broadcastXml.append("<Notify>\r\n");
  670 + broadcastXml.append("<CmdType>Broadcast</CmdType>\r\n");
  671 + broadcastXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  672 + broadcastXml.append("<SourceID>" + sipConfig.getId() + "</SourceID>\r\n");
  673 + broadcastXml.append("<TargetID>" + device.getDeviceId() + "</TargetID>\r\n");
  674 + broadcastXml.append("</Notify>\r\n");
  675 +
  676 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  677 + : udpSipProvider.getNewCallId();
  678 +
  679 + Request request = headerProvider.createMessageRequest(device, broadcastXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
  680 + transmitRequest(device.getTransport(), request, errorEvent);
  681 +
  682 + }
  683 +
  684 +
  685 + /**
  686 + * 音视频录像控制
  687 + *
  688 + * @param device 视频设备
  689 + * @param channelId 预览通道
  690 + * @param recordCmdStr 录像命令:Record / StopRecord
  691 + */
  692 + @Override
  693 + public void recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  694 + StringBuffer cmdXml = new StringBuffer(200);
  695 + String charset = device.getCharset();
  696 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  697 + cmdXml.append("<Control>\r\n");
  698 + cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
  699 + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  700 + if (ObjectUtils.isEmpty(channelId)) {
  701 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  702 + } else {
  703 + cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
  704 + }
  705 + cmdXml.append("<RecordCmd>" + recordCmdStr + "</RecordCmd>\r\n");
  706 + cmdXml.append("</Control>\r\n");
  707 +
  708 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  709 + : udpSipProvider.getNewCallId();
  710 +
  711 + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
  712 + transmitRequest(device.getTransport(), request, errorEvent);
  713 + }
  714 +
  715 + /**
  716 + * 远程启动控制命令
  717 + *
  718 + * @param device 视频设备
  719 + */
  720 + @Override
  721 + public void teleBootCmd(Device device) throws InvalidArgumentException, SipException, ParseException {
  722 +
  723 + StringBuffer cmdXml = new StringBuffer(200);
  724 + String charset = device.getCharset();
  725 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  726 + cmdXml.append("<Control>\r\n");
  727 + cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
  728 + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  729 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  730 + cmdXml.append("<TeleBoot>Boot</TeleBoot>\r\n");
  731 + cmdXml.append("</Control>\r\n");
  732 +
  733 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  734 + : udpSipProvider.getNewCallId();
  735 +
  736 + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
  737 + transmitRequest(device.getTransport(), request);
  738 + }
  739 +
  740 + /**
  741 + * 报警布防/撤防命令
  742 + *
  743 + * @param device 视频设备
  744 + * @param guardCmdStr "SetGuard"/"ResetGuard"
  745 + */
  746 + @Override
  747 + public void guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  748 +
  749 + StringBuffer cmdXml = new StringBuffer(200);
  750 + String charset = device.getCharset();
  751 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  752 + cmdXml.append("<Control>\r\n");
  753 + cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
  754 + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  755 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  756 + cmdXml.append("<GuardCmd>" + guardCmdStr + "</GuardCmd>\r\n");
  757 + cmdXml.append("</Control>\r\n");
  758 +
  759 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  760 + : udpSipProvider.getNewCallId();
  761 +
  762 + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
  763 + transmitRequest(device.getTransport(), request, errorEvent);
  764 + }
  765 +
  766 + /**
  767 + * 报警复位命令
  768 + *
  769 + * @param device 视频设备
  770 + */
  771 + @Override
  772 + public void alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  773 +
  774 + StringBuffer cmdXml = new StringBuffer(200);
  775 + String charset = device.getCharset();
  776 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  777 + cmdXml.append("<Control>\r\n");
  778 + cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
  779 + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  780 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  781 + cmdXml.append("<AlarmCmd>ResetAlarm</AlarmCmd>\r\n");
  782 + if (!ObjectUtils.isEmpty(alarmMethod) || !ObjectUtils.isEmpty(alarmType)) {
  783 + cmdXml.append("<Info>\r\n");
  784 + }
  785 + if (!ObjectUtils.isEmpty(alarmMethod)) {
  786 + cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n");
  787 + }
  788 + if (!ObjectUtils.isEmpty(alarmType)) {
  789 + cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n");
  790 + }
  791 + if (!ObjectUtils.isEmpty(alarmMethod) || !ObjectUtils.isEmpty(alarmType)) {
  792 + cmdXml.append("</Info>\r\n");
  793 + }
  794 + cmdXml.append("</Control>\r\n");
  795 +
  796 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  797 + : udpSipProvider.getNewCallId();
  798 +
  799 + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
  800 + transmitRequest(device.getTransport(), request, errorEvent);
  801 + }
  802 +
  803 + /**
  804 + * 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧
  805 + *
  806 + * @param device 视频设备
  807 + * @param channelId 预览通道
  808 + */
  809 + @Override
  810 + public void iFrameCmd(Device device, String channelId) throws InvalidArgumentException, SipException, ParseException {
  811 +
  812 + StringBuffer cmdXml = new StringBuffer(200);
  813 + String charset = device.getCharset();
  814 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  815 + cmdXml.append("<Control>\r\n");
  816 + cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
  817 + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  818 + if (ObjectUtils.isEmpty(channelId)) {
  819 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  820 + } else {
  821 + cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
  822 + }
  823 + cmdXml.append("<IFameCmd>Send</IFameCmd>\r\n");
  824 + cmdXml.append("</Control>\r\n");
  825 +
  826 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  827 + : udpSipProvider.getNewCallId();
  828 +
  829 + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
  830 + transmitRequest(device.getTransport(), request);
  831 + }
  832 +
  833 + /**
  834 + * 看守位控制命令
  835 + *
  836 + * @param device 视频设备
  837 + * @param enabled 看守位使能:1 = 开启,0 = 关闭
  838 + * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s)
  839 + * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255
  840 + */
  841 + @Override
  842 + public void homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  843 +
  844 + StringBuffer cmdXml = new StringBuffer(200);
  845 + String charset = device.getCharset();
  846 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  847 + cmdXml.append("<Control>\r\n");
  848 + cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
  849 + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  850 + if (ObjectUtils.isEmpty(channelId)) {
  851 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  852 + } else {
  853 + cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
  854 + }
  855 + cmdXml.append("<HomePosition>\r\n");
  856 + if (NumericUtil.isInteger(enabled) && (!enabled.equals("0"))) {
  857 + cmdXml.append("<Enabled>1</Enabled>\r\n");
  858 + if (NumericUtil.isInteger(resetTime)) {
  859 + cmdXml.append("<ResetTime>" + resetTime + "</ResetTime>\r\n");
  860 + } else {
  861 + cmdXml.append("<ResetTime>0</ResetTime>\r\n");
  862 + }
  863 + if (NumericUtil.isInteger(presetIndex)) {
  864 + cmdXml.append("<PresetIndex>" + presetIndex + "</PresetIndex>\r\n");
  865 + } else {
  866 + cmdXml.append("<PresetIndex>0</PresetIndex>\r\n");
  867 + }
  868 + } else {
  869 + cmdXml.append("<Enabled>0</Enabled>\r\n");
  870 + }
  871 + cmdXml.append("</HomePosition>\r\n");
  872 + cmdXml.append("</Control>\r\n");
  873 +
  874 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  875 + : udpSipProvider.getNewCallId();
  876 +
  877 + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
  878 + transmitRequest(device.getTransport(), request, errorEvent);
  879 + }
  880 +
  881 + /**
  882 + * 设备配置命令
  883 + *
  884 + * @param device 视频设备
  885 + */
  886 + @Override
  887 + public void deviceConfigCmd(Device device) {
  888 + // TODO Auto-generated method stub
  889 + }
  890 +
  891 + /**
  892 + * 设备配置命令:basicParam
  893 + *
  894 + * @param device 视频设备
  895 + * @param channelId 通道编码(可选)
  896 + * @param name 设备/通道名称(可选)
  897 + * @param expiration 注册过期时间(可选)
  898 + * @param heartBeatInterval 心跳间隔时间(可选)
  899 + * @param heartBeatCount 心跳超时次数(可选)
  900 + */
  901 + @Override
  902 + public void deviceBasicConfigCmd(Device device, String channelId, String name, String expiration,
  903 + String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  904 +
  905 + StringBuffer cmdXml = new StringBuffer(200);
  906 + String charset = device.getCharset();
  907 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  908 + cmdXml.append("<Control>\r\n");
  909 + cmdXml.append("<CmdType>DeviceConfig</CmdType>\r\n");
  910 + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  911 + if (ObjectUtils.isEmpty(channelId)) {
  912 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  913 + } else {
  914 + cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
  915 + }
  916 + cmdXml.append("<BasicParam>\r\n");
  917 + if (!ObjectUtils.isEmpty(name)) {
  918 + cmdXml.append("<Name>" + name + "</Name>\r\n");
  919 + }
  920 + if (NumericUtil.isInteger(expiration)) {
  921 + if (Integer.valueOf(expiration) > 0) {
  922 + cmdXml.append("<Expiration>" + expiration + "</Expiration>\r\n");
  923 + }
  924 + }
  925 + if (NumericUtil.isInteger(heartBeatInterval)) {
  926 + if (Integer.valueOf(heartBeatInterval) > 0) {
  927 + cmdXml.append("<HeartBeatInterval>" + heartBeatInterval + "</HeartBeatInterval>\r\n");
  928 + }
  929 + }
  930 + if (NumericUtil.isInteger(heartBeatCount)) {
  931 + if (Integer.valueOf(heartBeatCount) > 0) {
  932 + cmdXml.append("<HeartBeatCount>" + heartBeatCount + "</HeartBeatCount>\r\n");
  933 + }
  934 + }
  935 + cmdXml.append("</BasicParam>\r\n");
  936 + cmdXml.append("</Control>\r\n");
  937 +
  938 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  939 + : udpSipProvider.getNewCallId();
  940 +
  941 + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
  942 + transmitRequest(device.getTransport(), request, errorEvent);
  943 + }
  944 +
  945 + /**
  946 + * 查询设备状态
  947 + *
  948 + * @param device 视频设备
  949 + */
  950 + @Override
  951 + public void deviceStatusQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  952 +
  953 + String charset = device.getCharset();
  954 + StringBuffer catalogXml = new StringBuffer(200);
  955 + catalogXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  956 + catalogXml.append("<Query>\r\n");
  957 + catalogXml.append("<CmdType>DeviceStatus</CmdType>\r\n");
  958 + catalogXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  959 + catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  960 + catalogXml.append("</Query>\r\n");
  961 +
  962 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  963 + : udpSipProvider.getNewCallId();
  964 +
  965 + Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
  966 +
  967 + transmitRequest(device.getTransport(), request, errorEvent);
  968 + }
  969 +
  970 + /**
  971 + * 查询设备信息
  972 + *
  973 + * @param device 视频设备
  974 + */
  975 + @Override
  976 + public void deviceInfoQuery(Device device) throws InvalidArgumentException, SipException, ParseException {
  977 +
  978 + StringBuffer catalogXml = new StringBuffer(200);
  979 + String charset = device.getCharset();
  980 + catalogXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  981 + catalogXml.append("<Query>\r\n");
  982 + catalogXml.append("<CmdType>DeviceInfo</CmdType>\r\n");
  983 + catalogXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  984 + catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  985 + catalogXml.append("</Query>\r\n");
  986 +
  987 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  988 + : udpSipProvider.getNewCallId();
  989 +
  990 + Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
  991 +
  992 + transmitRequest(device.getTransport(), request);
  993 +
  994 + }
  995 +
  996 + /**
  997 + * 查询目录列表
  998 + *
  999 + * @param device 视频设备
  1000 + */
  1001 + @Override
  1002 + public void catalogQuery(Device device, int sn, SipSubscribe.Event errorEvent) throws SipException, InvalidArgumentException, ParseException {
  1003 +
  1004 + StringBuffer catalogXml = new StringBuffer(200);
  1005 + String charset = device.getCharset();
  1006 + catalogXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  1007 + catalogXml.append("<Query>\r\n");
  1008 + catalogXml.append(" <CmdType>Catalog</CmdType>\r\n");
  1009 + catalogXml.append(" <SN>" + sn + "</SN>\r\n");
  1010 + catalogXml.append(" <DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  1011 + catalogXml.append("</Query>\r\n");
  1012 +
  1013 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  1014 + : udpSipProvider.getNewCallId();
  1015 +
  1016 + Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
  1017 +
  1018 + transmitRequest(device.getTransport(), request, errorEvent);
  1019 + }
  1020 +
  1021 + /**
  1022 + * 查询录像信息
  1023 + *
  1024 + * @param device 视频设备
  1025 + * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
  1026 + * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
  1027 + */
  1028 + @Override
  1029 + public void recordInfoQuery(Device device, String channelId, String startTime, String endTime, int sn, Integer secrecy, String type, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  1030 + if (secrecy == null) {
  1031 + secrecy = 0;
  1032 + }
  1033 + if (type == null) {
  1034 + type = "all";
  1035 + }
  1036 +
  1037 + StringBuffer recordInfoXml = new StringBuffer(200);
  1038 + String charset = device.getCharset();
  1039 + recordInfoXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  1040 + recordInfoXml.append("<Query>\r\n");
  1041 + recordInfoXml.append("<CmdType>RecordInfo</CmdType>\r\n");
  1042 + recordInfoXml.append("<SN>" + sn + "</SN>\r\n");
  1043 + recordInfoXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
  1044 + if (startTime != null) {
  1045 + recordInfoXml.append("<StartTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(startTime) + "</StartTime>\r\n");
  1046 + }
  1047 + if (endTime != null) {
  1048 + recordInfoXml.append("<EndTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(endTime) + "</EndTime>\r\n");
  1049 + }
  1050 + if (secrecy != null) {
  1051 + recordInfoXml.append("<Secrecy> " + secrecy + " </Secrecy>\r\n");
  1052 + }
  1053 + if (type != null) {
  1054 + // 大华NVR要求必须增加一个值为all的文本元素节点Type
  1055 + recordInfoXml.append("<Type>" + type + "</Type>\r\n");
  1056 + }
  1057 + recordInfoXml.append("</Query>\r\n");
  1058 +
  1059 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  1060 + : udpSipProvider.getNewCallId();
  1061 +
  1062 + Request request = headerProvider.createMessageRequest(device, recordInfoXml.toString(),
  1063 + SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
  1064 +
  1065 + transmitRequest(device.getTransport(), request, errorEvent, okEvent);
  1066 + }
  1067 +
  1068 + /**
  1069 + * 查询报警信息
  1070 + *
  1071 + * @param device 视频设备
  1072 + * @param startPriority 报警起始级别(可选)
  1073 + * @param endPriority 报警终止级别(可选)
  1074 + * @param alarmMethod 报警方式条件(可选)
  1075 + * @param alarmType 报警类型
  1076 + * @param startTime 报警发生起始时间(可选)
  1077 + * @param endTime 报警发生终止时间(可选)
  1078 + * @return true = 命令发送成功
  1079 + */
  1080 + @Override
  1081 + public void alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod, String alarmType,
  1082 + String startTime, String endTime, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  1083 +
  1084 + StringBuffer cmdXml = new StringBuffer(200);
  1085 + String charset = device.getCharset();
  1086 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  1087 + cmdXml.append("<Query>\r\n");
  1088 + cmdXml.append("<CmdType>Alarm</CmdType>\r\n");
  1089 + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  1090 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  1091 + if (!ObjectUtils.isEmpty(startPriority)) {
  1092 + cmdXml.append("<StartAlarmPriority>" + startPriority + "</StartAlarmPriority>\r\n");
  1093 + }
  1094 + if (!ObjectUtils.isEmpty(endPriority)) {
  1095 + cmdXml.append("<EndAlarmPriority>" + endPriority + "</EndAlarmPriority>\r\n");
  1096 + }
  1097 + if (!ObjectUtils.isEmpty(alarmMethod)) {
  1098 + cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n");
  1099 + }
  1100 + if (!ObjectUtils.isEmpty(alarmType)) {
  1101 + cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n");
  1102 + }
  1103 + if (!ObjectUtils.isEmpty(startTime)) {
  1104 + cmdXml.append("<StartAlarmTime>" + startTime + "</StartAlarmTime>\r\n");
  1105 + }
  1106 + if (!ObjectUtils.isEmpty(endTime)) {
  1107 + cmdXml.append("<EndAlarmTime>" + endTime + "</EndAlarmTime>\r\n");
  1108 + }
  1109 + cmdXml.append("</Query>\r\n");
  1110 +
  1111 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  1112 + : udpSipProvider.getNewCallId();
  1113 +
  1114 + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
  1115 + transmitRequest(device.getTransport(), request, errorEvent);
  1116 + }
  1117 +
  1118 + /**
  1119 + * 查询设备配置
  1120 + *
  1121 + * @param device 视频设备
  1122 + * @param channelId 通道编码(可选)
  1123 + * @param configType 配置类型:
  1124 + */
  1125 + @Override
  1126 + public void deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  1127 +
  1128 + StringBuffer cmdXml = new StringBuffer(200);
  1129 + String charset = device.getCharset();
  1130 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  1131 + cmdXml.append("<Query>\r\n");
  1132 + cmdXml.append("<CmdType>ConfigDownload</CmdType>\r\n");
  1133 + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  1134 + if (ObjectUtils.isEmpty(channelId)) {
  1135 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  1136 + } else {
  1137 + cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
  1138 + }
  1139 + cmdXml.append("<ConfigType>" + configType + "</ConfigType>\r\n");
  1140 + cmdXml.append("</Query>\r\n");
  1141 +
  1142 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  1143 + : udpSipProvider.getNewCallId();
  1144 +
  1145 + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
  1146 + transmitRequest(device.getTransport(), request, errorEvent);
  1147 + }
  1148 +
  1149 + /**
  1150 + * 查询设备预置位置
  1151 + *
  1152 + * @param device 视频设备
  1153 + */
  1154 + @Override
  1155 + public void presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  1156 +
  1157 + StringBuffer cmdXml = new StringBuffer(200);
  1158 + String charset = device.getCharset();
  1159 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  1160 + cmdXml.append("<Query>\r\n");
  1161 + cmdXml.append("<CmdType>PresetQuery</CmdType>\r\n");
  1162 + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  1163 + if (ObjectUtils.isEmpty(channelId)) {
  1164 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  1165 + } else {
  1166 + cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
  1167 + }
  1168 + cmdXml.append("</Query>\r\n");
  1169 +
  1170 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  1171 + : udpSipProvider.getNewCallId();
  1172 +
  1173 + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null, callIdHeader);
  1174 + transmitRequest(device.getTransport(), request, errorEvent);
  1175 + }
  1176 +
  1177 + /**
  1178 + * 查询移动设备位置数据
  1179 + *
  1180 + * @param device 视频设备
  1181 + */
  1182 + @Override
  1183 + public void mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  1184 +
  1185 + StringBuffer mobilePostitionXml = new StringBuffer(200);
  1186 + String charset = device.getCharset();
  1187 + mobilePostitionXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  1188 + mobilePostitionXml.append("<Query>\r\n");
  1189 + mobilePostitionXml.append("<CmdType>MobilePosition</CmdType>\r\n");
  1190 + mobilePostitionXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  1191 + mobilePostitionXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  1192 + mobilePostitionXml.append("<Interval>60</Interval>\r\n");
  1193 + mobilePostitionXml.append("</Query>\r\n");
  1194 +
  1195 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  1196 + : udpSipProvider.getNewCallId();
  1197 +
  1198 + Request request = headerProvider.createMessageRequest(device, mobilePostitionXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
  1199 +
  1200 + transmitRequest(device.getTransport(), request, errorEvent);
  1201 +
  1202 + }
  1203 +
  1204 + /**
  1205 + * 订阅、取消订阅移动位置
  1206 + *
  1207 + * @param device 视频设备
  1208 + * @return true = 命令发送成功
  1209 + */
  1210 + @Override
  1211 + public SIPRequest mobilePositionSubscribe(Device device, SIPRequest requestOld, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  1212 +
  1213 + StringBuffer subscribePostitionXml = new StringBuffer(200);
  1214 + String charset = device.getCharset();
  1215 + subscribePostitionXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  1216 + subscribePostitionXml.append("<Query>\r\n");
  1217 + subscribePostitionXml.append("<CmdType>MobilePosition</CmdType>\r\n");
  1218 + subscribePostitionXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  1219 + subscribePostitionXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  1220 + if (device.getSubscribeCycleForMobilePosition() > 0) {
  1221 + subscribePostitionXml.append("<Interval>" + device.getMobilePositionSubmissionInterval() + "</Interval>\r\n");
  1222 + }
  1223 + subscribePostitionXml.append("</Query>\r\n");
  1224 +
  1225 + CallIdHeader callIdHeader;
  1226 +
  1227 + if (requestOld != null) {
  1228 + callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(requestOld.getCallIdHeader().getCallId());
  1229 + } else {
  1230 + callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  1231 + : udpSipProvider.getNewCallId();
  1232 + }
  1233 + SIPRequest request = (SIPRequest) headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), requestOld, device.getSubscribeCycleForMobilePosition(), "presence", callIdHeader); //Position;id=" + tm.substring(tm.length() - 4));
  1234 +
  1235 + transmitRequest(device.getTransport(), request, errorEvent, okEvent);
  1236 + return request;
  1237 + }
  1238 +
  1239 + /**
  1240 + * 订阅、取消订阅报警信息
  1241 + *
  1242 + * @param device 视频设备
  1243 + * @param expires 订阅过期时间(0 = 取消订阅)
  1244 + * @param startPriority 报警起始级别(可选)
  1245 + * @param endPriority 报警终止级别(可选)
  1246 + * @param alarmMethod 报警方式条件(可选)
  1247 + * @param alarmType 报警类型
  1248 + * @param startTime 报警发生起始时间(可选)
  1249 + * @param endTime 报警发生终止时间(可选)
  1250 + * @return true = 命令发送成功
  1251 + */
  1252 + @Override
  1253 + public void alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime) throws InvalidArgumentException, SipException, ParseException {
  1254 +
  1255 + StringBuffer cmdXml = new StringBuffer(200);
  1256 + String charset = device.getCharset();
  1257 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  1258 + cmdXml.append("<Query>\r\n");
  1259 + cmdXml.append("<CmdType>Alarm</CmdType>\r\n");
  1260 + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  1261 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  1262 + if (!ObjectUtils.isEmpty(startPriority)) {
  1263 + cmdXml.append("<StartAlarmPriority>" + startPriority + "</StartAlarmPriority>\r\n");
  1264 + }
  1265 + if (!ObjectUtils.isEmpty(endPriority)) {
  1266 + cmdXml.append("<EndAlarmPriority>" + endPriority + "</EndAlarmPriority>\r\n");
  1267 + }
  1268 + if (!ObjectUtils.isEmpty(alarmMethod)) {
  1269 + cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n");
  1270 + }
  1271 + if (!ObjectUtils.isEmpty(alarmType)) {
  1272 + cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n");
  1273 + }
  1274 + if (!ObjectUtils.isEmpty(startTime)) {
  1275 + cmdXml.append("<StartAlarmTime>" + startTime + "</StartAlarmTime>\r\n");
  1276 + }
  1277 + if (!ObjectUtils.isEmpty(endTime)) {
  1278 + cmdXml.append("<EndAlarmTime>" + endTime + "</EndAlarmTime>\r\n");
  1279 + }
  1280 + cmdXml.append("</Query>\r\n");
  1281 +
  1282 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  1283 + : udpSipProvider.getNewCallId();
  1284 +
  1285 + Request request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), null, expires, "presence", callIdHeader);
  1286 + transmitRequest(device.getTransport(), request);
  1287 +
  1288 + }
  1289 +
  1290 + @Override
  1291 + public SIPRequest catalogSubscribe(Device device, SIPRequest requestOld, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
  1292 +
  1293 + StringBuffer cmdXml = new StringBuffer(200);
  1294 + String charset = device.getCharset();
  1295 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  1296 + cmdXml.append("<Query>\r\n");
  1297 + cmdXml.append("<CmdType>Catalog</CmdType>\r\n");
  1298 + cmdXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  1299 + cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  1300 + cmdXml.append("</Query>\r\n");
  1301 +
  1302 + CallIdHeader callIdHeader;
  1303 +
  1304 + if (requestOld != null) {
  1305 + callIdHeader = sipFactory.createHeaderFactory().createCallIdHeader(requestOld.getCallIdHeader().getCallId());
  1306 + } else {
  1307 + callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  1308 + : udpSipProvider.getNewCallId();
  1309 + }
  1310 +
  1311 + // 有效时间默认为60秒以上
  1312 + SIPRequest request = (SIPRequest) headerProvider.createSubscribeRequest(device, cmdXml.toString(), requestOld, device.getSubscribeCycleForCatalog(), "Catalog",
  1313 + callIdHeader);
  1314 + transmitRequest(device.getTransport(), request, errorEvent, okEvent);
  1315 + return request;
  1316 + }
  1317 +
  1318 + @Override
  1319 + public void dragZoomCmd(Device device, String channelId, String cmdString) throws InvalidArgumentException, SipException, ParseException {
  1320 +
  1321 + StringBuffer dragXml = new StringBuffer(200);
  1322 + String charset = device.getCharset();
  1323 + dragXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
  1324 + dragXml.append("<Control>\r\n");
  1325 + dragXml.append("<CmdType>DeviceControl</CmdType>\r\n");
  1326 + dragXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  1327 + if (ObjectUtils.isEmpty(channelId)) {
  1328 + dragXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
  1329 + } else {
  1330 + dragXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
  1331 + }
  1332 + dragXml.append(cmdString);
  1333 + dragXml.append("</Control>\r\n");
  1334 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  1335 + : udpSipProvider.getNewCallId();
  1336 + Request request = headerProvider.createMessageRequest(device, dragXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
  1337 + logger.debug("拉框信令: " + request.toString());
  1338 + transmitRequest(device.getTransport(), request);
  1339 + }
  1340 +
  1341 +
  1342 + @Override
  1343 + public void transmitRequest(String transport, Request request) throws SipException, ParseException {
  1344 + transmitRequest(transport, request, null, null);
  1345 + }
  1346 +
  1347 + @Override
  1348 + public void transmitRequest(String transport, Request request, SipSubscribe.Event errorEvent) throws SipException, ParseException {
  1349 + transmitRequest(transport, request, errorEvent, null);
  1350 + }
  1351 +
  1352 + @Override
  1353 + public void transmitRequest(String transport, Request request, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws SipException, ParseException {
  1354 +
  1355 + if (request.getHeader(UserAgentHeader.NAME) == null) {
  1356 + try {
  1357 + request.addHeader(SipUtils.createUserAgentHeader(sipFactory, gitUtil));
  1358 + } catch (ParseException e) {
  1359 + logger.error("添加UserAgentHeader失败", e);
  1360 + }
  1361 + }
  1362 +
  1363 + CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME);
  1364 + // 添加错误订阅
  1365 + if (errorEvent != null) {
  1366 + sipSubscribe.addErrorSubscribe(callIdHeader.getCallId(), (eventResult -> {
  1367 + errorEvent.response(eventResult);
  1368 + sipSubscribe.removeErrorSubscribe(eventResult.callId);
  1369 + sipSubscribe.removeOkSubscribe(eventResult.callId);
  1370 + }));
  1371 + }
  1372 + // 添加订阅
  1373 + if (okEvent != null) {
  1374 + sipSubscribe.addOkSubscribe(callIdHeader.getCallId(), eventResult -> {
  1375 + okEvent.response(eventResult);
  1376 + sipSubscribe.removeOkSubscribe(eventResult.callId);
  1377 + sipSubscribe.removeErrorSubscribe(eventResult.callId);
  1378 + });
  1379 + }
  1380 + if ("TCP".equals(transport)) {
  1381 + tcpSipProvider.sendRequest(request);
  1382 + } else if ("UDP".equals(transport)) {
  1383 + udpSipProvider.sendRequest(request);
  1384 + }
  1385 +
  1386 + }
  1387 +
  1388 +
  1389 + /**
  1390 + * 回放暂停
  1391 + */
  1392 + @Override
  1393 + public void playPauseCmd(Device device, StreamInfo streamInfo) throws InvalidArgumentException, ParseException, SipException {
  1394 + StringBuffer content = new StringBuffer(200);
  1395 + content.append("PAUSE RTSP/1.0\r\n");
  1396 + content.append("CSeq: " + getInfoCseq() + "\r\n");
  1397 + content.append("PauseTime: now\r\n");
  1398 +
  1399 + playbackControlCmd(device, streamInfo, content.toString(), null, null);
  1400 + }
  1401 +
  1402 +
  1403 + /**
  1404 + * 回放恢复
  1405 + */
  1406 + @Override
  1407 + public void playResumeCmd(Device device, StreamInfo streamInfo) throws InvalidArgumentException, ParseException, SipException {
  1408 + StringBuffer content = new StringBuffer(200);
  1409 + content.append("PLAY RTSP/1.0\r\n");
  1410 + content.append("CSeq: " + getInfoCseq() + "\r\n");
  1411 + content.append("Range: npt=now-\r\n");
  1412 +
  1413 + playbackControlCmd(device, streamInfo, content.toString(), null, null);
  1414 + }
  1415 +
  1416 + /**
  1417 + * 回放拖动播放
  1418 + */
  1419 + @Override
  1420 + public void playSeekCmd(Device device, StreamInfo streamInfo, long seekTime) throws InvalidArgumentException, ParseException, SipException {
  1421 + StringBuffer content = new StringBuffer(200);
  1422 + content.append("PLAY RTSP/1.0\r\n");
  1423 + content.append("CSeq: " + getInfoCseq() + "\r\n");
  1424 + content.append("Range: npt=" + Math.abs(seekTime) + "-\r\n");
  1425 +
  1426 + playbackControlCmd(device, streamInfo, content.toString(), null, null);
  1427 + }
  1428 +
  1429 + /**
  1430 + * 回放倍速播放
  1431 + */
  1432 + @Override
  1433 + public void playSpeedCmd(Device device, StreamInfo streamInfo, Double speed) throws InvalidArgumentException, ParseException, SipException {
  1434 + StringBuffer content = new StringBuffer(200);
  1435 + content.append("PLAY RTSP/1.0\r\n");
  1436 + content.append("CSeq: " + getInfoCseq() + "\r\n");
  1437 + content.append("Scale: " + String.format("%.6f", speed) + "\r\n");
  1438 +
  1439 + playbackControlCmd(device, streamInfo, content.toString(), null, null);
  1440 + }
  1441 +
  1442 + private int getInfoCseq() {
  1443 + return (int) ((Math.random() * 9 + 1) * Math.pow(10, 8));
  1444 + }
  1445 +
  1446 + @Override
  1447 + public void playbackControlCmd(Device device, StreamInfo streamInfo, String content, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws SipException, InvalidArgumentException, ParseException {
  1448 +
  1449 + SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(device.getDeviceId(), streamInfo.getChannelId(), null, streamInfo.getStream());
  1450 + if (ssrcTransaction == null) {
  1451 + logger.info("[回放控制]未找到视频流信息,设备:{}, 流ID: {}", device.getDeviceId(), streamInfo.getStream());
  1452 + return;
  1453 + }
  1454 +
  1455 + SIPRequest request = headerProvider.createInfoRequest(device, streamInfo.getChannelId(), content.toString(), ssrcTransaction.getSipTransactionInfo());
  1456 + if (request == null) {
  1457 + logger.info("[回放控制]构建Request信息失败,设备:{}, 流ID: {}", device.getDeviceId(), streamInfo.getStream());
  1458 + return;
  1459 + }
  1460 +
  1461 + transmitRequest(device.getTransport(), request, errorEvent, okEvent);
  1462 + }
  1463 +
  1464 + @Override
  1465 + public void sendAlarmMessage(Device device, DeviceAlarm deviceAlarm) throws InvalidArgumentException, SipException, ParseException {
  1466 + if (device == null) {
  1467 + return;
  1468 + }
  1469 + logger.info("[发送 报警通知] {}/{}->{},{}", device.getDeviceId(), deviceAlarm.getChannelId(),
  1470 + deviceAlarm.getLongitude(), deviceAlarm.getLatitude());
  1471 +
  1472 + String characterSet = device.getCharset();
  1473 + StringBuffer deviceStatusXml = new StringBuffer(600);
  1474 + deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
  1475 + deviceStatusXml.append("<Notify>\r\n");
  1476 + deviceStatusXml.append("<CmdType>Alarm</CmdType>\r\n");
  1477 + deviceStatusXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  1478 + deviceStatusXml.append("<DeviceID>" + deviceAlarm.getChannelId() + "</DeviceID>\r\n");
  1479 + deviceStatusXml.append("<AlarmPriority>" + deviceAlarm.getAlarmPriority() + "</AlarmPriority>\r\n");
  1480 + deviceStatusXml.append("<AlarmMethod>" + deviceAlarm.getAlarmMethod() + "</AlarmMethod>\r\n");
  1481 + deviceStatusXml.append("<AlarmTime>" + deviceAlarm.getAlarmTime() + "</AlarmTime>\r\n");
  1482 + deviceStatusXml.append("<AlarmDescription>" + deviceAlarm.getAlarmDescription() + "</AlarmDescription>\r\n");
  1483 + deviceStatusXml.append("<Longitude>" + deviceAlarm.getLongitude() + "</Longitude>\r\n");
  1484 + deviceStatusXml.append("<Latitude>" + deviceAlarm.getLatitude() + "</Latitude>\r\n");
  1485 + deviceStatusXml.append("<info>\r\n");
  1486 + deviceStatusXml.append("<AlarmType>" + deviceAlarm.getAlarmType() + "</AlarmType>\r\n");
  1487 + deviceStatusXml.append("</info>\r\n");
  1488 + deviceStatusXml.append("</Notify>\r\n");
  1489 +
  1490 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  1491 + : udpSipProvider.getNewCallId();
  1492 + Request request = headerProvider.createMessageRequest(device, deviceStatusXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, callIdHeader);
  1493 + transmitRequest(device.getTransport(), request);
  1494 +
  1495 +
  1496 + }
1853 1497 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
... ... @@ -13,12 +13,9 @@ import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
13 13 import com.genersoft.iot.vmp.service.IMediaServerService;
14 14 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
15 15 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
16   -import com.genersoft.iot.vmp.utils.SerializeUtils;
17 16 import gov.nist.javax.sip.SipProviderImpl;
18   -import gov.nist.javax.sip.SipStackImpl;
19 17 import gov.nist.javax.sip.message.MessageFactoryImpl;
20 18 import gov.nist.javax.sip.message.SIPRequest;
21   -import gov.nist.javax.sip.stack.SIPDialog;
22 19 import org.slf4j.Logger;
23 20 import org.slf4j.LoggerFactory;
24 21 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -32,13 +29,10 @@ import org.springframework.util.ObjectUtils;
32 29  
33 30 import com.genersoft.iot.vmp.utils.DateUtil;
34 31 import javax.sip.*;
35   -import javax.sip.address.SipURI;
36 32 import javax.sip.header.*;
37 33 import javax.sip.message.Request;
38   -import java.lang.reflect.Field;
39 34 import java.text.ParseException;
40 35 import java.util.ArrayList;
41   -import java.util.HashSet;
42 36 import java.util.List;
43 37  
44 38 @Component
... ... @@ -79,19 +73,18 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
79 73 private SubscribeHolder subscribeHolder;
80 74  
81 75 @Override
82   - public boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) {
83   - return register(parentPlatform, null, null, errorEvent, okEvent, false, true);
  76 + public void register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException {
  77 + register(parentPlatform, null, null, errorEvent, okEvent, false, true);
84 78 }
85 79  
86 80 @Override
87   - public boolean unregister(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) {
88   - return register(parentPlatform, null, null, errorEvent, okEvent, false, false);
  81 + public void unregister(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException {
  82 + register(parentPlatform, null, null, errorEvent, okEvent, false, false);
89 83 }
90 84  
91 85 @Override
92   - public boolean register(ParentPlatform parentPlatform, @Nullable String callId, @Nullable WWWAuthenticateHeader www,
93   - SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain, boolean isRegister) {
94   - try {
  86 + public void register(ParentPlatform parentPlatform, @Nullable String callId, @Nullable WWWAuthenticateHeader www,
  87 + SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain, boolean isRegister) throws SipException, InvalidArgumentException, ParseException {
95 88 Request request;
96 89 if (!registerAgain ) {
97 90 CallIdHeader callIdHeader = null;
... ... @@ -128,23 +121,10 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
128 121 }
129 122  
130 123 transmitRequest(parentPlatform, request, null, okEvent);
131   - return true;
132   - } catch (ParseException e) {
133   - e.printStackTrace();
134   - } catch (InvalidArgumentException e) {
135   - e.printStackTrace();
136   - } catch (PeerUnavailableException e) {
137   - e.printStackTrace();
138   - } catch (SipException e) {
139   - e.printStackTrace();
140   - }
141   - return false;
142 124 }
143 125  
144 126 @Override
145   - public String keepalive(ParentPlatform parentPlatform,SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) {
146   - String callId = null;
147   - try {
  127 + public String keepalive(ParentPlatform parentPlatform,SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws SipException, InvalidArgumentException, ParseException {
148 128 String characterSet = parentPlatform.getCharacterSet();
149 129 StringBuffer keepaliveXml = new StringBuffer(200);
150 130 keepaliveXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
... ... @@ -165,11 +145,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
165 145 SipUtils.getNewViaTag(),
166 146 callIdHeader);
167 147 transmitRequest(parentPlatform, request, errorEvent, okEvent);
168   - callId = callIdHeader.getCallId();
169   - } catch (ParseException | InvalidArgumentException | SipException e) {
170   - e.printStackTrace();
171   - }
172   - return callId;
  148 + return callIdHeader.getCallId();
173 149 }
174 150  
175 151 private void transmitRequest(ParentPlatform parentPlatform, Request request) throws SipException {
... ... @@ -208,39 +184,32 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
208 184 * @return
209 185 */
210 186 @Override
211   - public boolean catalogQuery(DeviceChannel channel, ParentPlatform parentPlatform, String sn, String fromTag, int size) {
  187 + public void catalogQuery(DeviceChannel channel, ParentPlatform parentPlatform, String sn, String fromTag, int size) throws SipException, InvalidArgumentException, ParseException {
212 188  
213 189 if ( parentPlatform ==null) {
214   - return false;
  190 + return ;
215 191 }
216   - try {
217   - List<DeviceChannel> channels = new ArrayList<>();
218   - if (channel != null) {
219   - channels.add(channel);
220   - }
221   - String catalogXml = getCatalogXml(channels, sn, parentPlatform, size);
  192 + List<DeviceChannel> channels = new ArrayList<>();
  193 + if (channel != null) {
  194 + channels.add(channel);
  195 + }
  196 + String catalogXml = getCatalogXml(channels, sn, parentPlatform, size);
222 197  
223   - // callid
224   - CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
225   - : udpSipProvider.getNewCallId();
  198 + // callid
  199 + CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
  200 + : udpSipProvider.getNewCallId();
226 201  
227   - Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, catalogXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
228   - transmitRequest(parentPlatform, request);
  202 + Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, catalogXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
  203 + transmitRequest(parentPlatform, request);
229 204  
230   - } catch (SipException | ParseException | InvalidArgumentException e) {
231   - e.printStackTrace();
232   - return false;
233   - }
234   - return true;
235 205 }
236 206  
237 207 @Override
238   - public boolean catalogQuery(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag) {
  208 + public void catalogQuery(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag) throws InvalidArgumentException, ParseException, SipException {
239 209 if ( parentPlatform ==null) {
240   - return false;
  210 + return ;
241 211 }
242 212 sendCatalogResponse(channels, parentPlatform, sn, fromTag, 0);
243   - return true;
244 213 }
245 214 private String getCatalogXml(List<DeviceChannel> channels, String sn, ParentPlatform parentPlatform, int size) {
246 215 String characterSet = parentPlatform.getCharacterSet();
... ... @@ -302,30 +271,30 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
302 271 return catalogXml.toString();
303 272 }
304 273  
305   - private void sendCatalogResponse(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag, int index) {
  274 + private void sendCatalogResponse(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag, int index) throws SipException, InvalidArgumentException, ParseException {
306 275 if (index >= channels.size()) {
307 276 return;
308 277 }
309   - try {
310   - List<DeviceChannel> deviceChannels;
311   - if (index + parentPlatform.getCatalogGroup() < channels.size()) {
312   - deviceChannels = channels.subList(index, index + parentPlatform.getCatalogGroup());
313   - }else {
314   - deviceChannels = channels.subList(index, channels.size());
315   - }
316   - String catalogXml = getCatalogXml(deviceChannels, sn, parentPlatform, channels.size());
317   - // callid
318   - CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
319   - : udpSipProvider.getNewCallId();
  278 + List<DeviceChannel> deviceChannels;
  279 + if (index + parentPlatform.getCatalogGroup() < channels.size()) {
  280 + deviceChannels = channels.subList(index, index + parentPlatform.getCatalogGroup());
  281 + }else {
  282 + deviceChannels = channels.subList(index, channels.size());
  283 + }
  284 + String catalogXml = getCatalogXml(deviceChannels, sn, parentPlatform, channels.size());
  285 + // callid
  286 + CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
  287 + : udpSipProvider.getNewCallId();
320 288  
321   - Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, catalogXml, fromTag, SipUtils.getNewViaTag(), callIdHeader);
322   - transmitRequest(parentPlatform, request, null, eventResult -> {
323   - int indexNext = index + parentPlatform.getCatalogGroup();
  289 + Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, catalogXml, fromTag, SipUtils.getNewViaTag(), callIdHeader);
  290 + transmitRequest(parentPlatform, request, null, eventResult -> {
  291 + int indexNext = index + parentPlatform.getCatalogGroup();
  292 + try {
324 293 sendCatalogResponse(channels, parentPlatform, sn, fromTag, indexNext);
325   - });
326   - } catch (SipException | ParseException | InvalidArgumentException e) {
327   - e.printStackTrace();
328   - }
  294 + } catch (SipException | InvalidArgumentException | ParseException e) {
  295 + logger.error("[命令发送失败] 国标级联 目录查询回复: {}", e.getMessage());
  296 + }
  297 + });
329 298 }
330 299  
331 300 /**
... ... @@ -336,36 +305,29 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
336 305 * @return
337 306 */
338 307 @Override
339   - public boolean deviceInfoResponse(ParentPlatform parentPlatform, String sn, String fromTag) {
  308 + public void deviceInfoResponse(ParentPlatform parentPlatform, String sn, String fromTag) throws SipException, InvalidArgumentException, ParseException {
340 309 if (parentPlatform == null) {
341   - return false;
342   - }
343   - try {
344   - String characterSet = parentPlatform.getCharacterSet();
345   - StringBuffer deviceInfoXml = new StringBuffer(600);
346   - deviceInfoXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
347   - deviceInfoXml.append("<Response>\r\n");
348   - deviceInfoXml.append("<CmdType>DeviceInfo</CmdType>\r\n");
349   - deviceInfoXml.append("<SN>" +sn + "</SN>\r\n");
350   - deviceInfoXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n");
351   - deviceInfoXml.append("<DeviceName>" + parentPlatform.getName() + "</DeviceName>\r\n");
352   - deviceInfoXml.append("<Manufacturer>wvp</Manufacturer>\r\n");
353   - deviceInfoXml.append("<Model>wvp-28181-2.0</Model>\r\n");
354   - deviceInfoXml.append("<Firmware>2.0.202107</Firmware>\r\n");
355   - deviceInfoXml.append("<Result>OK</Result>\r\n");
356   - deviceInfoXml.append("</Response>\r\n");
357   -
358   - CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
359   - : udpSipProvider.getNewCallId();
360   -
361   - Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceInfoXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
362   - transmitRequest(parentPlatform, request);
363   -
364   - } catch (SipException | ParseException | InvalidArgumentException e) {
365   - e.printStackTrace();
366   - return false;
  310 + return;
367 311 }
368   - return true;
  312 + String characterSet = parentPlatform.getCharacterSet();
  313 + StringBuffer deviceInfoXml = new StringBuffer(600);
  314 + deviceInfoXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
  315 + deviceInfoXml.append("<Response>\r\n");
  316 + deviceInfoXml.append("<CmdType>DeviceInfo</CmdType>\r\n");
  317 + deviceInfoXml.append("<SN>" +sn + "</SN>\r\n");
  318 + deviceInfoXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n");
  319 + deviceInfoXml.append("<DeviceName>" + parentPlatform.getName() + "</DeviceName>\r\n");
  320 + deviceInfoXml.append("<Manufacturer>wvp</Manufacturer>\r\n");
  321 + deviceInfoXml.append("<Model>wvp-28181-2.0</Model>\r\n");
  322 + deviceInfoXml.append("<Firmware>2.0.202107</Firmware>\r\n");
  323 + deviceInfoXml.append("<Result>OK</Result>\r\n");
  324 + deviceInfoXml.append("</Response>\r\n");
  325 +
  326 + CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
  327 + : udpSipProvider.getNewCallId();
  328 +
  329 + Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceInfoXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
  330 + transmitRequest(parentPlatform, request);
369 331 }
370 332  
371 333 /**
... ... @@ -376,129 +338,103 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
376 338 * @return
377 339 */
378 340 @Override
379   - public boolean deviceStatusResponse(ParentPlatform parentPlatform, String sn, String fromTag) {
  341 + public void deviceStatusResponse(ParentPlatform parentPlatform, String sn, String fromTag) throws SipException, InvalidArgumentException, ParseException {
380 342 if (parentPlatform == null) {
381   - return false;
  343 + return ;
382 344 }
383   - try {
384   - String characterSet = parentPlatform.getCharacterSet();
385   - StringBuffer deviceStatusXml = new StringBuffer(600);
386   - deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
387   - deviceStatusXml.append("<Response>\r\n");
388   - deviceStatusXml.append("<CmdType>DeviceStatus</CmdType>\r\n");
389   - deviceStatusXml.append("<SN>" +sn + "</SN>\r\n");
390   - deviceStatusXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n");
391   - deviceStatusXml.append("<Result>OK</Result>\r\n");
392   - deviceStatusXml.append("<Online>ONLINE</Online>\r\n");
393   - deviceStatusXml.append("<Status>OK</Status>\r\n");
394   - deviceStatusXml.append("</Response>\r\n");
395   -
396   - CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
397   - : udpSipProvider.getNewCallId();
398   -
399   - Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
400   - transmitRequest(parentPlatform, request);
  345 + String characterSet = parentPlatform.getCharacterSet();
  346 + StringBuffer deviceStatusXml = new StringBuffer(600);
  347 + deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
  348 + deviceStatusXml.append("<Response>\r\n");
  349 + deviceStatusXml.append("<CmdType>DeviceStatus</CmdType>\r\n");
  350 + deviceStatusXml.append("<SN>" +sn + "</SN>\r\n");
  351 + deviceStatusXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n");
  352 + deviceStatusXml.append("<Result>OK</Result>\r\n");
  353 + deviceStatusXml.append("<Online>ONLINE</Online>\r\n");
  354 + deviceStatusXml.append("<Status>OK</Status>\r\n");
  355 + deviceStatusXml.append("</Response>\r\n");
  356 +
  357 + CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
  358 + : udpSipProvider.getNewCallId();
  359 +
  360 + Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
  361 + transmitRequest(parentPlatform, request);
401 362  
402   - } catch (SipException | ParseException | InvalidArgumentException e) {
403   - e.printStackTrace();
404   - return false;
405   - }
406   - return true;
407 363 }
408 364  
409 365 @Override
410   - public boolean sendNotifyMobilePosition(ParentPlatform parentPlatform, GPSMsgInfo gpsMsgInfo, SubscribeInfo subscribeInfo) {
  366 + public void sendNotifyMobilePosition(ParentPlatform parentPlatform, GPSMsgInfo gpsMsgInfo, SubscribeInfo subscribeInfo) throws InvalidArgumentException, ParseException, NoSuchFieldException, SipException, IllegalAccessException {
411 367 if (parentPlatform == null) {
412   - return false;
  368 + return;
413 369 }
414 370 if (logger.isDebugEnabled()) {
415 371 logger.debug("[发送 移动位置订阅] {}/{}->{},{}", parentPlatform.getServerGBId(), gpsMsgInfo.getId(), gpsMsgInfo.getLng(), gpsMsgInfo.getLat());
416 372 }
417 373  
418   - try {
419   - String characterSet = parentPlatform.getCharacterSet();
420   - StringBuffer deviceStatusXml = new StringBuffer(600);
421   - deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
422   - deviceStatusXml.append("<Notify>\r\n");
423   - deviceStatusXml.append("<CmdType>MobilePosition</CmdType>\r\n");
424   - deviceStatusXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
425   - deviceStatusXml.append("<DeviceID>" + gpsMsgInfo.getId() + "</DeviceID>\r\n");
426   - deviceStatusXml.append("<Time>" + gpsMsgInfo.getTime() + "</Time>\r\n");
427   - deviceStatusXml.append("<Longitude>" + gpsMsgInfo.getLng() + "</Longitude>\r\n");
428   - deviceStatusXml.append("<Latitude>" + gpsMsgInfo.getLat() + "</Latitude>\r\n");
429   - deviceStatusXml.append("<Speed>" + gpsMsgInfo.getSpeed() + "</Speed>\r\n");
430   - deviceStatusXml.append("<Direction>" + gpsMsgInfo.getDirection() + "</Direction>\r\n");
431   - deviceStatusXml.append("<Altitude>" + gpsMsgInfo.getAltitude() + "</Altitude>\r\n");
432   - deviceStatusXml.append("</Notify>\r\n");
433   -
434   - sendNotify(parentPlatform, deviceStatusXml.toString(), subscribeInfo, eventResult -> {
435   - logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
436   - }, null);
437   -
438   - } catch (SipException | ParseException e) {
439   - e.printStackTrace();
440   - return false;
441   - } catch (NoSuchFieldException e) {
442   - e.printStackTrace();
443   - } catch (IllegalAccessException e) {
444   - e.printStackTrace();
445   - } catch (InvalidArgumentException e) {
446   - e.printStackTrace();
447   - }
448   - return true;
  374 + String characterSet = parentPlatform.getCharacterSet();
  375 + StringBuffer deviceStatusXml = new StringBuffer(600);
  376 + deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
  377 + deviceStatusXml.append("<Notify>\r\n");
  378 + deviceStatusXml.append("<CmdType>MobilePosition</CmdType>\r\n");
  379 + deviceStatusXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
  380 + deviceStatusXml.append("<DeviceID>" + gpsMsgInfo.getId() + "</DeviceID>\r\n");
  381 + deviceStatusXml.append("<Time>" + gpsMsgInfo.getTime() + "</Time>\r\n");
  382 + deviceStatusXml.append("<Longitude>" + gpsMsgInfo.getLng() + "</Longitude>\r\n");
  383 + deviceStatusXml.append("<Latitude>" + gpsMsgInfo.getLat() + "</Latitude>\r\n");
  384 + deviceStatusXml.append("<Speed>" + gpsMsgInfo.getSpeed() + "</Speed>\r\n");
  385 + deviceStatusXml.append("<Direction>" + gpsMsgInfo.getDirection() + "</Direction>\r\n");
  386 + deviceStatusXml.append("<Altitude>" + gpsMsgInfo.getAltitude() + "</Altitude>\r\n");
  387 + deviceStatusXml.append("</Notify>\r\n");
  388 +
  389 + sendNotify(parentPlatform, deviceStatusXml.toString(), subscribeInfo, eventResult -> {
  390 + logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
  391 + }, null);
  392 +
449 393 }
450 394  
451 395 @Override
452   - public boolean sendAlarmMessage(ParentPlatform parentPlatform, DeviceAlarm deviceAlarm) {
  396 + public void sendAlarmMessage(ParentPlatform parentPlatform, DeviceAlarm deviceAlarm) throws SipException, InvalidArgumentException, ParseException {
453 397 if (parentPlatform == null) {
454   - return false;
  398 + return;
455 399 }
456 400 logger.info("[发送报警通知] {}/{}->{},{}: {}", parentPlatform.getServerGBId(), deviceAlarm.getChannelId(),
457 401 deviceAlarm.getLongitude(), deviceAlarm.getLatitude(), JSONObject.toJSON(deviceAlarm));
458   - try {
459   - String characterSet = parentPlatform.getCharacterSet();
460   - StringBuffer deviceStatusXml = new StringBuffer(600);
461   - deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
462   - deviceStatusXml.append("<Notify>\r\n");
463   - deviceStatusXml.append("<CmdType>Alarm</CmdType>\r\n");
464   - deviceStatusXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
465   - deviceStatusXml.append("<DeviceID>" + deviceAlarm.getChannelId() + "</DeviceID>\r\n");
466   - deviceStatusXml.append("<AlarmPriority>" + deviceAlarm.getAlarmPriority() + "</AlarmPriority>\r\n");
467   - deviceStatusXml.append("<AlarmMethod>" + deviceAlarm.getAlarmMethod() + "</AlarmMethod>\r\n");
468   - deviceStatusXml.append("<AlarmTime>" + deviceAlarm.getAlarmTime() + "</AlarmTime>\r\n");
469   - deviceStatusXml.append("<AlarmDescription>" + deviceAlarm.getAlarmDescription() + "</AlarmDescription>\r\n");
470   - deviceStatusXml.append("<Longitude>" + deviceAlarm.getLongitude() + "</Longitude>\r\n");
471   - deviceStatusXml.append("<Latitude>" + deviceAlarm.getLatitude() + "</Latitude>\r\n");
472   - deviceStatusXml.append("<info>\r\n");
473   - deviceStatusXml.append("<AlarmType>" + deviceAlarm.getAlarmType() + "</AlarmType>\r\n");
474   - deviceStatusXml.append("</info>\r\n");
475   - deviceStatusXml.append("</Notify>\r\n");
476   -
477   - CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
478   - : udpSipProvider.getNewCallId();
479   -
480   - Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), SipUtils.getNewFromTag(), SipUtils.getNewViaTag(), callIdHeader);
481   - transmitRequest(parentPlatform, request);
  402 + String characterSet = parentPlatform.getCharacterSet();
  403 + StringBuffer deviceStatusXml = new StringBuffer(600);
  404 + deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
  405 + deviceStatusXml.append("<Notify>\r\n");
  406 + deviceStatusXml.append("<CmdType>Alarm</CmdType>\r\n");
  407 + deviceStatusXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
  408 + deviceStatusXml.append("<DeviceID>" + deviceAlarm.getChannelId() + "</DeviceID>\r\n");
  409 + deviceStatusXml.append("<AlarmPriority>" + deviceAlarm.getAlarmPriority() + "</AlarmPriority>\r\n");
  410 + deviceStatusXml.append("<AlarmMethod>" + deviceAlarm.getAlarmMethod() + "</AlarmMethod>\r\n");
  411 + deviceStatusXml.append("<AlarmTime>" + deviceAlarm.getAlarmTime() + "</AlarmTime>\r\n");
  412 + deviceStatusXml.append("<AlarmDescription>" + deviceAlarm.getAlarmDescription() + "</AlarmDescription>\r\n");
  413 + deviceStatusXml.append("<Longitude>" + deviceAlarm.getLongitude() + "</Longitude>\r\n");
  414 + deviceStatusXml.append("<Latitude>" + deviceAlarm.getLatitude() + "</Latitude>\r\n");
  415 + deviceStatusXml.append("<info>\r\n");
  416 + deviceStatusXml.append("<AlarmType>" + deviceAlarm.getAlarmType() + "</AlarmType>\r\n");
  417 + deviceStatusXml.append("</info>\r\n");
  418 + deviceStatusXml.append("</Notify>\r\n");
  419 +
  420 + CallIdHeader callIdHeader = parentPlatform.getTransport().equalsIgnoreCase("TCP") ? tcpSipProvider.getNewCallId()
  421 + : udpSipProvider.getNewCallId();
  422 +
  423 + Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), SipUtils.getNewFromTag(), SipUtils.getNewViaTag(), callIdHeader);
  424 + transmitRequest(parentPlatform, request);
482 425  
483   - } catch (SipException | ParseException e) {
484   - e.printStackTrace();
485   - return false;
486   - } catch (InvalidArgumentException e) {
487   - e.printStackTrace();
488   - }
489   - return true;
490 426 }
491 427  
492 428 @Override
493   - public boolean sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index) {
  429 + public void sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index) throws InvalidArgumentException, ParseException, NoSuchFieldException, SipException, IllegalAccessException {
494 430 if (parentPlatform == null || deviceChannels == null || deviceChannels.size() == 0 || subscribeInfo == null) {
495   - return false;
  431 + return;
496 432 }
497 433 if (index == null) {
498 434 index = 0;
499 435 }
500 436 if (index >= deviceChannels.size()) {
501   - return true;
  437 + return;
502 438 }
503 439 List<DeviceChannel> channels;
504 440 if (index + parentPlatform.getCatalogGroup() < deviceChannels.size()) {
... ... @@ -506,32 +442,25 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
506 442 }else {
507 443 channels = deviceChannels.subList(index, deviceChannels.size());
508 444 }
509   - try {
510   - Integer finalIndex = index;
511   - String catalogXmlContent = getCatalogXmlContentForCatalogAddOrUpdate(parentPlatform, channels,
512   - deviceChannels.size(), type, subscribeInfo);
513   - sendNotify(parentPlatform, catalogXmlContent, subscribeInfo, eventResult -> {
514   - logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
515   - }, (eventResult -> {
  445 + Integer finalIndex = index;
  446 + String catalogXmlContent = getCatalogXmlContentForCatalogAddOrUpdate(parentPlatform, channels,
  447 + deviceChannels.size(), type, subscribeInfo);
  448 + sendNotify(parentPlatform, catalogXmlContent, subscribeInfo, eventResult -> {
  449 + logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
  450 + }, (eventResult -> {
  451 + try {
516 452 sendNotifyForCatalogAddOrUpdate(type, parentPlatform, deviceChannels, subscribeInfo,
517 453 finalIndex + parentPlatform.getCatalogGroup());
518   - }));
519   - } catch (SipException | ParseException e) {
520   - e.printStackTrace();
521   - return false;
522   - } catch (NoSuchFieldException e) {
523   - e.printStackTrace();
524   - } catch (IllegalAccessException e) {
525   - e.printStackTrace();
526   - } catch (InvalidArgumentException e) {
527   - e.printStackTrace();
528   - }
529   - return true;
  454 + } catch (InvalidArgumentException | ParseException | NoSuchFieldException | SipException |
  455 + IllegalAccessException e) {
  456 + logger.error("[命令发送失败] 国标级联 NOTIFY通知: {}", e.getMessage());
  457 + }
  458 + }));
530 459 }
531 460  
532   - private ClientTransaction sendNotify(ParentPlatform parentPlatform, String catalogXmlContent,
  461 + private void sendNotify(ParentPlatform parentPlatform, String catalogXmlContent,
533 462 SubscribeInfo subscribeInfo, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent )
534   - throws NoSuchFieldException, IllegalAccessException, SipException, ParseException, InvalidArgumentException {
  463 + throws SipException, ParseException, InvalidArgumentException {
535 464 MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory();
536 465 String characterSet = parentPlatform.getCharacterSet();
537 466 // 设置编码, 防止中文乱码
... ... @@ -539,50 +468,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
539 468  
540 469 SIPRequest notifyRequest = headerProviderPlatformProvider.createNotifyRequest(parentPlatform, catalogXmlContent, subscribeInfo);
541 470  
542   - notifyRequest.getCSeqHeader().setSeqNumber(redisCatchStorage.getCSEQ());
543   -
544   - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
545   - notifyRequest.setContent(catalogXmlContent, contentTypeHeader);
546   -
547   - SubscriptionStateHeader subscriptionState = sipFactory.createHeaderFactory()
548   - .createSubscriptionStateHeader(SubscriptionStateHeader.ACTIVE);
549   - notifyRequest.addHeader(subscriptionState);
550   -
551   - EventHeader event = sipFactory.createHeaderFactory().createEventHeader(subscribeInfo.getEventType());
552   - if (subscribeInfo.getEventId() != null) {
553   - event.setEventId(subscribeInfo.getEventId());
554   - }
555   - notifyRequest.addHeader(event);
556   - SipURI sipURI = (SipURI) notifyRequest.getRequestURI();
557   - sipURI.setHost(parentPlatform.getServerIP());
558   - sipURI.setPort(parentPlatform.getServerPort());
559   -
560   -// ClientTransaction transaction = subscribeInfo.getClientTransaction();
561   -// if (transaction == null || transaction.getState().equals(TransactionState.COMPLETED)) {
562   -// if ("TCP".equals(parentPlatform.getTransport())) {
563   -// transaction = tcpSipProvider.getNewClientTransaction(notifyRequest);
564   -// } else if ("UDP".equals(parentPlatform.getTransport())) {
565   -// transaction = udpSipProvider.getNewClientTransaction(notifyRequest);
566   -// }
567   -// }
568   -
569   - ClientTransaction transaction = null;
570   - if ("TCP".equals(parentPlatform.getTransport())) {
571   - transaction = tcpSipProvider.getNewClientTransaction(notifyRequest);
572   - } else if ("UDP".equals(parentPlatform.getTransport())) {
573   - transaction = udpSipProvider.getNewClientTransaction(notifyRequest);
574   - }
575   -
576   - // 添加错误订阅
577   - if (errorEvent != null) {
578   - sipSubscribe.addErrorSubscribe(subscribeInfo.getRequest().getCallIdHeader().getCallId(), errorEvent);
579   - }
580   - // 添加订阅
581   - if (okEvent != null) {
582   - sipSubscribe.addOkSubscribe(subscribeInfo.getRequest().getCallIdHeader().getCallId(), okEvent);
583   - }
584   - transaction.sendRequest();
585   - return transaction;
  471 + transmitRequest(parentPlatform, notifyRequest);
586 472 }
587 473  
588 474 private String getCatalogXmlContentForCatalogAddOrUpdate(ParentPlatform parentPlatform, List<DeviceChannel> channels, int sumNum, String type, SubscribeInfo subscribeInfo) {
... ... @@ -641,20 +527,21 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
641 527 }
642 528  
643 529 @Override
644   - public boolean sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels,
645   - SubscribeInfo subscribeInfo, Integer index) {
  530 + public void sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels,
  531 + SubscribeInfo subscribeInfo, Integer index) throws InvalidArgumentException, ParseException, NoSuchFieldException, SipException, IllegalAccessException {
646 532 if (parentPlatform == null
647 533 || deviceChannels == null
648 534 || deviceChannels.size() == 0
649 535 || subscribeInfo == null) {
650   - return false;
  536 + logger.warn("[缺少必要参数]");
  537 + return;
651 538 }
652 539  
653 540 if (index == null) {
654 541 index = 0;
655 542 }
656 543 if (index >= deviceChannels.size()) {
657   - return true;
  544 + return;
658 545 }
659 546 List<DeviceChannel> channels;
660 547 if (index + parentPlatform.getCatalogGroup() < deviceChannels.size()) {
... ... @@ -662,28 +549,19 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
662 549 }else {
663 550 channels = deviceChannels.subList(index, deviceChannels.size());
664 551 }
665   - try {
666   - Integer finalIndex = index;
667   - String catalogXmlContent = getCatalogXmlContentForCatalogOther(parentPlatform, channels, type);
668   - sendNotify(parentPlatform, catalogXmlContent, subscribeInfo, eventResult -> {
669   - logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
670   - }, (eventResult -> {
  552 + Integer finalIndex = index;
  553 + String catalogXmlContent = getCatalogXmlContentForCatalogOther(parentPlatform, channels, type);
  554 + sendNotify(parentPlatform, catalogXmlContent, subscribeInfo, eventResult -> {
  555 + logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
  556 + }, eventResult -> {
  557 + try {
671 558 sendNotifyForCatalogOther(type, parentPlatform, deviceChannels, subscribeInfo,
672 559 finalIndex + parentPlatform.getCatalogGroup());
673   - }));
674   - } catch (SipException e) {
675   - e.printStackTrace();
676   - } catch (ParseException e) {
677   - e.printStackTrace();
678   - } catch (NoSuchFieldException e) {
679   - e.printStackTrace();
680   - } catch (IllegalAccessException e) {
681   - e.printStackTrace();
682   - } catch (InvalidArgumentException e) {
683   - e.printStackTrace();
684   - }
685   -
686   - return true;
  560 + } catch (InvalidArgumentException | ParseException | NoSuchFieldException | SipException |
  561 + IllegalAccessException e) {
  562 + logger.error("[命令发送失败] 国标级联 NOTIFY通知: {}", e.getMessage());
  563 + }
  564 + });
687 565 }
688 566  
689 567 private String getCatalogXmlContentForCatalogOther(ParentPlatform parentPlatform, List<DeviceChannel> channels, String type) {
... ... @@ -713,113 +591,81 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
713 591 return catalogXml.toString();
714 592 }
715 593 @Override
716   - public boolean recordInfo(DeviceChannel deviceChannel, ParentPlatform parentPlatform, String fromTag, RecordInfo recordInfo) {
  594 + public void recordInfo(DeviceChannel deviceChannel, ParentPlatform parentPlatform, String fromTag, RecordInfo recordInfo) throws SipException, InvalidArgumentException, ParseException {
717 595 if ( parentPlatform ==null) {
718   - return false;
  596 + return ;
719 597 }
720   - try {
721   - String characterSet = parentPlatform.getCharacterSet();
722   - StringBuffer recordXml = new StringBuffer(600);
723   - recordXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
724   - recordXml.append("<Response>\r\n");
725   - recordXml.append("<CmdType>RecordInfo</CmdType>\r\n");
726   - recordXml.append("<SN>" +recordInfo.getSn() + "</SN>\r\n");
727   - recordXml.append("<DeviceID>" + recordInfo.getDeviceId() + "</DeviceID>\r\n");
728   - recordXml.append("<SumNum>" + recordInfo.getSumNum() + "</SumNum>\r\n");
729   - if (recordInfo.getRecordList() == null ) {
730   - recordXml.append("<RecordList Num=\"0\">\r\n");
731   - }else {
732   - recordXml.append("<RecordList Num=\"" + recordInfo.getRecordList().size()+"\">\r\n");
733   - if (recordInfo.getRecordList().size() > 0) {
734   - for (RecordItem recordItem : recordInfo.getRecordList()) {
735   - recordXml.append("<Item>\r\n");
736   - if (deviceChannel != null) {
737   - recordXml.append("<DeviceID>" + recordItem.getDeviceId() + "</DeviceID>\r\n");
738   - recordXml.append("<Name>" + recordItem.getName() + "</Name>\r\n");
739   - recordXml.append("<StartTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(recordItem.getStartTime()) + "</StartTime>\r\n");
740   - recordXml.append("<EndTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(recordItem.getEndTime()) + "</EndTime>\r\n");
741   - recordXml.append("<Secrecy>" + recordItem.getSecrecy() + "</Secrecy>\r\n");
742   - recordXml.append("<Type>" + recordItem.getType() + "</Type>\r\n");
743   - if (!ObjectUtils.isEmpty(recordItem.getFileSize())) {
744   - recordXml.append("<FileSize>" + recordItem.getFileSize() + "</FileSize>\r\n");
745   - }
746   - if (!ObjectUtils.isEmpty(recordItem.getFilePath())) {
747   - recordXml.append("<FilePath>" + recordItem.getFilePath() + "</FilePath>\r\n");
748   - }
  598 + String characterSet = parentPlatform.getCharacterSet();
  599 + StringBuffer recordXml = new StringBuffer(600);
  600 + recordXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
  601 + recordXml.append("<Response>\r\n");
  602 + recordXml.append("<CmdType>RecordInfo</CmdType>\r\n");
  603 + recordXml.append("<SN>" +recordInfo.getSn() + "</SN>\r\n");
  604 + recordXml.append("<DeviceID>" + recordInfo.getDeviceId() + "</DeviceID>\r\n");
  605 + recordXml.append("<SumNum>" + recordInfo.getSumNum() + "</SumNum>\r\n");
  606 + if (recordInfo.getRecordList() == null ) {
  607 + recordXml.append("<RecordList Num=\"0\">\r\n");
  608 + }else {
  609 + recordXml.append("<RecordList Num=\"" + recordInfo.getRecordList().size()+"\">\r\n");
  610 + if (recordInfo.getRecordList().size() > 0) {
  611 + for (RecordItem recordItem : recordInfo.getRecordList()) {
  612 + recordXml.append("<Item>\r\n");
  613 + if (deviceChannel != null) {
  614 + recordXml.append("<DeviceID>" + recordItem.getDeviceId() + "</DeviceID>\r\n");
  615 + recordXml.append("<Name>" + recordItem.getName() + "</Name>\r\n");
  616 + recordXml.append("<StartTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(recordItem.getStartTime()) + "</StartTime>\r\n");
  617 + recordXml.append("<EndTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(recordItem.getEndTime()) + "</EndTime>\r\n");
  618 + recordXml.append("<Secrecy>" + recordItem.getSecrecy() + "</Secrecy>\r\n");
  619 + recordXml.append("<Type>" + recordItem.getType() + "</Type>\r\n");
  620 + if (!ObjectUtils.isEmpty(recordItem.getFileSize())) {
  621 + recordXml.append("<FileSize>" + recordItem.getFileSize() + "</FileSize>\r\n");
  622 + }
  623 + if (!ObjectUtils.isEmpty(recordItem.getFilePath())) {
  624 + recordXml.append("<FilePath>" + recordItem.getFilePath() + "</FilePath>\r\n");
749 625 }
750   - recordXml.append("</Item>\r\n");
751 626 }
  627 + recordXml.append("</Item>\r\n");
752 628 }
753 629 }
  630 + }
754 631  
755   - recordXml.append("</RecordList>\r\n");
756   - recordXml.append("</Response>\r\n");
  632 + recordXml.append("</RecordList>\r\n");
  633 + recordXml.append("</Response>\r\n");
757 634  
758   - // callid
759   - CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
760   - : udpSipProvider.getNewCallId();
761   - Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, recordXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
762   - transmitRequest(parentPlatform, request);
  635 + // callid
  636 + CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  637 + : udpSipProvider.getNewCallId();
  638 + Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, recordXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
  639 + transmitRequest(parentPlatform, request);
763 640  
764   - } catch (SipException | ParseException | InvalidArgumentException e) {
765   - e.printStackTrace();
766   - return false;
767   - }
768   - return true;
769 641 }
770 642  
771 643 @Override
772   - public boolean sendMediaStatusNotify(ParentPlatform platform, SendRtpItem sendRtpItem) {
773   - if (sendRtpItem == null) {
774   - return false;
775   - }
776   - if (platform == null) {
777   - return false;
778   - }
779   -
780   - try{
781   -
782   - String characterSet = platform.getCharacterSet();
783   - StringBuffer mediaStatusXml = new StringBuffer(200);
784   - mediaStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
785   - mediaStatusXml.append("<Notify>\r\n");
786   - mediaStatusXml.append("<CmdType>MediaStatus</CmdType>\r\n");
787   - mediaStatusXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
788   - mediaStatusXml.append("<DeviceID>" + sendRtpItem.getChannelId() + "</DeviceID>\r\n");
789   - mediaStatusXml.append("<NotifyType>121</NotifyType>\r\n");
790   - mediaStatusXml.append("</Notify>\r\n");
791   -
792   - SIPRequest messageRequest = (SIPRequest)headerProviderPlatformProvider.createMessageRequest(platform, mediaStatusXml.toString(),
793   - sendRtpItem);
794   -
795   - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
796   - messageRequest.setContent(mediaStatusXml.toString(), contentTypeHeader);
797   - SipURI sipURI = (SipURI) messageRequest.getRequestURI();
798   - sipURI.setHost(platform.getServerIP());
799   - sipURI.setPort(platform.getServerPort());
800   - ClientTransaction clientTransaction;
801   - if ("TCP".equals(platform.getTransport())) {
802   - clientTransaction = tcpSipProvider.getNewClientTransaction(messageRequest);
803   - }else {
804   - clientTransaction = udpSipProvider.getNewClientTransaction(messageRequest);
805   - }
806   - clientTransaction.sendRequest();
807   - } catch (SipException e) {
808   - e.printStackTrace();
809   - return false;
810   - } catch (ParseException e) {
811   - e.printStackTrace();
812   - return false;
813   - } catch (InvalidArgumentException e) {
814   - throw new RuntimeException(e);
  644 + public void sendMediaStatusNotify(ParentPlatform platform, SendRtpItem sendRtpItem) throws SipException, InvalidArgumentException, ParseException {
  645 + if (sendRtpItem == null || platform == null) {
  646 + return;
815 647 }
816   - return true;
817 648  
818 649  
  650 + String characterSet = platform.getCharacterSet();
  651 + StringBuffer mediaStatusXml = new StringBuffer(200);
  652 + mediaStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
  653 + mediaStatusXml.append("<Notify>\r\n");
  654 + mediaStatusXml.append("<CmdType>MediaStatus</CmdType>\r\n");
  655 + mediaStatusXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
  656 + mediaStatusXml.append("<DeviceID>" + sendRtpItem.getChannelId() + "</DeviceID>\r\n");
  657 + mediaStatusXml.append("<NotifyType>121</NotifyType>\r\n");
  658 + mediaStatusXml.append("</Notify>\r\n");
  659 +
  660 + SIPRequest messageRequest = (SIPRequest)headerProviderPlatformProvider.createMessageRequest(platform, mediaStatusXml.toString(),
  661 + sendRtpItem);
  662 +
  663 + transmitRequest(platform, messageRequest);
  664 +
819 665 }
820 666  
821 667 @Override
822   - public void streamByeCmd(ParentPlatform platform, String callId) {
  668 + public void streamByeCmd(ParentPlatform platform, String callId) throws SipException, InvalidArgumentException, ParseException {
823 669 if (platform == null) {
824 670 return;
825 671 }
... ... @@ -830,7 +676,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
830 676 }
831 677  
832 678 @Override
833   - public void streamByeCmd(ParentPlatform platform, SendRtpItem sendRtpItem) {
  679 + public void streamByeCmd(ParentPlatform platform, SendRtpItem sendRtpItem) throws SipException, InvalidArgumentException, ParseException {
834 680 if (sendRtpItem == null ) {
835 681 logger.info("[向上级发送BYE], sendRtpItem 为NULL");
836 682 return;
... ... @@ -846,25 +692,10 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
846 692 mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc());
847 693 zlmrtpServerFactory.closeRTPServer(mediaServerItem, sendRtpItem.getStreamId());
848 694 }
849   - try {
850   -
851   - SIPRequest byeRequest = headerProviderPlatformProvider.createByeRequest(platform, sendRtpItem);
852   - if (byeRequest == null) {
853   - logger.warn("[向上级发送bye]:无法创建 byeRequest");
854   - }
855   - ClientTransaction clientTransaction;
856   - if ("TCP".equals(platform.getTransport())) {
857   - clientTransaction = tcpSipProvider.getNewClientTransaction(byeRequest);
858   - } else {
859   - clientTransaction = udpSipProvider.getNewClientTransaction(byeRequest);
860   - }
861   - clientTransaction.sendRequest();
862   - } catch (SipException e) {
863   - e.printStackTrace();
864   - } catch (ParseException e) {
865   - e.printStackTrace();
866   - } catch (InvalidArgumentException e) {
867   - throw new RuntimeException(e);
  695 + SIPRequest byeRequest = headerProviderPlatformProvider.createByeRequest(platform, sendRtpItem);
  696 + if (byeRequest == null) {
  697 + logger.warn("[向上级发送bye]:无法创建 byeRequest");
868 698 }
  699 + transmitRequest(platform,byeRequest);
869 700 }
870 701 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
... ... @@ -7,6 +7,7 @@ import gov.nist.javax.sip.SipStackImpl;
7 7 import gov.nist.javax.sip.message.SIPRequest;
8 8 import gov.nist.javax.sip.message.SIPResponse;
9 9 import gov.nist.javax.sip.stack.SIPServerTransaction;
  10 +import gov.nist.javax.sip.stack.SIPServerTransactionImpl;
10 11 import org.apache.commons.lang3.ArrayUtils;
11 12 import org.dom4j.Document;
12 13 import org.dom4j.DocumentException;
... ... @@ -57,33 +58,34 @@ public abstract class SIPRequestProcessorParent {
57 58 */
58 59 public ServerTransaction getServerTransaction(RequestEvent evt) {
59 60 Request request = evt.getRequest();
60   - ServerTransaction serverTransaction = evt.getServerTransaction();
  61 + SIPServerTransactionImpl serverTransaction = (SIPServerTransactionImpl)evt.getServerTransaction();
61 62 // 判断TCP还是UDP
62 63 ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
63 64 String transport = reqViaHeader.getTransport();
  65 + if (serverTransaction != null && serverTransaction.getOriginalRequest() == null) {
  66 + serverTransaction.setOriginalRequest((SIPRequest) evt.getRequest());
  67 + }
64 68 boolean isTcp = "TCP".equals(transport);
65 69  
66 70 if (serverTransaction == null) {
67 71 try {
68 72 if (isTcp) {
69 73 SipStackImpl stack = (SipStackImpl)tcpSipProvider.getSipStack();
70   - serverTransaction = (SIPServerTransaction) stack.findTransaction((SIPRequest)request, true);
  74 + serverTransaction = (SIPServerTransactionImpl) stack.findTransaction((SIPRequest)request, true);
71 75 if (serverTransaction == null) {
72   - serverTransaction = tcpSipProvider.getNewServerTransaction(request);
  76 + serverTransaction = (SIPServerTransactionImpl)tcpSipProvider.getNewServerTransaction(request);
73 77 }
74 78 } else {
75 79 SipStackImpl stack = (SipStackImpl)udpSipProvider.getSipStack();
76   - serverTransaction = (SIPServerTransaction) stack.findTransaction((SIPRequest)request, true);
  80 + serverTransaction = (SIPServerTransactionImpl) stack.findTransaction((SIPRequest)request, true);
77 81 if (serverTransaction == null) {
78   - serverTransaction = udpSipProvider.getNewServerTransaction(request);
  82 + serverTransaction = (SIPServerTransactionImpl)udpSipProvider.getNewServerTransaction(request);
79 83 }
80 84 }
81 85 } catch (TransactionAlreadyExistsException e) {
82 86 logger.error(e.getMessage());
83 87 } catch (TransactionUnavailableException e) {
84 88 logger.error(e.getMessage());
85   - }finally {
86   -
87 89 }
88 90 }
89 91 return serverTransaction;
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java
... ... @@ -29,12 +29,16 @@ import org.springframework.beans.factory.annotation.Autowired;
29 29 import org.springframework.stereotype.Component;
30 30  
31 31 import javax.sip.*;
  32 +import javax.sip.InvalidArgumentException;
32 33 import javax.sip.RequestEvent;
  34 +import javax.sip.SipException;
33 35 import javax.sip.address.SipURI;
34 36 import javax.sip.header.CallIdHeader;
35 37 import javax.sip.header.FromHeader;
36 38 import javax.sip.header.HeaderAddress;
37 39 import java.text.ParseException;
  40 +import javax.sip.header.ToHeader;
  41 +import java.text.ParseException;
38 42 import java.util.*;
39 43  
40 44 /**
... ... @@ -105,8 +109,8 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
105 109 SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId());
106 110 String is_Udp = sendRtpItem.isTcp() ? "0" : "1";
107 111 MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
108   - logger.info("收到ACK,rtp/{}开始向上级推流, 目标 {}:{},SSRC={}", sendRtpItem.getStreamId(), sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc());
109   - Map<String, Object> param = new HashMap<>();
  112 + logger.info("收到ACK,rtp/{}开始向上级推流, 目标={}:{},SSRC={}", sendRtpItem.getStreamId(), sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc());
  113 + Map<String, Object> param = new HashMap<>(12);
110 114 param.put("vhost","__defaultVhost__");
111 115 param.put("app",sendRtpItem.getApp());
112 116 param.put("stream",sendRtpItem.getStreamId());
... ... @@ -187,7 +191,11 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
187 191 // TODO 可能是语音对讲
188 192 }else {
189 193 // 向上级平台
190   - commanderForPlatform.streamByeCmd(parentPlatform, callIdHeader.getCallId());
  194 + try {
  195 + commanderForPlatform.streamByeCmd(parentPlatform, callIdHeader.getCallId());
  196 + } catch (SipException | InvalidArgumentException | ParseException e) {
  197 + logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
  198 + }
191 199 }
192 200 }
193 201 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java
1 1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
2 2  
3 3 import com.genersoft.iot.vmp.common.StreamInfo;
  4 +import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
4 5 import com.genersoft.iot.vmp.gb28181.bean.Device;
5 6 import com.genersoft.iot.vmp.gb28181.bean.InviteStreamType;
6 7 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
... ... @@ -12,13 +13,12 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor
12 13 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
13 14 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
14 15 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
  16 +import com.genersoft.iot.vmp.service.IDeviceService;
15 17 import com.genersoft.iot.vmp.service.IMediaServerService;
16 18 import com.genersoft.iot.vmp.service.IPlayService;
17 19 import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
18 20 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
19 21 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
20   -import com.genersoft.iot.vmp.utils.SerializeUtils;
21   -import gov.nist.javax.sip.stack.SIPDialog;
22 22 import org.slf4j.Logger;
23 23 import org.slf4j.LoggerFactory;
24 24 import org.springframework.beans.factory.InitializingBean;
... ... @@ -52,6 +52,9 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
52 52 private IRedisCatchStorage redisCatchStorage;
53 53  
54 54 @Autowired
  55 + private IDeviceService deviceService;
  56 +
  57 + @Autowired
55 58 private IVideoManagerStorage storager;
56 59  
57 60 @Autowired
... ... @@ -81,9 +84,13 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
81 84 */
82 85 @Override
83 86 public void process(RequestEvent evt) {
  87 +
84 88 try {
85 89 responseAck(getServerTransaction(evt), Response.OK);
86   - CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME);
  90 + } catch (SipException | InvalidArgumentException | ParseException e) {
  91 + logger.error("[回复BYE信息失败],{}", e.getMessage());
  92 + }
  93 + CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME);
87 94 String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
88 95 String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
89 96 SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId());
... ... @@ -103,7 +110,17 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
103 110 if (totalReaderCount <= 0) {
104 111 logger.info("[收到bye] {} 无其它观看者,通知设备停止推流", streamId);
105 112 if (sendRtpItem.getPlayType().equals(InviteStreamType.PLAY)) {
106   - cmder.streamByeCmd(sendRtpItem.getDeviceId(), channelId, streamId, null);
  113 + Device device = deviceService.queryDevice(sendRtpItem.getDeviceId());
  114 + if (device == null) {
  115 + logger.info("[收到bye] {} 通知设备停止推流时未找到设备信息", streamId);
  116 + }
  117 + try {
  118 + logger.warn("[停止点播] {}/{}", sendRtpItem.getDeviceId(), channelId);
  119 + cmder.streamByeCmd(device, channelId, streamId, null);
  120 + } catch (InvalidArgumentException | ParseException | SipException |
  121 + SsrcTransactionNotFoundException e) {
  122 + logger.error("[收到bye] {} 无其它观看者,通知设备停止推流, 发送BYE失败 {}",streamId, e.getMessage());
  123 + }
107 124 }
108 125 if (sendRtpItem.isOnlyAudio()) {
109 126 playService.stopAudioBroadcast(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId());
... ... @@ -127,8 +144,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
127 144 }
128 145 SsrcTransaction ssrcTransactionForPlay = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, "play", null);
129 146 if (ssrcTransactionForPlay != null){
130   - SIPDialog dialogForPlay = (SIPDialog) SerializeUtils.deSerialize(ssrcTransactionForPlay.getDialog());
131   - if (dialogForPlay.getCallId().getCallId().equals(callIdHeader.getCallId())){
  147 + if (ssrcTransactionForPlay.getCallId().equals(callIdHeader.getCallId())){
132 148 // 释放ssrc
133 149 MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlay.getMediaServerId());
134 150 if (mediaServerItem != null) {
... ... @@ -147,12 +163,6 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
147 163 streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlayBack.getStream());
148 164 }
149 165 }
150   - } catch (SipException e) {
151   - e.printStackTrace();
152   - } catch (InvalidArgumentException e) {
153   - e.printStackTrace();
154   - } catch (ParseException e) {
155   - e.printStackTrace();
156   - }
  166 +
157 167 }
158 168 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
... ... @@ -366,16 +366,20 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
366 366 content.append("m=video " + sendRtpItem.getLocalPort() + " RTP/AVP 96\r\n");
367 367 content.append("a=sendonly\r\n");
368 368 content.append("a=rtpmap:96 PS/90000\r\n");
369   - content.append("y=" + ssrc + "\r\n");
  369 + content.append("y=" + sendRtpItem.getSsrc() + "\r\n");
370 370 content.append("f=\r\n");
371 371  
372 372 try {
373 373 // 超时未收到Ack应该回复bye,当前等待时间为10秒
374 374 dynamicTask.startDelay(callIdHeader.getCallId(), () -> {
375 375 logger.info("Ack 等待超时");
376   - mediaServerService.releaseSsrc(mediaServerItemInUSe.getId(), ssrc);
  376 + mediaServerService.releaseSsrc(mediaServerItemInUSe.getId(), sendRtpItem.getSsrc());
377 377 // 回复bye
378   - cmderFroPlatform.streamByeCmd(platform, callIdHeader.getCallId());
  378 + try {
  379 + cmderFroPlatform.streamByeCmd(platform, callIdHeader.getCallId());
  380 + } catch (SipException | InvalidArgumentException | ParseException e) {
  381 + logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
  382 + }
379 383 }, 60 * 1000);
380 384 responseSdpAck(serverTransaction, content.toString(), platform);
381 385  
... ... @@ -455,6 +459,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
455 459 SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, device.isSsrcCheck(), false);
456 460 logger.info(JSONObject.toJSONString(ssrcInfo));
457 461 sendRtpItem.setStreamId(ssrcInfo.getStream());
  462 + sendRtpItem.setSsrc(ssrc.equals(ssrcDefault) ? ssrcInfo.getSsrc() : ssrc);
458 463  
459 464 // 写入redis, 超时时回复
460 465 redisCatchStorage.updateSendRTPSever(sendRtpItem);
... ... @@ -691,12 +696,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
691 696 mediaListManager.removedChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream());
692 697 try {
693 698 responseAck(serverTransaction, Response.TEMPORARILY_UNAVAILABLE, response.getMsg());
694   - } catch (SipException e) {
695   - throw new RuntimeException(e);
696   - } catch (InvalidArgumentException e) {
697   - throw new RuntimeException(e);
698   - } catch (ParseException e) {
699   - throw new RuntimeException(e);
  699 + } catch (SipException | InvalidArgumentException | ParseException e) {
  700 + logger.error("[命令发送失败] 国标级联 点播回复: {}", e.getMessage());
700 701 }
701 702 }
702 703 });
... ... @@ -763,12 +764,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
763 764 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
764 765 }
765 766 }
766   - } catch (InvalidArgumentException e) {
767   - throw new RuntimeException(e);
768   - } catch (ParseException e) {
769   - throw new RuntimeException(e);
770   - } catch (SipException e) {
771   - throw new RuntimeException(e);
  767 + } catch (InvalidArgumentException | ParseException | SipException e) {
  768 + logger.error("[命令发送失败] 国标级联 点播回复: {}", e.getMessage());
772 769 }
773 770  
774 771  
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java
... ... @@ -124,10 +124,9 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
124 124 }
125 125 } catch (DocumentException e) {
126 126 logger.error("处理NOTIFY消息时错误", e);
127   - } finally {
128   - taskQueueHandlerRun = false;
129 127 }
130 128 }
  129 + taskQueueHandlerRun = false;
131 130 });
132 131 }
133 132 } catch (SipException | InvalidArgumentException | ParseException e) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/info/InfoRequestProcessor.java
... ... @@ -93,7 +93,9 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I
93 93 responseAck(serverTransaction, Response.NOT_FOUND, "device "+ deviceId +" not found");
94 94 logger.warn("[设备未找到 ]: {}", deviceId);
95 95 if (sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()) != null){
96   - SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new DeviceNotFoundEvent(evt.getDialog()));
  96 + DeviceNotFoundEvent deviceNotFoundEvent = new DeviceNotFoundEvent(evt.getDialog());
  97 + deviceNotFoundEvent.setCallId(callIdHeader.getCallId());
  98 + SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(deviceNotFoundEvent);
97 99 sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()).response(eventResult);
98 100 };
99 101 }else {
... ... @@ -113,23 +115,15 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I
113 115 // 失败的回复
114 116 try {
115 117 responseAck(serverTransaction, eventResult.statusCode, eventResult.msg);
116   - } catch (SipException e) {
117   - e.printStackTrace();
118   - } catch (InvalidArgumentException e) {
119   - e.printStackTrace();
120   - } catch (ParseException e) {
121   - e.printStackTrace();
  118 + } catch (SipException | InvalidArgumentException | ParseException e) {
  119 + logger.error("[命令发送失败] 国标级联 录像控制: {}", e.getMessage());
122 120 }
123 121 }, eventResult -> {
124 122 // 成功的回复
125 123 try {
126 124 responseAck(serverTransaction, eventResult.statusCode);
127   - } catch (SipException e) {
128   - e.printStackTrace();
129   - } catch (InvalidArgumentException e) {
130   - e.printStackTrace();
131   - } catch (ParseException e) {
132   - e.printStackTrace();
  125 + } catch (SipException | InvalidArgumentException | ParseException e) {
  126 + logger.error("[命令发送失败] 国标级联 录像控制: {}", e.getMessage());
133 127 }
134 128 });
135 129 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java
... ... @@ -89,8 +89,6 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
89 89 ParentPlatform parentPlatform = storage.queryParentPlatByServerGBId(deviceId);
90 90 try {
91 91 if (device != null && parentPlatform != null) {
92   -
93   - logger.warn("[重复]平台与设备编号重复:{}", deviceId);
94 92 SIPRequest request = (SIPRequest) evt.getRequest();
95 93 String hostAddress = request.getRemoteAddress().getHostAddress();
96 94 int remotePort = request.getRemotePort();
... ... @@ -105,7 +103,9 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
105 103 responseAck(serverTransaction, Response.NOT_FOUND, "device "+ deviceId +" not found");
106 104 logger.warn("[设备未找到 ]: {}", deviceId);
107 105 if (sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()) != null){
108   - SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new DeviceNotFoundEvent(evt.getDialog()));
  106 + DeviceNotFoundEvent deviceNotFoundEvent = new DeviceNotFoundEvent(evt.getDialog());
  107 + deviceNotFoundEvent.setCallId(callIdHeader.getCallId());
  108 + SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(deviceNotFoundEvent);
109 109 sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()).response(eventResult);
110 110 };
111 111 }else {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/control/cmd/DeviceControlQueryMessageHandler.java
... ... @@ -16,6 +16,8 @@ import org.slf4j.Logger;
16 16 import org.slf4j.LoggerFactory;
17 17 import org.springframework.beans.factory.InitializingBean;
18 18 import org.springframework.beans.factory.annotation.Autowired;
  19 +import org.springframework.beans.factory.annotation.Qualifier;
  20 +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
19 21 import org.springframework.stereotype.Component;
20 22 import org.springframework.util.ObjectUtils;
21 23 import org.springframework.util.StringUtils;
... ... @@ -48,6 +50,10 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
48 50 @Autowired
49 51 private SIPCommanderFroPlatform cmderFroPlatform;
50 52  
  53 + @Qualifier("taskExecutor")
  54 + @Autowired
  55 + private ThreadPoolTaskExecutor taskExecutor;
  56 +
51 57 @Override
52 58 public void afterPropertiesSet() throws Exception {
53 59 controlMessageHandler.addHandler(cmdType, this);
... ... @@ -71,34 +77,30 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
71 77 if (parentPlatform.getServerGBId().equals(targetGBId)) {
72 78 // 远程启动本平台:需要在重新启动程序后先对SipStack解绑
73 79 logger.info("执行远程启动本平台命令");
74   - cmderFroPlatform.unregister(parentPlatform, null, null);
75   -
76   - Thread restartThread = new Thread(new Runnable() {
77   - @Override
78   - public void run() {
79   - try {
80   - Thread.sleep(3000);
81   - SipProvider up = (SipProvider) SpringBeanFactory.getBean("udpSipProvider");
82   - SipStackImpl stack = (SipStackImpl)up.getSipStack();
83   - stack.stop();
84   - Iterator listener = stack.getListeningPoints();
85   - while (listener.hasNext()) {
86   - stack.deleteListeningPoint((ListeningPoint) listener.next());
87   - }
88   - Iterator providers = stack.getSipProviders();
89   - while (providers.hasNext()) {
90   - stack.deleteSipProvider((SipProvider) providers.next());
91   - }
92   - VManageBootstrap.restart();
93   - } catch (InterruptedException ignored) {
94   - } catch (ObjectInUseException e) {
95   - e.printStackTrace();
  80 + try {
  81 + cmderFroPlatform.unregister(parentPlatform, null, null);
  82 + } catch (InvalidArgumentException | ParseException | SipException e) {
  83 + logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage());
  84 + }
  85 + taskExecutor.execute(()->{
  86 + try {
  87 + Thread.sleep(3000);
  88 + SipProvider up = (SipProvider) SpringBeanFactory.getBean("udpSipProvider");
  89 + SipStackImpl stack = (SipStackImpl)up.getSipStack();
  90 + stack.stop();
  91 + Iterator listener = stack.getListeningPoints();
  92 + while (listener.hasNext()) {
  93 + stack.deleteListeningPoint((ListeningPoint) listener.next());
96 94 }
  95 + Iterator providers = stack.getSipProviders();
  96 + while (providers.hasNext()) {
  97 + stack.deleteSipProvider((SipProvider) providers.next());
  98 + }
  99 + VManageBootstrap.restart();
  100 + } catch (InterruptedException | ObjectInUseException e) {
  101 + logger.error("[任务执行失败] 服务重启: {}", e.getMessage());
97 102 }
98 103 });
99   -
100   - restartThread.setDaemon(false);
101   - restartThread.start();
102 104 } else {
103 105 // 远程启动指定设备
104 106 }
... ... @@ -111,37 +113,29 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
111 113 try {
112 114 responseAck(serverTransaction, Response.NOT_FOUND);
113 115 return;
114   - } catch (SipException e) {
115   - e.printStackTrace();
116   - } catch (InvalidArgumentException e) {
117   - e.printStackTrace();
118   - } catch (ParseException e) {
119   - e.printStackTrace();
  116 + } catch (SipException | InvalidArgumentException | ParseException e) {
  117 + logger.error("[命令发送失败] 错误信息: {}", e.getMessage());
120 118 }
121 119 }
122   - cmder.fronEndCmd(deviceForPlatform, channelId, cmdString, eventResult -> {
123   - // 失败的回复
124   - try {
125   - responseAck(serverTransaction, eventResult.statusCode, eventResult.msg);
126   - } catch (SipException e) {
127   - e.printStackTrace();
128   - } catch (InvalidArgumentException e) {
129   - e.printStackTrace();
130   - } catch (ParseException e) {
131   - e.printStackTrace();
132   - }
133   - }, eventResult -> {
134   - // 成功的回复
135   - try {
136   - responseAck(serverTransaction, eventResult.statusCode);
137   - } catch (SipException e) {
138   - e.printStackTrace();
139   - } catch (InvalidArgumentException e) {
140   - e.printStackTrace();
141   - } catch (ParseException e) {
142   - e.printStackTrace();
143   - }
144   - });
  120 + try {
  121 + cmder.fronEndCmd(deviceForPlatform, channelId, cmdString, eventResult -> {
  122 + // 失败的回复
  123 + try {
  124 + responseAck(serverTransaction, eventResult.statusCode, eventResult.msg);
  125 + } catch (SipException | InvalidArgumentException | ParseException e) {
  126 + logger.error("[命令发送失败] 云台/前端回复: {}", e.getMessage());
  127 + }
  128 + }, eventResult -> {
  129 + // 成功的回复
  130 + try {
  131 + responseAck(serverTransaction, eventResult.statusCode);
  132 + } catch (SipException | InvalidArgumentException | ParseException e) {
  133 + logger.error("[命令发送失败] 云台/前端回复: {}", e.getMessage());
  134 + }
  135 + });
  136 + } catch (InvalidArgumentException | SipException | ParseException e) {
  137 + logger.error("[命令发送失败] 云台/前端: {}", e.getMessage());
  138 + }
145 139 }
146 140 }
147 141 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java
... ... @@ -217,12 +217,8 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
217 217 // 回复200 OK
218 218 try {
219 219 responseAck(getServerTransaction(evt), Response.OK);
220   - } catch (SipException e) {
221   - throw new RuntimeException(e);
222   - } catch (InvalidArgumentException e) {
223   - throw new RuntimeException(e);
224   - } catch (ParseException e) {
225   - throw new RuntimeException(e);
  220 + } catch (SipException | InvalidArgumentException | ParseException e) {
  221 + logger.error("[命令发送失败] 国标级联 报警通知回复: {}", e.getMessage());
226 222 }
227 223 Element deviceIdElement = rootElement.element("DeviceID");
228 224 String channelId = deviceIdElement.getText().toString();
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
... ... @@ -78,12 +78,8 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
78 78 deviceService.online(device);
79 79 }
80 80 }
81   - } catch (SipException e) {
82   - e.printStackTrace();
83   - } catch (InvalidArgumentException e) {
84   - e.printStackTrace();
85   - } catch (ParseException e) {
86   - e.printStackTrace();
  81 + } catch (SipException | InvalidArgumentException | ParseException e) {
  82 + logger.error("[命令发送失败] 国标级联 心跳回复: {}", e.getMessage());
87 83 }
88 84 }
89 85  
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java
1 1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd;
2 2  
3 3 import com.genersoft.iot.vmp.common.StreamInfo;
  4 +import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
4 5 import com.genersoft.iot.vmp.gb28181.bean.Device;
5 6 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
6 7 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
... ... @@ -67,12 +68,8 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i
67 68 // 回复200 OK
68 69 try {
69 70 responseAck(getServerTransaction(evt), Response.OK);
70   - } catch (SipException e) {
71   - e.printStackTrace();
72   - } catch (InvalidArgumentException e) {
73   - e.printStackTrace();
74   - } catch (ParseException e) {
75   - e.printStackTrace();
  71 + } catch (SipException | InvalidArgumentException | ParseException e) {
  72 + logger.error("[命令发送失败] 国标级联 录像流推送完毕,回复200OK: {}", e.getMessage());
76 73 }
77 74 CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME);
78 75 String NotifyType =getText(rootElement, "NotifyType");
... ... @@ -89,7 +86,12 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i
89 86 // 先从会话内查找
90 87 SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransaction(null, null, callIdHeader.getCallId(), null);
91 88 if (ssrcTransaction != null) { // 兼容海康 媒体通知 消息from字段不是设备ID的问题
92   - cmder.streamByeCmd(device.getDeviceId(), ssrcTransaction.getChannelId(), null, callIdHeader.getCallId());
  89 +
  90 + try {
  91 + cmder.streamByeCmd(device, ssrcTransaction.getChannelId(), null, callIdHeader.getCallId());
  92 + } catch (InvalidArgumentException | ParseException | SsrcTransactionNotFoundException | SipException e) {
  93 + logger.error("[录像流]推送完毕,收到关流通知, 发送BYE失败 {}", e.getMessage());
  94 + }
93 95  
94 96 // 如果级联播放,需要给上级发送此通知 TODO 多个上级同时观看一个下级 可能存在停错的问题,需要将点播CallId进行上下级绑定
95 97 SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, ssrcTransaction.getChannelId(), null, null);
... ... @@ -99,7 +101,11 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i
99 101 logger.warn("[级联消息发送]:发送MediaStatus发现上级平台{}不存在", sendRtpItem.getPlatformId());
100 102 return;
101 103 }
102   - sipCommanderFroPlatform.sendMediaStatusNotify(parentPlatform, sendRtpItem);
  104 + try {
  105 + sipCommanderFroPlatform.sendMediaStatusNotify(parentPlatform, sendRtpItem);
  106 + } catch (SipException | InvalidArgumentException | ParseException e) {
  107 + logger.error("[命令发送失败] 国标级联 录像播放完毕: {}", e.getMessage());
  108 + }
103 109 }
104 110 }
105 111 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/AlarmQueryMessageHandler.java
... ... @@ -59,12 +59,8 @@ public class AlarmQueryMessageHandler extends SIPRequestProcessorParent implemen
59 59 logger.info("不支持alarm查询");
60 60 try {
61 61 responseAck(getServerTransaction(evt), Response.NOT_FOUND, "not support alarm query");
62   - } catch (SipException e) {
63   - e.printStackTrace();
64   - } catch (InvalidArgumentException e) {
65   - e.printStackTrace();
66   - } catch (ParseException e) {
67   - e.printStackTrace();
  62 + } catch (SipException | InvalidArgumentException | ParseException e) {
  63 + logger.error("[命令发送失败] 国标级联 alarm查询回复200OK: {}", e.getMessage());
68 64 }
69 65  
70 66 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java
... ... @@ -100,12 +100,8 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem
100 100 // 回复无通道
101 101 cmderFroPlatform.catalogQuery(null, parentPlatform, sn, fromHeader.getTag(), 0);
102 102 }
103   - } catch (SipException e) {
104   - e.printStackTrace();
105   - } catch (InvalidArgumentException e) {
106   - e.printStackTrace();
107   - } catch (ParseException e) {
108   - e.printStackTrace();
  103 + } catch (SipException | InvalidArgumentException | ParseException e) {
  104 + logger.error("[命令发送失败] 国标级联 目录查询: {}", e.getMessage());
109 105 }
110 106  
111 107 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceInfoQueryMessageHandler.java
... ... @@ -49,14 +49,14 @@ public class DeviceInfoQueryMessageHandler extends SIPRequestProcessorParent imp
49 49 try {
50 50 // 回复200 OK
51 51 responseAck(getServerTransaction(evt), Response.OK);
52   - } catch (SipException e) {
53   - e.printStackTrace();
54   - } catch (InvalidArgumentException e) {
55   - e.printStackTrace();
56   - } catch (ParseException e) {
57   - e.printStackTrace();
  52 + } catch (SipException | InvalidArgumentException | ParseException e) {
  53 + logger.error("[命令发送失败] DeviceInfo查询回复: {}", e.getMessage());
58 54 }
59 55 String sn = rootElement.element("SN").getText();
60   - cmderFroPlatform.deviceInfoResponse(parentPlatform, sn, fromHeader.getTag());
  56 + try {
  57 + cmderFroPlatform.deviceInfoResponse(parentPlatform, sn, fromHeader.getTag());
  58 + } catch (SipException | InvalidArgumentException | ParseException e) {
  59 + logger.error("[命令发送失败] 国标级联 DeviceInfo查询回复: {}", e.getMessage());
  60 + }
61 61 }
62 62 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceStatusQueryMessageHandler.java
... ... @@ -62,14 +62,14 @@ public class DeviceStatusQueryMessageHandler extends SIPRequestProcessorParent i
62 62 // 回复200 OK
63 63 try {
64 64 responseAck(getServerTransaction(evt), Response.OK);
65   - } catch (SipException e) {
66   - e.printStackTrace();
67   - } catch (InvalidArgumentException e) {
68   - e.printStackTrace();
69   - } catch (ParseException e) {
70   - e.printStackTrace();
  65 + } catch (SipException | InvalidArgumentException | ParseException e) {
  66 + logger.error("[命令发送失败] 国标级联 DeviceStatus查询回复200OK: {}", e.getMessage());
71 67 }
72 68 String sn = rootElement.element("SN").getText();
73   - cmderFroPlatform.deviceStatusResponse(parentPlatform, sn, fromHeader.getTag());
  69 + try {
  70 + cmderFroPlatform.deviceStatusResponse(parentPlatform, sn, fromHeader.getTag());
  71 + } catch (SipException | InvalidArgumentException | ParseException e) {
  72 + logger.error("[命令发送失败] 国标级联 DeviceStatus查询回复: {}", e.getMessage());
  73 + }
74 74 }
75 75 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/RecordInfoQueryMessageHandler.java
... ... @@ -103,53 +103,45 @@ public class RecordInfoQueryMessageHandler extends SIPRequestProcessorParent imp
103 103 DeviceChannel deviceChannel = storager.queryChannelInParentPlatform(parentPlatform.getServerGBId(), channelId);
104 104 // 接收录像数据
105 105 recordEndEventListener.addEndEventHandler(deviceChannel.getDeviceId(), channelId, (recordInfo)->{
106   - cmderFroPlatform.recordInfo(deviceChannel, parentPlatform, fromHeader.getTag(), recordInfo);
  106 + try {
  107 + cmderFroPlatform.recordInfo(deviceChannel, parentPlatform, fromHeader.getTag(), recordInfo);
  108 + } catch (SipException | InvalidArgumentException | ParseException e) {
  109 + logger.error("[命令发送失败] 国标级联 回复录像数据: {}", e.getMessage());
  110 + }
107 111 });
108   - commander.recordInfoQuery(device, channelId, DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(startTime),
109   - DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(endTime), sn, secrecy, type, (eventResult -> {
110   - // 回复200 OK
111   - try {
112   - responseAck(serverTransaction, Response.OK);
113   - } catch (SipException e) {
114   - e.printStackTrace();
115   - } catch (InvalidArgumentException e) {
116   - e.printStackTrace();
117   - } catch (ParseException e) {
118   - e.printStackTrace();
119   - }
120   - }),(eventResult -> {
121   - // 查询失败
122   - try {
123   - responseAck(serverTransaction, eventResult.statusCode, eventResult.msg);
124   - } catch (SipException e) {
125   - e.printStackTrace();
126   - } catch (InvalidArgumentException e) {
127   - e.printStackTrace();
128   - } catch (ParseException e) {
129   - e.printStackTrace();
130   - }
131   - }));
  112 + try {
  113 + commander.recordInfoQuery(device, channelId, DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(startTime),
  114 + DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(endTime), sn, secrecy, type, (eventResult -> {
  115 + // 回复200 OK
  116 + try {
  117 + responseAck(serverTransaction, Response.OK);
  118 + } catch (SipException | InvalidArgumentException | ParseException e) {
  119 + logger.error("[命令发送失败] 录像查询回复: {}", e.getMessage());
  120 + }
  121 + }),(eventResult -> {
  122 + // 查询失败
  123 + try {
  124 + responseAck(serverTransaction, eventResult.statusCode, eventResult.msg);
  125 + } catch (SipException | InvalidArgumentException | ParseException e) {
  126 + logger.error("[命令发送失败] 录像查询回复: {}", e.getMessage());
  127 + }
  128 + }));
  129 + } catch (InvalidArgumentException | ParseException | SipException e) {
  130 + logger.error("[命令发送失败] 录像查询: {}", e.getMessage());
  131 + }
132 132  
133 133 }else if (channelSources.get(1).getCount() > 0) { // 直播流
134 134 // TODO
135 135 try {
136 136 responseAck(serverTransaction, Response.NOT_IMPLEMENTED); // 回复未实现
137   - } catch (SipException e) {
138   - e.printStackTrace();
139   - } catch (InvalidArgumentException e) {
140   - e.printStackTrace();
141   - } catch (ParseException e) {
142   - e.printStackTrace();
  137 + } catch (SipException | InvalidArgumentException | ParseException e) {
  138 + logger.error("[命令发送失败] 录像查询: {}", e.getMessage());
143 139 }
144 140 }else { // 错误的请求
145 141 try {
146 142 responseAck(serverTransaction, Response.BAD_REQUEST);
147   - } catch (SipException e) {
148   - e.printStackTrace();
149   - } catch (InvalidArgumentException e) {
150   - e.printStackTrace();
151   - } catch (ParseException e) {
152   - e.printStackTrace();
  143 + } catch (SipException | InvalidArgumentException | ParseException e) {
  144 + logger.error("[命令发送失败] 录像查询: {}", e.getMessage());
153 145 }
154 146 }
155 147 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/BroadcastResponseMessageHandler.java
... ... @@ -63,7 +63,7 @@ public class BroadcastResponseMessageHandler extends SIPRequestProcessorParent i
63 63 audioBroadcastManager.update(audioBroadcastCatch);
64 64 responseAck(evt, Response.OK);
65 65 } catch (ParseException | SipException | InvalidArgumentException e) {
66   - e.printStackTrace();
  66 + logger.error("[命令发送失败] 国标级联 语音喊话: {}", e.getMessage());
67 67 }
68 68 }
69 69  
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java
... ... @@ -56,24 +56,8 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
56 56 private IVideoManagerStorage storager;
57 57  
58 58 @Autowired
59   - private DeferredResultHolder deferredResultHolder;
60   -
61   - @Autowired
62 59 private CatalogDataCatch catalogDataCatch;
63 60  
64   - @Autowired
65   - private SipConfig config;
66   -
67   - @Autowired
68   - private EventPublisher publisher;
69   -
70   - //by brewswang
71   - @Autowired
72   - private UserSetting userSetting;
73   -
74   - @Autowired
75   - private IRedisCatchStorage redisCatchStorage;
76   -
77 61 @Qualifier("taskExecutor")
78 62 @Autowired
79 63 private ThreadPoolTaskExecutor taskExecutor;
... ... @@ -87,89 +71,74 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
87 71 public void handForDevice(RequestEvent evt, Device device, Element element) {
88 72 taskQueue.offer(new HandlerCatchData(evt, device, element));
89 73 // 回复200 OK
  74 + ServerTransaction serverTransaction = getServerTransaction(evt);
90 75 try {
91   - ServerTransaction serverTransaction = getServerTransaction(evt);
92 76 responseAck(serverTransaction, Response.OK);
93   - if (!taskQueueHandlerRun) {
94   - taskQueueHandlerRun = true;
95   - taskExecutor.execute(()-> {
96   - while (!taskQueue.isEmpty()) {
97   - HandlerCatchData take = taskQueue.poll();
98   - try {
99   - Element rootElement = getRootElement(take.getEvt(), take.getDevice().getCharset());
100   - if (rootElement == null) {
101   - logger.warn("[ 收到通道 ] content cannot be null, {}", evt.getRequest());
102   - continue;
103   - }
104   - Element deviceListElement = rootElement.element("DeviceList");
105   - Element sumNumElement = rootElement.element("SumNum");
106   - Element snElement = rootElement.element("SN");
107   - if (snElement == null || sumNumElement == null || deviceListElement == null) {
108   - responseAck(serverTransaction, Response.BAD_REQUEST, "xml error");
109   - continue;
110   - }
111   - int sumNum = Integer.parseInt(sumNumElement.getText());
112   -
113   - if (sumNum == 0) {
114   - logger.info("[收到通道]设备:{}的: 0个", take.getDevice().getDeviceId());
115   - // 数据已经完整接收
116   - storager.cleanChannelsForDevice(take.getDevice().getDeviceId());
117   - catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), null);
118   - }else {
119   - Iterator<Element> deviceListIterator = deviceListElement.elementIterator();
120   - if (deviceListIterator != null) {
121   - List<DeviceChannel> channelList = new ArrayList<>();
122   - // 遍历DeviceList
123   - while (deviceListIterator.hasNext()) {
124   - Element itemDevice = deviceListIterator.next();
125   - Element channelDeviceElement = itemDevice.element("DeviceID");
126   - if (channelDeviceElement == null) {
127   - continue;
128   - }
129   - DeviceChannel deviceChannel = XmlUtil.channelContentHander(itemDevice, device, null);
130   - deviceChannel.setDeviceId(take.getDevice().getDeviceId());
131   -
132   - channelList.add(deviceChannel);
133   - }
134   - int sn = Integer.parseInt(snElement.getText());
135   - catalogDataCatch.put(take.getDevice().getDeviceId(), sn, sumNum, take.getDevice(), channelList);
136   - logger.info("[收到通道]设备: {} -> {}个,{}/{}", take.getDevice().getDeviceId(), channelList.size(), catalogDataCatch.get(take.getDevice().getDeviceId()) == null ? 0 :catalogDataCatch.get(take.getDevice().getDeviceId()).size(), sumNum);
137   - if (catalogDataCatch.get(take.getDevice().getDeviceId()).size() == sumNum) {
138   - // 数据已经完整接收, 此时可能存在某个设备离线变上线的情况,但是考虑到性能,此处不做处理,
139   - // 目前支持设备通道上线通知时和设备上线时向上级通知
140   - boolean resetChannelsResult = storager.resetChannels(take.getDevice().getDeviceId(), catalogDataCatch.get(take.getDevice().getDeviceId()));
141   - if (!resetChannelsResult) {
142   - String errorMsg = "接收成功,写入失败,共" + sumNum + "条,已接收" + catalogDataCatch.get(take.getDevice().getDeviceId()).size() + "条";
143   - catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), errorMsg);
144   - }else {
145   - catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), null);
146   - }
147   - }
  77 + } catch (SipException | InvalidArgumentException | ParseException e) {
  78 + logger.error("[命令发送失败] 目录查询回复: {}", e.getMessage());
  79 + }
  80 + if (!taskQueueHandlerRun) {
  81 + taskQueueHandlerRun = true;
  82 + taskExecutor.execute(() -> {
  83 + while (!taskQueue.isEmpty()) {
  84 + HandlerCatchData take = taskQueue.poll();
  85 + Element rootElement = null;
  86 + try {
  87 + rootElement = getRootElement(take.getEvt(), take.getDevice().getCharset());
  88 + } catch (DocumentException e) {
  89 + logger.error("[xml解析] 失败: ", e);
  90 + continue;
  91 + }
  92 + if (rootElement == null) {
  93 + logger.warn("[ 收到通道 ] content cannot be null, {}", evt.getRequest());
  94 + continue;
  95 + }
  96 + Element deviceListElement = rootElement.element("DeviceList");
  97 + Element sumNumElement = rootElement.element("SumNum");
  98 + Element snElement = rootElement.element("SN");
  99 + int sumNum = Integer.parseInt(sumNumElement.getText());
  100 +
  101 + if (sumNum == 0) {
  102 + logger.info("[收到通道]设备:{}的: 0个", take.getDevice().getDeviceId());
  103 + // 数据已经完整接收
  104 + storager.cleanChannelsForDevice(take.getDevice().getDeviceId());
  105 + catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), null);
  106 + } else {
  107 + Iterator<Element> deviceListIterator = deviceListElement.elementIterator();
  108 + if (deviceListIterator != null) {
  109 + List<DeviceChannel> channelList = new ArrayList<>();
  110 + // 遍历DeviceList
  111 + while (deviceListIterator.hasNext()) {
  112 + Element itemDevice = deviceListIterator.next();
  113 + Element channelDeviceElement = itemDevice.element("DeviceID");
  114 + if (channelDeviceElement == null) {
  115 + continue;
148 116 }
  117 + DeviceChannel deviceChannel = XmlUtil.channelContentHander(itemDevice, device, null);
  118 + deviceChannel.setDeviceId(take.getDevice().getDeviceId());
149 119  
  120 + channelList.add(deviceChannel);
  121 + }
  122 + int sn = Integer.parseInt(snElement.getText());
  123 + catalogDataCatch.put(take.getDevice().getDeviceId(), sn, sumNum, take.getDevice(), channelList);
  124 + logger.info("[收到通道]设备: {} -> {}个,{}/{}", take.getDevice().getDeviceId(), channelList.size(), catalogDataCatch.get(take.getDevice().getDeviceId()) == null ? 0 : catalogDataCatch.get(take.getDevice().getDeviceId()).size(), sumNum);
  125 + if (catalogDataCatch.get(take.getDevice().getDeviceId()).size() == sumNum) {
  126 + // 数据已经完整接收, 此时可能存在某个设备离线变上线的情况,但是考虑到性能,此处不做处理,
  127 + // 目前支持设备通道上线通知时和设备上线时向上级通知
  128 + boolean resetChannelsResult = storager.resetChannels(take.getDevice().getDeviceId(), catalogDataCatch.get(take.getDevice().getDeviceId()));
  129 + if (!resetChannelsResult) {
  130 + String errorMsg = "接收成功,写入失败,共" + sumNum + "条,已接收" + catalogDataCatch.get(take.getDevice().getDeviceId()).size() + "条";
  131 + catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), errorMsg);
  132 + } else {
  133 + catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), null);
  134 + }
150 135 }
151   - } catch (DocumentException e) {
152   - e.printStackTrace();
153   - } catch (InvalidArgumentException e) {
154   - e.printStackTrace();
155   - } catch (ParseException e) {
156   - e.printStackTrace();
157   - } catch (SipException e) {
158   - e.printStackTrace();
159   - } finally {
160   - taskQueueHandlerRun = false;
161 136 }
  137 +
162 138 }
163   - });
164   - }
165   - } catch (SipException e) {
166   - throw new RuntimeException(e);
167   - } catch (InvalidArgumentException e) {
168   - throw new RuntimeException(e);
169   - } catch (ParseException e) {
170   - throw new RuntimeException(e);
171   - } finally {
172   - taskQueueHandlerRun = false;
  139 + }
  140 + taskQueueHandlerRun = false;
  141 + });
173 142 }
174 143  
175 144 }
... ... @@ -182,7 +151,7 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
182 151 public SyncStatus getChannelSyncProgress(String deviceId) {
183 152 if (catalogDataCatch.get(deviceId) == null) {
184 153 return null;
185   - }else {
  154 + } else {
186 155 return catalogDataCatch.getSyncStatus(deviceId);
187 156 }
188 157 }
... ... @@ -190,7 +159,7 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
190 159 public boolean isSyncRunning(String deviceId) {
191 160 if (catalogDataCatch.get(deviceId) == null) {
192 161 return false;
193   - }else {
  162 + } else {
194 163 return catalogDataCatch.isSyncRunning(deviceId);
195 164 }
196 165 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/ConfigDownloadResponseMessageHandler.java
... ... @@ -63,12 +63,8 @@ public class ConfigDownloadResponseMessageHandler extends SIPRequestProcessorPar
63 63 msg.setKey(key);
64 64 msg.setData(json);
65 65 deferredResultHolder.invokeAllResult(msg);
66   - } catch (SipException e) {
67   - e.printStackTrace();
68   - } catch (InvalidArgumentException e) {
69   - e.printStackTrace();
70   - } catch (ParseException e) {
71   - e.printStackTrace();
  66 + } catch (SipException | InvalidArgumentException | ParseException e) {
  67 + logger.error("[命令发送失败] 国标级联 设备配置查询: {}", e.getMessage());
72 68 }
73 69  
74 70 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceControlResponseMessageHandler.java
... ... @@ -58,12 +58,8 @@ public class DeviceControlResponseMessageHandler extends SIPRequestProcessorPare
58 58 msg.setKey(key);
59 59 msg.setData(json);
60 60 deferredResultHolder.invokeAllResult(msg);
61   - } catch (SipException e) {
62   - e.printStackTrace();
63   - } catch (InvalidArgumentException e) {
64   - e.printStackTrace();
65   - } catch (ParseException e) {
66   - e.printStackTrace();
  61 + } catch (SipException | InvalidArgumentException | ParseException e) {
  62 + logger.error("[命令发送失败] 国标级联 设备控制: {}", e.getMessage());
67 63 }
68 64 }
69 65  
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceStatusResponseMessageHandler.java
... ... @@ -60,12 +60,8 @@ public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParen
60 60 // 回复200 OK
61 61 try {
62 62 responseAck(getServerTransaction(evt), Response.OK);
63   - } catch (SipException e) {
64   - e.printStackTrace();
65   - } catch (InvalidArgumentException e) {
66   - e.printStackTrace();
67   - } catch (ParseException e) {
68   - e.printStackTrace();
  63 + } catch (SipException | InvalidArgumentException | ParseException e) {
  64 + logger.error("[命令发送失败] 国标级联 设备状态应答回复200OK: {}", e.getMessage());
69 65 }
70 66 Element deviceIdElement = element.element("DeviceID");
71 67 Element onlineElement = element.element("Online");
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/PresetQueryResponseMessageHandler.java
... ... @@ -50,12 +50,12 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent
50 50  
51 51 @Override
52 52 public void handForDevice(RequestEvent evt, Device device, Element element) {
53   - Element rootElement = null;
54   - try {
55 53  
56   - ServerTransaction serverTransaction = getServerTransaction(evt);
  54 + ServerTransaction serverTransaction = getServerTransaction(evt);
  55 +
  56 + try {
  57 + Element rootElement = getRootElement(evt, device.getCharset());
57 58  
58   - rootElement = getRootElement(evt, device.getCharset());
59 59 if (rootElement == null) {
60 60 logger.warn("[ 设备预置位查询应答 ] content cannot be null, {}", evt.getRequest());
61 61 responseAck(serverTransaction, Response.BAD_REQUEST);
... ... @@ -66,32 +66,29 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent
66 66 //该字段可能为通道或则设备的id
67 67 String deviceId = getText(rootElement, "DeviceID");
68 68 String key = DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + deviceId;
69   - if (snElement == null || presetListNumElement == null) {
  69 + if (snElement == null || presetListNumElement == null) {
70 70 responseAck(serverTransaction, Response.BAD_REQUEST, "xml error");
71 71 return;
72 72 }
73 73 int sumNum = Integer.parseInt(presetListNumElement.attributeValue("Num"));
74 74 List<PresetQuerySipReq> presetQuerySipReqList = new ArrayList<>();
75 75 if (sumNum > 0) {
76   - for (Iterator<Element> presetIterator = presetListNumElement.elementIterator();presetIterator.hasNext();){
  76 + for (Iterator<Element> presetIterator = presetListNumElement.elementIterator(); presetIterator.hasNext(); ) {
77 77 Element itemListElement = presetIterator.next();
78 78 PresetQuerySipReq presetQuerySipReq = new PresetQuerySipReq();
79   - for (Iterator<Element> itemListIterator = itemListElement.elementIterator();itemListIterator.hasNext();){
80   - // 遍历item
81   - Element itemOne = itemListIterator.next();
82   - String name = itemOne.getName();
83   - String textTrim = itemOne.getTextTrim();
84   - if("PresetID".equalsIgnoreCase(name)){
85   - presetQuerySipReq.setPresetId(textTrim);
86   - }else {
87   - presetQuerySipReq.setPresetName(textTrim);
88   - }
  79 + for (Iterator<Element> itemListIterator = itemListElement.elementIterator(); itemListIterator.hasNext(); ) {
  80 + // 遍历item
  81 + Element itemOne = itemListIterator.next();
  82 + String name = itemOne.getName();
  83 + String textTrim = itemOne.getTextTrim();
  84 + if ("PresetID".equalsIgnoreCase(name)) {
  85 + presetQuerySipReq.setPresetId(textTrim);
  86 + } else {
  87 + presetQuerySipReq.setPresetName(textTrim);
  88 + }
89 89 }
90 90 presetQuerySipReqList.add(presetQuerySipReq);
91   -
92   -
93 91 }
94   -
95 92 }
96 93 RequestMessage requestMessage = new RequestMessage();
97 94 requestMessage.setKey(key);
... ... @@ -99,13 +96,9 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent
99 96 deferredResultHolder.invokeAllResult(requestMessage);
100 97 responseAck(serverTransaction, Response.OK);
101 98 } catch (DocumentException e) {
102   - e.printStackTrace();
103   - } catch (InvalidArgumentException e) {
104   - e.printStackTrace();
105   - } catch (ParseException e) {
106   - e.printStackTrace();
107   - } catch (SipException e) {
108   - e.printStackTrace();
  99 + logger.error("[解析xml]失败: ", e);
  100 + } catch (InvalidArgumentException | ParseException | SipException e) {
  101 + logger.error("[命令发送失败] 设备预置位查询应答处理: {}", e.getMessage());
109 102 }
110 103 }
111 104  
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/RecordInfoResponseMessageHandler.java
... ... @@ -147,21 +147,16 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent
147 147 }
148 148 }
149 149 } catch (DocumentException e) {
150   - throw new RuntimeException(e);
151   - } finally {
152   - taskQueueHandlerRun = false;
  150 + logger.error("xml解析异常: ", e);
153 151 }
154 152 }
  153 + taskQueueHandlerRun = false;
155 154 });
156 155 }
157 156  
158   - } catch (SipException e) {
159   - e.printStackTrace();
160   - } catch (InvalidArgumentException e) {
161   - e.printStackTrace();
162   - } catch (ParseException e) {
163   - e.printStackTrace();
164   - }finally {
  157 + } catch (SipException | InvalidArgumentException | ParseException e) {
  158 + logger.error("[命令发送失败] 国标级联 国标录像: {}", e.getMessage());
  159 + } finally {
165 160 taskQueueHandlerRun = false;
166 161 }
167 162 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/InviteResponseProcessor.java
1 1 package com.genersoft.iot.vmp.gb28181.transmit.event.response.impl;
2 2  
3 3 import com.genersoft.iot.vmp.conf.SipConfig;
  4 +import com.genersoft.iot.vmp.gb28181.bean.Device;
  5 +import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
4 6 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
5 7 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
  8 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
  9 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
6 10 import com.genersoft.iot.vmp.gb28181.transmit.event.response.SIPResponseProcessorAbstract;
7 11 import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
  12 +import com.genersoft.iot.vmp.service.IDeviceService;
8 13 import com.genersoft.iot.vmp.utils.GitUtil;
9 14 import gov.nist.javax.sip.ResponseEventExt;
  15 +import gov.nist.javax.sip.SipProviderImpl;
10 16 import gov.nist.javax.sip.message.SIPResponse;
11 17 import gov.nist.javax.sip.stack.SIPClientTransaction;
12 18 import gov.nist.javax.sip.stack.SIPDialog;
  19 +import gov.nist.javax.sip.stack.SIPTransaction;
  20 +import gov.nist.javax.sip.stack.SIPTransactionImpl;
13 21 import org.slf4j.Logger;
14 22 import org.slf4j.LoggerFactory;
15 23 import org.springframework.beans.factory.annotation.Autowired;
  24 +import org.springframework.beans.factory.annotation.Qualifier;
16 25 import org.springframework.stereotype.Component;
17 26  
18 27 import javax.sdp.SdpFactory;
... ... @@ -54,6 +63,20 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
54 63 @Autowired
55 64 private GitUtil gitUtil;
56 65  
  66 + @Autowired
  67 + private ISIPCommander commander;
  68 +
  69 + @Autowired
  70 + private IDeviceService deviceService;
  71 +
  72 + @Autowired
  73 + private SIPRequestHeaderProvider headerProvider;
  74 +
  75 + @Autowired
  76 + @Qualifier(value="udpSipProvider")
  77 + private SipProviderImpl udpSipProvider;
  78 +
  79 +
57 80 @Override
58 81 public void afterPropertiesSet() throws Exception {
59 82 // 添加消息处理的订阅
... ... @@ -71,7 +94,8 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
71 94 @Override
72 95 public void process(ResponseEvent evt ){
73 96 try {
74   - Response response = evt.getResponse();
  97 +
  98 + SIPResponse response = (SIPResponse)evt.getResponse();
75 99 int statusCode = response.getStatusCode();
76 100 // trying不会回复
77 101 if (statusCode == Response.TRYING) {
... ... @@ -80,10 +104,7 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
80 104 // 下发ack
81 105 if (statusCode == Response.OK) {
82 106 ResponseEventExt event = (ResponseEventExt)evt;
83   - SIPDialog dialog = new SIPDialog((SIPClientTransaction) event.getClientTransaction(), (SIPResponse) event.getResponse());
84   - CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
85   - Request reqAck = dialog.createAck(cseq.getSeqNumber());
86   - SipURI requestURI = (SipURI) reqAck.getRequestURI();
  107 +
87 108 String contentString = new String(response.getRawContent());
88 109 // jainSip不支持y=字段, 移除以解析。
89 110 int ssrcIndex = contentString.indexOf("y=");
... ... @@ -96,29 +117,15 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
96 117 } else {
97 118 sdp = SdpFactory.getInstance().createSessionDescription(contentString);
98 119 }
99   - requestURI.setUser(sdp.getOrigin().getUsername());
100   - try {
101   - requestURI.setHost(event.getRemoteIpAddress());
102   - } catch (ParseException e) {
103   - e.printStackTrace();
104   - }
105   - requestURI.setPort(event.getRemotePort());
106   - reqAck.setRequestURI(requestURI);
107   - UserAgentHeader userAgentHeader = SipUtils.createUserAgentHeader(sipFactory, gitUtil);
108   - reqAck.addHeader(userAgentHeader);
109   - Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getIp()+":"+sipConfig.getPort()));
110   - reqAck.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
111   - logger.info("[回复ack] {}-> {}:{} ",requestURI, event.getRemoteIpAddress(), event.getRemotePort());
  120 + SipURI requestUri = sipFactory.createAddressFactory().createSipURI(sdp.getOrigin().getUsername(), event.getRemoteIpAddress() + ":" + event.getRemotePort());
  121 + Request reqAck = headerProvider.createAckRequest(requestUri, response);
112 122  
113   - dialog.sendAck(reqAck);
  123 + logger.info("[回复ack] {}-> {}:{} ", sdp.getOrigin().getUsername(), event.getRemoteIpAddress(), event.getRemotePort());
  124 + commander.transmitRequest(response.getTopmostViaHeader().getTransport(), reqAck, null, null);
114 125  
115 126 }
116   - } catch (InvalidArgumentException | SipException e) {
117   - e.printStackTrace();
118   - } catch (ParseException e) {
119   - throw new RuntimeException(e);
120   - } catch (SdpParseException e) {
121   - throw new RuntimeException(e);
  127 + } catch (InvalidArgumentException | ParseException | SipException | SdpParseException e) {
  128 + logger.info("[点播回复ACK],异常:", e );
122 129 }
123 130 }
124 131  
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/RegisterResponseProcessor.java
... ... @@ -15,10 +15,13 @@ import org.slf4j.LoggerFactory;
15 15 import org.springframework.beans.factory.annotation.Autowired;
16 16 import org.springframework.stereotype.Component;
17 17  
  18 +import javax.sip.InvalidArgumentException;
18 19 import javax.sip.ResponseEvent;
  20 +import javax.sip.SipException;
19 21 import javax.sip.header.CallIdHeader;
20 22 import javax.sip.header.WWWAuthenticateHeader;
21 23 import javax.sip.message.Response;
  24 +import java.text.ParseException;
22 25  
23 26 /**
24 27 * @description:Register响应处理器
... ... @@ -87,7 +90,11 @@ public class RegisterResponseProcessor extends SIPResponseProcessorAbstract {
87 90  
88 91 if (response.getStatusCode() == Response.UNAUTHORIZED) {
89 92 WWWAuthenticateHeader www = (WWWAuthenticateHeader)response.getHeader(WWWAuthenticateHeader.NAME);
90   - sipCommanderForPlatform.register(parentPlatform, callId, www, null, null, true, platformRegisterInfo.isRegister());
  93 + try {
  94 + sipCommanderForPlatform.register(parentPlatform, callId, www, null, null, true, platformRegisterInfo.isRegister());
  95 + } catch (SipException | InvalidArgumentException | ParseException e) {
  96 + logger.error("[命令发送失败] 国标级联 再次注册: {}", e.getMessage());
  97 + }
91 98 }else if (response.getStatusCode() == Response.OK){
92 99  
93 100 if (platformRegisterInfo.isRegister()) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/timeout/impl/TimeoutProcessorImpl.java
1 1 package com.genersoft.iot.vmp.gb28181.transmit.event.timeout.impl;
2 2  
  3 +import com.genersoft.iot.vmp.conf.SystemInfoTimerTask;
3 4 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
4 5 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
5 6 import com.genersoft.iot.vmp.gb28181.transmit.event.timeout.ITimeoutProcessor;
  7 +import org.slf4j.Logger;
  8 +import org.slf4j.LoggerFactory;
6 9 import org.springframework.beans.factory.InitializingBean;
7 10 import org.springframework.beans.factory.annotation.Autowired;
8 11 import org.springframework.stereotype.Component;
... ... @@ -13,6 +16,8 @@ import javax.sip.header.CallIdHeader;
13 16 @Component
14 17 public class TimeoutProcessorImpl implements InitializingBean, ITimeoutProcessor {
15 18  
  19 + private Logger logger = LoggerFactory.getLogger(TimeoutProcessorImpl.class);
  20 +
16 21 @Autowired
17 22 private SIPProcessorObserver processorObserver;
18 23  
... ... @@ -36,7 +41,7 @@ public class TimeoutProcessorImpl implements InitializingBean, ITimeoutProcessor
36 41 sipSubscribe.removeErrorSubscribe(callId);
37 42 sipSubscribe.removeOkSubscribe(callId);
38 43 } catch (Exception e) {
39   - e.printStackTrace();
  44 + logger.error("[超时事件失败]: {}", e.getMessage());
40 45 }
41 46 }
42 47 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/utils/SipUtils.java
... ... @@ -70,4 +70,47 @@ public class SipUtils {
70 70 return String.valueOf(System.currentTimeMillis());
71 71 }
72 72  
  73 +
  74 + /**
  75 + * 云台指令码计算
  76 + *
  77 + * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
  78 + * @param upDown 镜头上移下移 0:停止 1:上移 2:下移
  79 + * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
  80 + * @param moveSpeed 镜头移动速度 默认 0XFF (0-255)
  81 + * @param zoomSpeed 镜头缩放速度 默认 0X1 (0-255)
  82 + */
  83 + public static String cmdString(int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed) {
  84 + int cmdCode = 0;
  85 + if (leftRight == 2) {
  86 + cmdCode|=0x01; // 右移
  87 + } else if(leftRight == 1) {
  88 + cmdCode|=0x02; // 左移
  89 + }
  90 + if (upDown == 2) {
  91 + cmdCode|=0x04; // 下移
  92 + } else if(upDown == 1) {
  93 + cmdCode|=0x08; // 上移
  94 + }
  95 + if (inOut == 2) {
  96 + cmdCode |= 0x10; // 放大
  97 + } else if(inOut == 1) {
  98 + cmdCode |= 0x20; // 缩小
  99 + }
  100 + StringBuilder builder = new StringBuilder("A50F01");
  101 + String strTmp;
  102 + strTmp = String.format("%02X", cmdCode);
  103 + builder.append(strTmp, 0, 2);
  104 + strTmp = String.format("%02X", moveSpeed);
  105 + builder.append(strTmp, 0, 2);
  106 + builder.append(strTmp, 0, 2);
  107 + strTmp = String.format("%X", zoomSpeed);
  108 + builder.append(strTmp, 0, 1).append("0");
  109 + //计算校验码
  110 + int checkCode = (0XA5 + 0X0F + 0X01 + cmdCode + moveSpeed + moveSpeed + (zoomSpeed /*<< 4*/ & 0XF0)) % 0X100;
  111 + strTmp = String.format("%02X", checkCode);
  112 + builder.append(strTmp, 0, 2);
  113 + return builder.toString();
  114 + }
  115 +
73 116 }
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
1 1 package com.genersoft.iot.vmp.media.zlm;
2 2  
  3 +import java.text.ParseException;
3 4 import java.util.HashMap;
4 5 import java.util.List;
5 6 import java.util.Map;
... ... @@ -7,6 +8,7 @@ import java.util.Map;
7 8 import com.alibaba.fastjson.JSON;
8 9 import com.genersoft.iot.vmp.common.StreamInfo;
9 10 import com.genersoft.iot.vmp.conf.UserSetting;
  11 +import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
10 12 import com.genersoft.iot.vmp.gb28181.bean.*;
11 13 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
12 14 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
... ... @@ -31,6 +33,8 @@ import com.alibaba.fastjson.JSONObject;
31 33 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
32 34  
33 35 import javax.servlet.http.HttpServletRequest;
  36 +import javax.sip.InvalidArgumentException;
  37 +import javax.sip.SipException;
34 38  
35 39 /**
36 40 * @description:针对 ZLMediaServer的hook事件监听
... ... @@ -59,6 +63,9 @@ public class ZLMHttpHookListener {
59 63 private IRedisCatchStorage redisCatchStorage;
60 64  
61 65 @Autowired
  66 + private IDeviceService deviceService;
  67 +
  68 + @Autowired
62 69 private IMediaServerService mediaServerService;
63 70  
64 71 @Autowired
... ... @@ -515,7 +522,11 @@ public class ZLMHttpHookListener {
515 522 String platformId = sendRtpItem.getPlatformId();
516 523 ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId);
517 524  
518   - commanderFroPlatform.streamByeCmd(platform, sendRtpItem);
  525 + try {
  526 + commanderFroPlatform.streamByeCmd(platform, sendRtpItem);
  527 + } catch (SipException | InvalidArgumentException | ParseException e) {
  528 + logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
  529 + }
519 530 }
520 531 }
521 532 }
... ... @@ -552,21 +563,41 @@ public class ZLMHttpHookListener {
552 563 if (sendRtpItems.size() > 0) {
553 564 for (SendRtpItem sendRtpItem : sendRtpItems) {
554 565 ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId());
555   - commanderFroPlatform.streamByeCmd(parentPlatform, sendRtpItem.getCallId());
  566 + try {
  567 + commanderFroPlatform.streamByeCmd(parentPlatform, sendRtpItem.getCallId());
  568 + } catch (SipException | InvalidArgumentException | ParseException e) {
  569 + logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
  570 + }
556 571 redisCatchStorage.deleteSendRTPServer(parentPlatform.getServerGBId(), sendRtpItem.getChannelId(),
557 572 sendRtpItem.getCallId(), sendRtpItem.getStreamId());
558 573 }
559 574 }
560 575 }
561   - cmder.streamByeCmd(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId(),
562   - streamInfoForPlayCatch.getStream(), null);
  576 + Device device = deviceService.queryDevice(streamInfoForPlayCatch.getDeviceID());
  577 + if (device != null) {
  578 + try {
  579 + cmder.streamByeCmd(device, streamInfoForPlayCatch.getChannelId(),
  580 + streamInfoForPlayCatch.getStream(), null);
  581 + } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) {
  582 + logger.error("[无人观看]点播, 发送BYE失败 {}", e.getMessage());
  583 + }
  584 + }
  585 +
563 586 redisCatchStorage.stopPlay(streamInfoForPlayCatch);
564 587 storager.stopPlay(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId());
565 588 }else{
566 589 StreamInfo streamInfoForPlayBackCatch = redisCatchStorage.queryPlayback(null, null, streamId, null);
567 590 if (streamInfoForPlayBackCatch != null) {
568   - cmder.streamByeCmd(streamInfoForPlayBackCatch.getDeviceID(),
569   - streamInfoForPlayBackCatch.getChannelId(), streamInfoForPlayBackCatch.getStream(), null);
  591 + Device device = deviceService.queryDevice(streamInfoForPlayCatch.getDeviceID());
  592 + if (device != null) {
  593 + try {
  594 + cmder.streamByeCmd(device,streamInfoForPlayBackCatch.getChannelId(),
  595 + streamInfoForPlayBackCatch.getStream(), null);
  596 + } catch (InvalidArgumentException | ParseException | SipException |
  597 + SsrcTransactionNotFoundException e) {
  598 + logger.error("[无人观看]回放, 发送BYE失败 {}", e.getMessage());
  599 + }
  600 + }
570 601 redisCatchStorage.stopPlayback(streamInfoForPlayBackCatch.getDeviceID(),
571 602 streamInfoForPlayBackCatch.getChannelId(), streamInfoForPlayBackCatch.getStream(), null);
572 603 }else {
... ... @@ -689,7 +720,11 @@ public class ZLMHttpHookListener {
689 720 if (sendRtpItems.size() > 0) {
690 721 for (SendRtpItem sendRtpItem : sendRtpItems) {
691 722 ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId());
692   - commanderFroPlatform.streamByeCmd(parentPlatform, sendRtpItem.getCallId());
  723 + try {
  724 + commanderFroPlatform.streamByeCmd(parentPlatform, sendRtpItem.getCallId());
  725 + } catch (SipException | InvalidArgumentException | ParseException e) {
  726 + logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
  727 + }
693 728 redisCatchStorage.deleteSendRTPServer(parentPlatform.getServerGBId(), sendRtpItem.getChannelId(),
694 729 sendRtpItem.getCallId(), sendRtpItem.getStreamId());
695 730 }
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java
... ... @@ -68,7 +68,6 @@ public class ZLMMediaListManager {
68 68 private Map<String, ChannelOnlineEvent> channelOnPublishEvents = new ConcurrentHashMap<>();
69 69  
70 70 public StreamPushItem addPush(MediaItem mediaItem) {
71   - // 查找此直播流是否存在redis预设gbId
72 71 StreamPushItem transform = streamPushService.transform(mediaItem);
73 72 StreamPushItem pushInDb = streamPushService.getPush(mediaItem.getApp(), mediaItem.getStream());
74 73 transform.setPushIng(mediaItem.isRegist());
... ... @@ -82,15 +81,14 @@ public class ZLMMediaListManager {
82 81 streamPushMapper.update(transform);
83 82 gbStreamMapper.updateMediaServer(mediaItem.getApp(), mediaItem.getStream(), mediaItem.getMediaServerId());
84 83 }
85   - if (transform != null) {
86   - if (getChannelOnlineEventLister(transform.getApp(), transform.getStream()) != null) {
87   - try {
88   - getChannelOnlineEventLister(transform.getApp(), transform.getStream()).run(transform.getApp(), transform.getStream(), transform.getServerId());
89   - } catch (ParseException e) {
90   - throw new RuntimeException(e);
91   - }
92   - removedChannelOnlineEventLister(transform.getApp(), transform.getStream());
  84 + ChannelOnlineEvent channelOnlineEventLister = getChannelOnlineEventLister(transform.getApp(), transform.getStream());
  85 + if ( channelOnlineEventLister != null) {
  86 + try {
  87 + channelOnlineEventLister.run(transform.getApp(), transform.getStream(), transform.getServerId());;
  88 + } catch (ParseException e) {
  89 + logger.error("addPush: ", e);
93 90 }
  91 + removedChannelOnlineEventLister(transform.getApp(), transform.getStream());
94 92 }
95 93 return transform;
96 94 }
... ... @@ -99,11 +97,12 @@ public class ZLMMediaListManager {
99 97 MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
100 98 // 查看推流状态
101 99 if (zlmrtpServerFactory.isStreamReady(mediaServerItem, app, stream)) {
102   - if (getChannelOnlineEventLister(app, stream) != null) {
  100 + ChannelOnlineEvent channelOnlineEventLister = getChannelOnlineEventLister(app, stream);
  101 + if (channelOnlineEventLister != null) {
103 102 try {
104   - getChannelOnlineEventLister(app, stream).run(app, stream, mediaServerId);
  103 + channelOnlineEventLister.run(app, stream, mediaServerId);
105 104 } catch (ParseException e) {
106   - throw new RuntimeException(e);
  105 + logger.error("sendStreamEvent: ", e);
107 106 }
108 107 removedChannelOnlineEventLister(app, stream);
109 108 }
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
... ... @@ -26,6 +26,9 @@ import org.springframework.stereotype.Service;
26 26 import org.springframework.util.ObjectUtils;
27 27 import org.springframework.util.StringUtils;
28 28  
  29 +import javax.sip.InvalidArgumentException;
  30 +import javax.sip.SipException;
  31 +import java.text.ParseException;
29 32 import java.time.Instant;
30 33 import java.util.ArrayList;
31 34 import java.util.Collections;
... ... @@ -95,7 +98,11 @@ public class DeviceServiceImpl implements IDeviceService {
95 98 logger.info("[设备上线,首次注册]: {},查询设备信息以及通道信息", device.getDeviceId());
96 99 deviceMapper.add(device);
97 100 redisCatchStorage.updateDevice(device);
98   - commander.deviceInfoQuery(device);
  101 + try {
  102 + commander.deviceInfoQuery(device);
  103 + } catch (InvalidArgumentException | SipException | ParseException e) {
  104 + logger.error("[命令发送失败] 查询设备信息: {}", e.getMessage());
  105 + }
99 106 sync(device);
100 107 }else {
101 108 if(device.getOnline() == 0){
... ... @@ -104,7 +111,11 @@ public class DeviceServiceImpl implements IDeviceService {
104 111 logger.info("[设备上线,离线状态下重新注册]: {},查询设备信息以及通道信息", device.getDeviceId());
105 112 deviceMapper.update(device);
106 113 redisCatchStorage.updateDevice(device);
107   - commander.deviceInfoQuery(device);
  114 + try {
  115 + commander.deviceInfoQuery(device);
  116 + } catch (InvalidArgumentException | SipException | ParseException e) {
  117 + logger.error("[命令发送失败] 查询设备信息: {}", e.getMessage());
  118 + }
108 119 sync(device);
109 120 // TODO 如果设备下的通道级联到了其他平台,那么需要发送事件或者notify给上级平台
110 121 }else {
... ... @@ -129,6 +140,7 @@ public class DeviceServiceImpl implements IDeviceService {
129 140  
130 141 @Override
131 142 public void offline(String deviceId) {
  143 + logger.info("[设备离线], device:{}", deviceId);
132 144 Device device = deviceMapper.getDeviceByDeviceId(deviceId);
133 145 if (device == null) {
134 146 return;
... ... @@ -238,15 +250,28 @@ public class DeviceServiceImpl implements IDeviceService {
238 250 }
239 251 int sn = (int)((Math.random()*9+1)*100000);
240 252 catalogResponseMessageHandler.setChannelSyncReady(device, sn);
241   - sipCommander.catalogQuery(device, sn, event -> {
242   - String errorMsg = String.format("同步通道失败,错误码: %s, %s", event.statusCode, event.msg);
  253 + try {
  254 + sipCommander.catalogQuery(device, sn, event -> {
  255 + String errorMsg = String.format("同步通道失败,错误码: %s, %s", event.statusCode, event.msg);
  256 + catalogResponseMessageHandler.setChannelSyncEnd(device.getDeviceId(), errorMsg);
  257 + });
  258 + } catch (SipException | InvalidArgumentException | ParseException e) {
  259 + logger.error("[同步通道], 信令发送失败:{}", e.getMessage() );
  260 + String errorMsg = String.format("同步通道失败,信令发送失败: %s", e.getMessage());
243 261 catalogResponseMessageHandler.setChannelSyncEnd(device.getDeviceId(), errorMsg);
244   - });
  262 + }
245 263 }
246 264  
247 265 @Override
248 266 public Device queryDevice(String deviceId) {
249   - return deviceMapper.getDeviceByDeviceId(deviceId);
  267 + Device device = redisCatchStorage.getDevice(deviceId);
  268 + if (device == null) {
  269 + device = deviceMapper.getDeviceByDeviceId(deviceId);
  270 + if (device != null) {
  271 + redisCatchStorage.updateDevice(device);
  272 + }
  273 + }
  274 + return device;
250 275 }
251 276  
252 277 @Override
... ... @@ -266,7 +291,11 @@ public class DeviceServiceImpl implements IDeviceService {
266 291 if (device == null || device.getOnline() == 0) {
267 292 return;
268 293 }
269   - sipCommander.deviceStatusQuery(device, null);
  294 + try {
  295 + sipCommander.deviceStatusQuery(device, null);
  296 + } catch (InvalidArgumentException | SipException | ParseException e) {
  297 + logger.error("[命令发送失败] 设备状态查询: {}", e.getMessage());
  298 + }
270 299  
271 300 }
272 301  
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java
... ... @@ -20,7 +20,10 @@ import org.slf4j.LoggerFactory;
20 20 import org.springframework.beans.factory.annotation.Autowired;
21 21 import org.springframework.stereotype.Service;
22 22  
  23 +import javax.sip.InvalidArgumentException;
  24 +import javax.sip.SipException;
23 25 import javax.sip.TimeoutEvent;
  26 +import java.text.ParseException;
24 27 import java.util.HashMap;
25 28 import java.util.List;
26 29 import java.util.Map;
... ... @@ -99,9 +102,13 @@ public class PlatformServiceImpl implements IPlatformService {
99 102 if (parentPlatform.isEnable()) {
100 103 // 保存时启用就发送注册
101 104 // 注册成功时由程序直接调用了online方法
102   - commanderForPlatform.register(parentPlatform, eventResult -> {
103   - logger.info("[国标级联] {},添加向上级注册失败,请确定上级平台可用时重新保存", parentPlatform.getServerGBId());
104   - }, null);
  105 + try {
  106 + commanderForPlatform.register(parentPlatform, eventResult -> {
  107 + logger.info("[国标级联] {},添加向上级注册失败,请确定上级平台可用时重新保存", parentPlatform.getServerGBId());
  108 + }, null);
  109 + } catch (InvalidArgumentException | ParseException | SipException e) {
  110 + logger.error("[命令发送失败] 国标级联: {}", e.getMessage());
  111 + }
105 112 }
106 113 return result > 0;
107 114 }
... ... @@ -130,46 +137,62 @@ public class PlatformServiceImpl implements IPlatformService {
130 137 // 添加注册任务
131 138 dynamicTask.startDelay(registerTaskKey,
132 139 // 注册失败(注册成功时由程序直接调用了online方法)
133   - ()->commanderForPlatform.register(parentPlatform, eventResult -> offline(parentPlatform),null),
  140 + ()-> {
  141 + try {
  142 + commanderForPlatform.register(parentPlatform, eventResult -> offline(parentPlatform),null);
  143 + } catch (InvalidArgumentException | ParseException | SipException e) {
  144 + logger.error("[命令发送失败] 国标级联定时注册: {}", e.getMessage());
  145 + }
  146 + },
134 147 (parentPlatform.getExpires() - 10) *1000);
135 148  
136 149 final String keepaliveTaskKey = KEEPALIVE_KEY_PREFIX + parentPlatform.getServerGBId();
137 150 if (!dynamicTask.contains(keepaliveTaskKey)) {
138 151 // 添加心跳任务
139 152 dynamicTask.startCron(keepaliveTaskKey,
140   - ()-> commanderForPlatform.keepalive(parentPlatform, eventResult -> {
141   - // 心跳失败
142   - if (eventResult.type == SipSubscribe.EventResultType.timeout) {
143   - // 心跳超时
144   - ParentPlatformCatch platformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId());
145   - // 此时是第三次心跳超时, 平台离线
146   - if (platformCatch.getKeepAliveReply() == 2) {
147   - // 设置平台离线,并重新注册
148   - offline(parentPlatform);
149   - logger.info("[国标级联] {},三次心跳超时后再次发起注册", parentPlatform.getServerGBId());
150   - commanderForPlatform.register(parentPlatform, eventResult1 -> {
151   - logger.info("[国标级联] {},三次心跳超时后再次发起注册仍然失败,开始定时发起注册,间隔为1分钟", parentPlatform.getServerGBId());
152   - // 添加注册任务
153   - dynamicTask.startCron(registerTaskKey,
154   - // 注册失败(注册成功时由程序直接调用了online方法)
155   - ()->logger.info("[国标级联] {},平台离线后持续发起注册,失败", parentPlatform.getServerGBId()),
156   - 60*1000);
157   - }, null);
158   - }
  153 + ()-> {
  154 + try {
  155 + commanderForPlatform.keepalive(parentPlatform, eventResult -> {
  156 + // 心跳失败
  157 + if (eventResult.type == SipSubscribe.EventResultType.timeout) {
  158 + // 心跳超时
  159 + ParentPlatformCatch platformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId());
  160 + // 此时是第三次心跳超时, 平台离线
  161 + if (platformCatch.getKeepAliveReply() == 2) {
  162 + // 设置平台离线,并重新注册
  163 + offline(parentPlatform);
  164 + logger.info("[国标级联] {},三次心跳超时后再次发起注册", parentPlatform.getServerGBId());
  165 + try {
  166 + commanderForPlatform.register(parentPlatform, eventResult1 -> {
  167 + logger.info("[国标级联] {},三次心跳超时后再次发起注册仍然失败,开始定时发起注册,间隔为1分钟", parentPlatform.getServerGBId());
  168 + // 添加注册任务
  169 + dynamicTask.startCron(registerTaskKey,
  170 + // 注册失败(注册成功时由程序直接调用了online方法)
  171 + ()->logger.info("[国标级联] {},平台离线后持续发起注册,失败", parentPlatform.getServerGBId()),
  172 + 60*1000);
  173 + }, null);
  174 + } catch (InvalidArgumentException | ParseException | SipException e) {
  175 + logger.error("[命令发送失败] 国标级联 注册: {}", e.getMessage());
  176 + }
  177 + }
159 178  
160   - }else {
161   - logger.warn("[国标级联]发送心跳收到错误,code: {}, msg: {}", eventResult.statusCode, eventResult.msg);
162   - }
  179 + }else {
  180 + logger.warn("[国标级联]发送心跳收到错误,code: {}, msg: {}", eventResult.statusCode, eventResult.msg);
  181 + }
163 182  
164   - }, eventResult -> {
165   - // 心跳成功
166   - // 清空之前的心跳超时计数
167   - ParentPlatformCatch platformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId());
168   - if (platformCatch.getKeepAliveReply() > 0) {
169   - platformCatch.setKeepAliveReply(0);
170   - redisCatchStorage.updatePlatformCatchInfo(platformCatch);
  183 + }, eventResult -> {
  184 + // 心跳成功
  185 + // 清空之前的心跳超时计数
  186 + ParentPlatformCatch platformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId());
  187 + if (platformCatch.getKeepAliveReply() > 0) {
  188 + platformCatch.setKeepAliveReply(0);
  189 + redisCatchStorage.updatePlatformCatchInfo(platformCatch);
  190 + }
  191 + });
  192 + } catch (SipException | InvalidArgumentException | ParseException e) {
  193 + logger.error("[命令发送失败] 国标级联 发送心跳: {}", e.getMessage());
171 194 }
172   - }),
  195 + },
173 196 (parentPlatform.getKeepTimeout() - 10)*1000);
174 197 }
175 198 }
... ... @@ -225,14 +248,18 @@ public class PlatformServiceImpl implements IPlatformService {
225 248 @Override
226 249 public void login(ParentPlatform parentPlatform) {
227 250 final String registerTaskKey = REGISTER_KEY_PREFIX + parentPlatform.getServerGBId();
228   - commanderForPlatform.register(parentPlatform, eventResult1 -> {
229   - logger.info("[国标级联] {},开始定时发起注册,间隔为1分钟", parentPlatform.getServerGBId());
230   - // 添加注册任务
231   - dynamicTask.startCron(registerTaskKey,
232   - // 注册失败(注册成功时由程序直接调用了online方法)
233   - ()->logger.info("[国标级联] {},平台离线后持续发起注册,失败", parentPlatform.getServerGBId()),
234   - 60*1000);
235   - }, null);
  251 + try {
  252 + commanderForPlatform.register(parentPlatform, eventResult1 -> {
  253 + logger.info("[国标级联] {},开始定时发起注册,间隔为1分钟", parentPlatform.getServerGBId());
  254 + // 添加注册任务
  255 + dynamicTask.startCron(registerTaskKey,
  256 + // 注册失败(注册成功时由程序直接调用了online方法)
  257 + ()->logger.info("[国标级联] {},平台离线后持续发起注册,失败", parentPlatform.getServerGBId()),
  258 + 60*1000);
  259 + }, null);
  260 + } catch (InvalidArgumentException | ParseException | SipException e) {
  261 + logger.error("[命令发送失败] 国标级联注册: {}", e.getMessage());
  262 + }
236 263 }
237 264  
238 265 @Override
... ... @@ -259,7 +286,12 @@ public class PlatformServiceImpl implements IPlatformService {
259 286 continue;
260 287 }
261 288 // 发送GPS消息
262   - commanderForPlatform.sendNotifyMobilePosition(platform, gpsMsgInfo, subscribe);
  289 + try {
  290 + commanderForPlatform.sendNotifyMobilePosition(platform, gpsMsgInfo, subscribe);
  291 + } catch (InvalidArgumentException | ParseException | NoSuchFieldException | SipException |
  292 + IllegalAccessException e) {
  293 + logger.error("[命令发送失败] 国标级联 移动位置通知: {}", e.getMessage());
  294 + }
263 295 }
264 296 }
265 297 }
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
... ... @@ -2,13 +2,18 @@ package com.genersoft.iot.vmp.service.impl;
2 2  
3 3 import java.math.BigDecimal;
4 4 import java.math.RoundingMode;
  5 +import java.text.ParseException;
5 6 import java.util.*;
6 7  
7 8 import javax.sip.InvalidArgumentException;
8 9 import javax.sip.ResponseEvent;
  10 +import javax.sip.SipException;
9 11  
10 12 import com.genersoft.iot.vmp.gb28181.bean.*;
11 13 import com.genersoft.iot.vmp.conf.exception.ControllerException;
  14 +import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
  15 +import com.genersoft.iot.vmp.gb28181.bean.*;
  16 +import com.genersoft.iot.vmp.service.IDeviceService;
12 17 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
13 18 import org.slf4j.Logger;
14 19 import org.slf4j.LoggerFactory;
... ... @@ -118,6 +123,10 @@ public class PlayServiceImpl implements IPlayService {
118 123 @Autowired
119 124 private VideoStreamSessionManager streamSession;
120 125  
  126 +
  127 + @Autowired
  128 + private IDeviceService deviceService;
  129 +
121 130 @Autowired
122 131 private UserSetting userSetting;
123 132  
... ... @@ -289,14 +298,14 @@ public class PlayServiceImpl implements IPlayService {
289 298 System.out.println("设置超时任务: " + timeOutTaskKey);
290 299 dynamicTask.startDelay( timeOutTaskKey,()->{
291 300  
292   - SIPDialog dialog = streamSession.getDialogByStream(device.getDeviceId(), channelId, finalSsrcInfo.getStream());
293   - if (dialog != null) {
294   - logger.info("[点播超时] 收流超时 deviceId: {}, channelId: {},端口:{}, SSRC: {}", device.getDeviceId(), channelId, finalSsrcInfo.getPort(), finalSsrcInfo.getSsrc());
295   - timeoutCallback.run(1, "收流超时");
296   - // 点播超时回复BYE 同时释放ssrc以及此次点播的资源
297   - cmder.streamByeCmd(device.getDeviceId(), channelId, finalSsrcInfo.getStream(), null);
298   - }else {
299   - logger.info("[点播超时] 消息未响应 deviceId: {}, channelId: {},端口:{}, SSRC: {}", device.getDeviceId(), channelId, finalSsrcInfo.getPort(), finalSsrcInfo.getSsrc());
  301 + logger.info("[点播超时] 收流超时 deviceId: {}, channelId: {},端口:{}, SSRC: {}", device.getDeviceId(), channelId, finalSsrcInfo.getPort(), finalSsrcInfo.getSsrc());
  302 + timeoutCallback.run(1, "收流超时");
  303 + // 点播超时回复BYE 同时释放ssrc以及此次点播的资源
  304 + try {
  305 + cmder.streamByeCmd(device, channelId, finalSsrcInfo.getStream(), null);
  306 + } catch (InvalidArgumentException | ParseException | SipException e) {
  307 + logger.error("[点播超时], 发送BYE失败 {}", e.getMessage());
  308 + } catch (SsrcTransactionNotFoundException e) {
300 309 timeoutCallback.run(0, "点播超时");
301 310 mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc());
302 311 mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream());
... ... @@ -310,73 +319,87 @@ public class PlayServiceImpl implements IPlayService {
310 319 logger.info("[点播端口分配异常],deviceId={},channelId={},ssrcInfo={}", device.getDeviceId(), channelId, ssrcInfo);
311 320 return;
312 321 }
313   - cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> {
314   - logger.info("收到订阅消息: " + response.toJSONString());
315   - System.out.println("停止超时任务: " + timeOutTaskKey);
316   - dynamicTask.stop(timeOutTaskKey);
317   - // hook响应
318   - onPublishHandlerForPlay(mediaServerItemInuse, response, device.getDeviceId(), channelId, uuid);
319   - hookEvent.response(mediaServerItemInuse, response);
320   - logger.info("[点播成功] deviceId: {}, channelId: {}", device.getDeviceId(), channelId);
321   -
322   - }, (event) -> {
323   - ResponseEvent responseEvent = (ResponseEvent)event.event;
324   - String contentString = new String(responseEvent.getResponse().getRawContent());
325   - // 获取ssrc
326   - int ssrcIndex = contentString.indexOf("y=");
327   - // 检查是否有y字段
328   - if (ssrcIndex >= 0) {
329   - //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段 TODO 后续对不规范的非10位ssrc兼容
330   - String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
331   - // 查询到ssrc不一致且开启了ssrc校验则需要针对处理
332   - if (ssrc.equals(ssrcInResponse)) {
333   - return;
334   - }
335   - logger.info("[点播消息] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse );
336   - if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) {
337   - logger.info("[点播消息] SSRC修正 {}->{}", ssrc, ssrcInResponse);
338   -
339   - if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) {
340   - // ssrc 不可用
341   - // 释放ssrc
342   - mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc());
343   - streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream());
344   - event.msg = "下级自定义了ssrc,但是此ssrc不可用";
345   - event.statusCode = 400;
346   - errorEvent.response(event);
  322 + try {
  323 + cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> {
  324 + logger.info("收到订阅消息: " + response.toJSONString());
  325 + System.out.println("停止超时任务: " + timeOutTaskKey);
  326 + dynamicTask.stop(timeOutTaskKey);
  327 + // hook响应
  328 + onPublishHandlerForPlay(mediaServerItemInuse, response, device.getDeviceId(), channelId, uuid);
  329 + hookEvent.response(mediaServerItemInuse, response);
  330 + logger.info("[点播成功] deviceId: {}, channelId: {}", device.getDeviceId(), channelId);
  331 +
  332 + }, (event) -> {
  333 + ResponseEvent responseEvent = (ResponseEvent)event.event;
  334 + String contentString = new String(responseEvent.getResponse().getRawContent());
  335 + // 获取ssrc
  336 + int ssrcIndex = contentString.indexOf("y=");
  337 + // 检查是否有y字段
  338 + if (ssrcIndex >= 0) {
  339 + //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段 TODO 后续对不规范的非10位ssrc兼容
  340 + String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
  341 + // 查询到ssrc不一致且开启了ssrc校验则需要针对处理
  342 + if (ssrc.equals(ssrcInResponse)) {
347 343 return;
348 344 }
  345 + logger.info("[点播消息] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse );
  346 + if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) {
  347 + logger.info("[点播消息] SSRC修正 {}->{}", ssrc, ssrcInResponse);
  348 +
  349 + if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) {
  350 + // ssrc 不可用
  351 + // 释放ssrc
  352 + mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc());
  353 + streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream());
  354 + event.msg = "下级自定义了ssrc,但是此ssrc不可用";
  355 + event.statusCode = 400;
  356 + errorEvent.response(event);
  357 + return;
  358 + }
349 359  
350   - // 单端口模式streamId也有变化,需要重新设置监听
351   - if (!mediaServerItem.isRtpEnable()) {
352   - // 添加订阅
353   - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtsp", mediaServerItem.getId());
354   - subscribe.removeSubscribe(hookSubscribe);
355   - hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase());
356   - subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response)->{
357   - logger.info("[ZLM HOOK] ssrc修正后收到订阅消息: " + response.toJSONString());
358   - dynamicTask.stop(timeOutTaskKey);
359   - // hook响应
360   - onPublishHandlerForPlay(mediaServerItemInUse, response, device.getDeviceId(), channelId, uuid);
361   - hookEvent.response(mediaServerItemInUse, response);
362   - });
363   - }
364   - // 关闭rtp server
365   - mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream());
366   - // 重新开启ssrc server
367   - mediaServerService.openRTPServer(mediaServerItem, finalSsrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), false, finalSsrcInfo.getPort());
  360 + // 单端口模式streamId也有变化,需要重新设置监听
  361 + if (!mediaServerItem.isRtpEnable()) {
  362 + // 添加订阅
  363 + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtsp", mediaServerItem.getId());
  364 + subscribe.removeSubscribe(hookSubscribe);
  365 + hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase());
  366 + subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response)->{
  367 + logger.info("[ZLM HOOK] ssrc修正后收到订阅消息: " + response.toJSONString());
  368 + dynamicTask.stop(timeOutTaskKey);
  369 + // hook响应
  370 + onPublishHandlerForPlay(mediaServerItemInUse, response, device.getDeviceId(), channelId, uuid);
  371 + hookEvent.response(mediaServerItemInUse, response);
  372 + });
  373 + }
  374 + // 关闭rtp server
  375 + mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream());
  376 + // 重新开启ssrc server
  377 + mediaServerService.openRTPServer(mediaServerItem, finalSsrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), false, finalSsrcInfo.getPort());
368 378  
  379 + }
369 380 }
370   - }
371   - }, (event) -> {
  381 + }, (event) -> {
  382 + dynamicTask.stop(timeOutTaskKey);
  383 + mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream());
  384 + // 释放ssrc
  385 + mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc());
  386 +
  387 + streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream());
  388 + errorEvent.response(event);
  389 + });
  390 + } catch (InvalidArgumentException | SipException | ParseException e) {
  391 +
  392 + logger.error("[命令发送失败] 点播消息: {}", e.getMessage());
372 393 dynamicTask.stop(timeOutTaskKey);
373 394 mediaServerService.closeRTPServer(mediaServerItem, finalSsrcInfo.getStream());
374 395 // 释放ssrc
375 396 mediaServerService.releaseSsrc(mediaServerItem.getId(), finalSsrcInfo.getSsrc());
376 397  
377 398 streamSession.remove(device.getDeviceId(), channelId, finalSsrcInfo.getStream());
378   - errorEvent.response(event);
379   - });
  399 + SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new CmdSendFailEvent(null));
  400 + eventResult.msg = "命令发送失败";
  401 + errorEvent.response(eventResult);
  402 + }
380 403 }
381 404  
382 405 @Override
... ... @@ -467,17 +490,18 @@ public class PlayServiceImpl implements IPlayService {
467 490 playBackResult.setCode(ErrorCode.ERROR100.getCode());
468 491 playBackResult.setMsg("回放超时");
469 492 playBackResult.setData(requestMessage);
470   - SIPDialog dialog = streamSession.getDialogByStream(deviceId, channelId, ssrcInfo.getStream());
471   - // 点播超时回复BYE 同时释放ssrc以及此次点播的资源
472   - if (dialog != null) {
  493 +
  494 + try {
  495 + cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null);
  496 + } catch (InvalidArgumentException | ParseException | SipException e) {
  497 + logger.error("[录像流]回放超时 发送BYE失败 {}", e.getMessage());
  498 + } catch (SsrcTransactionNotFoundException e) {
473 499 // 点播超时回复BYE 同时释放ssrc以及此次点播的资源
474   - cmder.streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), null);
475   - }else {
476 500 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
477 501 mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
478 502 streamSession.remove(deviceId, channelId, ssrcInfo.getStream());
479 503 }
480   - cmder.streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), null);
  504 +
481 505 // 回复之前所有的点播请求
482 506 playBackCallback.call(playBackResult);
483 507 result.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "回放超时"));
... ... @@ -517,59 +541,67 @@ public class PlayServiceImpl implements IPlayService {
517 541 playBackCallback.call(playBackResult);
518 542 };
519 543  
520   - cmder.playbackStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, infoCallBack,
521   - hookEvent, eventResult -> {
522   - if (eventResult.type == SipSubscribe.EventResultType.response) {
523   - ResponseEvent responseEvent = (ResponseEvent)eventResult.event;
524   - String contentString = new String(responseEvent.getResponse().getRawContent());
525   - // 获取ssrc
526   - int ssrcIndex = contentString.indexOf("y=");
527   - // 检查是否有y字段
528   - if (ssrcIndex >= 0) {
529   - //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段 TODO 后续对不规范的非10位ssrc兼容
530   - String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
531   - // 查询到ssrc不一致且开启了ssrc校验则需要针对处理
532   - if (ssrcInfo.getSsrc().equals(ssrcInResponse)) {
533   - return;
534   - }
535   - logger.info("[回放消息] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse );
536   - if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) {
537   - logger.info("[回放消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse);
538   -
539   - if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) {
540   - // ssrc 不可用
541   - // 释放ssrc
542   - mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
543   - streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
544   - eventResult.msg = "下级自定义了ssrc,但是此ssrc不可用";
545   - eventResult.statusCode = 400;
546   - errorEvent.response(eventResult);
  544 + try {
  545 + cmder.playbackStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, infoCallBack,
  546 + hookEvent, eventResult -> {
  547 + if (eventResult.type == SipSubscribe.EventResultType.response) {
  548 + ResponseEvent responseEvent = (ResponseEvent)eventResult.event;
  549 + String contentString = new String(responseEvent.getResponse().getRawContent());
  550 + // 获取ssrc
  551 + int ssrcIndex = contentString.indexOf("y=");
  552 + // 检查是否有y字段
  553 + if (ssrcIndex >= 0) {
  554 + //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段 TODO 后续对不规范的非10位ssrc兼容
  555 + String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
  556 + // 查询到ssrc不一致且开启了ssrc校验则需要针对处理
  557 + if (ssrcInfo.getSsrc().equals(ssrcInResponse)) {
547 558 return;
548 559 }
549   -
550   - // 单端口模式streamId也有变化,需要重新设置监听
551   - if (!mediaServerItem.isRtpEnable()) {
552   - // 添加订阅
553   - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId());
554   - subscribe.removeSubscribe(hookSubscribe);
555   - hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase());
556   - subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response)->{
557   - logger.info("[ZLM HOOK] ssrc修正后收到订阅消息: " + response.toJSONString());
558   - dynamicTask.stop(playBackTimeOutTaskKey);
559   - // hook响应
560   - onPublishHandlerForPlay(mediaServerItemInUse, response, device.getDeviceId(), channelId, uuid);
561   - hookEvent.call(new InviteStreamInfo(mediaServerItem, null, eventResult.callId, "rtp", ssrcInfo.getStream()));
562   - });
  560 + logger.info("[回放消息] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse );
  561 + if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) {
  562 + logger.info("[回放消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse);
  563 +
  564 + if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) {
  565 + // ssrc 不可用
  566 + // 释放ssrc
  567 + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
  568 + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
  569 + eventResult.msg = "下级自定义了ssrc,但是此ssrc不可用";
  570 + eventResult.statusCode = 400;
  571 + errorEvent.response(eventResult);
  572 + return;
  573 + }
  574 +
  575 + // 单端口模式streamId也有变化,需要重新设置监听
  576 + if (!mediaServerItem.isRtpEnable()) {
  577 + // 添加订阅
  578 + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId());
  579 + subscribe.removeSubscribe(hookSubscribe);
  580 + hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase());
  581 + subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response)->{
  582 + logger.info("[ZLM HOOK] ssrc修正后收到订阅消息: " + response.toJSONString());
  583 + dynamicTask.stop(playBackTimeOutTaskKey);
  584 + // hook响应
  585 + onPublishHandlerForPlay(mediaServerItemInUse, response, device.getDeviceId(), channelId, uuid);
  586 + hookEvent.call(new InviteStreamInfo(mediaServerItem, null, eventResult.callId, "rtp", ssrcInfo.getStream()));
  587 + });
  588 + }
  589 + // 关闭rtp server
  590 + mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
  591 + // 重新开启ssrc server
  592 + mediaServerService.openRTPServer(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), true, ssrcInfo.getPort());
563 593 }
564   - // 关闭rtp server
565   - mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
566   - // 重新开启ssrc server
567   - mediaServerService.openRTPServer(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), true, ssrcInfo.getPort());
568 594 }
569 595 }
570   - }
571 596  
572   - }, errorEvent);
  597 + }, errorEvent);
  598 + } catch (InvalidArgumentException | SipException | ParseException e) {
  599 + logger.error("[命令发送失败] 回放: {}", e.getMessage());
  600 +
  601 + SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new CmdSendFailEvent(null));
  602 + eventResult.msg = "命令发送失败";
  603 + errorEvent.response(eventResult);
  604 + }
573 605 return result;
574 606 }
575 607  
... ... @@ -615,54 +647,57 @@ public class PlayServiceImpl implements IPlayService {
615 647 downloadResult.setCode(ErrorCode.ERROR100.getCode());
616 648 downloadResult.setMsg("录像下载请求超时");
617 649 hookCallBack.call(downloadResult);
618   - SIPDialog dialog = streamSession.getDialogByStream(deviceId, channelId, ssrcInfo.getStream());
  650 +
619 651 // 点播超时回复BYE 同时释放ssrc以及此次点播的资源
620   - if (dialog != null) {
621   - // 点播超时回复BYE 同时释放ssrc以及此次点播的资源
622   - cmder.streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), null);
623   - }else {
  652 + try {
  653 + cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null);
  654 + } catch (InvalidArgumentException | ParseException | SipException e) {
  655 + logger.error("[录像流]录像下载请求超时, 发送BYE失败 {}", e.getMessage());
  656 + } catch (SsrcTransactionNotFoundException e) {
624 657 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
625 658 mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
626 659 streamSession.remove(deviceId, channelId, ssrcInfo.getStream());
627 660 }
628   - cmder.streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), null);
629 661 // 回复之前所有的点播请求
630 662 hookCallBack.call(downloadResult);
631 663 }, userSetting.getPlayTimeout());
632   - cmder.downloadStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, infoCallBack,
633   - inviteStreamInfo -> {
634   - logger.info("收到订阅消息: " + inviteStreamInfo.getResponse().toJSONString());
635   - dynamicTask.stop(downLoadTimeOutTaskKey);
636   - StreamInfo streamInfo = onPublishHandler(inviteStreamInfo.getMediaServerItem(), inviteStreamInfo.getResponse(), deviceId, channelId);
637   - streamInfo.setStartTime(startTime);
638   - streamInfo.setEndTime(endTime);
639   - if (streamInfo == null) {
640   - logger.warn("录像下载API调用失败!");
641   - wvpResult.setCode(-1);
642   - wvpResult.setMsg("录像下载API调用失败");
643   - downloadResult.setCode(-1);
  664 +
  665 + SipSubscribe.Event errorEvent = event -> {
  666 + dynamicTask.stop(downLoadTimeOutTaskKey);
  667 + downloadResult.setCode(ErrorCode.ERROR100.getCode());
  668 + downloadResult.setMsg(String.format("录像下载失败, 错误码: %s, %s", event.statusCode, event.msg));
  669 + wvpResult.setCode(ErrorCode.ERROR100.getCode());
  670 + wvpResult.setMsg(String.format("录像下载失败, 错误码: %s, %s", event.statusCode, event.msg));
  671 + downloadResult.setEvent(event);
  672 + hookCallBack.call(downloadResult);
  673 + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
  674 + };
  675 +
  676 + try {
  677 + cmder.downloadStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, infoCallBack,
  678 + inviteStreamInfo -> {
  679 + logger.info("收到订阅消息: " + inviteStreamInfo.getResponse().toJSONString());
  680 + dynamicTask.stop(downLoadTimeOutTaskKey);
  681 + StreamInfo streamInfo = onPublishHandler(inviteStreamInfo.getMediaServerItem(), inviteStreamInfo.getResponse(), deviceId, channelId);
  682 + streamInfo.setStartTime(startTime);
  683 + streamInfo.setEndTime(endTime);
  684 + redisCatchStorage.startDownload(streamInfo, inviteStreamInfo.getCallId());
  685 + wvpResult.setCode(ErrorCode.SUCCESS.getCode());
  686 + wvpResult.setMsg(ErrorCode.SUCCESS.getMsg());
  687 + wvpResult.setData(streamInfo);
  688 + downloadResult.setCode(ErrorCode.SUCCESS.getCode());
  689 + downloadResult.setMsg(ErrorCode.SUCCESS.getMsg());
  690 + downloadResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem());
  691 + downloadResult.setResponse(inviteStreamInfo.getResponse());
644 692 hookCallBack.call(downloadResult);
645   - return ;
646   - }
647   - redisCatchStorage.startDownload(streamInfo, inviteStreamInfo.getCallId());
648   - wvpResult.setCode(ErrorCode.SUCCESS.getCode());
649   - wvpResult.setMsg(ErrorCode.SUCCESS.getMsg());
650   - wvpResult.setData(streamInfo);
651   - downloadResult.setCode(ErrorCode.SUCCESS.getCode());
652   - downloadResult.setMsg(ErrorCode.SUCCESS.getMsg());
653   - downloadResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem());
654   - downloadResult.setResponse(inviteStreamInfo.getResponse());
655   - hookCallBack.call(downloadResult);
656   - }, event -> {
657   - dynamicTask.stop(downLoadTimeOutTaskKey);
658   - downloadResult.setCode(ErrorCode.ERROR100.getCode());
659   - downloadResult.setMsg(String.format("录像下载失败, 错误码: %s, %s", event.statusCode, event.msg));
660   - wvpResult.setCode(ErrorCode.ERROR100.getCode());
661   - wvpResult.setMsg(String.format("录像下载失败, 错误码: %s, %s", event.statusCode, event.msg));
662   - downloadResult.setEvent(event);
663   - hookCallBack.call(downloadResult);
664   - streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
665   - });
  693 + }, errorEvent);
  694 + } catch (InvalidArgumentException | SipException | ParseException e) {
  695 + logger.error("[命令发送失败] 录像下载: {}", e.getMessage());
  696 +
  697 + SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new CmdSendFailEvent(null));
  698 + eventResult.msg = "命令发送失败";
  699 + errorEvent.response(eventResult);
  700 + }
666 701 return result;
667 702 }
668 703  
... ... @@ -741,7 +776,11 @@ public class PlayServiceImpl implements IPlayService {
741 776 for (SendRtpItem sendRtpItem : sendRtpItems) {
742 777 if (sendRtpItem.getMediaServerId().equals(mediaServerId)) {
743 778 ParentPlatform platform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId());
744   - sipCommanderFroPlatform.streamByeCmd(platform, sendRtpItem.getCallId());
  779 + try {
  780 + sipCommanderFroPlatform.streamByeCmd(platform, sendRtpItem.getCallId());
  781 + } catch (SipException | InvalidArgumentException | ParseException e) {
  782 + logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
  783 + }
745 784 }
746 785 }
747 786 }
... ... @@ -750,8 +789,17 @@ public class PlayServiceImpl implements IPlayService {
750 789 if (allSsrc.size() > 0) {
751 790 for (SsrcTransaction ssrcTransaction : allSsrc) {
752 791 if(ssrcTransaction.getMediaServerId().equals(mediaServerId)) {
753   - cmder.streamByeCmd(ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId(),
754   - ssrcTransaction.getStream(), null);
  792 + Device device = deviceService.queryDevice(ssrcTransaction.getDeviceId());
  793 + if (device == null) {
  794 + continue;
  795 + }
  796 + try {
  797 + cmder.streamByeCmd(device, ssrcTransaction.getChannelId(),
  798 + ssrcTransaction.getStream(), null);
  799 + } catch (InvalidArgumentException | ParseException | SipException |
  800 + SsrcTransactionNotFoundException e) {
  801 + logger.error("[zlm离线]为正在使用此zlm的设备, 发送BYE失败 {}", e.getMessage());
  802 + }
755 803 }
756 804 }
757 805 }
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushUploadFileHandler.java
... ... @@ -93,7 +93,6 @@ public class StreamPushUploadFileHandler extends AnalysisEventListener&lt;StreamPus
93 93 try {
94 94 gBMap.put(streamPushExcelDto.getApp() + streamPushExcelDto.getStream(), streamPushExcelDto.getGbId());
95 95 }catch (IllegalArgumentException e) {
96   - e.printStackTrace();
97 96 errorGBList.add(streamPushExcelDto.getGbId() + "(不同的app+stream使用了相同的国标ID)");
98 97 return;
99 98 }
... ...
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisAlarmMsgListener.java
... ... @@ -16,7 +16,10 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
16 16 import org.springframework.stereotype.Component;
17 17 import org.springframework.util.ObjectUtils;
18 18  
  19 +import javax.sip.InvalidArgumentException;
  20 +import javax.sip.SipException;
19 21 import javax.validation.constraints.NotNull;
  22 +import java.text.ParseException;
20 23 import java.util.List;
21 24 import java.util.concurrent.ConcurrentLinkedQueue;
22 25  
... ... @@ -78,16 +81,28 @@ public class RedisAlarmMsgListener implements MessageListener {
78 81 List<ParentPlatform> parentPlatforms = storage.queryEnableParentPlatformList(true);
79 82 if (parentPlatforms.size() > 0) {
80 83 for (ParentPlatform parentPlatform : parentPlatforms) {
81   - commanderForPlatform.sendAlarmMessage(parentPlatform, deviceAlarm);
  84 + try {
  85 + commanderForPlatform.sendAlarmMessage(parentPlatform, deviceAlarm);
  86 + } catch (SipException | InvalidArgumentException | ParseException e) {
  87 + logger.error("[命令发送失败] 国标级联 发送报警: {}", e.getMessage());
  88 + }
82 89 }
83 90 }
84 91 }else {
85 92 Device device = storage.queryVideoDevice(gbId);
86 93 ParentPlatform platform = storage.queryParentPlatByServerGBId(gbId);
87 94 if (device != null && platform == null) {
88   - commander.sendAlarmMessage(device, deviceAlarm);
  95 + try {
  96 + commander.sendAlarmMessage(device, deviceAlarm);
  97 + } catch (InvalidArgumentException | SipException | ParseException e) {
  98 + logger.error("[命令发送失败] 发送报警: {}", e.getMessage());
  99 + }
89 100 }else if (device == null && platform != null){
90   - commanderForPlatform.sendAlarmMessage(platform, deviceAlarm);
  101 + try {
  102 + commanderForPlatform.sendAlarmMessage(platform, deviceAlarm);
  103 + } catch (InvalidArgumentException | SipException | ParseException e) {
  104 + logger.error("[命令发送失败] 发送报警: {}", e.getMessage());
  105 + }
91 106 }else {
92 107 logger.warn("无法确定" + gbId + "是平台还是设备");
93 108 }
... ...
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java
... ... @@ -156,7 +156,7 @@ public class RedisGbPlayMsgListener implements MessageListener {
156 156 try {
157 157 playMsgCallback.handler(responseSendItemMsg);
158 158 } catch (ParseException e) {
159   - throw new RuntimeException(e);
  159 + logger.error("[REDIS消息处理异常] ", e);
160 160 }
161 161 }
162 162 break;
... ...
src/main/java/com/genersoft/iot/vmp/utils/GpsUtil.java
... ... @@ -17,49 +17,6 @@ public class GpsUtil {
17 17 public static BaiduPoint Wgs84ToBd09(String xx, String yy) {
18 18  
19 19  
20   -// try {
21   -// Socket s = new Socket("api.map.baidu.com", 80);
22   -// BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream(), "UTF-8"));
23   -// OutputStream out = s.getOutputStream();
24   -// StringBuffer sb = new StringBuffer("GET /ag/coord/convert?from=0&to=4");
25   -// sb.append("&x=" + xx + "&y=" + yy);
26   -// sb.append("&callback=BMap.Convertor.cbk_3976 HTTP/1.1\r\n");
27   -// sb.append("User-Agent: Java/1.6.0_20\r\n");
28   -// sb.append("Host: api.map.baidu.com:80\r\n");
29   -// sb.append("Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2\r\n");
30   -// sb.append("Connection: Close\r\n");
31   -// sb.append("\r\n");
32   -// out.write(sb.toString().getBytes());
33   -// String json = "";
34   -// String tmp = "";
35   -// while ((tmp = br.readLine()) != null) {
36   -// // logger.info(tmp);
37   -// json += tmp;
38   -// }
39   -//
40   -// s.close();
41   -// int start = json.indexOf("cbk_3976");
42   -// int end = json.lastIndexOf("}");
43   -// if (start != -1 && end != -1 && json.contains("\"x\":\"")) {
44   -// json = json.substring(start, end);
45   -// String[] point = json.split(",");
46   -// String x = point[1].split(":")[1].replace("\"", "");
47   -// String y = point[2].split(":")[1].replace("\"", "");
48   -// BaiduPoint bdPoint= new BaiduPoint();
49   -// bdPoint.setBdLng(new String(decode(x)));
50   -// bdPoint.setBdLat(new String(decode(y)));
51   -// return bdPoint;
52   -// //return (new String(decode(x)) + "," + new String(decode(y)));
53   -// } else {
54   -// logger.info("gps坐标无效!!");
55   -// }
56   -// out.close();
57   -// br.close();
58   -// } catch (Exception e) {
59   -// e.printStackTrace();
60   -// }
61   -
62   -
63 20 double lng = Double.parseDouble(xx);
64 21 double lat = Double.parseDouble(yy);
65 22 Double[] gcj02 = Coordtransform.WGS84ToGCJ02(lng, lat);
... ...
src/main/java/com/genersoft/iot/vmp/utils/IpUtil.java deleted 100644 → 0
1   -package com.genersoft.iot.vmp.utils;
2   -
3   -
4   -import javax.servlet.http.HttpServletRequest;
5   -import java.net.InetAddress;
6   -import java.net.UnknownHostException;
7   -
8   -public class IpUtil {
9   - public static String getIpAddr(HttpServletRequest request) {
10   - String ipAddress = null;
11   - try {
12   - ipAddress = request.getHeader("x-forwarded-for");
13   - if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
14   - ipAddress = request.getHeader("Proxy-Client-IP");
15   - }
16   - if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
17   - ipAddress = request.getHeader("WL-Proxy-Client-IP");
18   - }
19   - if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
20   - ipAddress = request.getRemoteAddr();
21   - if (ipAddress.equals("127.0.0.1")) {
22   - // 根据网卡取本机配置的IP
23   - InetAddress inet = null;
24   - try {
25   - inet = InetAddress.getLocalHost();
26   - } catch (UnknownHostException e) {
27   - e.printStackTrace();
28   - }
29   - ipAddress = inet.getHostAddress();
30   - }
31   - }
32   - // 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
33   - if (ipAddress != null && ipAddress.length() > 15) { // "***.***.***.***".length()
34   - // = 15
35   - if (ipAddress.indexOf(",") > 0) {
36   - ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
37   - }
38   - }
39   - } catch (Exception e) {
40   - ipAddress="";
41   - }
42   - // ipAddress = this.getRequest().getRemoteAddr();
43   -
44   - return ipAddress;
45   - }
46   -}
47   -
48   -
src/main/java/com/genersoft/iot/vmp/utils/JarFileUtils.java deleted 100644 → 0
1   -package com.genersoft.iot.vmp.utils;
2   -
3   -import org.slf4j.Logger;
4   -import org.slf4j.LoggerFactory;
5   -import org.springframework.stereotype.Component;
6   -import org.springframework.util.ClassUtils;
7   -
8   -import java.io.BufferedReader;
9   -import java.io.IOException;
10   -import java.io.InputStream;
11   -import java.io.InputStreamReader;
12   -import java.util.HashMap;
13   -import java.util.Map;
14   -import java.util.jar.JarEntry;
15   -import java.util.jar.JarFile;
16   -
17   -/**
18   - * 一个优秀的颓废程序猿
19   - */
20   -@Component
21   -public class JarFileUtils {
22   - private static Logger log = LoggerFactory.getLogger(JarFileUtils.class);
23   - private static Map<String, String> map = new HashMap<>();
24   -
25   - public Map<String, String> readJarFile() {
26   - JarFile jarFile = null;
27   - BufferedReader br = null;
28   - try {
29   - // 获取jar的运行路径,因linux下jar的路径为”file:/app/.../test.jar!/BOOT-INF/class!/“这种格式,所以需要去掉”file:“和”!/BOOT-INF/class!/“
30   - String jarFilePath = ClassUtils.getDefaultClassLoader().getResource("").getPath().replace("!/BOOT-INF/classes!/", "");
31   - if (jarFilePath.startsWith("file")) {
32   - jarFilePath = jarFilePath.substring(5);
33   - }
34   - log.debug("jarFilePath:" + jarFilePath);
35   - // 通过JarFile的getJarEntry方法读取META-INF/MANIFEST.MF
36   - jarFile = new JarFile(jarFilePath);
37   - JarEntry entry = jarFile.getJarEntry("META-INF/MANIFEST.MF");
38   - log.info("读取的内容:" + entry.toString());
39   - // 如果读取到MANIFEST.MF文件内容,则转换为string
40   - if (entry != null) {
41   - InputStream in = jarFile.getInputStream(entry);
42   -
43   - StringBuilder sb = new StringBuilder();
44   - br = new BufferedReader(new InputStreamReader(in));
45   - String line = "";
46   - while ((line = br.readLine()) != null) {
47   - if (line != null && line.contains(":")) {
48   - int index = line.indexOf(":");
49   - map.put(line.substring(0, index).trim(), line.substring(index + 1, line.length()).trim());
50   - }
51   - }
52   - return map;
53   - }
54   - } catch (IOException e) {
55   - log.debug("读取MANIFEST.MF文件异常:" + e.getMessage());
56   - } finally {
57   - try {
58   - if (null != br) {
59   - br.close();
60   - }
61   - if (null != jarFile) {
62   - jarFile.close();
63   - }
64   - } catch (IOException e) {
65   - e.printStackTrace();
66   - }
67   - }
68   -
69   - return map;
70   -
71   - }
72   -
73   -}
src/main/java/com/genersoft/iot/vmp/utils/SerializeUtils.java deleted 100644 → 0
1   -package com.genersoft.iot.vmp.utils;
2   -
3   -import java.io.*;
4   -
5   -public class SerializeUtils {
6   - public static byte[] serialize(Object obj){
7   - byte[] bytes = null;
8   - try {
9   - ByteArrayOutputStream baos=new ByteArrayOutputStream();;
10   - ObjectOutputStream oos=new ObjectOutputStream(baos);
11   - oos.writeObject(obj);
12   - bytes=baos.toByteArray();
13   - baos.close();
14   - oos.close();
15   - } catch (IOException e) {
16   - e.printStackTrace();
17   - }
18   - return bytes;
19   - }
20   - public static Object deSerialize(byte[] bytes){
21   - Object obj=null;
22   - try {
23   - ByteArrayInputStream bais=new ByteArrayInputStream(bytes);
24   - ObjectInputStream ois=new ObjectInputStream(bais);
25   - obj=ois.readObject();
26   - } catch (Exception e) {
27   - e.printStackTrace();
28   - }
29   - return obj;
30   - }
31   -}
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/MobilePosition/MobilePositionController.java
1 1 package com.genersoft.iot.vmp.vmanager.gb28181.MobilePosition;
2 2  
  3 +import java.text.ParseException;
3 4 import java.util.List;
4 5 import java.util.UUID;
5 6  
... ... @@ -31,6 +32,9 @@ import org.springframework.web.bind.annotation.RequestParam;
31 32 import org.springframework.web.bind.annotation.RestController;
32 33 import org.springframework.web.context.request.async.DeferredResult;
33 34  
  35 +import javax.sip.InvalidArgumentException;
  36 +import javax.sip.SipException;
  37 +
34 38 /**
35 39 * 位置信息管理
36 40 */
... ... @@ -105,13 +109,18 @@ public class MobilePositionController {
105 109 Device device = storager.queryVideoDevice(deviceId);
106 110 String uuid = UUID.randomUUID().toString();
107 111 String key = DeferredResultHolder.CALLBACK_CMD_MOBILEPOSITION + deviceId;
108   - cmder.mobilePostitionQuery(device, event -> {
109   - RequestMessage msg = new RequestMessage();
110   - msg.setId(uuid);
111   - msg.setKey(key);
112   - msg.setData(String.format("获取移动位置信息失败,错误码: %s, %s", event.statusCode, event.msg));
113   - resultHolder.invokeResult(msg);
114   - });
  112 + try {
  113 + cmder.mobilePostitionQuery(device, event -> {
  114 + RequestMessage msg = new RequestMessage();
  115 + msg.setId(uuid);
  116 + msg.setKey(key);
  117 + msg.setData(String.format("获取移动位置信息失败,错误码: %s, %s", event.statusCode, event.msg));
  118 + resultHolder.invokeResult(msg);
  119 + });
  120 + } catch (InvalidArgumentException | SipException | ParseException e) {
  121 + logger.error("[命令发送失败] 获取移动位置信息: {}", e.getMessage());
  122 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
  123 + }
115 124 DeferredResult<MobilePosition> result = new DeferredResult<MobilePosition>(5*1000L);
116 125 result.onTimeout(()->{
117 126 logger.warn(String.format("获取移动位置信息超时"));
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/alarm/AlarmController.java
... ... @@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
6 6 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
7 7 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
8 8 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
  9 +import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookListener;
9 10 import com.genersoft.iot.vmp.service.IDeviceAlarmService;
10 11 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
11 12 import com.genersoft.iot.vmp.utils.DateUtil;
... ... @@ -16,6 +17,8 @@ import io.swagger.v3.oas.annotations.Operation;
16 17 import io.swagger.v3.oas.annotations.Parameter;
17 18 import io.swagger.v3.oas.annotations.responses.ApiResponse;
18 19 import io.swagger.v3.oas.annotations.tags.Tag;
  20 +import org.slf4j.Logger;
  21 +import org.slf4j.LoggerFactory;
19 22 import org.springframework.beans.factory.annotation.Autowired;
20 23 import org.springframework.http.HttpStatus;
21 24 import org.springframework.http.ResponseEntity;
... ... @@ -23,6 +26,9 @@ import org.springframework.util.ObjectUtils;
23 26 import org.springframework.util.StringUtils;
24 27 import org.springframework.web.bind.annotation.*;
25 28  
  29 +import javax.sip.InvalidArgumentException;
  30 +import javax.sip.SipException;
  31 +import java.text.ParseException;
26 32 import java.time.LocalDateTime;
27 33 import java.util.Arrays;
28 34 import java.util.List;
... ... @@ -33,6 +39,8 @@ import java.util.List;
33 39 @RequestMapping("/api/alarm")
34 40 public class AlarmController {
35 41  
  42 + private final static Logger logger = LoggerFactory.getLogger(AlarmController.class);
  43 +
36 44 @Autowired
37 45 private IDeviceAlarmService deviceAlarmService;
38 46  
... ... @@ -108,9 +116,19 @@ public class AlarmController {
108 116 deviceAlarm.setLatitude(39.33333);
109 117  
110 118 if (device != null && platform == null) {
111   - commander.sendAlarmMessage(device, deviceAlarm);
  119 +
  120 + try {
  121 + commander.sendAlarmMessage(device, deviceAlarm);
  122 + } catch (InvalidArgumentException | SipException | ParseException e) {
  123 +
  124 + }
112 125 }else if (device == null && platform != null){
113   - commanderForPlatform.sendAlarmMessage(platform, deviceAlarm);
  126 + try {
  127 + commanderForPlatform.sendAlarmMessage(platform, deviceAlarm);
  128 + } catch (SipException | InvalidArgumentException | ParseException e) {
  129 + logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
  130 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
  131 + }
114 132 }else {
115 133 throw new ControllerException(ErrorCode.ERROR100.getCode(),"无法确定" + deviceId + "是平台还是设备");
116 134 }
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceConfig.java
... ... @@ -8,12 +8,14 @@
8 8 package com.genersoft.iot.vmp.vmanager.gb28181.device;
9 9  
10 10 import com.alibaba.fastjson.JSONObject;
  11 +import com.genersoft.iot.vmp.conf.exception.ControllerException;
11 12 import com.genersoft.iot.vmp.gb28181.bean.Device;
12 13 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
13 14 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
14 15 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
15 16 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
16 17  
  18 +import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
17 19 import io.swagger.v3.oas.annotations.Operation;
18 20 import io.swagger.v3.oas.annotations.Parameter;
19 21 import io.swagger.v3.oas.annotations.tags.Tag;
... ... @@ -26,6 +28,9 @@ import org.springframework.util.StringUtils;
26 28 import org.springframework.web.bind.annotation.*;
27 29 import org.springframework.web.context.request.async.DeferredResult;
28 30  
  31 +import javax.sip.InvalidArgumentException;
  32 +import javax.sip.SipException;
  33 +import java.text.ParseException;
29 34 import java.util.UUID;
30 35  
31 36 @Tag(name = "国标设备配置")
... ... @@ -75,14 +80,19 @@ public class DeviceConfig {
75 80 Device device = storager.queryVideoDevice(deviceId);
76 81 String uuid = UUID.randomUUID().toString();
77 82 String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + deviceId + channelId;
78   - cmder.deviceBasicConfigCmd(device, channelId, name, expiration, heartBeatInterval, heartBeatCount, event -> {
79   - RequestMessage msg = new RequestMessage();
80   - msg.setId(uuid);
81   - msg.setKey(key);
82   - msg.setData(String.format("设备配置操作失败,错误码: %s, %s", event.statusCode, event.msg));
83   - resultHolder.invokeResult(msg);
84   - });
85   - DeferredResult<String> result = new DeferredResult<String>(3 * 1000L);
  83 + try {
  84 + cmder.deviceBasicConfigCmd(device, channelId, name, expiration, heartBeatInterval, heartBeatCount, event -> {
  85 + RequestMessage msg = new RequestMessage();
  86 + msg.setId(uuid);
  87 + msg.setKey(key);
  88 + msg.setData(String.format("设备配置操作失败,错误码: %s, %s", event.statusCode, event.msg));
  89 + resultHolder.invokeResult(msg);
  90 + });
  91 + } catch (InvalidArgumentException | SipException | ParseException e) {
  92 + logger.error("[命令发送失败] 设备配置: {}", e.getMessage());
  93 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
  94 + }
  95 + DeferredResult<String> result = new DeferredResult<String>(3 * 1000L);
86 96 result.onTimeout(() -> {
87 97 logger.warn(String.format("设备配置操作超时, 设备未返回应答指令"));
88 98 // 释放rtpserver
... ... @@ -121,14 +131,19 @@ public class DeviceConfig {
121 131 String key = DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (ObjectUtils.isEmpty(channelId) ? deviceId : channelId);
122 132 String uuid = UUID.randomUUID().toString();
123 133 Device device = storager.queryVideoDevice(deviceId);
124   - cmder.deviceConfigQuery(device, channelId, configType, event -> {
125   - RequestMessage msg = new RequestMessage();
126   - msg.setId(uuid);
127   - msg.setKey(key);
128   - msg.setData(String.format("获取设备配置失败,错误码: %s, %s", event.statusCode, event.msg));
129   - resultHolder.invokeResult(msg);
130   - });
131   - DeferredResult<String> result = new DeferredResult<String > (3 * 1000L);
  134 + try {
  135 + cmder.deviceConfigQuery(device, channelId, configType, event -> {
  136 + RequestMessage msg = new RequestMessage();
  137 + msg.setId(uuid);
  138 + msg.setKey(key);
  139 + msg.setData(String.format("获取设备配置失败,错误码: %s, %s", event.statusCode, event.msg));
  140 + resultHolder.invokeResult(msg);
  141 + });
  142 + } catch (InvalidArgumentException | SipException | ParseException e) {
  143 + logger.error("[命令发送失败] 获取设备配置: {}", e.getMessage());
  144 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
  145 + }
  146 + DeferredResult<String> result = new DeferredResult<String > (3 * 1000L);
132 147 result.onTimeout(()->{
133 148 logger.warn(String.format("获取设备配置超时"));
134 149 // 释放rtpserver
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceControl.java
... ... @@ -29,6 +29,9 @@ import org.springframework.util.StringUtils;
29 29 import org.springframework.web.bind.annotation.*;
30 30 import org.springframework.web.context.request.async.DeferredResult;
31 31  
  32 +import javax.sip.InvalidArgumentException;
  33 +import javax.sip.SipException;
  34 +import java.text.ParseException;
32 35 import java.util.UUID;
33 36  
34 37 @Tag(name = "国标设备控制")
... ... @@ -61,10 +64,12 @@ public class DeviceControl {
61 64 logger.debug("设备远程启动API调用");
62 65 }
63 66 Device device = storager.queryVideoDevice(deviceId);
64   - if (!cmder.teleBootCmd(device)) {
65   - logger.warn("设备远程启动API调用失败!");
66   - throw new ControllerException(ErrorCode.ERROR100);
67   - }
  67 + try {
  68 + cmder.teleBootCmd(device);
  69 + } catch (InvalidArgumentException | SipException | ParseException e) {
  70 + logger.error("[命令发送失败] 远程启动: {}", e.getMessage());
  71 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
  72 + }
68 73 }
69 74  
70 75 /**
... ... @@ -101,13 +106,18 @@ public class DeviceControl {
101 106 return result;
102 107 }
103 108 resultHolder.put(key, uuid, result);
104   - cmder.recordCmd(device, channelId, recordCmdStr, event -> {
105   - RequestMessage msg = new RequestMessage();
106   - msg.setId(uuid);
107   - msg.setKey(key);
108   - msg.setData(String.format("开始/停止录像操作失败,错误码: %s, %s", event.statusCode, event.msg));
109   - resultHolder.invokeAllResult(msg);
110   - });
  109 + try {
  110 + cmder.recordCmd(device, channelId, recordCmdStr, event -> {
  111 + RequestMessage msg = new RequestMessage();
  112 + msg.setId(uuid);
  113 + msg.setKey(key);
  114 + msg.setData(String.format("开始/停止录像操作失败,错误码: %s, %s", event.statusCode, event.msg));
  115 + resultHolder.invokeAllResult(msg);
  116 + });
  117 + } catch (InvalidArgumentException | SipException | ParseException e) {
  118 + logger.error("[命令发送失败] 开始/停止录像: {}", e.getMessage());
  119 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
  120 + }
111 121  
112 122 return result;
113 123 }
... ... @@ -123,21 +133,26 @@ public class DeviceControl {
123 133 @Parameter(name = "channelId", description = "通道国标编号", required = true)
124 134 @Parameter(name = "guardCmdStr", description = "命令, 可选值:SetGuard(布防),ResetGuard(撤防)", required = true)
125 135 @GetMapping("/guard/{deviceId}/{guardCmdStr}")
126   - public DeferredResult<ResponseEntity<String>> guardApi(@PathVariable String deviceId, String channelId, @PathVariable String guardCmdStr) {
  136 + public DeferredResult<String> guardApi(@PathVariable String deviceId, String channelId, @PathVariable String guardCmdStr) {
127 137 if (logger.isDebugEnabled()) {
128 138 logger.debug("布防/撤防API调用");
129 139 }
130 140 Device device = storager.queryVideoDevice(deviceId);
131 141 String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId + channelId;
132 142 String uuid =UUID.randomUUID().toString();
133   - cmder.guardCmd(device, guardCmdStr, event -> {
134   - RequestMessage msg = new RequestMessage();
135   - msg.setId(uuid);
136   - msg.setKey(key);
137   - msg.setData(String.format("布防/撤防操作失败,错误码: %s, %s", event.statusCode, event.msg));
138   - resultHolder.invokeResult(msg);
139   - });
140   - DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(3 * 1000L);
  143 + try {
  144 + cmder.guardCmd(device, guardCmdStr, event -> {
  145 + RequestMessage msg = new RequestMessage();
  146 + msg.setId(uuid);
  147 + msg.setKey(key);
  148 + msg.setData(String.format("布防/撤防操作失败,错误码: %s, %s", event.statusCode, event.msg));
  149 + resultHolder.invokeResult(msg);
  150 + });
  151 + } catch (InvalidArgumentException | SipException | ParseException e) {
  152 + logger.error("[命令发送失败] 布防/撤防操作: {}", e.getMessage());
  153 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage());
  154 + }
  155 + DeferredResult<String> result = new DeferredResult<>(3 * 1000L);
141 156 resultHolder.put(key, uuid, result);
142 157 result.onTimeout(() -> {
143 158 logger.warn(String.format("布防/撤防操作超时, 设备未返回应答指令"));
... ... @@ -174,14 +189,19 @@ public class DeviceControl {
174 189 Device device = storager.queryVideoDevice(deviceId);
175 190 String uuid = UUID.randomUUID().toString();
176 191 String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId + channelId;
177   - cmder.alarmCmd(device, alarmMethod, alarmType, event -> {
178   - RequestMessage msg = new RequestMessage();
179   - msg.setId(uuid);
180   - msg.setKey(key);
181   - msg.setData(String.format("报警复位操作失败,错误码: %s, %s", event.statusCode, event.msg));
182   - resultHolder.invokeResult(msg);
183   - });
184   - DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(3 * 1000L);
  192 + try {
  193 + cmder.alarmCmd(device, alarmMethod, alarmType, event -> {
  194 + RequestMessage msg = new RequestMessage();
  195 + msg.setId(uuid);
  196 + msg.setKey(key);
  197 + msg.setData(String.format("报警复位操作失败,错误码: %s, %s", event.statusCode, event.msg));
  198 + resultHolder.invokeResult(msg);
  199 + });
  200 + } catch (InvalidArgumentException | SipException | ParseException e) {
  201 + logger.error("[命令发送失败] 报警复位: {}", e.getMessage());
  202 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
  203 + }
  204 + DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(3 * 1000L);
185 205 result.onTimeout(() -> {
186 206 logger.warn(String.format("报警复位操作超时, 设备未返回应答指令"));
187 207 // 释放rtpserver
... ... @@ -205,23 +225,23 @@ public class DeviceControl {
205 225 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
206 226 @Parameter(name = "channelId", description = "通道国标编号")
207 227 @GetMapping("/i_frame/{deviceId}")
208   - public ResponseEntity<String> iFrame(@PathVariable String deviceId,
  228 + public JSONObject iFrame(@PathVariable String deviceId,
209 229 @RequestParam(required = false) String channelId) {
210 230 if (logger.isDebugEnabled()) {
211 231 logger.debug("强制关键帧API调用");
212 232 }
213 233 Device device = storager.queryVideoDevice(deviceId);
214   - boolean sucsess = cmder.iFrameCmd(device, channelId);
215   - if (sucsess) {
216   - JSONObject json = new JSONObject();
217   - json.put("DeviceID", deviceId);
218   - json.put("ChannelID", channelId);
219   - json.put("Result", "OK");
220   - return new ResponseEntity<>(json.toJSONString(), HttpStatus.OK);
221   - } else {
222   - logger.warn("强制关键帧API调用失败!");
223   - return new ResponseEntity<String>("强制关键帧API调用失败!", HttpStatus.INTERNAL_SERVER_ERROR);
  234 + try {
  235 + cmder.iFrameCmd(device, channelId);
  236 + } catch (InvalidArgumentException | SipException | ParseException e) {
  237 + logger.error("[命令发送失败] 强制关键帧: {}", e.getMessage());
  238 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
224 239 }
  240 + JSONObject json = new JSONObject();
  241 + json.put("DeviceID", deviceId);
  242 + json.put("ChannelID", channelId);
  243 + json.put("Result", "OK");
  244 + return json;
225 245 }
226 246  
227 247 /**
... ... @@ -240,7 +260,7 @@ public class DeviceControl {
240 260 @Parameter(name = "presetIndex", description = "调用预置位编号")
241 261 @Parameter(name = "resetTime", description = "自动归位时间间隔")
242 262 @GetMapping("/home_position/{deviceId}/{enabled}")
243   - public DeferredResult<ResponseEntity<String>> homePositionApi(@PathVariable String deviceId,
  263 + public DeferredResult<String> homePositionApi(@PathVariable String deviceId,
244 264 @PathVariable String enabled,
245 265 @RequestParam(required = false) String resetTime,
246 266 @RequestParam(required = false) String presetIndex,
... ... @@ -251,14 +271,19 @@ public class DeviceControl {
251 271 String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (ObjectUtils.isEmpty(channelId) ? deviceId : channelId);
252 272 String uuid = UUID.randomUUID().toString();
253 273 Device device = storager.queryVideoDevice(deviceId);
254   - cmder.homePositionCmd(device, channelId, enabled, resetTime, presetIndex, event -> {
255   - RequestMessage msg = new RequestMessage();
256   - msg.setId(uuid);
257   - msg.setKey(key);
258   - msg.setData(String.format("看守位控制操作失败,错误码: %s, %s", event.statusCode, event.msg));
259   - resultHolder.invokeResult(msg);
260   - });
261   - DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(3 * 1000L);
  274 + try {
  275 + cmder.homePositionCmd(device, channelId, enabled, resetTime, presetIndex, event -> {
  276 + RequestMessage msg = new RequestMessage();
  277 + msg.setId(uuid);
  278 + msg.setKey(key);
  279 + msg.setData(String.format("看守位控制操作失败,错误码: %s, %s", event.statusCode, event.msg));
  280 + resultHolder.invokeResult(msg);
  281 + });
  282 + } catch (InvalidArgumentException | SipException | ParseException e) {
  283 + logger.error("[命令发送失败] 看守位控制: {}", e.getMessage());
  284 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
  285 + }
  286 + DeferredResult<String> result = new DeferredResult<>(3 * 1000L);
262 287 result.onTimeout(() -> {
263 288 logger.warn(String.format("看守位控制操作超时, 设备未返回应答指令"));
264 289 // 释放rtpserver
... ... @@ -297,14 +322,14 @@ public class DeviceControl {
297 322 @Parameter(name = "lengthx", description = "拉框长度像素值", required = true)
298 323 @Parameter(name = "lengthy", description = "lengthy", required = true)
299 324 @GetMapping("drag_zoom/zoom_in")
300   - public ResponseEntity<String> dragZoomIn(@RequestParam String deviceId,
  325 + public void dragZoomIn(@RequestParam String deviceId,
301 326 @RequestParam(required = false) String channelId,
302 327 @RequestParam int length,
303 328 @RequestParam int width,
304 329 @RequestParam int midpointx,
305 330 @RequestParam int midpointy,
306 331 @RequestParam int lengthx,
307   - @RequestParam int lengthy){
  332 + @RequestParam int lengthy) throws RuntimeException {
308 333 if (logger.isDebugEnabled()) {
309 334 logger.debug(String.format("设备拉框放大 API调用,deviceId:%s ,channelId:%s ,length:%d ,width:%d ,midpointx:%d ,midpointy:%d ,lengthx:%d ,lengthy:%d",deviceId, channelId, length, width, midpointx, midpointy,lengthx, lengthy));
310 335 }
... ... @@ -318,8 +343,12 @@ public class DeviceControl {
318 343 cmdXml.append("<LengthX>" + lengthx+ "</LengthX>\r\n");
319 344 cmdXml.append("<LengthY>" + lengthy+ "</LengthY>\r\n");
320 345 cmdXml.append("</DragZoomIn>\r\n");
321   - cmder.dragZoomCmd(device, channelId, cmdXml.toString());
322   - return new ResponseEntity<String>("success", HttpStatus.OK);
  346 + try {
  347 + cmder.dragZoomCmd(device, channelId, cmdXml.toString());
  348 + } catch (InvalidArgumentException | SipException | ParseException e) {
  349 + logger.error("[命令发送失败] 拉框放大: {}", e.getMessage());
  350 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
  351 + }
323 352 }
324 353  
325 354 /**
... ... @@ -344,7 +373,7 @@ public class DeviceControl {
344 373 @Parameter(name = "lengthx", description = "拉框长度像素值", required = true)
345 374 @Parameter(name = "lengthy", description = "拉框宽度像素值", required = true)
346 375 @GetMapping("/drag_zoom/zoom_out")
347   - public ResponseEntity<String> dragZoomOut(@RequestParam String deviceId,
  376 + public void dragZoomOut(@RequestParam String deviceId,
348 377 @RequestParam(required = false) String channelId,
349 378 @RequestParam int length,
350 379 @RequestParam int width,
... ... @@ -366,7 +395,11 @@ public class DeviceControl {
366 395 cmdXml.append("<LengthX>" + lengthx+ "</LengthX>\r\n");
367 396 cmdXml.append("<LengthY>" + lengthy+ "</LengthY>\r\n");
368 397 cmdXml.append("</DragZoomOut>\r\n");
369   - cmder.dragZoomCmd(device, channelId, cmdXml.toString());
370   - return new ResponseEntity<String>("success",HttpStatus.OK);
  398 + try {
  399 + cmder.dragZoomCmd(device, channelId, cmdXml.toString());
  400 + } catch (InvalidArgumentException | SipException | ParseException e) {
  401 + logger.error("[命令发送失败] 拉框缩小: {}", e.getMessage());
  402 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
  403 + }
371 404 }
372 405 }
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
... ... @@ -39,8 +39,11 @@ import org.springframework.web.context.request.async.DeferredResult;
39 39  
40 40 import javax.servlet.http.HttpServletResponse;
41 41 import javax.sip.DialogState;
  42 +import javax.sip.InvalidArgumentException;
  43 +import javax.sip.SipException;
42 44 import java.io.*;
43 45 import java.nio.file.Files;
  46 +import java.text.ParseException;
44 47 import java.util.*;
45 48  
46 49 @Tag(name = "国标设备查询", description = "国标设备查询")
... ... @@ -315,13 +318,18 @@ public class DeviceQuery {
315 318 result.setResult(new ResponseEntity(String.format("设备%s不存在", deviceId),HttpStatus.OK));
316 319 return result;
317 320 }
318   - cmder.deviceStatusQuery(device, event -> {
319   - RequestMessage msg = new RequestMessage();
320   - msg.setId(uuid);
321   - msg.setKey(key);
322   - msg.setData(String.format("获取设备状态失败,错误码: %s, %s", event.statusCode, event.msg));
323   - resultHolder.invokeResult(msg);
324   - });
  321 + try {
  322 + cmder.deviceStatusQuery(device, event -> {
  323 + RequestMessage msg = new RequestMessage();
  324 + msg.setId(uuid);
  325 + msg.setKey(key);
  326 + msg.setData(String.format("获取设备状态失败,错误码: %s, %s", event.statusCode, event.msg));
  327 + resultHolder.invokeResult(msg);
  328 + });
  329 + } catch (InvalidArgumentException | SipException | ParseException e) {
  330 + logger.error("[命令发送失败] 获取设备状态: {}", e.getMessage());
  331 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
  332 + }
325 333 result.onTimeout(()->{
326 334 logger.warn(String.format("获取设备状态超时"));
327 335 // 释放rtpserver
... ... @@ -368,14 +376,19 @@ public class DeviceQuery {
368 376 Device device = storager.queryVideoDevice(deviceId);
369 377 String key = DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId;
370 378 String uuid = UUID.randomUUID().toString();
371   - cmder.alarmInfoQuery(device, startPriority, endPriority, alarmMethod, alarmType, startTime, endTime, event -> {
372   - RequestMessage msg = new RequestMessage();
373   - msg.setId(uuid);
374   - msg.setKey(key);
375   - msg.setData(String.format("设备报警查询失败,错误码: %s, %s",event.statusCode, event.msg));
376   - resultHolder.invokeResult(msg);
377   - });
378   - DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String >> (3 * 1000L);
  379 + try {
  380 + cmder.alarmInfoQuery(device, startPriority, endPriority, alarmMethod, alarmType, startTime, endTime, event -> {
  381 + RequestMessage msg = new RequestMessage();
  382 + msg.setId(uuid);
  383 + msg.setKey(key);
  384 + msg.setData(String.format("设备报警查询失败,错误码: %s, %s",event.statusCode, event.msg));
  385 + resultHolder.invokeResult(msg);
  386 + });
  387 + } catch (InvalidArgumentException | SipException | ParseException e) {
  388 + logger.error("[命令发送失败] 设备报警查询: {}", e.getMessage());
  389 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
  390 + }
  391 + DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String >> (3 * 1000L);
379 392 result.onTimeout(()->{
380 393 logger.warn(String.format("设备报警查询超时"));
381 394 // 释放rtpserver
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/media/MediaController.java
... ... @@ -96,7 +96,7 @@ public class MediaController {
96 96 try {
97 97 Thread.sleep(1000);
98 98 } catch (InterruptedException e) {
99   - e.printStackTrace();
  99 + logger.error("[线程休眠失败], {}", e.getMessage());
100 100 }
101 101 if (useSourceIpAsStreamIp != null && useSourceIpAsStreamIp) {
102 102 String host = request.getHeader("Host");
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java
... ... @@ -29,6 +29,9 @@ import org.springframework.util.ObjectUtils;
29 29 import org.springframework.web.bind.annotation.*;
30 30 import com.genersoft.iot.vmp.conf.SipConfig;
31 31  
  32 +import javax.sip.InvalidArgumentException;
  33 +import javax.sip.SipException;
  34 +import java.text.ParseException;
32 35 import java.util.List;
33 36  
34 37 /**
... ... @@ -212,20 +215,37 @@ public class PlatformController {
212 215 // 保存时启用就发送注册
213 216 if (parentPlatform.isEnable()) {
214 217 if (parentPlatformOld != null && parentPlatformOld.isStatus()) {
215   - commanderForPlatform.unregister(parentPlatformOld, null, null);
  218 + try {
  219 + commanderForPlatform.unregister(parentPlatformOld, null, null);
  220 + } catch (InvalidArgumentException | ParseException | SipException e) {
  221 + logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage());
  222 + }
216 223 try {
217 224 Thread.sleep(500);
218 225 } catch (InterruptedException e) {
219   - e.printStackTrace();
  226 + logger.error("[线程休眠失败] : {}", e.getMessage());
220 227 }
221 228 // 只要保存就发送注册
222   - commanderForPlatform.register(parentPlatform, null, null);
  229 + try {
  230 + commanderForPlatform.register(parentPlatform, null, null);
  231 + } catch (InvalidArgumentException | ParseException | SipException e) {
  232 + logger.error("[命令发送失败] 国标级联 注册: {}", e.getMessage());
  233 + }
  234 +
223 235 } else {
224 236 // 只要保存就发送注册
225   - commanderForPlatform.register(parentPlatform, null, null);
  237 + try {
  238 + commanderForPlatform.register(parentPlatform, null, null);
  239 + } catch (InvalidArgumentException | ParseException | SipException e) {
  240 + logger.error("[命令发送失败] 国标级联 注册: {}", e.getMessage());
  241 + }
226 242 }
227 243 } else if (parentPlatformOld != null && parentPlatformOld.isEnable() && !parentPlatform.isEnable()) { // 关闭启用时注销
228   - commanderForPlatform.unregister(parentPlatformOld, null, null);
  244 + try {
  245 + commanderForPlatform.unregister(parentPlatformOld, null, null);
  246 + } catch (InvalidArgumentException | ParseException | SipException e) {
  247 + logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage());
  248 + }
229 249 // 停止订阅相关的定时任务
230 250 subscribeHolder.removeAllSubscribe(parentPlatform.getServerGBId());
231 251 }
... ... @@ -258,17 +278,21 @@ public class PlatformController {
258 278 throw new ControllerException(ErrorCode.ERROR100.getCode(), "平台不存在");
259 279 }
260 280 // 发送离线消息,无论是否成功都删除缓存
261   - commanderForPlatform.unregister(parentPlatform, (event -> {
262   - // 清空redis缓存
263   - redisCatchStorage.delPlatformCatchInfo(parentPlatform.getServerGBId());
264   - redisCatchStorage.delPlatformKeepalive(parentPlatform.getServerGBId());
265   - redisCatchStorage.delPlatformRegister(parentPlatform.getServerGBId());
266   - }), (event -> {
267   - // 清空redis缓存
268   - redisCatchStorage.delPlatformCatchInfo(parentPlatform.getServerGBId());
269   - redisCatchStorage.delPlatformKeepalive(parentPlatform.getServerGBId());
270   - redisCatchStorage.delPlatformRegister(parentPlatform.getServerGBId());
271   - }));
  281 + try {
  282 + commanderForPlatform.unregister(parentPlatform, (event -> {
  283 + // 清空redis缓存
  284 + redisCatchStorage.delPlatformCatchInfo(parentPlatform.getServerGBId());
  285 + redisCatchStorage.delPlatformKeepalive(parentPlatform.getServerGBId());
  286 + redisCatchStorage.delPlatformRegister(parentPlatform.getServerGBId());
  287 + }), (event -> {
  288 + // 清空redis缓存
  289 + redisCatchStorage.delPlatformCatchInfo(parentPlatform.getServerGBId());
  290 + redisCatchStorage.delPlatformKeepalive(parentPlatform.getServerGBId());
  291 + redisCatchStorage.delPlatformRegister(parentPlatform.getServerGBId());
  292 + }));
  293 + } catch (InvalidArgumentException | ParseException | SipException e) {
  294 + logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage());
  295 + }
272 296  
273 297 boolean deleteResult = storager.deleteParentPlatform(parentPlatform);
274 298 storager.delCatalogByPlatformId(parentPlatform.getServerGBId());
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
... ... @@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.vmanager.gb28181.play;
3 3 import com.alibaba.fastjson.JSONArray;
4 4 import com.genersoft.iot.vmp.common.StreamInfo;
5 5 import com.genersoft.iot.vmp.conf.exception.ControllerException;
  6 +import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
6 7 import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
7 8 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
8 9 import com.genersoft.iot.vmp.gb28181.bean.Device;
... ... @@ -37,6 +38,9 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
37 38 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
38 39 import org.springframework.web.context.request.async.DeferredResult;
39 40  
  41 +import javax.sip.InvalidArgumentException;
  42 +import javax.sip.SipException;
  43 +import java.text.ParseException;
40 44 import java.util.List;
41 45 import java.util.UUID;
42 46  
... ... @@ -107,12 +111,23 @@ public class PlayController {
107 111 throw new ControllerException(ErrorCode.ERROR400);
108 112 }
109 113  
  114 + Device device = storager.queryVideoDevice(deviceId);
  115 + if (device == null) {
  116 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "设备[" + deviceId + "]不存在");
  117 + }
  118 +
110 119 StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
111 120 if (streamInfo == null) {
112 121 throw new ControllerException(ErrorCode.ERROR100.getCode(), "点播未找到");
113 122 }
114 123  
115   - cmder.streamByeCmd(deviceId, channelId, streamInfo.getStream(), null, null);
  124 + try {
  125 + logger.warn("[停止点播] {}/{}", device.getDeviceId(), channelId);
  126 + cmder.streamByeCmd(device, channelId, streamInfo.getStream(), null, null);
  127 + } catch (InvalidArgumentException | SipException | ParseException | SsrcTransactionNotFoundException e) {
  128 + logger.error("[命令发送失败] 停止点播, 发送BYE: {}", e.getMessage());
  129 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
  130 + }
116 131 redisCatchStorage.stopPlay(streamInfo);
117 132  
118 133 storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
... ... @@ -201,42 +216,44 @@ public class PlayController {
201 216 @Parameter(name = "timeout", description = "推流超时时间(秒)", required = true)
202 217 @GetMapping("/broadcast/{deviceId}/{channelId}")
203 218 @PostMapping("/broadcast/{deviceId}/{channelId}")
204   - public DeferredResult<WVPResult<AudioBroadcastResult>> broadcastApi(@PathVariable String deviceId, @PathVariable String channelId, Integer timeout) {
  219 + public DeferredResult<String> broadcastApi(@PathVariable String deviceId, @PathVariable String channelId, Integer timeout) {
205 220 if (logger.isDebugEnabled()) {
206 221 logger.debug("语音广播API调用");
207 222 }
208 223 Device device = storager.queryVideoDevice(deviceId);
  224 + DeferredResult<String> result = new DeferredResult<>(3 * 1000L);
209 225 if (device == null) {
210   - WVPResult<AudioBroadcastResult> result = new WVPResult<>();
211   - result.setCode(-1);
212   - result.setMsg("未找到设备: " + deviceId);
213   - DeferredResult<WVPResult<AudioBroadcastResult>> deferredResult = new DeferredResult<>();
214   - deferredResult.setResult(result);
215   - return deferredResult;
  226 + result.setResult("未找到设备: " + deviceId);
  227 + return result;
216 228 }
217 229 if (channelId == null) {
218   - WVPResult<AudioBroadcastResult> result = new WVPResult<>();
219   - result.setCode(-1);
220   - result.setMsg("未找到通道: " + channelId);
221   - DeferredResult<WVPResult<AudioBroadcastResult>> deferredResult = new DeferredResult<>();
222   - deferredResult.setResult(result);
223   - return deferredResult;
  230 + result.setResult("未找到通道: " + channelId);
  231 + return result;
224 232 }
225   -
226   - String key = DeferredResultHolder.CALLBACK_CMD_BROADCAST + deviceId;
  233 + String key = DeferredResultHolder.CALLBACK_CMD_BROADCAST + deviceId;
227 234 if (resultHolder.exist(key, null)) {
228   - WVPResult<AudioBroadcastResult> wvpResult = new WVPResult<>();
229   - wvpResult.setCode(-1);
230   - wvpResult.setMsg("设备使用中");
231   - DeferredResult<WVPResult<AudioBroadcastResult>> deferredResult = new DeferredResult<>();
232   - deferredResult.setResult(wvpResult);
233   - return deferredResult;
  235 + result.setResult("设备使用中");
  236 + return result;
234 237 }
235 238 if (timeout == null){
236 239 timeout = 30;
237 240 }
238   - DeferredResult<WVPResult<AudioBroadcastResult>> result = new DeferredResult<>(timeout.longValue()*1000 + 2000);
239 241 String uuid = UUID.randomUUID().toString();
  242 +
  243 + result.onTimeout(() -> {
  244 + logger.warn("语音广播操作超时, 设备未返回应答指令");
  245 + RequestMessage msg = new RequestMessage();
  246 + msg.setKey(key);
  247 + msg.setId(uuid);
  248 + JSONObject json = new JSONObject();
  249 + json.put("DeviceID", deviceId);
  250 + json.put("CmdType", "Broadcast");
  251 + json.put("Result", "Failed");
  252 + json.put("Error", "Timeout. Device did not response to broadcast command.");
  253 + msg.setData(json);
  254 + resultHolder.invokeResult(msg);
  255 + });
  256 +
240 257 result.onTimeout(()->{
241 258 WVPResult<AudioBroadcastResult> wvpResult = new WVPResult<>();
242 259 wvpResult.setCode(-1);
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java
... ... @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.vmanager.gb28181.playback;
2 2  
3 3 import com.genersoft.iot.vmp.common.StreamInfo;
4 4 import com.genersoft.iot.vmp.conf.exception.ControllerException;
  5 +import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
5 6 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
6 7 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
7 8 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
... ... @@ -21,12 +22,15 @@ import org.springframework.web.bind.annotation.PathVariable;
21 22 import org.springframework.web.bind.annotation.RequestMapping;
22 23 import org.springframework.web.bind.annotation.RestController;
23 24  
24   -import com.alibaba.fastjson.JSONObject;
25 25 import com.genersoft.iot.vmp.gb28181.bean.Device;
26 26 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
27 27 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
28 28 import org.springframework.web.context.request.async.DeferredResult;
29 29  
  30 +import javax.sip.InvalidArgumentException;
  31 +import javax.sip.SipException;
  32 +import java.text.ParseException;
  33 +
30 34 /**
31 35 * @author lin
32 36 */
... ... @@ -92,7 +96,15 @@ public class PlaybackController {
92 96 if (ObjectUtils.isEmpty(deviceId) || ObjectUtils.isEmpty(channelId) || ObjectUtils.isEmpty(stream)) {
93 97 throw new ControllerException(ErrorCode.ERROR400);
94 98 }
95   - cmder.streamByeCmd(deviceId, channelId, stream, null);
  99 + Device device = storager.queryVideoDevice(deviceId);
  100 + if (device == null) {
  101 + throw new ControllerException(ErrorCode.ERROR400.getCode(), "设备:" + deviceId + " 未找到");
  102 + }
  103 + try {
  104 + cmder.streamByeCmd(device, channelId, stream, null);
  105 + } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) {
  106 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "发送bye失败: " + e.getMessage());
  107 + }
96 108 }
97 109  
98 110  
... ... @@ -107,7 +119,11 @@ public class PlaybackController {
107 119 throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在");
108 120 }
109 121 Device device = storager.queryVideoDevice(streamInfo.getDeviceID());
110   - cmder.playPauseCmd(device, streamInfo);
  122 + try {
  123 + cmder.playPauseCmd(device, streamInfo);
  124 + } catch (InvalidArgumentException | ParseException | SipException e) {
  125 + throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
  126 + }
111 127 }
112 128  
113 129  
... ... @@ -122,7 +138,11 @@ public class PlaybackController {
122 138 throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在");
123 139 }
124 140 Device device = storager.queryVideoDevice(streamInfo.getDeviceID());
125   - cmder.playResumeCmd(device, streamInfo);
  141 + try {
  142 + cmder.playResumeCmd(device, streamInfo);
  143 + } catch (InvalidArgumentException | ParseException | SipException e) {
  144 + throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
  145 + }
126 146 }
127 147  
128 148  
... ... @@ -138,7 +158,11 @@ public class PlaybackController {
138 158 throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在");
139 159 }
140 160 Device device = storager.queryVideoDevice(streamInfo.getDeviceID());
141   - cmder.playSeekCmd(device, streamInfo, seekTime);
  161 + try {
  162 + cmder.playSeekCmd(device, streamInfo, seekTime);
  163 + } catch (InvalidArgumentException | ParseException | SipException e) {
  164 + throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
  165 + }
142 166 }
143 167  
144 168 @Operation(summary = "回放倍速播放")
... ... @@ -157,6 +181,10 @@ public class PlaybackController {
157 181 throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持的speed(0.25 0.5 1、2、4)");
158 182 }
159 183 Device device = storager.queryVideoDevice(streamInfo.getDeviceID());
160   - cmder.playSpeedCmd(device, streamInfo, speed);
  184 + try {
  185 + cmder.playSpeedCmd(device, streamInfo, speed);
  186 + } catch (InvalidArgumentException | ParseException | SipException e) {
  187 + throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
  188 + }
161 189 }
162 190 }
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/ptz/PtzController.java
1 1 package com.genersoft.iot.vmp.vmanager.gb28181.ptz;
2 2  
3 3  
  4 +import com.genersoft.iot.vmp.conf.exception.ControllerException;
  5 +import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
4 6 import io.swagger.v3.oas.annotations.Operation;
5 7 import io.swagger.v3.oas.annotations.Parameter;
6 8 import io.swagger.v3.oas.annotations.tags.Tag;
... ... @@ -18,6 +20,9 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
18 20 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
19 21 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
20 22  
  23 +import javax.sip.InvalidArgumentException;
  24 +import javax.sip.SipException;
  25 +import java.text.ParseException;
21 26 import java.util.UUID;
22 27  
23 28 @Tag(name = "云台控制")
... ... @@ -98,7 +103,12 @@ public class PtzController {
98 103 default:
99 104 break;
100 105 }
101   - cmder.frontEndCmd(device, channelId, cmdCode, horizonSpeed, verticalSpeed, zoomSpeed);
  106 + try {
  107 + cmder.frontEndCmd(device, channelId, cmdCode, horizonSpeed, verticalSpeed, zoomSpeed);
  108 + } catch (SipException | InvalidArgumentException | ParseException e) {
  109 + logger.error("[命令发送失败] 云台控制: {}", e.getMessage());
  110 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
  111 + }
102 112 }
103 113  
104 114  
... ... @@ -117,7 +127,12 @@ public class PtzController {
117 127 }
118 128 Device device = storager.queryVideoDevice(deviceId);
119 129  
120   - cmder.frontEndCmd(device, channelId, cmdCode, parameter1, parameter2, combindCode2);
  130 + try {
  131 + cmder.frontEndCmd(device, channelId, cmdCode, parameter1, parameter2, combindCode2);
  132 + } catch (SipException | InvalidArgumentException | ParseException e) {
  133 + logger.error("[命令发送失败] 前端控制: {}", e.getMessage());
  134 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
  135 + }
121 136 }
122 137  
123 138  
... ... @@ -146,13 +161,18 @@ public class PtzController {
146 161 return result;
147 162 }
148 163 resultHolder.put(key, uuid, result);
149   - cmder.presetQuery(device, channelId, event -> {
150   - RequestMessage msg = new RequestMessage();
151   - msg.setId(uuid);
152   - msg.setKey(key);
153   - msg.setData(String.format("获取设备预置位失败,错误码: %s, %s", event.statusCode, event.msg));
154   - resultHolder.invokeResult(msg);
155   - });
  164 + try {
  165 + cmder.presetQuery(device, channelId, event -> {
  166 + RequestMessage msg = new RequestMessage();
  167 + msg.setId(uuid);
  168 + msg.setKey(key);
  169 + msg.setData(String.format("获取设备预置位失败,错误码: %s, %s", event.statusCode, event.msg));
  170 + resultHolder.invokeResult(msg);
  171 + });
  172 + } catch (InvalidArgumentException | SipException | ParseException e) {
  173 + logger.error("[命令发送失败] 获取设备预置位: {}", e.getMessage());
  174 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
  175 + }
156 176 return result;
157 177 }
158 178 }
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java
... ... @@ -3,7 +3,9 @@ package com.genersoft.iot.vmp.vmanager.gb28181.record;
3 3 import com.alibaba.fastjson.JSONObject;
4 4 import com.genersoft.iot.vmp.common.StreamInfo;
5 5 import com.genersoft.iot.vmp.conf.exception.ControllerException;
  6 +import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
6 7 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
  8 +import com.genersoft.iot.vmp.service.IDeviceService;
7 9 import com.genersoft.iot.vmp.service.IMediaServerService;
8 10 import com.genersoft.iot.vmp.service.IPlayService;
9 11 import com.genersoft.iot.vmp.utils.DateUtil;
... ... @@ -31,6 +33,9 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
31 33 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
32 34 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
33 35  
  36 +import javax.sip.InvalidArgumentException;
  37 +import javax.sip.SipException;
  38 +import java.text.ParseException;
34 39 import java.time.LocalDate;
35 40 import java.util.UUID;
36 41  
... ... @@ -54,6 +59,12 @@ public class GBRecordController {
54 59 @Autowired
55 60 private IPlayService playService;
56 61  
  62 + @Autowired
  63 + private IDeviceService deviceService;
  64 +
  65 +
  66 +
  67 +
57 68 @Operation(summary = "录像查询")
58 69 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
59 70 @Parameter(name = "channelId", description = "通道国标编号", required = true)
... ... @@ -81,13 +92,18 @@ public class GBRecordController {
81 92 RequestMessage msg = new RequestMessage();
82 93 msg.setId(uuid);
83 94 msg.setKey(key);
84   - cmder.recordInfoQuery(device, channelId, startTime, endTime, sn, null, null, null, (eventResult -> {
85   - WVPResult<RecordInfo> wvpResult = new WVPResult<>();
86   - wvpResult.setCode(ErrorCode.ERROR100.getCode());
87   - wvpResult.setMsg("查询录像失败, status: " + eventResult.statusCode + ", message: " + eventResult.msg);
88   - msg.setData(wvpResult);
89   - resultHolder.invokeResult(msg);
90   - }));
  95 + try {
  96 + cmder.recordInfoQuery(device, channelId, startTime, endTime, sn, null, null, null, (eventResult -> {
  97 + WVPResult<RecordInfo> wvpResult = new WVPResult<>();
  98 + wvpResult.setCode(ErrorCode.ERROR100.getCode());
  99 + wvpResult.setMsg("查询录像失败, status: " + eventResult.statusCode + ", message: " + eventResult.msg);
  100 + msg.setData(wvpResult);
  101 + resultHolder.invokeResult(msg);
  102 + }));
  103 + } catch (InvalidArgumentException | SipException | ParseException e) {
  104 + logger.error("[命令发送失败] 查询录像: {}", e.getMessage());
  105 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
  106 + }
91 107  
92 108 // 录像查询以channelId作为deviceId查询
93 109 resultHolder.put(key, uuid, result);
... ... @@ -131,14 +147,24 @@ public class GBRecordController {
131 147 @GetMapping("/download/stop/{deviceId}/{channelId}/{stream}")
132 148 public void playStop(@PathVariable String deviceId, @PathVariable String channelId, @PathVariable String stream) {
133 149  
134   - cmder.streamByeCmd(deviceId, channelId, stream, null);
135   -
136 150 if (logger.isDebugEnabled()) {
137 151 logger.debug(String.format("设备历史媒体下载停止 API调用,deviceId/channelId:%s_%s", deviceId, channelId));
138 152 }
139 153  
140 154 if (deviceId == null || channelId == null) {
141   - throw new ControllerException(ErrorCode.ERROR100);
  155 + throw new ControllerException(ErrorCode.ERROR400);
  156 + }
  157 +
  158 + Device device = deviceService.queryDevice(deviceId);
  159 + if (device == null) {
  160 + throw new ControllerException(ErrorCode.ERROR400.getCode(), "设备:" + deviceId + "未找到");
  161 + }
  162 +
  163 + try {
  164 + cmder.streamByeCmd(device, channelId, stream, null);
  165 + } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) {
  166 + logger.error("[停止历史媒体下载]停止历史媒体下载,发送BYE失败 {}", e.getMessage());
  167 + throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
142 168 }
143 169 }
144 170  
... ...
src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiControlController.java
1 1 package com.genersoft.iot.vmp.web.gb28181;
2 2  
3 3 import com.alibaba.fastjson.JSONObject;
  4 +import com.genersoft.iot.vmp.conf.exception.ControllerException;
4 5 import com.genersoft.iot.vmp.gb28181.bean.Device;
5 6 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
6 7 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
  8 +import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
7 9 import org.slf4j.Logger;
8 10 import org.slf4j.LoggerFactory;
9 11 import org.springframework.beans.factory.annotation.Autowired;
10 12 import org.springframework.web.bind.annotation.*;
11 13  
  14 +import javax.sip.InvalidArgumentException;
  15 +import javax.sip.SipException;
  16 +import java.text.ParseException;
  17 +
12 18 /**
13 19 * API兼容:设备控制
14 20 */
... ... @@ -35,7 +41,7 @@ public class ApiControlController {
35 41 * @return
36 42 */
37 43 @RequestMapping(value = "/ptz")
38   - private JSONObject list(String serial,String command,
  44 + private void list(String serial,String command,
39 45 @RequestParam(required = false)Integer channel,
40 46 @RequestParam(required = false)String code,
41 47 @RequestParam(required = false)Integer speed){
... ... @@ -48,9 +54,7 @@ public class ApiControlController {
48 54 if (speed == null) {speed = 0;}
49 55 Device device = storager.queryVideoDevice(serial);
50 56 if (device == null) {
51   - JSONObject result = new JSONObject();
52   - result.put("error","device[ " + serial + " ]未找到");
53   - return result;
  57 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "device[ " + serial + " ]未找到");
54 58 }
55 59 int cmdCode = 0;
56 60 switch (command){
... ... @@ -91,7 +95,11 @@ public class ApiControlController {
91 95 break;
92 96 }
93 97 // 默认值 50
94   - cmder.frontEndCmd(device, code, cmdCode, speed, speed, speed);
95   - return null;
  98 + try {
  99 + cmder.frontEndCmd(device, code, cmdCode, speed, speed, speed);
  100 + } catch (SipException | InvalidArgumentException | ParseException e) {
  101 + logger.error("[命令发送失败] 云台控制: {}", e.getMessage());
  102 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
  103 + }
96 104 }
97 105 }
... ...
src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiStreamController.java
... ... @@ -3,10 +3,12 @@ package com.genersoft.iot.vmp.web.gb28181;
3 3 import com.alibaba.fastjson.JSONObject;
4 4 import com.genersoft.iot.vmp.common.StreamInfo;
5 5 import com.genersoft.iot.vmp.conf.UserSetting;
  6 +import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
6 7 import com.genersoft.iot.vmp.gb28181.bean.Device;
7 8 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
8 9 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
9 10 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
  11 +import com.genersoft.iot.vmp.service.IDeviceService;
10 12 import com.genersoft.iot.vmp.service.IPlayService;
11 13 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
12 14 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
... ... @@ -17,6 +19,10 @@ import org.springframework.beans.factory.annotation.Autowired;
17 19 import org.springframework.web.bind.annotation.*;
18 20 import org.springframework.web.context.request.async.DeferredResult;
19 21  
  22 +import javax.sip.InvalidArgumentException;
  23 +import javax.sip.SipException;
  24 +import java.text.ParseException;
  25 +
20 26 /**
21 27 * API兼容:实时直播
22 28 */
... ... @@ -41,6 +47,9 @@ public class ApiStreamController {
41 47 private IRedisCatchStorage redisCatchStorage;
42 48  
43 49 @Autowired
  50 + private IDeviceService deviceService;
  51 +
  52 + @Autowired
44 53 private IPlayService playService;
45 54  
46 55 /**
... ... @@ -74,10 +83,12 @@ public class ApiStreamController {
74 83 JSONObject result = new JSONObject();
75 84 result.put("error","device[ " + serial + " ]未找到");
76 85 resultDeferredResult.setResult(result);
  86 + return resultDeferredResult;
77 87 }else if (device.getOnline() == 0) {
78 88 JSONObject result = new JSONObject();
79 89 result.put("error","device[ " + code + " ]offline");
80 90 resultDeferredResult.setResult(result);
  91 + return resultDeferredResult;
81 92 }
82 93 resultDeferredResult.onTimeout(()->{
83 94 logger.info("播放等待超时");
... ... @@ -93,10 +104,12 @@ public class ApiStreamController {
93 104 JSONObject result = new JSONObject();
94 105 result.put("error","channel[ " + code + " ]未找到");
95 106 resultDeferredResult.setResult(result);
  107 + return resultDeferredResult;
96 108 }else if (deviceChannel.getStatus() == 0) {
97 109 JSONObject result = new JSONObject();
98 110 result.put("error","channel[ " + code + " ]offline");
99 111 resultDeferredResult.setResult(result);
  112 + return resultDeferredResult;
100 113 }
101 114 MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
102 115 PlayResult play = playService.play(newMediaServerItem, serial, code, (mediaServerItem, response)->{
... ... @@ -134,18 +147,6 @@ public class ApiStreamController {
134 147 result.put("RelaySize", "");
135 148 result.put("ChannelPTZType", "0");
136 149 resultDeferredResult.setResult(result);
137   -// Class<?> aClass = responseEntity.getClass().getSuperclass();
138   -// Field body = null;
139   -// try {
140   -// // 使用反射动态修改返回的body
141   -// body = aClass.getDeclaredField("body");
142   -// body.setAccessible(true);
143   -// body.set(responseEntity, result);
144   -// } catch (NoSuchFieldException e) {
145   -// e.printStackTrace();
146   -// } catch (IllegalAccessException e) {
147   -// e.printStackTrace();
148   -// }
149 150 }, (eventResult) -> {
150 151 JSONObject result = new JSONObject();
151 152 result.put("error", "channel[ " + code + " ] " + eventResult.msg);
... ... @@ -177,7 +178,19 @@ public class ApiStreamController {
177 178 result.put("error","未找到流信息");
178 179 return result;
179 180 }
180   - cmder.streamByeCmd(serial, code, streamInfo.getStream(), null);
  181 + Device device = deviceService.queryDevice(serial);
  182 + if (device == null) {
  183 + JSONObject result = new JSONObject();
  184 + result.put("error","未找到设备");
  185 + return result;
  186 + }
  187 + try {
  188 + cmder.streamByeCmd(device, code, streamInfo.getStream(), null);
  189 + } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) {
  190 + JSONObject result = new JSONObject();
  191 + result.put("error","发送BYE失败:" + e.getMessage());
  192 + return result;
  193 + }
181 194 redisCatchStorage.stopPlay(streamInfo);
182 195 storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
183 196 return null;
... ...